我尝试使用monolog开始将我的日志发送到弹性搜索。 (我使用Symfony2)。
我已经设置了这样的独白:
monolog:
handlers:
elasticsearch:
elasticsearch:
host: %logger_elastic_host%
port: %logger_elastic_port%
type: elasticsearch
level: info
它只用了几分钟才发现这个错误消息(致命错误,我删除了无用的东西):
创建:/ monolog / logs / AVQKYsGRPmEhlo7mDfrN导致 MapperParsingException [无法解析[context.stack.args]];嵌套: ElasticsearchIllegalArgumentException [未知属性[class]];
我一直在和我的同事一起寻找解决方法。我们发现的是:
问题在于背景总是非常不同。
我们想要的是:
是否有人使用Monolog登录Elasticsearch
你们如何设法避免这个问题。 (我们如何设法避免它?)
答案 0 :(得分:1)
这是因为ES从第一个文档创建了一个映射。如果之后插入的任何文档具有相同的属性但具有其他类型/格式,那么ES将抛出错误。
解决方案是创建自定义monolog格式化程序并注册它:
config.yml:
elasticsearch:
type: elasticsearch
elasticsearch:
host: elasticsearch
ignore_error: true
formatter: my_elasticsearch_formatter
这一行将使Monolog \ Handler \ ElasticSearchHandler忽略Ruflin的Elastica包中的任何其他错误:
ignore_error: true
然后使用以下名称注册服务:my_elasticsearch_formatter:
<service id="my_elasticsearch_formatter" class="AppBundle\Services\MyFormatter">
<argument type="string">monolog</argument>
<argument type="string">logs</argument>
</service>
第一个参数是索引名称,第二个参数是类型。
格式化程序类:
<?php
namespace AppBundle\Services;
use function json_encode;
use Monolog\Formatter\ElasticaFormatter;
use function var_dump;
class MyFormatter extends ElasticaFormatter
{
/**
* @param string $index
* @param string $type
*/
public function __construct($index, $type)
{
parent::__construct($index, $type);
}
/**
* @param array $record
* @return array|\Elastica\Document|mixed|string
*/
public function format(array $record)
{
$record['context'] = json_encode($record['context']);
return parent::format($record);
}
}
这个解决方案的缺点是它将json_encode上下文。您将无法按ES中上下文的内部属性进行过滤,但至少您不会丢失有关日志的重要信息。