github地址:https://github.com/Seldaek/monolog

使用 Monolog

  • 安装
  • 核心概念
  • 日志级别
  • 配置一个日志服务
  • 为记录添加额外的数据
  • 使用通道
  • 自定义日志格式

Monolog是php下比较全又容易扩展的记录日志组件。目前有包括Symfony 、Laravel、 CakePHP等诸多知名php框架都内置了Monolog。

Monolog可以把你的日志发送到文件,sockets,收件箱,数据库和各种web服务器上。一些特殊的组件可以给你带来特殊的日志策略。

安装

Monolog 在 Packagist (monolog/monolog) 上可用,并且可以通过 Composer 安装:

composer require monolog/monolog

如果你不使用 Composer, 那你可以从 GitHub 上获取代码,然后使用任何兼容 PSR-0 的自动加载器(比如Symfony2 ClassLoader 组件)来加载 Monolog 的类

核心概念

每一个日志服务实例 (Logger) 都有一个通道(名称),并有一个处理器 (Handler)栈. 无论何时你添加一条 记录 到对应的日志服务实例,这个处理器栈将被遍历一遍:每个处理器都将依次决定是否要处理这条记录,而如果要处理,则遍历结束(译注:类似DOM事件冒泡)。

这样子可以创建非常灵活的日志配置。比如一个 StreamHandler 可以把所有日志都写入磁盘,而上面加个MailHandler 可以把错误日志作为邮件发送出去。处理器还有一个 $bubble 属性定义了是否屏蔽某条记录或者处理了某条记录。在这个示例中,配置 MailHandler 的 $bubble 参数为 false 则意味着 MailHandler 将不会把自己已处理过的记录继续冒泡给 StreamHandler.

你可以创建许多日志服务实例(Logger),每一个则定义一个通道(比如数据库、请求、路由...)。而每一个日志服务实例都可以组合各种各样的处理器,可以共享处理器也可以不共享。这个通道将会在日志中反映出来,从而允许你可以很容易地查看或者筛选记录。

每一个处理还会有一个格式化器(Formatter)。如果你没有配置一个,则一个有意义的默认的格式化器将被创建。格式化器用来规范化并格式化输入的记录,以便处理器能输出一些有用的信息。

不支持自定义的严重性级别。只支持使用RFC 5424中定义的八个级别(调试/Debug、信息/Info、提示/Notice、警告/Warning、错误/Error、严重/Critical、警报/Alert、紧急/Emergency)来作为基本的筛选目的。不过,如果为了排序或者其他需要灵活性的使用场景,你可以添加加工程序(Processor)从而可以在(处理器)处理前添加额外的信息(标签、用户IP...)。

日志级别

Monolog 支持一下 RFC 5424 中的日志级别:

  • 调试/DEBUG (100): 详细的调试信息。
  • 信息/INFO (200): 有意义的事件,比如用户登录、SQL日志。
  • 提示/NOTICE (250): 正常但是值得注意的事件。
  • 警告/WARNING (300): 异常事件,但是并不是错误。比如使用了废弃了的API,错误地使用了一个API,以及其他不希望发生但是并非必要的错误。
  • 错误/ERROR (400): 运行时的错误,不需要立即注意到,但是需要被专门记录并监控到。
  • 严重/CRITICAL (500): 边界条件/危笃场景。比如应用组件不可用了,未预料到的异常。
  • 警报/ALERT (550): 必须立即采取行动。比如整个网站都挂了,数据库不可用了等。这种情况应该发送短信警报,并把你叫醒。
  • 紧急/EMERGENCY (600): 紧急请求:系统不可用了。

配置一个日志服务

这里有一个基本的配置,可以记录日志到文件,并在 DEBUG 级别下记录到 firephp 中:

<?php

use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\FirePHPHandler; // 创建日志服务
$logger = new Logger('my_logger'); // 添加一些处理器
$logger->pushHandler(new StreamHandler(__DIR__.'/my_app.log', Logger::DEBUG));
$logger->pushHandler(new FirePHPHandler()); // 现在你就可以用日志服务了
$logger->info('My logger is now ready');

解释一下。第一步是创建日志服务实例,这个实例后将在代码中用到。唯一的参数是通道的名称,它在你有多个日志服务实例的时候很有用。(更多详情参见下面)

