zalora/punyan
最新稳定版本:1.0.1
Composer 安装命令:
composer require zalora/punyan
包简介
PHP implementation of Bunyan
README 文档
README
Punyan is the PHP implementation of the Bunyan Logger originally written for node.js
Requirements
- Linux / OS X (Maybe someone with Windows wants to try?)
- PHP 7.x
- Composer
- NPM
Installation
$ composer require zalora/punyan
tl;dr logger to go
{
"writers": [
{
"stream": {
"url": "/tmp/myproject.log",
"filters": [{ "priority": { "priority": "info" } }]
}
}
]
}
$config = [ 'writers' => [ ['stream' => [ 'url' => '/tmp/myproject.log', 'filters' => [ ['priority' => ['priority' => 'info']] ] ]] ] ];
<?php use Zalora\Punyan\Logger; use Zalora\Punyan\ZLog; ZLog::setInstance(new Logger('MyAppName', $config)); ... ZLog::info('Informative log message', ['param1' => 'stuffs']);
$ sudo npm install -g bunyan
$ tail -f /tmp/myproject.log | bunyan -o short -L
Bunyan is actually one of the few npm modules which installed without a single warning or error!
The Config file
The example config is written in JSON-format, every other format works, too as long as it represents the same structure. The logger itself expects an array with the same structure.
{
"mute": false,
"filters": [
{ "priority": {"priority": "info", "operator": ">="} }
],
"writers": [
{
"Stream": {
"mute": false,
"url": "php://stdout",
"filters": [
{ "priority": { "priority": "warn" } },
{ "ns": { "namespace": "Service", "searchMethod": "contains" } }
]
}
}
]
}
Top level options
- mute: The top level mute mutes the whole logger, the mute inside the writers only applies for this specific writer
- filters: The top level filter applies to the whole logger, the filters inside the writers only apply to the specific writer
- writers: Every logger can have zero or more writers (Of course it's more fun with more than zero writers...)
- exceptionHandler: To make sure we can mask sensitive data, we need to implement our own special exceptionHandler, so we made this method configurable. Think about passwords or other sensitive data you don't want to have in your logfiles
Filters
- Callback
- DiscoBouncer
- NoFilter
- Namespace
- Priority
- Regular Expression
To add a filter you have to add a structure like this to the filters array:
{ "<filter_name>": { "option1": "value1", "option2": "value2" } }
Callback
Callback filters have to return (true|false) and are passed in the LogEvent object to have some data for evaluation.
The only option is:
- function: You better make sure it's callable
If you don't return anything, false is assumed. It's of course also your responsibility to make sure the class is loaded or an autoloader is present to do that.
Example:
{ "callback": { "function": "MyClass::myStaticMethod" }
DiscoBouncer
The name says it all: It will filter everything. This filter doesn't have options and is currently used for unit tests. If you find a real world use case, let me know. I'm curious.
Example:
{ "discoBouncer": {} }
NoFilter
Opposite of the DiscoBouncer, lets everything pass.
Example:
{ "noFilter": {} }
Namespace (Ns)
This filter is applied on your class name (including the namespace), so you can e.g. use it to assign your modules a separate logfile. Regular Expressions are validated during init of the logger.
Options:
- namespace: What to search for in the namespace
- searchMethod: (optional, default 'startsWith') One of those: (startsWith|contains|regexp)
If you use regexp as searchMethod, namespace contains your regular expression
Examples:
This will accept only logs from classes which contain the token 'Service':
{ "ns": { "namespace": "Service", "searchMethod": "contains" } }
My regex foo is incredibly low, sorry for this example. I hope this matches every class which ends with Hello:
{ "ns": { "namespace": "/Hello$/", "searchMethod": "regexp" } }
Priority
Priority filters filter by priority (Surprise...), e.g. if the filter level is set to 'info' then everything from info on passes. I guess there's not that much to explain.
Here's the full options list:
- priority: One of those (trace|debug|info|warn|error|fatal)
- operator: (optional, default >=) You don't want to modify that...
Example:
{ "priority": { "priority": "warn", "operator": ">=" } }
Regexp
Match a field (log message by default) against your regular expression pattern. These are the options of the filter:
- pattern: (mandatory) your regular expression
- field: (optional, default 'msg') The field in the context to run your regexp against . To access nested values, use a dot as separator, e.g.
request.srcto access$context['request']['src'] - returnValueOnMissingField: (optional, default false) If the field doesn't exist return either true or false
Example:
{ "regexp": { "pattern": "/^https/", "field": "request.url", "returnValueOnMissingField": false } }
Match all URLs which start with https, in case there are no URLs logged, discard the log entry.
Writers
Currently there's only one writer (StreamWriter), in a later version I'll add a few more to support FirePHP and Slack. The three options every writer has are:
- mute (true|false) default is false
- origin (true|false) default is true
- bubble (true|false) default is true
Mute
This will (Cpt. Obvious) mute the writer and suppress any potential output
Origin
Origin adds an array with information about where the log call was triggered, it contains the following fields:
- file
- line
- class
- function
This is e.g. required for the Namespace filter. If you set origin to false and add a Ns-Filter, the filter will always return false.
Bubble
Once a writer logged the message, the log event is not sent to other writers. Example:
{
"filters": [
{ "priority": { "priority": "info" } }
],
"writers": [
{
"Stream": {
"origin": true,
"bubble": false,
"url": "services.log",
"filters": [
{ "ns": { "namespace": "Service", "searchMethod": "contains" } }
]
}
},
{
"Stream": {
"origin": true,
"url": "common.log",
"filters": []
}
}
]
}
The services.log keeps all log events which come from classes which contain the word Service in their class name. Without bubbling the log message would be in both files, as the stream writer for common.log doesn't have any filters. So bubbling can be used to prevent duplicate log messages. Keep in mind that the order in which you define your writers is important when you use bubbling!
Disclaimer: I stole the word "bubbling" from Monolog
StreamWriter
The StreamWriter supports all writeable streams (http://php.net/manual/en/wrappers.php), e.g.
- php://memory
- file:///tmp/myproject.log
- php://stdout
Options:
- url: The url you want to write (append) to
- filters: Filters are optional, but at least an empty array must exist
- mute: (optional, default false) Like every writer, it can be muted
The stream will be opened during the init process, so in case of files you know very early if it's writeable or not
Processors
I stole the name again from Monolog, because I couldn't come up with a better one... They're also doing the same: Add additional to every log event.
Of course you can do that manually, but it's a lot of work and it clutters the code, because it will be executed even if the log message itself is filtered out. So you move this code into a Processor and attach it to a writer. From that moment on it will gather all the required information automatically.
Processors have one common field:
- onDemand (true|false) default is false
The additional data is stored under the key 'proc', which is defined in Zalora\Punyan\IProcessor.
Example:
{ "Web": { "onDemand": true } or { "Web": { } }
Web Processor
The following data is added to the proc array of every log event:
- url:
$_SERVER['REQUEST_URI'] - ip:
$_SERVER['REMOTE_ADDR'] - http_method:
$_SERVER['REQUEST_METHOD'] - server:
$_SERVER['SERVER_NAME'] - referrer:
$_SERVER['HTTP_REFERER]
Known Problems
- The only supported format is Bunyan; this is not really a problem, more a design decision. I might loosen that to be able to support other JSON based services if someone's interested...
FAQs
Why reinvent the wheel?
Actually I couldn't find a logger I liked, which does NOT implement the PSR-3 interface. At first I thought implementing a Formatter for Monolog should do the trick, but the log levels wouldn't match properly and using a mapping seemed too hackish.
As we want to use the tooling the bunyan project provides, we have to stay format-compatible. And here we have yet another logger for PHP.
What's planned?
Configuration storage
In order to change log levels you have to change a file or even worse change code. I want to provide a small CLI program which changes the configuration without a need for writeable files or redeploy. This can be achieved by storing the configuration in a key value store
New Filters
- Rate Limit: Together with bubbling turned off, you can omit sending half a billion emails overnight ;-)
- Sampler: Filter out a certain percentage of the events
New Writers
- AMQP: Sending logs to RabbitMQ
- Slack: Your favorite Messenger
- FirePHP: Sending log events to the browser during development
- Responsys: Sending important logs via E-Mail (Keep the rate limit in mind...)
- New Relic: Your favorite application monitoring tool
- Redis: Persist your logs to a Redis list
zalora/punyan 适用场景与选型建议
zalora/punyan 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 20.64k 次下载、GitHub Stars 达 5, 最近一次更新时间为 2016 年 01 月 25 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「log」 「logging」 「json」 「logger」 「bunyan」 「punyan」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 zalora/punyan 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 zalora/punyan 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 zalora/punyan 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Kinikit - PHP Application development framework MVC component
A Zend Framework module that sets up Monolog for logging in applications.
ext-json wrapper with sane defaults
A package to cast json fields, each sub-keys is castable
Asynchronous Sentry for Symfony - Fire and forget
Stackdriver handler for Monolog (codeinternetapplications/monolog-stackdriver Fork).
统计信息
- 总下载量: 20.64k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 5
- 点击次数: 21
- 依赖项目数: 2
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2016-01-25