Look at the nitro quick start to learn more how to get started.
My favorite logger, Morgan adapted into Freeman for Nitro with simple utils and middleware.
Credits to:
Start by adding fs, ua-parser-js and morgan to your Nitro project.
- Create a new file in your
./server/utilsfolder calledlogger.tsor in my casefreeman.ts, not really relevant. Add the following code:
import morgan from 'morgan'
import userAgentParser from 'ua-parser-js'
import fs from 'fs'
const morganJSONFormat = () => JSON.stringify({
method: ':method',
url: ':url',
http_version: ':http-version',
remote_addr: ':remote-addr',
response_time: ':response-time',
status: ':status',
content_length: ':res[content-length]',
'@timestamp': ':date[iso]',
user_agent: ':user-agent',
referrer: ':referrer',
accept: ':req[accept]',
accept_language: ':req[accept-language]',
accept_encoding: ':req[accept-encoding]',
host: ':req[host]',
})
export const accessLogStream = fs.createWriteStream('access.log', { flags: 'a' });
export const logger = morgan(morganJSONFormat(), {
stream: {
write: (message) => {
const data = JSON.parse(message); // Parse the log message
parseUserAgent(data); // Process the parsed log data
const logData = JSON.stringify(data); // Convert the processed data back to JSON
accessLogStream.write(logData + '\n'); // Write the log data to the file
return true;
},
},
});
export const parseUserAgent = function (data) {
if (data.user_agent) {
const ua = userAgentParser(data.user_agent)
if (ua.browser) {
data.user_agent_browser_name = ua.browser.name
data.user_agent_browser_version = ua.browser.major || ua.browser.version
}
if (ua.os) {
data.user_agent_os_name = ua.os.name
data.user_agent_os_version = ua.os.version
}
}
}- Create a new file in
./server/middleware/calledlog.tswith the following content:
export default defineEventHandler((event) => {
logger(event.node.req, event.node.res, function () {
return
})
})Example with Log splitting
export default defineEventHandler((event) => {
if (getRequestURL(event).pathname === '/') {
logger(event.node.req, event.node.res, function () {
// Optional callback function for handling errors or additional logic
console.log("Logged:", getRequestURL(event).pathname)
return;
});
}
if (getRequestURL(event).pathname === '/specific-path') {
logger(event.node.req, event.node.res, function () {
console.log("Logged:", getRequestURL(event).pathname)
return;
});
}
})That's it.
The log util should automagicaly fire with every incoming request or response
and append it too access.log at the root of your workspace.
Always use writeStreams and don't block the event loop with sync write to disk Ops. If you want to optimize, forward your requests to another standalone Nitro server or third party service, just for logging. Or you could use Nitro Tasks (scheduled CRON jobs) to clean up the file every 24h.