Wie kann Node Full-Link-Protokolle elegant drucken? Der folgende Artikel zeigt Ihnen, wie Sie Full-Link-Protokolle in node elegant ausdrucken können. Ich hoffe, er wird Ihnen helfen!
Wenn ein Benutzer ein Problem meldet: Wenn bei der Verwendung einer bestimmten Online-Funktion ein Fehler auftritt, wie können Sie ihn schnell und genau lokalisieren? Wie kann die Optimierung effektiv verfolgt werden, wenn eine bestimmte Anforderungsschnittstelle Daten langsam zurückgibt?
Wie wir alle wissen, werden bei einer Anfrage wahrscheinlich die folgenden Protokolle generiert:
1. AceesLog: Benutzerzugriffsprotokoll
3 . SQL: SQL-Abfrageprotokoll
4. ThirdParty: Drittanbieter-Dienstprotokoll
Wie kann man alle durch eine Anfrage generierten Protokolle verfolgen?
Der allgemeine Ansatz besteht darin, eine requestId als eindeutige Kennung zu verwenden,
dann eine Middleware zu schreiben, die requestId in den Kontext einzufügen und, wenn eine Protokollierung erforderlich ist, sie aus dem Kontext zu nehmen und auszudrucken,
In Drittanbietern Dienste und SQL Im Protokoll muss die Anforderungs-ID auch zum Drucken an die entsprechende Funktion übergeben werden. Es ist zu mühsam, sie Schicht für Schicht zu übergeben, und der Code ist auch relativ aufdringlich.
Unser Ziel ist es, die Eindringlichkeit des Codes zu reduzieren, ihn einmal einzuschleusen und automatisch zu verfolgen.
Nach der Recherche können async_hooks den Lebenszyklus des asynchronen Verhaltens verfolgen. In jeder asynchronen Ressource (jede Anforderung ist eine asynchrone Ressource) gibt es zwei IDs,
bzw. asyncId (die aktuelle Lebenszyklus-ID der asynchronen Ressource). , trigerAsyncId (ID der übergeordneten asynchronen Ressource).
async_hooks bietet die folgenden Lebenszyklus-Hooks zur Überwachung asynchroner Ressourcen:
asyncHook = async_hook.createHook({ // 监听异步资源的创建 init(asyncId,type,triggerAsyncId,resource){}, // 异步资源回调函数开始执行之前 before(asyncId){}, // 异步资源回调函数开始执行后 after(asyncId){}, // 监听异步资源的销毁 destroy(asyncId){} })
Wenn wir dann eine Zuordnung erstellen, wird jede asyncId einem Speicher zugeordnet und die entsprechende requestId im Speicher gespeichert, dann kann die requestId leicht abgerufen werden.
Zufälligerweise wurde die cls-hooked-Bibliothek basierend auf async_hooks gekapselt. Sie verwaltet eine Kopie der Daten in derselben asynchronen Ressource und speichert sie in Form von Schlüssel-Wert-Paaren. (Hinweis: async_hooked muss in der höheren Version des Knotens>=8.2.1 verwendet werden.) Natürlich gibt es in der Community auch andere Implementierungen, z. B. cls-session, node-continuation-local-storage usw.
Das Folgende ist ein Beispiel dafür, wie ich cls-hooked in meinem Projekt angewendet habe:
/session.js erstellt einen benannten Speicherplatz
const createNamespace = require('cls-hooked').createNamespace const session = createNamespace('requestId-store') module.exports = session
/logger.js druckt das Protokoll
const session = require('./session') module.exports = { info: (message) => { const requestId = session.get('requestId') console.log(`requestId:${requestId}`, message) }, error: (message) => { const requestId = session.get('requestId') console.error(`requestId:${requestId}`, message) } }
/sequelize.js SQL ruft den Logger auf um das Protokoll zu drucken
const logger = require("./logger") new Sequelize( logging: function (sql, costtime) { logger.error( `sql exe : ${sql} | costtime ${costtime} ms` ); } )
/app.js Legen Sie die Anforderungs-ID fest, legen Sie die Anforderungs-ID fest, um den Antwortheader zurückzugeben, und drucken Sie das Zugriffsprotokoll aus
const session = require('./session') const logger = require('./logger') async function accessHandler(ctx, next) { const requestId = ctx.header['x-request-id'] || uuid() const params = ctx.request.body ? JSON.stringify(ctx.request.body) : JSON.stringify(ctx.request.query) // 设置requestId session.run(() => { session.set('requestId', requestId) logger.info(`url:${ctx.request.path};params:${params}`) next() // 设置返回响应头 ctx.res.setHeader('X-Request-Id',requestId) }) }
Werfen wir einen Blick auf das Protokoll, wenn ein Anforderungspfad /home?a=1 ist :
访问日志: requestId:79f422a6-6151-4bfd-93ca-3c6f892fb9ac url:/home;params:{"a":"1"} Sql日志: requestId:79f422a6-6151-4bfd-93ca-3c6f892fb9ac sql exe : Executed (default): SELECT `id` FROM t_user
Sie können die gesamte Anfrage sehen. Die Protokollanforderungs-ID des Links ist dieselbe. Wenn später ein Alarm an die Alarmplattform gesendet wird, können wir anhand der requestId den gesamten von dieser Anfrage ausgeführten Link finden.
Aufmerksame Schüler bemerken möglicherweise, dass ich die requestId auch im von der Schnittstelle zurückgegebenen Antwortheader festgelegt habe. Der Zweck besteht darin, die requestId direkt vom Browser zu erfahren, wenn festgestellt wird, dass die Antwort langsam ist oder Probleme vorliegen.
2. LeistungsaufwandDas ist der Speichernutzungsvergleich:
Es ist etwa 10 % mehr, als wenn async_hook nicht verwendet wird.
Für unser QPS-System mit 100 Level ist es in Ordnung, aber wenn es sich um einen Dienst mit hoher Parallelität handelt, müssen wir es möglicherweise sorgfältig prüfen.
ps: Wenn es Fehler gibt, weisen Sie sie bitte darauf hin. Kommentieren Sie nicht, wenn Sie sie nicht mögen
Weitere Informationen zu Knoten finden Sie unter:
nodejs-TutorialDas obige ist der detaillierte Inhalt vonBringen Sie Ihnen Schritt für Schritt bei, wie Sie Full-Link-Protokolle elegant im Knoten drucken. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!