diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 70b278b9ac..1bdff92077 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,7 +10,7 @@ env: # Otherwise, set variable to the commit of your branch on # opentelemetry-python-contrib which is compatible with these Core repo # changes. - CONTRIB_REPO_SHA: 511709802466a751786047b7d98c2eb84801b34f + CONTRIB_REPO_SHA: 2edd017c22edb4896e182c934bc199d716495ce6 # This is needed because we do not clone the core repo in contrib builds anymore. # When running contrib builds as part of core builds, we use actions/checkout@v2 which # does not set an environment variable (simply just runs tox), which is different when diff --git a/CHANGELOG.md b/CHANGELOG.md index aeb41a3c58..3ce6fc4251 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ 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 +- Use BoundedAttributes instead of raw dict to extract attributes from LogRecord and Support dropped_attributes_count in LogRecord ([#3310](https://github.com/open-telemetry/opentelemetry-python/pull/3310)) +## Version 1.18.0/0.39b0 (2023-05-04) - Select histogram aggregation with an environment variable ([#3265](https://github.com/open-telemetry/opentelemetry-python/pull/3265)) diff --git a/README.md b/README.md index 1cad936e57..ce1bf2c59d 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,6 @@ Maintainers ([@open-telemetry/python-maintainers](https://github.com/orgs/open-t - [Diego Hurtado](https://github.com/ocelotl), Lightstep - [Leighton Chen](https://github.com/lzchen), Microsoft -- [Srikanth Chekuri](https://github.com/srikanthccv), signoz.io Emeritus Maintainers: @@ -125,6 +124,7 @@ Emeritus Maintainers: - [Chris Kleinknecht](https://github.com/c24t), Google - [Owais Lone](https://github.com/owais), Splunk - [Reiley Yang](https://github.com/reyang), Microsoft +- [Srikanth Chekuri](https://github.com/srikanthccv), signoz.io - [Yusuke Tsutsumi](https://github.com/toumorokoshi), Google *For more information about the maintainer role, see the [community repository](https://github.com/open-telemetry/community/blob/main/community-membership.md#maintainer).* diff --git a/eachdist.ini b/eachdist.ini index c33b4e0923..896dabb66e 100644 --- a/eachdist.ini +++ b/eachdist.ini @@ -11,7 +11,7 @@ sortfirst= exporter/* [stable] -version=1.18.0.dev +version=1.19.0.dev packages= opentelemetry-sdk @@ -30,7 +30,7 @@ packages= opentelemetry-api [prerelease] -version=0.39b0.dev +version=0.40b0.dev packages= opentelemetry-opentracing-shim diff --git a/exporter/opentelemetry-exporter-jaeger-proto-grpc/src/opentelemetry/exporter/jaeger/proto/grpc/version.py b/exporter/opentelemetry-exporter-jaeger-proto-grpc/src/opentelemetry/exporter/jaeger/proto/grpc/version.py index 6b6b22d30f..8e6645935a 100644 --- a/exporter/opentelemetry-exporter-jaeger-proto-grpc/src/opentelemetry/exporter/jaeger/proto/grpc/version.py +++ b/exporter/opentelemetry-exporter-jaeger-proto-grpc/src/opentelemetry/exporter/jaeger/proto/grpc/version.py @@ -13,4 +13,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "1.18.0.dev" +__version__ = "1.19.0.dev" diff --git a/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/version.py b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/version.py index 6b6b22d30f..8e6645935a 100644 --- a/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/version.py +++ b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/version.py @@ -13,4 +13,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "1.18.0.dev" +__version__ = "1.19.0.dev" diff --git a/exporter/opentelemetry-exporter-jaeger/pyproject.toml b/exporter/opentelemetry-exporter-jaeger/pyproject.toml index 95c93736de..cc7c45cbd1 100644 --- a/exporter/opentelemetry-exporter-jaeger/pyproject.toml +++ b/exporter/opentelemetry-exporter-jaeger/pyproject.toml @@ -26,8 +26,8 @@ classifiers = [ "Typing :: Typed", ] dependencies = [ - "opentelemetry-exporter-jaeger-proto-grpc == 1.18.0.dev", - "opentelemetry-exporter-jaeger-thrift == 1.18.0.dev", + "opentelemetry-exporter-jaeger-proto-grpc == 1.19.0.dev", + "opentelemetry-exporter-jaeger-thrift == 1.19.0.dev", ] [project.optional-dependencies] diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/version.py b/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/version.py index 6b6b22d30f..8e6645935a 100644 --- a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/version.py +++ b/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/version.py @@ -13,4 +13,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "1.18.0.dev" +__version__ = "1.19.0.dev" diff --git a/exporter/opentelemetry-exporter-opencensus/pyproject.toml b/exporter/opentelemetry-exporter-opencensus/pyproject.toml index 48e0a59ea4..f906b87bb7 100644 --- a/exporter/opentelemetry-exporter-opencensus/pyproject.toml +++ b/exporter/opentelemetry-exporter-opencensus/pyproject.toml @@ -28,7 +28,7 @@ classifiers = [ dependencies = [ "grpcio >= 1.0.0, < 2.0.0", "opencensus-proto >= 0.1.0, < 1.0.0", - "opentelemetry-api >= 1.18.0.dev", + "opentelemetry-api >= 1.19.0.dev", "opentelemetry-sdk >= 1.15", "protobuf ~= 3.13", "setuptools >= 16.0", diff --git a/exporter/opentelemetry-exporter-opencensus/src/opentelemetry/exporter/opencensus/version.py b/exporter/opentelemetry-exporter-opencensus/src/opentelemetry/exporter/opencensus/version.py index eb62a67e28..87b20fddc3 100644 --- a/exporter/opentelemetry-exporter-opencensus/src/opentelemetry/exporter/opencensus/version.py +++ b/exporter/opentelemetry-exporter-opencensus/src/opentelemetry/exporter/opencensus/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "0.39b0.dev" +__version__ = "0.40b0.dev" diff --git a/exporter/opentelemetry-exporter-otlp-proto-common/pyproject.toml b/exporter/opentelemetry-exporter-otlp-proto-common/pyproject.toml index 5f872cd086..64e2767dee 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-common/pyproject.toml +++ b/exporter/opentelemetry-exporter-otlp-proto-common/pyproject.toml @@ -25,7 +25,7 @@ classifiers = [ "Programming Language :: Python :: 3.11", ] dependencies = [ - "opentelemetry-proto == 1.18.0.dev", + "opentelemetry-proto == 1.19.0.dev", ] [project.urls] diff --git a/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/version.py b/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/version.py index 80d12781d3..168a28bae9 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/version.py +++ b/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "1.18.0.dev" +__version__ = "1.19.0.dev" diff --git a/exporter/opentelemetry-exporter-otlp-proto-grpc/pyproject.toml b/exporter/opentelemetry-exporter-otlp-proto-grpc/pyproject.toml index 82ec2b0a19..ebeaa35745 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-grpc/pyproject.toml +++ b/exporter/opentelemetry-exporter-otlp-proto-grpc/pyproject.toml @@ -31,9 +31,9 @@ dependencies = [ "googleapis-common-protos ~= 1.52", "grpcio >= 1.0.0, < 2.0.0", "opentelemetry-api ~= 1.15", - "opentelemetry-proto == 1.18.0.dev", - "opentelemetry-sdk ~= 1.18.0.dev", - "opentelemetry-exporter-otlp-proto-common == 1.18.0.dev", + "opentelemetry-proto == 1.19.0.dev", + "opentelemetry-sdk ~= 1.19.0.dev", + "opentelemetry-exporter-otlp-proto-common == 1.19.0.dev", ] [project.optional-dependencies] diff --git a/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/version.py b/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/version.py index 80d12781d3..168a28bae9 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/version.py +++ b/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "1.18.0.dev" +__version__ = "1.19.0.dev" diff --git a/exporter/opentelemetry-exporter-otlp-proto-http/pyproject.toml b/exporter/opentelemetry-exporter-otlp-proto-http/pyproject.toml index 54f2b67249..10eeafccf5 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-http/pyproject.toml +++ b/exporter/opentelemetry-exporter-otlp-proto-http/pyproject.toml @@ -30,9 +30,9 @@ dependencies = [ "backoff >= 1.10.0, < 3.0.0; python_version>='3.7'", "googleapis-common-protos ~= 1.52", "opentelemetry-api ~= 1.15", - "opentelemetry-proto == 1.18.0.dev", - "opentelemetry-sdk ~= 1.18.0.dev", - "opentelemetry-exporter-otlp-proto-common == 1.18.0.dev", + "opentelemetry-proto == 1.19.0.dev", + "opentelemetry-sdk ~= 1.19.0.dev", + "opentelemetry-exporter-otlp-proto-common == 1.19.0.dev", "requests ~= 2.7", ] diff --git a/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/version.py b/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/version.py index 80d12781d3..168a28bae9 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/version.py +++ b/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "1.18.0.dev" +__version__ = "1.19.0.dev" diff --git a/exporter/opentelemetry-exporter-otlp/pyproject.toml b/exporter/opentelemetry-exporter-otlp/pyproject.toml index 8af01b433c..a2bb316e36 100644 --- a/exporter/opentelemetry-exporter-otlp/pyproject.toml +++ b/exporter/opentelemetry-exporter-otlp/pyproject.toml @@ -26,8 +26,8 @@ classifiers = [ "Typing :: Typed", ] dependencies = [ - "opentelemetry-exporter-otlp-proto-grpc == 1.18.0.dev", - "opentelemetry-exporter-otlp-proto-http == 1.18.0.dev", + "opentelemetry-exporter-otlp-proto-grpc == 1.19.0.dev", + "opentelemetry-exporter-otlp-proto-http == 1.19.0.dev", ] [project.entry-points.opentelemetry_logs_exporter] diff --git a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/version.py b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/version.py index 80d12781d3..168a28bae9 100644 --- a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/version.py +++ b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "1.18.0.dev" +__version__ = "1.19.0.dev" diff --git a/exporter/opentelemetry-exporter-prometheus/src/opentelemetry/exporter/prometheus/version.py b/exporter/opentelemetry-exporter-prometheus/src/opentelemetry/exporter/prometheus/version.py index eb62a67e28..87b20fddc3 100644 --- a/exporter/opentelemetry-exporter-prometheus/src/opentelemetry/exporter/prometheus/version.py +++ b/exporter/opentelemetry-exporter-prometheus/src/opentelemetry/exporter/prometheus/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "0.39b0.dev" +__version__ = "0.40b0.dev" diff --git a/exporter/opentelemetry-exporter-zipkin-json/src/opentelemetry/exporter/zipkin/json/version.py b/exporter/opentelemetry-exporter-zipkin-json/src/opentelemetry/exporter/zipkin/json/version.py index 80d12781d3..168a28bae9 100644 --- a/exporter/opentelemetry-exporter-zipkin-json/src/opentelemetry/exporter/zipkin/json/version.py +++ b/exporter/opentelemetry-exporter-zipkin-json/src/opentelemetry/exporter/zipkin/json/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "1.18.0.dev" +__version__ = "1.19.0.dev" diff --git a/exporter/opentelemetry-exporter-zipkin-proto-http/pyproject.toml b/exporter/opentelemetry-exporter-zipkin-proto-http/pyproject.toml index 8764b35d43..6e0069848f 100644 --- a/exporter/opentelemetry-exporter-zipkin-proto-http/pyproject.toml +++ b/exporter/opentelemetry-exporter-zipkin-proto-http/pyproject.toml @@ -27,7 +27,7 @@ classifiers = [ ] dependencies = [ "opentelemetry-api ~= 1.3", - "opentelemetry-exporter-zipkin-json == 1.18.0.dev", + "opentelemetry-exporter-zipkin-json == 1.19.0.dev", "opentelemetry-sdk ~= 1.11", "protobuf ~= 3.12", "requests ~= 2.7", diff --git a/exporter/opentelemetry-exporter-zipkin-proto-http/src/opentelemetry/exporter/zipkin/proto/http/version.py b/exporter/opentelemetry-exporter-zipkin-proto-http/src/opentelemetry/exporter/zipkin/proto/http/version.py index 80d12781d3..168a28bae9 100644 --- a/exporter/opentelemetry-exporter-zipkin-proto-http/src/opentelemetry/exporter/zipkin/proto/http/version.py +++ b/exporter/opentelemetry-exporter-zipkin-proto-http/src/opentelemetry/exporter/zipkin/proto/http/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "1.18.0.dev" +__version__ = "1.19.0.dev" diff --git a/exporter/opentelemetry-exporter-zipkin/pyproject.toml b/exporter/opentelemetry-exporter-zipkin/pyproject.toml index 03dedc6dea..5a1325e20c 100644 --- a/exporter/opentelemetry-exporter-zipkin/pyproject.toml +++ b/exporter/opentelemetry-exporter-zipkin/pyproject.toml @@ -26,8 +26,8 @@ classifiers = [ "Typing :: Typed", ] dependencies = [ - "opentelemetry-exporter-zipkin-json == 1.18.0.dev", - "opentelemetry-exporter-zipkin-proto-http == 1.18.0.dev", + "opentelemetry-exporter-zipkin-json == 1.19.0.dev", + "opentelemetry-exporter-zipkin-proto-http == 1.19.0.dev", ] [project.optional-dependencies] diff --git a/exporter/opentelemetry-exporter-zipkin/src/opentelemetry/exporter/zipkin/version.py b/exporter/opentelemetry-exporter-zipkin/src/opentelemetry/exporter/zipkin/version.py index 80d12781d3..168a28bae9 100644 --- a/exporter/opentelemetry-exporter-zipkin/src/opentelemetry/exporter/zipkin/version.py +++ b/exporter/opentelemetry-exporter-zipkin/src/opentelemetry/exporter/zipkin/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "1.18.0.dev" +__version__ = "1.19.0.dev" diff --git a/opentelemetry-api/src/opentelemetry/version.py b/opentelemetry-api/src/opentelemetry/version.py index 80d12781d3..168a28bae9 100644 --- a/opentelemetry-api/src/opentelemetry/version.py +++ b/opentelemetry-api/src/opentelemetry/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "1.18.0.dev" +__version__ = "1.19.0.dev" diff --git a/opentelemetry-proto/src/opentelemetry/proto/version.py b/opentelemetry-proto/src/opentelemetry/proto/version.py index 80d12781d3..168a28bae9 100644 --- a/opentelemetry-proto/src/opentelemetry/proto/version.py +++ b/opentelemetry-proto/src/opentelemetry/proto/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "1.18.0.dev" +__version__ = "1.19.0.dev" diff --git a/opentelemetry-sdk/pyproject.toml b/opentelemetry-sdk/pyproject.toml index 5be574f3a2..88f3ca8f01 100644 --- a/opentelemetry-sdk/pyproject.toml +++ b/opentelemetry-sdk/pyproject.toml @@ -26,8 +26,8 @@ classifiers = [ "Typing :: Typed", ] dependencies = [ - "opentelemetry-api == 1.18.0.dev", - "opentelemetry-semantic-conventions == 0.39b0.dev", + "opentelemetry-api == 1.19.0.dev", + "opentelemetry-semantic-conventions == 0.40b0.dev", "setuptools >= 16.0", "typing-extensions >= 3.7.4", ] diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py index a86fbaee0f..881bb9a4b2 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py @@ -18,6 +18,7 @@ Logger, LoggerProvider, LoggingHandler, + LogLimits, LogRecord, LogRecordProcessor, ) @@ -27,6 +28,7 @@ "Logger", "LoggerProvider", "LoggingHandler", + "LogLimits", "LogRecord", "LogRecordProcessor", ] diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py index eda9b093c9..7410138067 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py @@ -19,6 +19,7 @@ import logging import threading import traceback +from os import environ from time import time_ns from typing import Any, Callable, Optional, Tuple, Union @@ -31,6 +32,11 @@ get_logger_provider, std_to_otel, ) +from opentelemetry.attributes import BoundedAttributes +from opentelemetry.sdk.environment_variables import ( + OTEL_ATTRIBUTE_COUNT_LIMIT, + OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT, +) from opentelemetry.sdk.resources import Resource from opentelemetry.sdk.util import ns_to_iso_str from opentelemetry.sdk.util.instrumentation import InstrumentationScope @@ -45,6 +51,101 @@ _logger = logging.getLogger(__name__) +_DEFAULT_OTEL_ATTRIBUTE_COUNT_LIMIT = 128 +_ENV_VALUE_UNSET = "" + + +class LogLimits: + """This class is based on a SpanLimits class in the Tracing module. + + This class represents the limits that should be enforced on recorded data such as events, links, attributes etc. + + This class does not enforce any limits itself. It only provides a way to read limits from env, + default values and from user provided arguments. + + All limit arguments must be either a non-negative integer, ``None`` or ``LogLimits.UNSET``. + + - All limit arguments are optional. + - If a limit argument is not set, the class will try to read its value from the corresponding + environment variable. + - If the environment variable is not set, the default value, if any, will be used. + + Limit precedence: + + - If a model specific limit is set, it will be used. + - Else if the corresponding global limit is set, it will be used. + - Else if the model specific limit has a default value, the default value will be used. + - Else if the global limit has a default value, the default value will be used. + + Args: + max_attributes: Maximum number of attributes that can be added to a span, event, and link. + Environment variable: ``OTEL_ATTRIBUTE_COUNT_LIMIT`` + Default: {_DEFAULT_OTEL_ATTRIBUTE_COUNT_LIMIT} + max_attribute_length: Maximum length an attribute value can have. Values longer than + the specified length will be truncated. + """ + + UNSET = -1 + + def __init__( + self, + max_attributes: Optional[int] = None, + max_attribute_length: Optional[int] = None, + ): + + # attribute count + global_max_attributes = self._from_env_if_absent( + max_attributes, OTEL_ATTRIBUTE_COUNT_LIMIT + ) + self.max_attributes = ( + global_max_attributes + if global_max_attributes is not None + else _DEFAULT_OTEL_ATTRIBUTE_COUNT_LIMIT + ) + + # attribute length + self.max_attribute_length = self._from_env_if_absent( + max_attribute_length, + OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT, + ) + + def __repr__(self): + return f"{type(self).__name__}(max_attributes={self.max_attributes}, max_attribute_length={self.max_attribute_length})" + + @classmethod + def _from_env_if_absent( + cls, value: Optional[int], env_var: str, default: Optional[int] = None + ) -> Optional[int]: + if value == cls.UNSET: + return None + + err_msg = "{0} must be a non-negative integer but got {}" + + # if no value is provided for the limit, try to load it from env + if value is None: + # return default value if env var is not set + if env_var not in environ: + return default + + str_value = environ.get(env_var, "").strip().lower() + if str_value == _ENV_VALUE_UNSET: + return None + + try: + value = int(str_value) + except ValueError: + raise ValueError(err_msg.format(env_var, str_value)) + + if value < 0: + raise ValueError(err_msg.format(env_var, value)) + return value + + +_UnsetLogLimits = LogLimits( + max_attributes=LogLimits.UNSET, + max_attribute_length=LogLimits.UNSET, +) + class LogRecord(APILogRecord): """A LogRecord instance represents an event being logged. @@ -66,6 +167,7 @@ def __init__( body: Optional[Any] = None, resource: Optional[Resource] = None, attributes: Optional[Attributes] = None, + limits: Optional[LogLimits] = _UnsetLogLimits, ): super().__init__( **{ @@ -77,7 +179,12 @@ def __init__( "severity_text": severity_text, "severity_number": severity_number, "body": body, - "attributes": attributes, + "attributes": BoundedAttributes( + maxlen=limits.max_attributes, + attributes=attributes if bool(attributes) else None, + immutable=False, + max_value_len=limits.max_attribute_length, + ), } ) self.resource = resource @@ -93,7 +200,9 @@ def to_json(self, indent=4) -> str: "body": self.body, "severity_number": repr(self.severity_number), "severity_text": self.severity_text, - "attributes": self.attributes, + "attributes": dict(self.attributes) + if bool(self.attributes) + else None, "timestamp": ns_to_iso_str(self.timestamp), "trace_id": f"0x{format_trace_id(self.trace_id)}" if self.trace_id is not None @@ -109,6 +218,12 @@ def to_json(self, indent=4) -> str: indent=indent, ) + @property + def dropped_attributes(self) -> int: + if self.attributes: + return self.attributes.dropped + return 0 + class LogData: """Readable LogRecord data plus associated InstrumentationLibrary.""" diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/version.py b/opentelemetry-sdk/src/opentelemetry/sdk/version.py index 80d12781d3..168a28bae9 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/version.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "1.18.0.dev" +__version__ = "1.19.0.dev" diff --git a/opentelemetry-sdk/tests/logs/test_handler.py b/opentelemetry-sdk/tests/logs/test_handler.py index b9c40608e1..04cf5640f5 100644 --- a/opentelemetry-sdk/tests/logs/test_handler.py +++ b/opentelemetry-sdk/tests/logs/test_handler.py @@ -17,6 +17,7 @@ from opentelemetry._logs import SeverityNumber from opentelemetry._logs import get_logger as APIGetLogger +from opentelemetry.attributes import BoundedAttributes from opentelemetry.sdk import trace from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler from opentelemetry.semconv.trace import SpanAttributes @@ -91,6 +92,7 @@ def test_log_record_user_attributes(self): self.assertIsNotNone(log_record) self.assertEqual(log_record.attributes, {"http.status_code": 200}) + self.assertTrue(isinstance(log_record.attributes, BoundedAttributes)) def test_log_record_exception(self): """Exception information will be included in attributes""" diff --git a/opentelemetry-sdk/tests/logs/test_log_limits.py b/opentelemetry-sdk/tests/logs/test_log_limits.py new file mode 100644 index 0000000000..c2135b6569 --- /dev/null +++ b/opentelemetry-sdk/tests/logs/test_log_limits.py @@ -0,0 +1,40 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest + +from opentelemetry.sdk._logs import LogLimits +from opentelemetry.sdk._logs._internal import ( + _DEFAULT_OTEL_ATTRIBUTE_COUNT_LIMIT, +) + + +class TestLogLimits(unittest.TestCase): + def test_log_limits_repr_unset(self): + expected = f"LogLimits(max_attributes={_DEFAULT_OTEL_ATTRIBUTE_COUNT_LIMIT}, max_attribute_length=None)" + limits = str(LogLimits()) + + self.assertEqual(expected, limits) + + def test_log_limits_max_attributes(self): + expected = 1 + limits = LogLimits(max_attributes=1) + + self.assertEqual(expected, limits.max_attributes) + + def test_log_limits_max_attribute_length(self): + expected = 1 + limits = LogLimits(max_attribute_length=1) + + self.assertEqual(expected, limits.max_attribute_length) diff --git a/opentelemetry-sdk/tests/logs/test_log_record.py b/opentelemetry-sdk/tests/logs/test_log_record.py index 7142408c4c..a5993e5833 100644 --- a/opentelemetry-sdk/tests/logs/test_log_record.py +++ b/opentelemetry-sdk/tests/logs/test_log_record.py @@ -15,7 +15,8 @@ import json import unittest -from opentelemetry.sdk._logs import LogRecord +from opentelemetry.attributes import BoundedAttributes +from opentelemetry.sdk._logs import LogLimits, LogRecord class TestLogRecord(unittest.TestCase): @@ -39,3 +40,67 @@ def test_log_record_to_json(self): body="a log line", ).to_json() self.assertEqual(expected, actual) + + def test_log_record_bounded_attributes(self): + attr = {"key": "value"} + + result = LogRecord(timestamp=0, body="a log line", attributes=attr) + + self.assertTrue(isinstance(result.attributes, BoundedAttributes)) + + def test_log_record_dropped_attributes_empty_limits(self): + attr = {"key": "value"} + + result = LogRecord(timestamp=0, body="a log line", attributes=attr) + + self.assertTrue(result.dropped_attributes == 0) + + def test_log_record_dropped_attributes_set_limits_max_attribute(self): + attr = {"key": "value", "key2": "value2"} + limits = LogLimits( + max_attributes=1, + ) + + result = LogRecord( + timestamp=0, body="a log line", attributes=attr, limits=limits + ) + self.assertTrue(result.dropped_attributes == 1) + + def test_log_record_dropped_attributes_set_limits_max_attribute_length( + self, + ): + attr = {"key": "value", "key2": "value2"} + expected = {"key": "v", "key2": "v"} + limits = LogLimits( + max_attribute_length=1, + ) + + result = LogRecord( + timestamp=0, body="a log line", attributes=attr, limits=limits + ) + self.assertTrue(result.dropped_attributes == 0) + self.assertEqual(expected, result.attributes) + + def test_log_record_dropped_attributes_set_limits(self): + attr = {"key": "value", "key2": "value2"} + expected = {"key2": "v"} + limits = LogLimits( + max_attributes=1, + max_attribute_length=1, + ) + + result = LogRecord( + timestamp=0, body="a log line", attributes=attr, limits=limits + ) + self.assertTrue(result.dropped_attributes == 1) + self.assertEqual(expected, result.attributes) + + def test_log_record_dropped_attributes_unset_limits(self): + attr = {"key": "value", "key2": "value2"} + limits = LogLimits() + + result = LogRecord( + timestamp=0, body="a log line", attributes=attr, limits=limits + ) + self.assertTrue(result.dropped_attributes == 0) + self.assertEqual(attr, result.attributes) diff --git a/opentelemetry-semantic-conventions/src/opentelemetry/semconv/version.py b/opentelemetry-semantic-conventions/src/opentelemetry/semconv/version.py index eb62a67e28..87b20fddc3 100644 --- a/opentelemetry-semantic-conventions/src/opentelemetry/semconv/version.py +++ b/opentelemetry-semantic-conventions/src/opentelemetry/semconv/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "0.39b0.dev" +__version__ = "0.40b0.dev" diff --git a/propagator/opentelemetry-propagator-b3/src/opentelemetry/propagators/b3/version.py b/propagator/opentelemetry-propagator-b3/src/opentelemetry/propagators/b3/version.py index 80d12781d3..168a28bae9 100644 --- a/propagator/opentelemetry-propagator-b3/src/opentelemetry/propagators/b3/version.py +++ b/propagator/opentelemetry-propagator-b3/src/opentelemetry/propagators/b3/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "1.18.0.dev" +__version__ = "1.19.0.dev" diff --git a/propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/version.py b/propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/version.py index 80d12781d3..168a28bae9 100644 --- a/propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/version.py +++ b/propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "1.18.0.dev" +__version__ = "1.19.0.dev" diff --git a/shim/opentelemetry-opencensus-shim/pyproject.toml b/shim/opentelemetry-opencensus-shim/pyproject.toml index 43bef2fdd5..19b072b19a 100644 --- a/shim/opentelemetry-opencensus-shim/pyproject.toml +++ b/shim/opentelemetry-opencensus-shim/pyproject.toml @@ -34,7 +34,7 @@ dependencies = [ [project.optional-dependencies] test = [ - "opentelemetry-test-utils == 0.39b0.dev", + "opentelemetry-test-utils == 0.40b0.dev", "opencensus == 0.11.1", ] diff --git a/shim/opentelemetry-opencensus-shim/src/opentelemetry/shim/opencensus/version.py b/shim/opentelemetry-opencensus-shim/src/opentelemetry/shim/opencensus/version.py index eb62a67e28..87b20fddc3 100644 --- a/shim/opentelemetry-opencensus-shim/src/opentelemetry/shim/opencensus/version.py +++ b/shim/opentelemetry-opencensus-shim/src/opentelemetry/shim/opencensus/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "0.39b0.dev" +__version__ = "0.40b0.dev" diff --git a/shim/opentelemetry-opentracing-shim/pyproject.toml b/shim/opentelemetry-opentracing-shim/pyproject.toml index 6345b77d35..5ef3579520 100644 --- a/shim/opentelemetry-opentracing-shim/pyproject.toml +++ b/shim/opentelemetry-opentracing-shim/pyproject.toml @@ -33,7 +33,7 @@ dependencies = [ [project.optional-dependencies] test = [ - "opentelemetry-test-utils == 0.39b0.dev", + "opentelemetry-test-utils == 0.40b0.dev", "opentracing ~= 2.2.0", ] diff --git a/shim/opentelemetry-opentracing-shim/src/opentelemetry/shim/opentracing_shim/version.py b/shim/opentelemetry-opentracing-shim/src/opentelemetry/shim/opentracing_shim/version.py index eb62a67e28..87b20fddc3 100644 --- a/shim/opentelemetry-opentracing-shim/src/opentelemetry/shim/opentracing_shim/version.py +++ b/shim/opentelemetry-opentracing-shim/src/opentelemetry/shim/opentracing_shim/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "0.39b0.dev" +__version__ = "0.40b0.dev" diff --git a/tests/opentelemetry-test-utils/pyproject.toml b/tests/opentelemetry-test-utils/pyproject.toml index fb1c0915f4..41fc56244f 100644 --- a/tests/opentelemetry-test-utils/pyproject.toml +++ b/tests/opentelemetry-test-utils/pyproject.toml @@ -25,8 +25,8 @@ classifiers = [ ] dependencies = [ "asgiref ~= 3.0", - "opentelemetry-api == 1.18.0.dev", - "opentelemetry-sdk == 1.18.0.dev", + "opentelemetry-api == 1.19.0.dev", + "opentelemetry-sdk == 1.19.0.dev", ] [project.optional-dependencies] diff --git a/tests/opentelemetry-test-utils/src/opentelemetry/test/version.py b/tests/opentelemetry-test-utils/src/opentelemetry/test/version.py index 15f6e2a9b4..a4a2694c89 100644 --- a/tests/opentelemetry-test-utils/src/opentelemetry/test/version.py +++ b/tests/opentelemetry-test-utils/src/opentelemetry/test/version.py @@ -1 +1 @@ -__version__ = "0.39b0.dev" +__version__ = "0.40b0.dev"