Skip to content
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
32 changes: 28 additions & 4 deletions src/instana/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,11 @@
# The precedence is as follows:
# environment variables > in-code configuration >
# > agent config (configuration.yaml) > default value
if any(k.startswith("INSTANA_TRACING_FILTER_") for k in os.environ):
# Check for new span filtering env vars
if any(
k.startswith("INSTANA_TRACING_FILTER_") and os.environ[k]
for k in os.environ
):
# Check for new span filtering env vars (only if at least one has a non-empty value)
parsed_filter = parse_filter_rules_env_vars()
if parsed_filter["exclude"] or parsed_filter["include"]:
self.span_filters = parsed_filter
Expand Down Expand Up @@ -387,14 +390,20 @@
f"Will also capture these custom headers: {self.extra_http_headers}"
)

def set_tracing(self, tracing: Dict[str, Any]) -> None:

Check failure on line 393 in src/instana/options.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 21 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=instana_python-sensor&issues=AZ70IZCm2oNuUBvrCF78&open=AZ70IZCm2oNuUBvrCF78&pullRequest=885
"""
Set tracing options from the agent config.
@param tracing: tracing configuration dictionary
@return: None
"""
if "filter" in tracing and not self.span_filters:
self.span_filters = parse_filter_rules(tracing["filter"])
if "filter" in tracing and not self._has_high_priority_span_filter_source():
parsed = parse_filter_rules(tracing["filter"])
for policy in ("exclude", "include"):
rules = parsed.get(policy, [])
if rules:
if policy not in self.span_filters:
self.span_filters[policy] = []
self.span_filters[policy].extend(rules)

if "kafka" in tracing:
if (
Expand Down Expand Up @@ -427,6 +436,21 @@
# Handle stack trace configuration from agent config
self.set_stack_trace_from_agent(tracing)

def _has_high_priority_span_filter_source(self) -> bool:
"""Return True if a higher-priority span filter source (env var, YAML, or in-code config)
has already been configured, in which case the agent-provided filter should be ignored."""
return (
any(
k.startswith("INSTANA_TRACING_FILTER_") and os.environ[k]
for k in os.environ
)
or "INSTANA_CONFIG_PATH" in os.environ
or (
isinstance(config.get("tracing"), dict)
and "filter" in config["tracing"]
)
)

def _should_apply_agent_global_config(self) -> bool:
"""Check if agent global config should be applied (lowest priority)."""
has_env_vars = (
Expand Down
74 changes: 70 additions & 4 deletions tests/test_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -689,8 +689,30 @@ def test_set_trace_configurations_by_agent_configuration(self) -> None:
self.base_options = StandardOptions()
self.base_options.set_tracing(test_tracing)

# set_tracing does not override span_filters when already set (has internal filters)
assert self.base_options.span_filters == {"exclude": INTERNAL_SPAN_FILTERS}
# Agent filter rules are appended after the internal filters (no high-priority source set).
agent_exclude = [
{
"name": "service1",
"suppression": True,
"attributes": [
{"key": "service", "values": ["service1"], "match_type": "strict"}
],
},
{
"name": "service2",
"suppression": True,
"attributes": [
{
"key": "method",
"values": ["method1", "method2"],
"match_type": "strict",
}
],
},
]
assert self.base_options.span_filters == {
"exclude": INTERNAL_SPAN_FILTERS + agent_exclude
}
assert self.base_options.kafka_trace_correlation

# Check disabled_spans list
Expand Down Expand Up @@ -908,7 +930,28 @@ def test_set_tracing(
}
self.standart_options.set_tracing(test_tracing)

assert self.standart_options.span_filters == {"exclude": INTERNAL_SPAN_FILTERS}
# Agent filter rules are appended after the internal filters (no high-priority source set).
expected_exclude = INTERNAL_SPAN_FILTERS + [
{
"name": "service1",
"suppression": True,
"attributes": [
{"key": "service", "values": ["service1"], "match_type": "strict"}
],
},
{
"name": "service2",
"suppression": True,
"attributes": [
{
"key": "method",
"values": ["method1", "method2"],
"match_type": "strict",
}
],
},
]
assert self.standart_options.span_filters == {"exclude": expected_exclude}
assert not self.standart_options.kafka_trace_correlation
assert (
"Binary header format for Kafka is deprecated. Please use string header format."
Expand Down Expand Up @@ -972,7 +1015,30 @@ def test_set_from(self) -> None:
self.standart_options.secrets_matcher == test_res_data["secrets"]["matcher"]
)
assert self.standart_options.secrets_list == test_res_data["secrets"]["list"]
assert self.standart_options.span_filters == {"exclude": INTERNAL_SPAN_FILTERS}
# Agent filter rules are appended after the internal filters.
agent_exclude = [
{
"name": "service1",
"suppression": True,
"attributes": [
{"key": "service", "values": ["service1"], "match_type": "strict"}
],
},
{
"name": "service2",
"suppression": True,
"attributes": [
{
"key": "method",
"values": ["method1", "method2"],
"match_type": "strict",
}
],
},
]
assert self.standart_options.span_filters == {
"exclude": INTERNAL_SPAN_FILTERS + agent_exclude
}

test_res_data2 = {
"extraHeaders": {"header1": "sample-match", "header2": ["sample", "list"]},
Expand Down
Loading