Arĝentakato
Arĝentakatoā€¢4mo ago

Logger Structure args

I am implementing a simple access log in Deno Fresh, but I am not quite sure how to use the standard library Logger. I want to record logs with remote host etc. at the beginning of the sentence like nginx logs, but can I specify the type of log argument? Currently, the implementation is as follows:
log.setup({
handlers: {
accsessLoggerFmt: new log.ConsoleHandler("INFO", {
formatter: (record) => {
const { datetime, levelName, msg, args } = record;

const d = new Date(datetime.getTime() - datetime.getTimezoneOffset() * 6e4);
const logTime = d.toISOString().slice(0, -5) + d.toString().replace(/^.*GMT([-+]\d{2})(\d{2}).*$/, "$1:$2");

let log = `${logTime} ${levelName.padEnd(7)}`;

for (const arg of args) {
log += ` ${arg}`;
}

log += ` ${msg}`;

return log;
}),
},
loggers: {
accessLogger: {
level: "INFO",
handlers: ["accsessLoggerFmt"],
},
},
});

const requestId = ...
const ip = ...

logger.info("Something", requestId, ip);
log.setup({
handlers: {
accsessLoggerFmt: new log.ConsoleHandler("INFO", {
formatter: (record) => {
const { datetime, levelName, msg, args } = record;

const d = new Date(datetime.getTime() - datetime.getTimezoneOffset() * 6e4);
const logTime = d.toISOString().slice(0, -5) + d.toString().replace(/^.*GMT([-+]\d{2})(\d{2}).*$/, "$1:$2");

let log = `${logTime} ${levelName.padEnd(7)}`;

for (const arg of args) {
log += ` ${arg}`;
}

log += ` ${msg}`;

return log;
}),
},
loggers: {
accessLogger: {
level: "INFO",
handlers: ["accsessLoggerFmt"],
},
},
});

const requestId = ...
const ip = ...

logger.info("Something", requestId, ip);
A current implementation requires inserting the remote host or other information to be displayed in the argument each time, which we believe is tedious and prone to errors. I have read the documentation but could not come up with a good solution. Any advice would be appreciated.
5 Replies
Deno AI Helper
Deno AI Helperā€¢4mo ago
In the standard Deno logging library, you can indeed customize the log message format to include additional information such as the remote host, similar to how nginx logs are structured. The formatter function you provide to a handler is responsible for constructing the log message format. From the documentation, it's clear that you can use a function-based formatter that takes a LogRecord as an argument and outputs a string. This allows you to define the exact format of your log messages, including any additional arguments you might want to include. Your current implementation is on the right track. You're using a custom formatter to structure your log messages. However, if you find it tedious to include the remote host or other information as arguments each time you log a message, you could consider creating a wrapper function around the logger that includes these details by default. Here's a simplified example of how you might create such a wrapper function:
import * as log from "https://deno.land/std/log/mod.ts";

// Set up your logger as before
log.setup({
// ... your existing setup
});

const accessLogger = log.getLogger("accessLogger");

// Define a wrapper function for logging access information
function logAccess(message, requestId, ip) {
// Here you can include the remote host and other details by default
// and call the logger's info method with the structured message
accessLogger.info(`${ip} ${requestId} ${message}`);
}

// Usage of the wrapper function
const requestId = "abc123";
const ip = "192.168.1.1";

logAccess("User accessed the dashboard", requestId, ip);
import * as log from "https://deno.land/std/log/mod.ts";

// Set up your logger as before
log.setup({
// ... your existing setup
});

const accessLogger = log.getLogger("accessLogger");

// Define a wrapper function for logging access information
function logAccess(message, requestId, ip) {
// Here you can include the remote host and other details by default
// and call the logger's info method with the structured message
accessLogger.info(`${ip} ${requestId} ${message}`);
}

// Usage of the wrapper function
const requestId = "abc123";
const ip = "192.168.1.1";

logAccess("User accessed the dashboard", requestId, ip);
By using a wrapper function like logAccess, you encapsulate the logic for structuring the log message and ensure that the remote host and other details are
Deno AI Helper
Deno AI Helperā€¢4mo ago
consistently included in every log entry. This approach reduces the chance of errors and makes your logging code cleaner and easier to maintain. Remember to adjust the wrapper function to include any additional information you need in your logs and to match the structure you desire. šŸ¦•
Leokuma
Leokumaā€¢4mo ago
I find std/logger too difficult to use. I prefer to use simple console.log or something
Leokuma
Leokumaā€¢4mo ago
There's also this module. I've never used it, though: https://github.com/onjara/optic
GitHub
GitHub - onjara/optic: A powerful logging framework for Deno
A powerful logging framework for Deno. Contribute to onjara/optic development by creating an account on GitHub.
Arĝentakato
Arĝentakatoā€¢4mo ago
Thank you. I will try the library you suggested.