Skip to content
Open
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
18 changes: 1 addition & 17 deletions src/instana/instrumentation/urllib3.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,23 +94,7 @@ def urlopen_with_instana(
tracer, parent_span, span_name = get_tracer_tuple()

# If we're not tracing, just return; boto3 has it's own visibility
# Also, skip creating spans for internal Instana calls when
# 'com.instana' appears in either the full URL, the path argument,
# or the connection host.
request_url_or_path = (
kwargs.get("request_url")
or kwargs.get("url")
or (args[1] if len(args) >= 2 else "")
or ""
)
host = getattr(instance, "host", "") or ""

if (
not tracer
or span_name == "boto3"
or "com.instana" in request_url_or_path
or "com.instana" in host
):
if not tracer or span_name == "boto3":
return wrapped(*args, **kwargs)

parent_context = parent_span.get_span_context() if parent_span else None
Expand Down
30 changes: 30 additions & 0 deletions src/instana/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,36 @@ def set_trace_configurations(self) -> None:

self.set_disable_trace_configurations()
self.set_stack_trace_configurations()
if "INSTANA_ALLOW_INTERNAL_SPANS" not in os.environ:
self.add_internal_span_filter()
Comment on lines +137 to +138
Copy link
Contributor

@GSVarsha GSVarsha Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @CagriYonca, the overall structure looks good to me!
But can you explain the significance of this block? Its a bit unclear to me

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've included this block in case the customer wants to see internal spans.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we aren't supposed to refer this as INTERNAL spans because that could mean the concept of INTERMEDIATE (neither ENTRY nor EXIT but useful/ interesting internal application code) spans. After some contemplating, I remember something that we discussed earlier about whether we should not capture those internal tracer calls at all (existing code) or capture these urllib3/ requests calls to the agent and filter later (this new code).

Although the latter looks more structured I think functionality-wise the earlier could be better because we might try to communicate to the agent multiple times and creating a span each time might be expensive and not something the end-user would be interested (to view with an env var like INSTANA_ALLOW_INTERNAL_SPANS ).

I would like to know the team's thoughts on this, TIA!


def add_internal_span_filter(self) -> None:
if "exclude" not in self.span_filters:
self.span_filters["exclude"] = []
self.span_filters["exclude"].extend(
[
{
"name": "filter-internal-spans-by-url",
"attributes": [
{
"key": "http.url",
"values": ["com.instana"],
"match_type": "contains",
}
],
},
{
"name": "filter-internal-spans-by-host",
"attributes": [
{
"key": "http.host",
"values": ["com.instana"],
"match_type": "contains",
}
],
},
]
)

def _apply_env_stack_trace_config(self) -> None:
"""Apply stack trace configuration from environment variables."""
Expand Down
17 changes: 11 additions & 6 deletions tests/clients/test_urllib3.py
Original file line number Diff line number Diff line change
Expand Up @@ -1006,12 +1006,15 @@ def test_internal_span_creation_with_url_in_hostname(self) -> None:

spans = self.recorder.queued_spans()

assert len(spans) == 1
assert len(spans) == 2

filtered_spans = agent.filter_spans(spans)
assert len(filtered_spans) == 1

test_span = spans[0]
test_span = filtered_spans[0]
assert test_span.data["sdk"]["name"] == "test"

urllib3_spans = [span for span in spans if span.n == "urllib3"]
urllib3_spans = [span for span in filtered_spans if span.n == "urllib3"]
assert len(urllib3_spans) == 0

def test_internal_span_creation_with_url_in_path(self) -> None:
Expand All @@ -1024,11 +1027,13 @@ def test_internal_span_creation_with_url_in_path(self) -> None:
pass

spans = self.recorder.queued_spans()
assert len(spans) == 2

assert len(spans) == 1
filtered_spans = agent.filter_spans(spans)
assert len(filtered_spans) == 1

test_span = spans[0]
test_span = filtered_spans[0]
assert test_span.data["sdk"]["name"] == "test"

urllib3_spans = [span for span in spans if span.n == "urllib3"]
urllib3_spans = [span for span in filtered_spans if span.n == "urllib3"]
assert len(urllib3_spans) == 0
1 change: 1 addition & 0 deletions tests/test_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class TestBaseOptions:
@pytest.fixture(autouse=True)
def _resource(self) -> Generator[None, None, None]:
self.base_options = None
os.environ["INSTANA_ALLOW_INTERNAL_SPANS"] = "True"
yield
if "tracing" in config.keys():
del config["tracing"]
Expand Down
Loading