2013-07-17 14 views
8

Sto sviluppando un server RESTful in node.js, usando Express come framework, e Winston, per il momento, come modulo logger. Questo server gestirà una grande quantità di richieste simultanee, e sarebbe molto utile per me essere in grado di tracciare le voci del registro per ogni specifica richiesta, usando qualcosa come un 'ID richiesta'. La soluzione diritta è solo per aggiungere questo ID come un'altra informazione di logging ogni volta che voglio fare una voce di log, ma significherà passare l''ID di richiesta' a ciascun metodo usato dal server.Come identificare la richiesta (tramite ID) attraverso la catena del middleware in Express.

Vorrei sapere se esiste un modulo node.js/javascript o una tecnica che mi consenta di farlo in un modo più semplice, senza dover aggirare l'ID della richiesta per ogni specifica richiesta.

risposta

4

È possibile utilizzare l'oggetto req che viene fornito con ogni richiesta espressa.
Così il primo percorso si farebbe nella vostra applicazione potrebbe essere:

var logIdIterator = 0; 

app.all('*', function(req, res, next) { 
    req.log = { 
    id: ++logIdIterator 
    } 
    return next(); 
}); 

E poi ovunque all'interno Express, è possibile accedere a tale id in req oggetto: req.log.id;
Sarà comunque necessario passare alcuni dati in funzioni che desiderano creare alcuni registri. In effetti, è possibile che la funzione di registrazione sia presente nell'oggetto req.log, in modo tale da garantire che la registrazione avvenga solo quando è disponibile l'accesso all'oggetto req.log.

+1

Grazie per la risposta. Devo anche usare la soluzione che proponi. Tuttavia, avevo in mente di identificare automaticamente l'ID da applicare. Una soluzione che ho implementato era quella di memorizzare l'ID nell'oggetto di richiesta, e quando chiamavo la mia funzione di registro personalizzato, cercava l'ID su nel callstack. So che questo è sbagliato per diversi motivi (l'accesso alle informazioni sui parametri di altre funzioni è vietato in "modalità rigorosa", non efficiente, e ottenere un nuovo stack quando viene attivato un evento I/O). Immagino che non sia possibile e la soluzione che hai proposto sembra essere quella che si adatta meglio. –

16

Se si incrementa automaticamente, l'analisi dei registri successiva non sarà in grado di identificare in modo univoco le richieste, poiché diverse istanze genereranno ID in collisione e il riavvio dell'applicazione causerà automaticamente collisioni di ID.

Ecco un'altra possibile soluzione.

Installare cuid:

npm install --save cuid 

Poi, nel tuo principale file app:

var cuid = require('cuid'); 
var requestId = function requestId(req, res, next) { 
    req.requestId = cuid(); 
    next(); 
}; 

// Then, at the top of your middleware: 
app.use(requestId); 

Ora si otterrà un ID di richiesta amichevole che è improbabile che si scontrano, e sarete in grado di identificare in modo univoco le richieste di analisi dei log e di debugging, anche su più istanze, e il riavvio del server.

+1

Sì, questa soluzione sicuramente migliore, ma il problema con questo è come si espone l'id nei registri di winston in modo che non si faccia molta duplicazione dei dati. –

+0

Vorrei anche utilizzare i domini (o qualsiasi altra cosa decidano di sostituire i domini con) in modo da non inquinare le chiamate di funzione passando le informazioni sulle richieste in tutti gli strati del codice. – CBP

+0

I domini sono stati deprecati e non ci sono piani concreti per una sostituzione. –

0

Non si dovrebbero utilizzare variabili globali.

Quello che mi piace fare è popolare un oggetto META prima di ogni richiesta.

Io uso un generatore di UUID (https://github.com/kelektiv/node-uuid) per una richiesta di ID

Ecco un esempio

app.all('*', function(req, res, next) { 
    req.meta = { 
     ip: req.headers['x-forwarded-for'] || req.connection.remoteAddress, 
     timestamp: uuid(), 
     user_agent: req.headers['user-agent'], 
     body: req.body, 
    } 
    return next(); 
    }) 
2

Ho faticato ricerca di una soluzione per questo problema. La cosa che non mi è piaciuta delle soluzioni suggerite qui è che implicano condividere l'oggetto req tra tutte le funzioni del progetto. Ho trovato una soluzione che combina il tuo approccio (creando un uuid per richiesta) e con una libreria (continuation-local-storage) che consente di condividere spazi dei nomi tra i moduli.

È possibile trovare la spiegazione in questa altra risposta: https://stackoverflow.com/a/47261545/5710581

Se volete maggiori informazioni, ho scritto tutte queste idee e tutto il codice in un post, al fine di spiegare tutto in un unico luogo: Express.js: Logging info with global unique request ID – Node.js

Problemi correlati