Maison  >  Article  >  interface Web  >  Utiliser Morgan dans des cas pratiques (avec code)

Utiliser Morgan dans des cas pratiques (avec code)

php中世界最好的语言
php中世界最好的语言original
2018-06-11 09:50:131667parcourir

Cette fois je vais vous présenter l'utilisation de morgan dans un cas pratique (avec code). Quelles sont les précautions pour utiliser morgan dans un cas pratique, regardons-y.

Aperçu du chapitre

Morgan est le middleware de journalisation par défaut d'Express. Il peut également être utilisé indépendamment d'Express en tant que composant de journalisation node.js. Cet article va du superficiel au profond, et le contenu comprend principalement :

  1. Exemples d'introduction à l'utilisation de Morgan

  2. Comment enregistrer les journaux dans des fichiers locaux

  3. Instructions et exemples d'utilisation de l'API principale

  4. Utilisation avancée : 1. Fractionnement des journaux 2. Écrire les journaux dans la base de données

  5. Analyse du code source : format de journal de Morgan et précompilation

Exemple de démarrage

Tout d'abord, initialiser le projet.

npm install express morgan

Ensuite, ajoutez le code suivant dans basic.js.

var express = require('express');
var app = express();
var morgan = require('morgan');
app.use(morgan('short'));
app.use(function(req, res, next){
 res.send('ok');
});
app.listen(3000);

node basic.jsExécutez le programme et accédez à http://127.0.0.1:3000 dans le navigateur. Le journal d'impression est le suivant

➜ 2016.12.11-. advanced- morgan git:(master) ✗ node basic.js
::ffff:127.0.0.1 - GET / HTTP/1.1 304 - - 3.019 ms
::ffff:127.0.0.1 - GET /favicon.ico HTTP/ 1.1 200 2 - 0,984 ms

Imprimer le journal dans un fichier local

Morgan prend en charge l'élément de configuration du flux, qui peut être utilisé pour atteindre l'objectif effet de l'atterrissage du journal. Le code est le suivant :

var express = require('express');
var app = express();
var morgan = require('morgan');
var fs = require('fs');
var path = require('path');
var accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), {flags: 'a'});
app.use(morgan('short', {stream: accessLogStream}));
app.use(function(req, res, next){
 res.send('ok');
});
app.listen(3000);

Explication de l'utilisation

API principale

morgan a très peu d'API, et le plus fréquemment utilisé est morgan(). Il renvoie un middleware de journalisation express.

morgan(format, options)

La description du paramètre est la suivante :

  1. format : Facultatif, Morgan a défini plusieurs formats de journaux, chaque format a un nom correspondant, tel que combiné, court, etc., la valeur par défaut est par défaut. Les différences entre les différents formats peuvent être trouvées ici. Ce qui suit explique comment personnaliser le format du journal.

  2. options : facultatives, éléments de configuration, y compris le flux (couramment utilisé), le saut et l'immédiat.

  3. stream : configuration du flux de sortie du journal, la valeur par défaut est process.stdout.

  4. ignorer : si vous souhaitez ignorer la journalisation, veuillez vous référer à ici pour l'utilisation.

  5. immédiat : valeur booléenne, la valeur par défaut est false. Lorsque vrai, le journal sera enregistré dès que la demande est reçue ; si faux, le journal sera enregistré après le retour de la demande.

Format de journal personnalisé

Comprenez d'abord les deux concepts de Morgan : le format et le jeton. Très simple :

  1. format : format du journal, qui est essentiellement une chaîne représentant le format du journal, tel que :method :url :status :res[content-length] - :response-time MS.

  2. Jeton : les composants de format, tels que :method et :url ci-dessus, sont ce qu'on appelle des jetons.

Après avoir clarifié la différence entre le format et le jeton, vous pouvez jeter un œil aux API clés concernant la personnalisation des formats de journaux dans Morgan.

morgan.format(name, format); // 自定义日志格式
morgan.token(name, fn); // 自定义token

Le format personnalisé

est très simple. Définissez d'abord le format de journal nommé joke via morgan.format(), puis transmettez morgan('joke') Appelez-le.

var express = require('express');
var app = express();
var morgan = require('morgan');
morgan.format('joke', '[joke] :method :url :status');
app.use(morgan('joke'));
app.use(function(req, res, next){
 res.send('ok');
});
app.listen(3000);

Jetons un coup d'œil aux résultats en cours d'exécution

➜ 2016.12.11-advanced-morgan git:(master) ✗ node morgan.format.js
[ blague] GET / 304
[blague] GET /favicon.ico 200

Jeton personnalisé

Le code est le suivant, personnalisé via Morgan. token(), puis ajoutez le jeton personnalisé au format personnalisé.

