Front-Commerce uses the winston library for logging. This guide explains how to configure it and use it in your own code.
When you need to log something in a javascript environment, the first thing that
comes to mind is obviously console.log
. But the issue with it is that you
won't be able access it in the long term. Especially since some Node.js server
environments don't keep a trace of the stdout/stderr of your application.
To avoid this, we're using a custom logging interface based on
winston
(a well-known logging solution
in the Node.js ecosystem). It allows you to create a logger and configure it in
your my-module/config/logging.js
file to send your logs to different systems.
Use the base loggers
There are three default loggers coming with Front-Commerce:
server logger
Reports any message sent through the default
winston
import in express routes
winston.info({
message: `Customer returned from ${methodCode} (${actionName})`,
date: format(new Date()),
});
client logger
Reports any log message from the client side
import logHandler from "web/core/logs/logHandler";
logHandler.getLogger().error(e);
access logger
Logs automatically any request incoming on your server
Configure the loggers
Without configuration, a logger does nothing. You need to configure what to do with the message reported by the different loggers.
module.exports = {
server: [
{
type: "file",
filename: "server.log",
},
],
payment: [
{
type: "file",
filename: "payment.log",
},
],
client: [
{
type: "file",
filename: "client.log",
},
],
access: [
{
type: "file",
filename: "access.log",
},
],
security: [
{
type: "file",
filename: "security.log",
},
],
};
In this example, we've told the logging system to output every message in four
files server.log
, payment.log
, client.log
, access.log
that will be
accessible in the logs/
folder of your application.
But how does this work?
In fact, the object that we exports tells the logging system that for each logger (identified by the keys of the object), we will add an array of transports.
This means that for each logger, each message will be sent using these transports. Currently, the following types of logger transports are supported in Front-Commerce:
type: "file"
: it will append the message to a file in your server's filesystem.
The only option available isfilename
which is the name of the file that will be put in thelogs
folder of your project.type: "sentry"
: it will send the message to a sentry instance. Sentry is a tool that will make it easier to triage errors and assign some of your team members to their resolution.
The only option available isoptions
which is the object given to the transport lib winston-sentry-logtype: "console"
: it will send the message to stdout/stderr. This is intended for customers that already have a log collection system (centralized logging for kubernetes or a cloud platform).type: "custom"
: You can provide your ownwinston.transports
configuration within thetransport
attribute. This is intended for customers that need more control on the logging strategies.
Add a new logger
Splitting your messages in the four default loggers (access
, client
,
server
, payment
) might be enough. But in some cases, you may want to move
the messages into another logger to make it either to follow what happens for a
specific feature.
The new loggers you will create are only available server side. If you need to use this logger from the client side, you will need to either create a GraphQL mutation or a custom HTTP endpoint. This will allow the client to send a message to the server which will then be able to log it.
To do so, you can add a new custom logger
module.exports = {
// ... the rest of your logger configuration
myLoggerName: [
{
type: "file",
filename: "server.log",
},
],
};
By doing this, you've configured your logger. But you still need to use it by
importing the loggingService
that will let you create the logger.
import loggingService from "server/core/logs/loggingService";
const logger = loggingService.createLogger("myLoggerName");
This will then be used just like the
winston API:
logger.log(type, message, data)
.
Log to the console
You can redirect all your logs to the console with the following code
module.exports = {
server: [
{
type: "console",
},
],
payment: [
{
type: "console",
},
],
client: [
{
type: "console",
},
],
access: [
{
type: "console",
},
],
security: [
{
type: "console",
},
],
};
Automatic logging configuration
You can also automate the logging configuration based on whether the application
is deployed on our cloud offer (V2) or not using the following
my-module/config/logging.js
const makeLogAccordingToEnv = (filename) =>
process.env.FRONT_COMMERCE_CLOUD_VERSION === "2"
? { type: "console" }
: { type: "file", filename };
module.exports = {
server: [makeLogAccordingToEnv("server.log")],
client: [makeLogAccordingToEnv("client.log")],
access: [makeLogAccordingToEnv("access.log")],
payment: [makeLogAccordingToEnv("payment.log")],
security: [makeLogAccordingToEnv("security.log")],
};
Custom logger implementation
You can implement a custom logger like the following example
const winston = require("winston");
module.exports = {
server: [
{
type: "custom",
transport: new winston.transports.Console({
format: winston.format.simple(),
}),
},
],
};
See available Winston transports for more details