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

Add support for span collection limit via env vars #1377

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
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ def setUp(self):
self._test_span = trace._Span("test_span", context=context)
self._test_span.start()
self._test_span.end()
# pylint: disable=protected-access
Configuration._reset()

def tearDown(self):
# pylint: disable=protected-access
Configuration._reset()

def test_constructor_default(self):
"""Test the default values assigned by constructor."""
Expand Down Expand Up @@ -142,8 +148,6 @@ def test_constructor_by_environment_variables(self):

environ_patcher.stop()

Configuration._reset()

def test_nsec_to_usec_round(self):
# pylint: disable=protected-access
nsec_to_usec_round = jaeger_exporter._nsec_to_usec_round
Expand Down
2 changes: 2 additions & 0 deletions opentelemetry-sdk/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
([#1440](https://github.com/open-telemetry/opentelemetry-python/pull/1440))
- Add `fields` to propagators
([#1374](https://github.com/open-telemetry/opentelemetry-python/pull/1374))
- Add support for OTEL_SPAN_{ATTRIBUTE_COUNT_LIMIT,EVENT_COUNT_LIMIT,LINK_COUNT_LIMIT}
([#1377](https://github.com/open-telemetry/opentelemetry-python/pull/1377))

## Version 0.16b0

Expand Down
19 changes: 11 additions & 8 deletions opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

from opentelemetry import context as context_api
from opentelemetry import trace as trace_api
from opentelemetry.configuration import Configuration
from opentelemetry.sdk import util
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import sampling
Expand All @@ -49,9 +50,11 @@

logger = logging.getLogger(__name__)

MAX_NUM_ATTRIBUTES = 1000
MAX_NUM_EVENTS = 1000
MAX_NUM_LINKS = 1000
SPAN_ATTRIBUTE_COUNT_LIMIT = Configuration().get(
"SPAN_ATTRIBUTE_COUNT_LIMIT", 1000
)
SPAN_EVENT_COUNT_LIMIT = Configuration().get("SPAN_EVENT_COUNT_LIMIT", 1000)
SPAN_LINK_COUNT_LIMIT = Configuration().get("SPAN_LINK_COUNT_LIMIT", 1000)
VALID_ATTR_VALUE_TYPES = (bool, str, int, float)


Expand Down Expand Up @@ -446,7 +449,7 @@ def __init__(
self.attributes = self._new_attributes()
else:
self.attributes = BoundedDict.from_map(
MAX_NUM_ATTRIBUTES, attributes
SPAN_ATTRIBUTE_COUNT_LIMIT, attributes
)

self.events = self._new_events()
Expand All @@ -462,7 +465,7 @@ def __init__(
if links is None:
self.links = self._new_links()
else:
self.links = BoundedList.from_seq(MAX_NUM_LINKS, links)
self.links = BoundedList.from_seq(SPAN_LINK_COUNT_LIMIT, links)

self._end_time = None # type: Optional[int]
self._start_time = None # type: Optional[int]
Expand All @@ -483,15 +486,15 @@ def __repr__(self):

@staticmethod
def _new_attributes():
return BoundedDict(MAX_NUM_ATTRIBUTES)
return BoundedDict(SPAN_ATTRIBUTE_COUNT_LIMIT)

@staticmethod
def _new_events():
return BoundedList(MAX_NUM_EVENTS)
return BoundedList(SPAN_EVENT_COUNT_LIMIT)

@staticmethod
def _new_links():
return BoundedList(MAX_NUM_LINKS)
return BoundedList(SPAN_LINK_COUNT_LIMIT)

@staticmethod
def _format_context(context):
Expand Down
50 changes: 50 additions & 0 deletions opentelemetry-sdk/tests/trace/test_trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@
import shutil
import subprocess
import unittest
from importlib import reload
from logging import ERROR, WARNING
from typing import Optional
from unittest import mock

import pytest

from opentelemetry import trace as trace_api
from opentelemetry.configuration import Configuration
from opentelemetry.context import Context
from opentelemetry.sdk import resources, trace
from opentelemetry.sdk.trace import Resource, sampling
Expand Down Expand Up @@ -1182,3 +1186,49 @@ def test_attributes_to_json(self):
+ date_str
+ '", "attributes": {"key2": "value2"}}], "links": [], "resource": {}}',
)


class TestSpanLimits(unittest.TestCase):
def setUp(self):
# reset global state of configuration object
# pylint: disable=protected-access
Configuration._reset()

def tearDown(self):
# reset global state of configuration object
# pylint: disable=protected-access
Configuration._reset()

@mock.patch.dict(
"os.environ",
{
"OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT": "10",
"OTEL_SPAN_EVENT_COUNT_LIMIT": "20",
"OTEL_SPAN_LINK_COUNT_LIMIT": "30",
},
)
def test_span_environment_limits(self):
reload(trace)
tracer = new_tracer()
ids_generator = trace_api.RandomIdsGenerator()
some_links = [
trace_api.Link(
trace_api.SpanContext(
trace_id=ids_generator.generate_trace_id(),
span_id=ids_generator.generate_span_id(),
is_remote=False,
)
)
for _ in range(100)
]
with pytest.raises(ValueError):
with tracer.start_as_current_span("root", links=some_links):
pass

with tracer.start_as_current_span("root") as root:
for idx in range(100):
root.set_attribute("my_attribute_{}".format(idx), 0)
root.add_event("my_event_{}".format(idx))

self.assertEqual(len(root.attributes), 10)
self.assertEqual(len(root.events), 20)