diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 934573973..dab85b92b 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -44,6 +44,7 @@ endif::[] * Implement partial transaction support in AWS lambda {pull}1784[#1784] * Add instrumentation for redis.asyncio {pull}1807[#1807] * Add support for urllib3 v2.0.1+ {pull}1822[#1822] +* Add `service.environment` to log correlation {pull}1833[#1833] [float] ===== Bug fixes diff --git a/elasticapm/handlers/logging.py b/elasticapm/handlers/logging.py index 4161215dd..e5b79fc12 100644 --- a/elasticapm/handlers/logging.py +++ b/elasticapm/handlers/logging.py @@ -232,11 +232,15 @@ def _add_attributes_to_log_record(record): service_name = client.config.service_name if client else None record.elasticapm_service_name = service_name + service_environment = client.config.environment if client else None + record.elasticapm_service_environment = service_environment + record.elasticapm_labels = { "transaction.id": transaction_id, "trace.id": trace_id, "span.id": span_id, "service.name": service_name, + "service.environment": service_environment, } return record @@ -273,6 +277,7 @@ def format(self, record): record.elasticapm_trace_id = None record.elasticapm_span_id = None record.elasticapm_service_name = None + record.elasticapm_service_environment = None return super(Formatter, self).format(record=record) def formatTime(self, record, datefmt=None): @@ -281,4 +286,5 @@ def formatTime(self, record, datefmt=None): record.elasticapm_trace_id = None record.elasticapm_span_id = None record.elasticapm_service_name = None + record.elasticapm_service_environment = None return super(Formatter, self).formatTime(record=record, datefmt=datefmt) diff --git a/elasticapm/handlers/structlog.py b/elasticapm/handlers/structlog.py index 0b0736834..911277f30 100644 --- a/elasticapm/handlers/structlog.py +++ b/elasticapm/handlers/structlog.py @@ -57,6 +57,7 @@ def structlog_processor(logger, method_name, event_dict): client = get_client() if client: event_dict["service.name"] = client.config.service_name + event_dict["service.environment"] = client.config.environment if transaction and transaction.trace_parent: event_dict["trace.id"] = transaction.trace_parent.trace_id span = execution_context.get_span() diff --git a/tests/handlers/logging/logging_tests.py b/tests/handlers/logging/logging_tests.py index b5c0802a7..8e23a0b69 100644 --- a/tests/handlers/logging/logging_tests.py +++ b/tests/handlers/logging/logging_tests.py @@ -266,6 +266,7 @@ def test_logging_filter_no_span(elasticapm_client): f.filter(record) assert record.elasticapm_transaction_id == transaction.id assert record.elasticapm_service_name == transaction.tracer.config.service_name + assert record.elasticapm_service_environment == transaction.tracer.config.environment assert record.elasticapm_trace_id == transaction.trace_parent.trace_id assert record.elasticapm_span_id is None assert record.elasticapm_labels @@ -289,6 +290,7 @@ def test_logging_filter_span(elasticapm_client): f.filter(record) assert record.elasticapm_transaction_id == transaction.id assert record.elasticapm_service_name == transaction.tracer.config.service_name + assert record.elasticapm_service_environment == transaction.tracer.config.environment assert record.elasticapm_trace_id == transaction.trace_parent.trace_id assert record.elasticapm_span_id == span.id assert record.elasticapm_labels @@ -304,6 +306,7 @@ def test_logging_filter_span(elasticapm_client): f.filter(record) assert record.elasticapm_transaction_id == transaction.id assert record.elasticapm_service_name == transaction.tracer.config.service_name + assert record.elasticapm_service_environment == transaction.tracer.config.environment assert record.elasticapm_trace_id == transaction.trace_parent.trace_id assert record.elasticapm_span_id is None assert record.elasticapm_labels @@ -317,6 +320,7 @@ def test_structlog_processor_span(elasticapm_client): new_dict = structlog_processor(None, None, event_dict) assert new_dict["transaction.id"] == transaction.id assert new_dict["service.name"] == transaction.tracer.config.service_name + assert new_dict["service.environment"] == transaction.tracer.config.environment assert new_dict["trace.id"] == transaction.trace_parent.trace_id assert new_dict["span.id"] == span.id @@ -331,6 +335,7 @@ def test_structlog_processor_span(elasticapm_client): new_dict = structlog_processor(None, None, event_dict) assert new_dict["transaction.id"] == transaction.id assert new_dict["service.name"] == transaction.tracer.config.service_name + assert new_dict["service.environment"] == transaction.tracer.config.environment assert new_dict["trace.id"] == transaction.trace_parent.trace_id assert "span.id" not in new_dict @@ -346,6 +351,7 @@ def test_automatic_log_record_factory_install(elasticapm_client): record = record_factory(__name__, logging.DEBUG, __file__, 252, "dummy_msg", [], None) assert record.elasticapm_transaction_id == transaction.id assert record.elasticapm_service_name == transaction.tracer.config.service_name + assert record.elasticapm_service_environment == transaction.tracer.config.environment assert record.elasticapm_trace_id == transaction.trace_parent.trace_id assert record.elasticapm_span_id == span.id assert record.elasticapm_labels @@ -358,11 +364,13 @@ def test_formatter(): assert "| elasticapm" in formatted_record assert hasattr(record, "elasticapm_transaction_id") assert hasattr(record, "elasticapm_service_name") + assert hasattr(record, "elasticapm_service_environment") record = logging.LogRecord(__name__, logging.DEBUG, __file__, 252, "dummy_msg", [], None) formatted_time = formatter.formatTime(record) assert formatted_time assert hasattr(record, "elasticapm_transaction_id") assert hasattr(record, "elasticapm_service_name") + assert hasattr(record, "elasticapm_service_environment") def test_logging_handler_no_client(recwarn):