这个日志服务实例自己是不是知道如何处理一条日志记录的。它把记录代理给了一些处理器。上面的代码中注册了两个处理器到栈中,以便允许使用两种不同的方式来处理日志记录。

注意,FirePHPHandler 是被先调用的,因而它被添加到了栈顶。这允许你临时添加一个禁止冒泡的处理器从而允许你覆盖其他配置的日志(处理器)。

如果你单独使用 Monolog, 并且在寻找一种简单的方式来配置许多处理器,那可以用
theorchard/monolog-cascade 。
它可以帮你使用PHP数组、YAML或者JSON来构建复杂的日志配置。

为记录添加额外的数据

Monolog 提供了两种不同的方式来为简单的文本消息增加额外的信息

使用上下文(context)

第一种方式是使用上下文(context),这允许你在传递记录的时候传递一个数组格式的数据:

<?php
$logger->info('Adding a new user', array('username' => 'Seldaek'));

简单的处理器(比如StreamHandler)将只是把数组转换成字符串。而复杂的处理器则可以利用上下文的优点(如 FirePHP 则将以一种优美的方式显示数组)。

使用加工程序(Processor)

第二种方式是使用加工程序来为所有的记录添加额外数据。加工程序可以是任何可以调用的函数。
加工程序接收日志记录作为参数,并且需要在修改了extra字段后再返回日志记录。让我们来写一个添加一些假数据的加工程序:

<?php
$logger->pushProcessor(function ($record) {
$record['extra']['dummy'] = 'Hello world!';
return $record;
});

Monolog提供了一些内置的加工程序,你可以在你的项目中使用它们。

小技巧:加工程序可以被注册到一个特定的处理器上而不是直接在日志服务实例上,从而可以只在对应的处理器上生效。

使用通道

通道是一种非常棒的方式来区分是应用的哪个部分的日志被记录下来的。这通常在大型项目中非常有用(而且被Symfony2的MonologBundle所使用)。

假设有两个日志服务实例共享了一个处理器,这个处理器将日志写入单个日志文件。通道则将允许你来区分是哪个日志服务实例记录了哪条日志。你可以很简单地通过通道来筛选日志。

<?php

use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\FirePHPHandler; // 创建一些处理器
$stream = new StreamHandler(__DIR__.'/my_app.log', Logger::DEBUG);
$firephp = new FirePHPHandler(); // 创建应用的主要日志服务实例
$logger = new Logger('my_logger');
$logger->pushHandler($stream);
$logger->pushHandler($firephp); // 使用另外的通道来创建安全相关的日志服务示例
$securityLogger = new Logger('security');
$securityLogger->pushHandler($stream);
$securityLogger->pushHandler($firephp); // 或者克隆第一个,只是改变下通道
$securityLogger = $logger->withName('security');

自定义日志格式

在Monolog中,可以很简单地来自定义日志的格式,无论是写入文件、套接字、邮件、数据库还是其他处理器。大多数处理器都是用 $record['formatted'] 这个值来自动写入日志设备。这个值依赖格式化器的配置。你可以选择预定义的格式化器类,也可以自己写一个(比如一个可读的多行文本文件)。

想要配置一个预定义的格式化器类,可以直接把它设置为处理器的字段:

// 默认的日期格式是 "Y-m-d H:i:s"
$dateFormat = "Y n j, g:i a";
// 默认的输出格式是 "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"
$output = "%datetime% > %level_name% > %message% %context% %extra%\n";
// 最后创建一个格式化器
$formatter = new LineFormatter($output, $dateFormat); // 创建一个处理器
$stream = new StreamHandler(__DIR__.'/my_app.log', Logger::DEBUG);
$stream->setFormatter($formatter); // 将其绑定到日志服务对象上
$securityLogger = new Logger('security');
$securityLogger->pushHandler($stream);

你还可以在多个处理器之间复用同一个格式化器,并且在多个日志服务实例间共享这些处理器

转 https://www.jianshu.com/p/b99dc5c3b760