var express = require('express');
var app = express();
var morgan = require('morgan');
// 自定义token
morgan.token('from', function(req, res){
 return req.query.from || '-';
});
// 自定义format,其中包含自定义的token
morgan.format('joke', '[joke] :method :url :status :from');
// 使用自定义的format
app.use(morgan('joke'));
app.use(function(req, res, next){
 res.send('ok');
});
app.listen(3000);

Exécutez le programme et visitez http://127.0.0.1:3000/hello?from=app et http://127.0.0.1:3000/hello?from=pc dans le navigateur <.>

➜ 2016.12.11-advanced-morgan git:(master) ✗ node morgan.token.js

[blague] GET /hello?from=app 200 app
[blague] GET /favicon.ico 304 -
[blague] GET /hello?from=pc 200 pc
[blague] GET /favicon.ico 304 -

高级使用

日志切割

一个线上应用,如果所有的日志都落地到同一个本地文件,时间久了,文件会变得非常大,既影响性能,又不便于查看。这时候,就需要用到日志分割了。

借助file-stream-rotator插件,可以轻松完成日志分割的工作。除了file-stream-rotator相关的配置代码,其余跟之前的例子差不多,这里不赘述。

var FileStreamRotator = require('file-stream-rotator')
var express = require('express')
var fs = require('fs')
var morgan = require('morgan')
var path = require('path')
var app = express()
var logDirectory = path.join(__dirname, 'log')
// ensure log directory exists
fs.existsSync(logDirectory) || fs.mkdirSync(logDirectory)
// create a rotating write stream
var accessLogStream = FileStreamRotator.getStream({
 date_format: 'YYYYMMDD',
 filename: path.join(logDirectory, 'access-%DATE%.log'),
 frequency: 'daily',
 verbose: false
})
// setup the logger
app.use(morgan('combined', {stream: accessLogStream}))
app.get('/', function (req, res) {
 res.send('hello, world!')
})

日志写入数据库

有的时候,我们会有这样的需求,将访问日志写入数据库。这种需求常见于需要实时查询统计的日志系统。

在morgan里该如何实现呢?从文档上,并没有看到适合的扩展接口。于是查阅了下morgan的源码,发现实现起来非常简单。

回顾下之前日志写入本地文件的例子,最关键的两行代码如下。通过stream指定日志的输出流。

var accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), {flags: 'a'});
app.use(morgan('short', {stream: accessLogStream}));

在morgan内部,大致实现是这样的(简化后)。

// opt为配置文件
var stream = opts.stream || process.stdout;
var logString = createLogString(); // 伪代码,根据format、token的定义,生成日志
stream.write(logString);

于是,可以用比较取巧的方式来实现目的:声明一个带write方法的对象,并作为stream配置传入。

var express = require('express');
var app = express();
var morgan = require('morgan');
// 带write方法的对象
var dbStream = {
 write: function(line){
 saveToDatabase(line); // 伪代码,保存到数据库
 }
};
// 将 dbStream 作为 stream 配置项的值
app.use(morgan('short', {stream: dbStream}));
app.use(function(req, res, next){
 res.send('ok');
});
app.listen(3000);

深入剖析

morgan的代码非常简洁,从设计上来说,morgan的生命周期包含:

token定义 --> 日志格式定义 -> 日志格式预编译 --> 请求达到/返回 --> 写日志

其中,token定义、日志格式定义前面已经讲到,这里就只讲下 日志格式预编译 的细节。

跟模板引擎预编译一样,日志格式预编译,也是为了提升性能。源码如下,最关键的代码就是compile(fmt)。

 function getFormatFunction (name) {
 // lookup format
 var fmt = morgan[name] || name || morgan.default
 // return compiled format
 return typeof fmt !== 'function'
 ? compile(fmt)
 : fmt
}

compile()方法的实现细节这里不赘述,着重看下compile(fmt)返回的内容:

var morgan = require('morgan');
var format = morgan['tiny'];
var fn = morgan.compile(format);
console.log(fn.toString());

运行上面程序,输出内容如下,其中tokens其实就是morgan。 

function anonymous(tokens, req, res
/**/) {
 return ""
 + (tokens["method"](req, res, undefined) || "-") + " "
 + (tokens["url"](req, res, undefined) || "-") + " "
 + (tokens["status"](req, res, undefined) || "-") + " "
 + (tokens["res"](req, res, "content-length") || "-") + " - "
 + (tokens["response-time"](req, res, undefined) || "-") + " ms";
}

看下morgan.token()的定义,就很清晰了

function token (name, fn) {
 morgan[name] = fn
 return this
}

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

如何查询文档创建日期、修改日期与储存大小

Vue+animate在项目中做出过渡动画

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn