1. 规范说明
.note-content {font-family: 'Helvetica Neue', Arial, 'Hiragino Sans GB', STHeiti, 'Microsoft YaHei', 'WenQuanYi Micro Hei', SimSun, Song, sans-serif;}

本文制定了日志类库的通用接口规范。

本规范的主要目的,是为了让日志类库以简单通用的方式,通过接收一个 Psr\Log\LoggerInterface 对象,来记录日志信息。 框架以及CMS内容管理系统如有需要,可以对此接口进行扩展,但需遵循本规范, 这才能保证在使用第三方的类库文件时,日志接口仍能正常对接。

关键词 “必须”(“MUST”)、“一定不可/一定不能”(“MUST NOT”)、“需要”(“REQUIRED”)、 “将会”(“SHALL”)、“不会”(“SHALL NOT”)、“应该”(“SHOULD”)、“不该”(“SHOULD NOT”)、 “推荐”(“RECOMMENDED”)、“可以”(“MAY”)和”可选“(“OPTIONAL”)的详细描述可参见 RFC 2119 。

本文中的 实现者 指的是实现了 LoggerInterface 接口的类库或者框架,反过来讲,他们就是 LoggerInterface 的 使用者。

1. 规范说明

1.1 基本规范

LoggerInterface 接口对外定义了八个方法,分别用来记录 RFC 5424 中定义的八个等级的日志:debug、 info、 notice、 warning、 error、 critical、 alert 以及 emergency 。

第九个方法 —— log,其第一个参数为记录的等级。可使用一个预先定义的等级常量作为参数来调用此方法,必须与直接调用以上八个方法具有相同的效果。如果传入的等级常量参数没有预先定义,则必须抛出 Psr\Log\InvalidArgumentException 类型的异常。在不确定的情况下,使用者不该使用未支持的等级常量来调用此方法。

1.2 记录信息

以上每个方法都接受一个字符串类型或者是有 __toString() 方法的对象作为记录信息参数,这样,实现者就能把它当成字符串来处理,否则实现者必须自己把它转换成字符串。

记录信息参数可以携带占位符,实现者可以根据上下文将其它替换成相应的值。

其中占位符必须与上下文数组中的键名保持一致。

占位符的名称必须由一个左花括号 { 以及一个右括号 } 包含。但花括号与名称之间一定不能有空格符。

占位符的名称应该只由 A-Z、 a-z,0-9、下划线 _、以及英文的句号 .组成,其它字符作为将来占位符规范的保留。

实现者可以通过对占位符采用不同的转义和转换策略,来生成最终的日志。 而使用者在不知道上下文的前提下,不该提前转义占位符。

以下是一个占位符使用的例子:

/** * 用上下文信息替换记录信息中的占位符 */
function interpolate($message, array $context = array()){
// 构建一个花括号包含的键名的替换数组
$replace = array();
foreach ($context as $key => $val) {
$replace['{' . $key . '}'] = $val;
}

// 替换记录信息中的占位符,最后返回修改后的记录信息。
return strtr($message, $replace);
}

// 含有带花括号占位符的记录信息。
$message = "User {username} created";

// 带有替换信息的上下文数组,键名为占位符名称,键值为替换值。
$context = array('username' => 'bolivar');

// 输出 "Username bolivar created"
echo interpolate($message, $context);
1.3 上下文

每个记录函数都接受一个上下文数组参数,用来装载字符串类型无法表示的信息。它可以装载任何信息,所以实现者必须确保能正确处理其装载的信息,对于其装载的数据,一定不能 抛出异常,或产生PHP出错、警告或提醒信息(error、warning、notice)。

如需通过上下文参数传入了一个 Exception 对象, 必须以 ‘exception’ 作为键名。 记录异常信息是很普遍的,所以如果它能够在记录类库的底层实现,就能够让实现者从异常信息中抽丝剥茧。 当然,实现者在使用它时,必须确保键名为 ‘exception’ 的键值是否真的是一个 Exception,毕竟它可以装载任何信息。

1.4 助手类和接口

Psr\Log\AbstractLogger 类使得只需继承它和实现其中的 log 方法,就能够很轻易地实现 LoggerInterface 接口,而另外八个方法就能够把记录信息和上下文信息传给它。

同样地,使用 Psr\Log\LoggerTrait 也只需实现其中的 log 方法。不过,需要特别注意的是,在traits可复用代码块还不能实现接口前,还需要 implement LoggerInterface。

在没有可用的日志记录器时, Psr\Log\NullLogger 接口可以为使用者提供一个备用的日志“黑洞”。不过,当上下文的构建非常消耗资源时,带条件检查的日志记录或许是更好的办法。

Psr\Log\LoggerAwareInterface 接口仅包括一个 setLogger(LoggerInterface $logger) 方法,框架可以使用它实现自动连接任意的日志记录实例。

Psr\Log\LoggerAwareTrait trait可复用代码块可以在任何的类里面使用,只需通过它提供的 $this->logger,就可以轻松地实现等同的接口。

Psr\Log\LogLevel 类装载了八个记录等级常量。

上述的接口、类和相关的异常类,以及一系列的实现检测文件,都包含在 psr/log 文件包中。

3. Psr\Log\LoggerInterface

<?php

namespace Psr\Log;

/** * 日志记录实例 * * 日志信息变量 —— message, **必须**是一个字符串或是实现了 __toString() 方法的对象。 * * 日志信息变量中**可以**包含格式如 “{foo}” (代表foo) 的占位符, * 它将会由上下文数组中键名为 "foo" 的键值替代。 * * 上下文数组可以携带任意的数据,唯一的限制是,当它携带的是一个 exception 对象时,它的键名 必须 是 "exception"。 * * 详情可参阅: https://github.com/PizzaLiu/PHP-FIG/blob/master/PSR-3-logger-interface-cn.md */
interface LoggerInterface
{
/** * 系统不可用 * * @param string $message * @param array $context * @return null */
public function emergency($message, array $context = array());

/** * **必须**立刻采取行动 * * 例如:在整个网站都垮掉了、数据库不可用了或者其他的情况下,**应该**发送一条警报短信把你叫醒。 * * @param string $message * @param array $context * @return null */
public function alert($message, array $context = array());

/** * 紧急情况 * * 例如:程序组件不可用或者出现非预期的异常。 * * @param string $message * @param array $context * @return null */
public function critical($message, array $context = array());

/** * 运行时出现的错误,不需要立刻采取行动,但必须记录下来以备检测。 * * @param string $message * @param array $context * @return null */
public function error($message, array $context = array());

/** * 出现非错误性的异常。 * * 例如:使用了被弃用的API、错误地使用了API或者非预想的不必要错误。 * * @param string $message * @param array $context * @return null */
public function warning($message, array $context = array());

/** * 一般性重要的事件。 * * @param string $message * @param array $context * @return null */
public function notice($message, array $context = array());

/** * 重要事件 * * 例如:用户登录和SQL记录。 * * @param string $message * @param array $context * @return null */
public function info($message, array $context = array());

/** * debug 详情 * * @param string $message * @param array $context * @return null */
public function debug($message, array $context = array());

/** * 任意等级的日志记录 * * @param mixed $level * @param string $message * @param array $context * @return null */
public function log($level, $message, array $context = array());
}

4. Psr\Log\LoggerAwareInterface

<?php

namespace Psr\Log;

/** * logger-aware 定义实例 */
interface LoggerAwareInterface
{
/** * 设置一个日志记录实例 * * @param LoggerInterface $logger * @return null */
public function setLogger(LoggerInterface $logger);
}

5. Psr\Log\LogLevel

<?php

namespace Psr\Log;

/** * 日志等级常量定义 */
class LogLevel
{
const EMERGENCY = 'emergency';
const ALERT = 'alert';
const CRITICAL = 'critical';
const ERROR = 'error';
const WARNING = 'warning';
const NOTICE = 'notice';
const INFO = 'info';
const DEBUG = 'debug';
}

