diff --git a/CHANGELOG.md b/CHANGELOG.md index af84693970d..325795ca7e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +- Logs: set `observed_timestamp` field + ([#3565](https://github.com/open-telemetry/opentelemetry-python/pull/3565)) - Add missing Resource SchemaURL in OTLP exporters ([#3652](https://github.com/open-telemetry/opentelemetry-python/pull/3652)) - Fix loglevel warning text diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py index ab9e69ba6d6..df23454be25 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py @@ -477,6 +477,7 @@ def _get_attributes(record: logging.LogRecord) -> Attributes: def _translate(self, record: logging.LogRecord) -> LogRecord: timestamp = int(record.created * 1e9) + observered_timestamp = time_ns() span_context = get_current_span().get_span_context() attributes = self._get_attributes(record) # This comment is taken from GanyedeNil's PR #3343, I have redacted it @@ -530,6 +531,7 @@ def _translate(self, record: logging.LogRecord) -> LogRecord: return LogRecord( timestamp=timestamp, + observed_timestamp=observered_timestamp, trace_id=span_context.trace_id, span_id=span_context.span_id, trace_flags=span_context.trace_flags, diff --git a/opentelemetry-sdk/tests/logs/test_handler.py b/opentelemetry-sdk/tests/logs/test_handler.py index 712e5be04b7..e1ef93bf34f 100644 --- a/opentelemetry-sdk/tests/logs/test_handler.py +++ b/opentelemetry-sdk/tests/logs/test_handler.py @@ -98,6 +98,20 @@ def test_log_record_no_span_context(self): log_record.trace_flags, INVALID_SPAN_CONTEXT.trace_flags ) + def test_log_record_observed_timestamp(self): + emitter_provider_mock = Mock(spec=LoggerProvider) + emitter_mock = APIGetLogger( + __name__, logger_provider=emitter_provider_mock + ) + logger = get_logger(logger_provider=emitter_provider_mock) + # Assert emit gets called for warning message + with self.assertLogs(level=logging.WARNING): + logger.warning("Warning message") + args, _ = emitter_mock.emit.call_args_list[0] + log_record = args[0] + + self.assertIsNotNone(log_record.observed_timestamp) + def test_log_record_user_attributes(self): """Attributes can be injected into logs by adding them to the LogRecord""" emitter_provider_mock = Mock(spec=LoggerProvider)