diff --git a/datadog_checks_base/changelog.d/18218.added b/datadog_checks_base/changelog.d/18218.added new file mode 100644 index 0000000000000..972dbb55d9f64 --- /dev/null +++ b/datadog_checks_base/changelog.d/18218.added @@ -0,0 +1 @@ +Enforce format of timestamp logs attribute \ No newline at end of file diff --git a/datadog_checks_base/datadog_checks/base/checks/base.py b/datadog_checks_base/datadog_checks/base/checks/base.py index 740976e91d275..89a4be342d97d 100644 --- a/datadog_checks_base/datadog_checks/base/checks/base.py +++ b/datadog_checks_base/datadog_checks/base/checks/base.py @@ -1000,7 +1000,10 @@ def send_log(self, data, cursor=None, stream='default'): Parameters: data (dict[str, str]): - The log data to send. + The log data to send. The following keys are treated specially, if present: + + - timestamp: should be an integer or float representing the number of seconds since the Unix epoch + - ddtags: if not defined, it will automatically be set based on the instance's `tags` option cursor (dict[str, Any] or None): Metadata associated with the log which will be saved to disk. The most recent value may be retrieved with the `get_log_cursor` method. @@ -1012,6 +1015,11 @@ def send_log(self, data, cursor=None, stream='default'): if 'ddtags' not in attributes and self.formatted_tags: attributes['ddtags'] = self.formatted_tags + timestamp = attributes.get('timestamp') + if timestamp is not None: + # convert seconds to milliseconds + attributes['timestamp'] = int(timestamp * 1000) + datadog_agent.send_log(to_json(attributes), self.check_id) if cursor is not None: self.write_persistent_cache('log_cursor_{}'.format(stream), to_json(cursor)) diff --git a/datadog_checks_base/tests/base/checks/test_agent_check.py b/datadog_checks_base/tests/base/checks/test_agent_check.py index 28012f2b6ddcf..244a041582b26 100644 --- a/datadog_checks_base/tests/base/checks/test_agent_check.py +++ b/datadog_checks_base/tests/base/checks/test_agent_check.py @@ -614,6 +614,24 @@ def test_stream(self, datadog_agent): assert check.get_log_cursor(stream='stream1') == {'data': '1'} assert check.get_log_cursor(stream='stream2') == {'data': '2'} + def test_timestamp(self, datadog_agent): + check = AgentCheck('check_name', {}, [{}]) + check.check_id = 'test' + + check.send_log({'message': 'foo', 'timestamp': 1722958617.2842212}) + check.send_log({'message': 'bar', 'timestamp': 1722958619.2358432}) + check.send_log({'message': 'baz', 'timestamp': 1722958620.5963688}) + + datadog_agent.assert_logs( + check.check_id, + [ + {'message': 'foo', 'timestamp': 1722958617284}, + {'message': 'bar', 'timestamp': 1722958619235}, + {'message': 'baz', 'timestamp': 1722958620596}, + ], + ) + assert check.get_log_cursor() is None + class TestLogsEnabledDetection: def test_default(self, datadog_agent):