Skip to content

Instantly share code, notes, and snippets.

@sumanmaity112
Last active March 7, 2022 17:16
Show Gist options
  • Save sumanmaity112/41ec20a1f595b8ca82c7b17a121845ca to your computer and use it in GitHub Desktop.
Save sumanmaity112/41ec20a1f595b8ca82c7b17a121845ca to your computer and use it in GitHub Desktop.
Example of stractured logging with MDC using log4js for NodeJs
import fetch from "node-fetch";
import {logger} from "./logWithMdc.js";
const fetchReceipt = (receiptId, log) => {
log.info(`Fetching receipt for ${receiptId}`)
// https://jsonplaceholder.typicode.com/todos/{id} can be used for testing
return fetch(`https://jsonplaceholder.typicode.com/todos/${receiptId}`)
.then(res => {
if (res.ok) {
log.info(`Successfully fetched receipt for ${receiptId}`)
return Promise.resolve(res);
} else {
log.error(`Unable to fetch receipt for ${receiptId}`)
return res.text().then(reason => Promise.reject(new Error(reason)));
}
})
}
const fetchReceipts = (events, mainLog) => {
return Promise.all(events.map(event => {
const log = logger();
log.addContext("traceId", event.traceId);
log.addContext("orderId", event.orderId);
return fetchReceipt(event.receiptId, log);
}));
};
const app = (log) => {
const events = [
{
traceId: "traceId-1",
orderId: "orderId-1",
receiptId: "1"
},
{
traceId: "traceId-2",
orderId: "orderId-2",
receiptId: "2"
},
{
traceId: "traceId-3",
orderId: "orderId-3",
receiptId: "3"
},
{
traceId: "traceId-4",
orderId: "orderId-4",
receiptId: "4"
},
{
traceId: "traceId-5",
orderId: "orderId-5",
receiptId: "5"
}
]
return fetchReceipts(events, log);
}
const execute = () => {
const log = logger();
app(log)
.then(receipts => log.info("Successfully fetched receipts"))
.catch(reason => log.error("Unable to fetch some of the receipts", reason))
}
execute();
import fetch from "node-fetch";
import {logger} from "./logWithoutMdc.js";
const fetchReceipt = (receiptId, log) => {
log.info(`Fetching receipt for ${receiptId}`)
// https://jsonplaceholder.typicode.com/todos/{id} can be used for testing
return fetch(`/receipts/${receiptId}`)
.then(res => {
if (res.ok) {
log.info(`Successfully fetched receipt for ${receiptId}`)
return Promise.resolve(res);
} else {
log.error(`Unable to fetch receipt for ${receiptId}`)
return res.text().then(reason => Promise.reject(new Error(reason)));
}
})
}
const fetchReceipts = (events, log) => Promise.all(events.map(event => fetchReceipt(event.receiptId, log)));
const app = (log) => {
const events = [
{
traceId: "traceId-1",
orderId: "orderId-1",
receiptId: "1"
},
{
traceId: "traceId-2",
orderId: "orderId-2",
receiptId: "2"
},
{
traceId: "traceId-3",
orderId: "orderId-3",
receiptId: "3"
},
{
traceId: "traceId-4",
orderId: "orderId-4",
receiptId: "4"
},
{
traceId: "traceId-5",
orderId: "orderId-5",
receiptId: "5"
}
]
return fetchReceipts(events, log);
}
const execute = () => {
const log = logger();
app(log)
.then(receipts => log.info("Successfully fetched receipts"))
.catch(reason => log.error("Unable to fetch some of the receipts", reason))
}
execute();
{"timestamp":"<timestamp>","level":"INFO","message":"Fetching receipt for 1","traceId":"traceId-1","orderId":"orderId-1"}
{"timestamp":"<timestamp>","level":"INFO","message":"Fetching receipt for 2","traceId":"traceId-2","orderId":"orderId-2"}
{"timestamp":"<timestamp>","level":"INFO","message":"Fetching receipt for 3","traceId":"traceId-3","orderId":"orderId-3"}
{"timestamp":"<timestamp>","level":"INFO","message":"Fetching receipt for 4","traceId":"traceId-4","orderId":"orderId-4"}
{"timestamp":"<timestamp>","level":"INFO","message":"Fetching receipt for 5","traceId":"traceId-5","orderId":"orderId-5"}
{"timestamp":"<timestamp>","level":"INFO","message":"Successfully fetched receipt for 3","traceId":"traceId-3","orderId":"orderId-3"}
{"timestamp":"<timestamp>","level":"INFO","message":"Successfully fetched receipt for 4","traceId":"traceId-4","orderId":"orderId-4"}
{"timestamp":"<timestamp>","level":"INFO","message":"Successfully fetched receipt for 2","traceId":"traceId-2","orderId":"orderId-2"}
{"timestamp":"<timestamp>","level":"INFO","message":"Successfully fetched receipt for 1","traceId":"traceId-1","orderId":"orderId-1"}
{"timestamp":"<timestamp>","level":"INFO","message":"Successfully fetched receipt for 5","traceId":"traceId-5","orderId":"orderId-5"}
{"timestamp":"<timestamp>","level":"INFO","message":"Successfully fetched receipts"}
[<timestamp>] default - Fetching receipt for 1
[<timestamp>] default - Fetching receipt for 2
[<timestamp>] default - Fetching receipt for 3
[<timestamp>] default - Fetching receipt for 4
[<timestamp>] default - Fetching receipt for 5
[<timestamp>] default - Successfully fetched receipt for 2
[<timestamp>] default - Successfully fetched receipt for 4
[<timestamp>] default - Successfully fetched receipt for 1
[<timestamp>] default - Successfully fetched receipt for 5
[<timestamp>] default - Successfully fetched receipt for 3
[<timestamp>] default - Successfully fetched receipts
import log4js from "log4js";
const format = (elements) =>
elements.map((element) =>
!(element instanceof Error) ? element.toString() : `${element.stack}`
);
log4js.addLayout("json", (config) => (logEvent) => {
const { startTime, data, level, context } = logEvent;
const newLog = {
timestamp: startTime,
level: level.levelStr,
message: format(data).join(config.separator),
...context,
};
return JSON.stringify(newLog);
});
log4js.configure({
appenders: {
stdout: { type: "stdout", layout: { type: "json", separator: "," } },
stderr: { type: "stderr", layout: { type: "json", separator: "," } },
error: { type: "logLevelFilter", appender: "stderr", level: "warn" },
information: {
type: "logLevelFilter",
appender: "stdout",
level: "debug",
maxLevel: "info",
},
},
categories: {
default: {
appenders: ["information", "error"],
level: "debug",
enableCallStack: true,
},
},
});
const logger = log4js.getLogger;
export { logger };
import log4js from "log4js";
log4js.configure({
appenders: {
stdout: { type: "stdout", layout: { type: "basic", separator: "," } },
stderr: { type: "stderr", layout: { type: "basic", separator: "," } },
error: { type: "logLevelFilter", appender: "stderr", level: "warn" },
information: {
type: "logLevelFilter",
appender: "stdout",
level: "debug",
maxLevel: "info",
},
},
categories: {
default: {
appenders: ["information", "error"],
level: "debug",
enableCallStack: true,
},
},
});
const logger = log4js.getLogger;
export { logger };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment