Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Log a warning when an attribute is discarded due to limits #3946

Merged
merged 8 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased
- Log a warning when a `LogRecord` in `sdk/log` has dropped attributes
due to reaching limits
([#3946](https://github.com/open-telemetry/opentelemetry-python/pull/3946))

- Fix RandomIdGenerator can generate invalid Span/Trace Ids
([#3949](https://github.com/open-telemetry/opentelemetry-python/pull/3949))
Expand Down
2 changes: 2 additions & 0 deletions opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

from opentelemetry.sdk._logs._internal import (
LogData,
LogDroppedAttributesWarning,
Logger,
LoggerProvider,
LoggingHandler,
Expand All @@ -31,4 +32,5 @@
"LogLimits",
"LogRecord",
"LogRecordProcessor",
"LogDroppedAttributesWarning",
]
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import logging
import threading
import traceback
import warnings
from os import environ
from time import time_ns
from typing import Any, Callable, Optional, Tuple, Union # noqa
Expand Down Expand Up @@ -57,6 +58,18 @@
_ENV_VALUE_UNSET = ""


class LogDroppedAttributesWarning(UserWarning):
emdneto marked this conversation as resolved.
Show resolved Hide resolved
"""Custom warning to indicate dropped log attributes due to limits.

This class is used to filter and handle these specific warnings separately
from other warnings, ensuring that they are only shown once without
interfering with default user warnings.
"""


warnings.simplefilter("once", LogDroppedAttributesWarning)
xrmx marked this conversation as resolved.
Show resolved Hide resolved


class LogLimits:
"""This class is based on a SpanLimits class in the Tracing module.

Expand Down Expand Up @@ -190,6 +203,12 @@ def __init__(
}
)
self.resource = resource
if self.dropped_attributes > 0:
warnings.warn(
"Log record attributes were dropped due to limits",
LogDroppedAttributesWarning,
stacklevel=2,
)

def __eq__(self, other: object) -> bool:
if not isinstance(other, LogRecord):
Expand Down
29 changes: 28 additions & 1 deletion opentelemetry-sdk/tests/logs/test_log_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@

import json
import unittest
import warnings

from opentelemetry.attributes import BoundedAttributes
from opentelemetry.sdk._logs import LogLimits, LogRecord
from opentelemetry.sdk._logs import (
LogDroppedAttributesWarning,
LogLimits,
LogRecord,
)


class TestLogRecord(unittest.TestCase):
Expand Down Expand Up @@ -98,6 +103,28 @@ def test_log_record_dropped_attributes_set_limits(self):
self.assertTrue(result.dropped_attributes == 1)
self.assertEqual(expected, result.attributes)

def test_log_record_dropped_attributes_set_limits_warning_once(self):
attr = {"key1": "value1", "key2": "value2"}
limits = LogLimits(
max_attributes=1,
max_attribute_length=1,
)

with warnings.catch_warnings(record=True) as cw:
for _ in range(10):
LogRecord(
timestamp=0,
body="a log line",
attributes=attr,
limits=limits,
)
self.assertEqual(len(cw), 1)
self.assertIsInstance(cw[-1].message, LogDroppedAttributesWarning)
self.assertIn(
"Log record attributes were dropped due to limits",
str(cw[-1].message),
)

def test_log_record_dropped_attributes_unset_limits(self):
attr = {"key": "value", "key2": "value2"}
limits = LogLimits()
Expand Down