PHP日志记录规范PSR-3的更多相关文章

  1. 前端学HTTP之日志记录

    前面的话 几乎所有的服务器和代理都会记录下它们所处理的HTTP事务摘要.这么做出于一系列的原因:跟踪使用情况.安全性.计费.错误检测等等.本文将谥介绍日志记录 记录内容 大多数情况下,日志的记录出于两 ...

  2. 谈下spring下的 aop日志记录

    在我们开发当中  我们需要对系统用户行为和 系统异常信息有个统一记录  以便后期的 用户行为分析和bug修复   当我们有这个需求时  我们的通常采取方式很多 1.比如我们定义一个规范 开发一个接口 ...

  3. 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之十 || AOP面向切面编程浅解析:简单日志记录 + 服务切面缓存

    代码已上传Github+Gitee,文末有地址 上回<从壹开始前后端分离[ .NET Core2.0 Api + Vue 2.0 + AOP + 分布式]框架之九 || 依赖注入IoC学习 + ...

  4. Atitit mysql 存储过程捕获所有异常,以及日志记录异常信息

    Atitit mysql 存储过程捕获所有异常,以及日志记录异常信息 1.1. 异常的处理模式exit  continue undo模式 1 1.2. 捕获所有异常使用        DECLARE ...

  5. [转]IIS 日志记录时间和实际时间 不一样

    今天偶然发现 2003 系统IIS 日志记录时间和实际时间总是差了8个小时,也就是慢了8个小时.苦苦找了半天才发现如下办法能解决 ,特发来分享下 解决1:如果 IIS日志记录默认使用的是W3C扩展日志 ...

  6. 【转】使用Log4Net进行日志记录

    首先说说为什么要进行日志记录.在一个完整的程序系统里面,日志系统是一个非常重要的功能组成部分.它可以记录下系统所产生的所有行为,并按照某种规范表达出来.我们可以使用日志系统所记录的信息为系统进行排错, ...

  7. tp5下通过composer实现日志记录功能

    tp5实现日志记录 1.安装 psr/log composer require psr/log 它的作用就是提供一套接口,实现正常的日志功能! 我们可以来细细的分析一下,LoggerInterface ...

  8. 谈谈对bug的一点想法,说说做好日志记录的重要性

    说起程序猿,总绕不开的一个话题就是bug,估计每个程序猿听到某某测试跑过来一脸淫笑的告诉你这个功能有个bug的时候,总有种恨不得掐死他的想法.其实程序猿跟bug的关系,感觉有点像父亲和儿子的关系,自己 ...

  9. 在云环境上使用SLF4J对Java程序进行日志记录

    我开发了一个Java应用,部署到云环境上之后,用postman测试发现不能按照我期望的工作,但是返回的消息对我没有任何帮助. 因为部署在云端的应用很难像本地Java应用一样调试,所以我打算用SLF4J ...

随机推荐

  1. BFC深入理解

    BFC 在上一篇文章中,清除浮动方法解析,我们谈及了一些使用css属性解决浮动带来的影响.但是在解决浮动带来的影响的方法中,如果细心思考,会产生如下疑问: 为什么overflow可以清除浮动带来的影响 ...

  2. Centos7更改默认启动模式(转载)

    今天心血来潮安装一个centos7的图形界面,但发现用之前的方式无法修改默认启动为命令行模式. 之前的方法:修改/etc/inittab文件中的           id:3:initdefault ...

  3. 获得设备的唯一标识符UDID

    在IOS5之后,苹果为避免根据UDID获得用户的信息,而禁止使用uniqueIdentifier获得UDID,但是仍有些应用需要根据UDID区分设备 有一个系统的库IOKit.framework可以获 ...

  4. IT菜鸟的生存指南(三)流行还是经典

    经常被刚入行的新人请教,想学一门开发语言,最好又简单工资又高又有发展前途.那门语言最好这个话题能在程序员群里吵一下午,所以我也就不掀起战争了. 个人建议如下: 工资高不高不在于学那门语言,而在于你的行 ...

  5. jqgrid+bootstrap样式实践

    jqgrid+bootstrap样式实践,报错数据加载,选中,删除等功能 需要引入的样式 bootstrap.min.css ui.jqgrid.css 需要引入的JS jquery.min.js b ...

  6. ckplayer 如何在PC上完美支持 m3u8播放

    使用过ckplayer的同学都知道,相对jwplayer等,它非常的容易配置和使用.功能也是基本满足我们的需求的. 一般情况我们都使用普通的视频格式比如mp4,flv等播放,但如果视频文件过大,会加载 ...

  7. linux定时任务crond export变量问题

    linux定时任务crond export变量问题 1)我写了一个重启resin的脚本,由于业务原因,需要定时在某一个时间重启下resin服务器,于是就在 crontab里配置了如下内容: 50 17 ...

  8. 一个C++版的嵌入式操作系统

     原创文章,转载请注明出处! 现世面上流传着很多嵌入式操作系统,都已经非常优秀,但本人(Sam的博客-博客园)还是自己编写了一个RTOS,不敢说优秀,但绝对是使用起来最简单的.先看一个工程截图与一段m ...

  9. Java实现office文档与pdf文档的在线预览功能

    最近项目有个需求要java实现office文档与pdf文档的在线预览功能,刚刚接到的时候就觉得有点难,以自己的水平难以在三四天做完.压力略大.后面查找百度资料.以及在同事与网友的帮助下,四天多把它做完 ...

  10. L2-011. 玩转二叉树

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAA28AAAHQCAIAAAC5rsUiAAAgAElEQVR4nO3dzYts953n+foXcpUL0Q