Monolog - Logging for PHP的更多相关文章

  1. Monolog - Logging for PHP 5.3+

    Monolog 是PHP的一个日志类库.相比于其他的日志类库,它有以下的特点: 功能强大.可以把日志发送到文件.socket.邮箱.数据库和各种web services. 遵循 PSR3 的接口规范. ...

  2. 记一次Monolog的BufferHandler使用

    laravel中可以设置自定义的日记channel(config/logging中设置),按照laravel-china的一篇文章,把log按一定格式并且以批量的方式写入日志文件: https://l ...

  3. 记一次monolog的RotatingFileHandler使用

    需求如下: 1.需要一种日记格式,能把同一次请求的日记归在一起,请求间的日记以空行隔开,即使并发操作也不会像laravel默认的日记一样很"被动"的记录(不同请求的日记可能被交替记 ...

  4. Logging with PSR-3 to Improve Reusability

    可以用composer的autoload来,导入自己写的类库.   composer dump-autoload -o  ----------------> 改成 composer update ...

  5. Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory

    学习架构探险,从零开始写Java Web框架时,在学习到springAOP时遇到一个异常: "C:\Program Files\Java\jdk1.7.0_40\bin\java" ...

  6. Oracle补全日志(Supplemental logging)

    Oracle补全日志(Supplemental logging)特性因其作用的不同可分为以下几种:最小(Minimal),支持所有字段(all),支持主键(primary key),支持唯一键(uni ...

  7. Java程序日志:java.util.logging.Logger类

    一.Logger 的级别 比log4j的级别详细,全部定义在java.util.logging.Level里面.各级别按降序排列如下:SEVERE(最高值)WARNINGINFOCONFIGFINEF ...

  8. python 学习笔记 -logging模块(日志)

    模块级函数 logging.getLogger([name]):返回一个logger对象,如果没有指定名字将返回root loggerlogging.debug().logging.info().lo ...

  9. python logging colorlog

    import logging LOG_LEVEL = logging.NOTSET LOGFORMAT = "[%(log_color)s%(levelname)s] [%(log_colo ...

随机推荐

  1. 微信开发者工具集成GitHub,多人协调开发,上传拉取等

    一,准备环境 1,提前安装git环境和GitHub做集成,不做多解释: 1,准备微信项目代码: 2,创建GitHub仓库: 二,创建GitHub仓库 1,创建一个空的GitHub仓库,不要任何文件和不 ...

  2. Kubernetes的资源控制器和Service(四)

    一.定义和分类 1,定义 k8s 中内建了很多控制器(controller ),这些相当于一个状态机,用来控制 Pod 的具体状态和行为. 2,类型 ReplicationController.Rep ...

  3. 动手编写—动态数组(Java实现)

    目录 数组基础回顾 自定义动态数组 动态数组的设计 抽象父类接口设计 抽象父类设计 动态数组之DynamicArray 补充数组缩容 全局的关系图 声明 数组基础回顾 1.数组是一种常见的数据结构,用 ...

  4. selenium常用api之切换:table切换、alert弹框切换、iframe框架切换

    10.查看浏览器打开了多少个table和当前页面在哪个table 测试:打开了浏览器后,打开了一个新的标签页之后,显示此时有2个table,浏览器中当前页面展示的是第2个页面,但是代码打印显示的仍然是 ...

  5. oldboy edu python full stack s22 day16 模块 random time datetime os sys hashlib collections

    今日内容笔记和代码: https://github.com/libo-sober/LearnPython/tree/master/day13 昨日内容回顾 自定义模块 模块的两种执行方式 __name ...

  6. redis命令和RedisTemplate操作对应表

    redis命令和RedisTemplate操作对应表 redisTemplate.opsForValue();//操作字符串 redisTemplate.opsForHash();//操作hash r ...

  7. Linux 命令: sed

    sed -- sed 命令对于Linux系统来说,在命令行修改,操作文本是非常的方便. 特别是批量的修改某些字符等,是非常省时省力的,非常适合在自动化的脚本中去应用. 如下的几个小例子: 1)如何删除 ...

  8. Python3基础数据类型(数字、字符串、元组、列表、集合、字典)

    笔记参考了菜鸟教程 Python 中的变量不需要声明,赋值才创建.赋值给变量的是什么类型变量就是什么类型 多个变量赋值 1 a, b, c = 1, 2, "runoob" 标准数 ...

  9. MySQL手注之报错注入

    报错注入: 指在页面中没有一个合适的数据返回点的情况下,利用mysql函数的报错来创造一个显位的注入.先来了解一下报错注入常用的函数 XML:指可扩展标记语言被设计用来传输和存储数据. concat: ...

  10. C 类型限定符

    C 类型限定符 1. Introduction C 语言中的大部分类型都可以用称为限定符(qualifier)的关键字 const. volatile. restrict. _Atomic 加以限定. ...