And*_*ord 10 php symfony monolog
我正在使用MonologBundle我的Symfony 2.8项目来管理日志消息.使用不同的Handlers方法将日志写入文件并通过电子邮件同时发送是没有问题的.
我想减少通过邮件收到的邮件数量.我已经使用DeduplicationHandler和FingersCrossed处理程序按错误级别进行筛选并避免重复消息.这工作正常,但还不够.
例如,我想减少有关PageNotFound错误的邮件数量.当然,如果/existingPage找不到,我想收到通知,但我对有关/.well-known/...文件的消息不感兴趣.
另一个示例是关于第三方CSV解析器组件中的错误的消息.我不感兴趣有几个已知且无害的错误,但当然其他错误也很重要.
这些错误/消息是由第三方代码生成的,我不能影响源.我完全可以忽略这些消息,但这不是我想要的.
我正在寻找一种按内容过滤消息的解决方案.如何在Monolog中完成?
我已经尝试使用a来解决这个HandlerWrapper问题,并在另一个问题中讨论了这个问题:这个想法是,HandlerWrapper作为过滤器.的HandlerWrapper是由独白调用时,它检查消息内容,并决定阉它应该被处理或不(例如丢弃所有消息,包括文本"./well-known/").如果消息通过,HandlerWrapper应该简单地将其移交给它的嵌套/包装处理程序.否则,将跳过该消息而不进行进一步处理.
然而,这个想法不起作用,而另一个问题的答案表明,a HandlerWrapper不是解决这个问题的正确方法.
所以新的/实际的问题是:如何为Monolog消息创建一个过滤器,让我控制一个特定的消息是否应该被处理?
我不确定为什么使用HandlerWrapper是错误的方法。
我遇到了同样的问题,并找到了一种方法来包装处理程序以过滤某些记录。
在此答案中,我描述了解决此问题的两种方法,一种更复杂且更容易的方法。
我要做的第一件事是创建一个扩展HandlerWrapper的新类,并添加了一些我可以过滤记录的逻辑:
use Monolog\Handler\HandlerWrapper;
class CustomHandler extends HandlerWrapper
{
public function isHandling(array $record)
{
if ($this->shouldFilter($record)) {
return false;
}
return $this->handler->isHandling($record);
}
public function handle(array $record)
{
if (!$this->isHandling($record)) {
return false;
}
return $this->handler->handle($record);
}
public function handleBatch(array $records)
{
foreach ($records as $record) {
$this->handle($record);
}
}
private function shouldFilter(array $record)
{
return mt_rand(0, 1) === 1;; // add logic here
}
}
Run Code Online (Sandbox Code Playgroud)
然后,我创建了一个服务定义和一个CompilerPass,可以在其中包装GroupHandler
services.yml
CustomHandler:
class: CustomHandler
abstract: true
arguments: ['']
Run Code Online (Sandbox Code Playgroud)
CustomHandler:
class: CustomHandler
abstract: true
arguments: ['']
Run Code Online (Sandbox Code Playgroud)
如您所见,我在这里遍历了所有定义,并找到将GroupHandler设置为其类的那些定义。在这种情况下,我向容器添加了一个新定义,用我的CustomHandler装饰了原始处理程序。
旁注:最初,我尝试包装所有处理程序(当然是CustomHandler除外),但是由于某些处理程序实现了其他接口(例如使用EventSubscriberInterface 的ConsoleHandler),因此无法正常工作并导致出现我不想处理的问题解决某些问题。
别忘了将此编译器传递添加到AppBundle类的容器中
class AppBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
$container->addCompilerPass(new CustomMonologHandlerPass());
}
}
Run Code Online (Sandbox Code Playgroud)
现在一切就绪,您必须对处理程序进行分组才能完成此工作:
app/config(_prod|_dev).yml
monolog:
handlers:
my_group:
type: group
members: [ 'graylog' ]
graylog:
type: gelf
publisher:
id: my.publisher
level: debug
formatter: my.formatter
Run Code Online (Sandbox Code Playgroud)
我们使用与复杂方式相同的CustomHandler,然后在配置中定义处理程序:
app/config(_prod|_dev).yml
monolog:
handlers:
graylog:
type: gelf
publisher:
id: my.publisher
level: debug
formatter: my.formatter
Run Code Online (Sandbox Code Playgroud)
用您自己的CustomHandler装饰您的services.yml中的处理程序
services.yml
CustomHandler:
class: CustomHandler
decorates: monolog.handler.graylog
arguments: ['@CustomHandler.inner']
Run Code Online (Sandbox Code Playgroud)
对于decorates属性,您必须使用format monolog.handler.$NAME_SPECIFIED_AS_KEY_IN_CONFIG,在这种情况下,它是graylog。
...就是这样
虽然这两种方法都可行,但是我使用了第一种方法,因为我们有几个symfony项目需要我这样做,而手动装饰所有处理程序并不是我想要的。
我希望这会有所帮助(即使我来不及回答:)
| 归档时间: |
|
| 查看次数: |
1399 次 |
| 最近记录: |