Loggføring av HTTP-forespørsler med Morgan
Denne teksten inngår i serien node.
Andre artikler i samme serie:
- Logging av interne feil med Winston
- Loggføring av HTTP-forespørsler med Morgan
- Node i «Express»-fart
- Feilhåndtering og feilkoder
- Fra kommandolinjen til server i Node
- Fra Markdown til JSON
- Jeg lærer Node.js
Morgan er en «middleware» (eller mellomvare på norsk) for å logge HTTP-forespørsler. Det gir utviklere og serveradministratorer full oversikt over aktiviteten, og kan være spesielt nyttig i forbindelse med feilsøking eller for å få et bilde av trafikken.
I forrige Node-innlegg konverterte jeg applikasjonen fra å benytte HTTP-modulen til fordel for mellomvaren Express.
Først installerte jeg Morgan fra NPM via terminalen npm install morgan. Deretter importerte jeg modulen i server.js.
const morgan = require("morgan");
Jeg leste dokumentasjonen , og la til følgende standardversjon av loggeverktøyet:
app.use(morgan(function (tokens, req, res) {
return [
tokens.method(req, res),
tokens.url(req, res),
tokens.status(req, res),
tokens.date(req, res),
tokens.res(req, res, 'content-length'), '-',
tokens['response-time'](req, res), 'ms'
].join(' ')
}))
Dette kallet la jeg til nederst i listen over «middleware», men det fungerte ikke. Den må ligge over endepunkthåndteringen app.use('/tasks', taskRoutes). For å kunne logge en forespørsel, må Morgan nemlig “hektes” på før forespørselen blir behandlet og returnert.
// Express middleware
app.use(express.json());
app.use(morgan(function (tokens, req, res) {
return [
tokens.method(req, res),
tokens.url(req, res),
tokens.status(req, res),
tokens.res(req, res, 'content-length'), '-',
tokens['response-time'](req, res), 'ms'
].join(' ')
}))
app.use('/tasks', taskRoutes);
app.use((req, res) => {res.status(404).json('Not found')});
Med Morgan installert, er flyten som følger:
- Forespørsel kommer inn, og Express kaller Morgans «middleware» med
req-,res- ognext-parameterne - Morgan registrerer forespørselen, og etablerer en overvåking eller “lytting” («callback») etter
finish-hendelse ires-objektet. Den lagrer også et tidsstempel før den kallernext()for å sende forespørselen videre - Forespørselen går videre til endepunkthåndtereren som behandler den, og klargjør en respons
- Responsen sendes til klienten, og
resfyrerfinish-hendelsen - Nodes «event loop» plukker opp Morgans «callback»-funksjon, og kjører den
- Først da logger Morgan — fordi den har all informasjonen den trenger, og sjekker tiden mot det lagrede tidsstempelet for å regne ut behandlingstiden for forespørselen.
MERK: Express sender
req,resognextinn i all mellomvare, slik at de får all informasjonen de trenger.next()er for å gå sende kontrollen videre til neste funksjon i rekken.
Logge til fil
Å se loggen i terminalen er vel og bra, men den kan fort forsvinne hvis terminalen lukkes eller tømmes. Derfor ønsket jeg å skrive til fil.
Ifølge dokumentasjonen må man etablere en skrivestrøm. Det vil si en kontinuerlig prosess, som sørger for å oppdatere så lenge applikasjonen kjører.
Jeg trengte også fs for filoperasjon, samt path for baner.
const fs = require('fs')
const path = require('path')
Deretter la jeg inn følgende:
fs.mkdirSync('logs', { recursive: true })
const accessLogStream = fs.createWriteStream(path.join(__dirname, 'logs', 'access.log'), { flags: 'a' })
recursive i fs.mkdirSync betyr å opprette mappen dersom den ikke allerede finnes fra før.
I accessLogStream definerte jeg banen for strømmen, samt satt flagget a som står for «append», slik at innkommende logger alltid legger seg i bunnen av filen, og ikke overskriver den fra gang til gang.
Nå får jeg følgende i log-filen:
GET /tasks 304 Wed, 03 Jun 2026 19:19:50 GMT - 1.311 ms
GET / 404 Wed, 03 Jun 2026 19:19:52 GMT 11 - 0.939 ms
Flytte til egen fil
Jeg hadde server.js så ren og fin, og det ønsker jeg å fortsette med. Derfor valgte jeg å opprette mappen middleware og filen morgan.js. Her limte jeg inn relevant kode, og eksporterte funksjonen direkte:
'use strict'
const morgan = require("morgan");
const fs = require('node:fs')
const path = require('node:path')
// create a write stream (in append mode)
fs.mkdirSync('logs', { recursive: true })
const accessLogStream = fs.createWriteStream(path.join(__dirname, '../logs', 'access.log'), { flags: 'a' })
const logger = morgan(function (tokens, req, res) {
return [
tokens.method(req, res),
tokens.url(req, res),
tokens.status(req, res),
tokens.date(req, res),
tokens.res(req, res, 'content-length'), '-',
tokens['response-time'](req, res), 'ms'
].join(' ')
}, { stream: accessLogStream })
module.exports = logger
Denne importere jeg så i server.js:
//...
const logger = require('./middleware/morgan')
//...
app.use(logger);
//...
Dette er bare noe av det som kan gjøres med Morgan, men det holder for mitt vedkommende i denne omgang. Nå går turen videre til Winston, som er en mer utviklet og avansert logger, som hjelper oss å holde oversikt over interne feil som måtte oppstå.