def _log_ecs_reformatting_callback(dict_key, old_value, new_value, config_instance): """ If ecs_logging is installed and log_ecs_reformatting is set to "override", we should set the ecs_logging.StdlibFormatter as the formatted for every handler in the root logger, and set the default processor for structlog to the ecs_logging.StructlogFormatter. """ if new_value.lower() == "override": try: import ecs_logging except ImportError: return # Stdlib root_logger = logging.getLogger() formatter = ecs_logging.StdlibFormatter() for handler in root_logger.handlers: handler.setFormatter(formatter) # Structlog try: import structlog structlog.configure(processors=[ecs_logging.StructlogFormatter()]) except ImportError: pass
def test_elasticapm_structlog_log_correlation_ecs_fields(spec_validator): apm = elasticapm.Client({"SERVICE_NAME": "apm-service", "DISABLE_SEND": True}) stream = StringIO() logger = structlog.PrintLogger(stream) logger = structlog.wrap_logger( logger, processors=[structlog_processor, ecs_logging.StructlogFormatter()] ) log = logger.new() apm.begin_transaction("test-transaction") try: with elasticapm.capture_span("test-span"): span_id = elasticapm.get_span_id() trace_id = elasticapm.get_trace_id() transaction_id = elasticapm.get_transaction_id() log.info("test message") finally: apm.end_transaction("test-transaction") ecs = json.loads(spec_validator(stream.getvalue().rstrip())) ecs.pop("@timestamp") assert ecs == { "ecs": {"version": "1.6.0"}, "log.level": "info", "message": "test message", "span": {"id": span_id}, "trace": {"id": trace_id}, "transaction": {"id": transaction_id}, "service": {"name": "apm-service"}, }
def test_event_dict_formatted(time, spec_validator): time.return_value = 1584720997.187709 formatter = ecs_logging.StructlogFormatter() assert spec_validator(formatter(None, "debug", make_event_dict())) == ( '{"@timestamp":"2020-03-20T16:16:37.187Z","log.level":"debug",' '"message":"test message","ecs":{"version":"1.6.0"},' '"log":{"logger":"logger-name"}}')
def test_can_be_set_as_processor(time, spec_validator): time.return_value = 1584720997.187709 stream = StringIO() structlog.configure( processors=[ecs_logging.StructlogFormatter()], wrapper_class=structlog.BoundLogger, context_class=dict, logger_factory=structlog.PrintLoggerFactory(stream), ) logger = structlog.get_logger("logger-name") logger.debug("test message", custom="key", **{"dot.ted": 1}) assert spec_validator(stream.getvalue()) == ( '{"@timestamp":"2020-03-20T16:16:37.187Z","log.level":"debug",' '"message":"test message","custom":"key","dot":{"ted":1},' '"ecs":{"version":"1.6.0"}}\n')
def test_conflicting_event_dict(): formatter = ecs_logging.StructlogFormatter() event_dict = make_event_dict() event_dict["foo.bar"] = "baz" with pytest.raises(TypeError): formatter(None, "debug", event_dict)