Loggføring av HTTP-forespørsler med Morgan

Red: 15. juni 2026 | Pub: 30. mai 2026 | #node, #programmering

Denne teksten inngår i serien node.

Andre artikler i samme serie:

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- og next-parameterne
  • Morgan registrerer forespørselen, og etablerer en overvåking eller “lytting” («callback») etter finish-hendelse i res-objektet. Den lagrer også et tidsstempel før den kaller next() 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 res fyrer finish-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, res og next inn 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å.


Ris, ros eller respons?

Send meg gjerne om du har en kommentar, korrektur eller konstruktiv kritikk til denne saken.