Skip to content

Conversation

@boscoraju-snyk
Copy link
Contributor

@boscoraju-snyk boscoraju-snyk commented Nov 30, 2025

  • I have added tests that cover my changes.
  • If adding a new instrumentation or changing an existing one, I've added screenshots from some observability platform showing the change.
  • PR name follows conventional commits format: feat(instrumentation): ... or fix(instrumentation): ....
  • (If applicable) I have updated the documentation accordingly.

This PR fixes an issue where the gRPC exporter was not being initialised correctly when using insecure OTLP collectors. It now correctly handles different URL schemes (grpc://, grpcs://, and no scheme) for the OTLP collector endpoint, ensuring that the insecure flag is properly set during gRPC exporter initialisation and that the endpoint is parsed correctly.


Important

Fixes gRPC exporter initialization in init_spans_exporter() to correctly handle URL schemes and set the insecure flag, with tests added for verification.

  • Behavior:
    • Fixes gRPC exporter initialization in init_spans_exporter() in tracing.py to handle grpc://, grpcs://, and no scheme correctly.
    • Sets insecure flag based on URL scheme: grpc:// and no scheme are insecure, grpcs:// is secure.
  • Tests:
    • Adds TestInitSpansExporter in test_sdk_initialization.py to test init_spans_exporter() with various URL schemes.
    • Uses unittest.mock.patch to verify OTLPSpanExporter initialization parameters.
  • Misc:
    • Adds urlparse import in tracing.py for URL parsing.

This description was created by Ellipsis for 386ebc4. You can customize this summary. It will automatically update as commits are pushed.

Summary by CodeRabbit

  • Bug Fixes
    • Improved span exporter initialization to correctly handle HTTP, HTTPS, gRPC and gRPCS endpoints, normalize endpoints (trim whitespace, handle trailing slashes, add v1/traces), and support scheme-less endpoints.
  • Tests
    • Added tests validating endpoint parsing, exporter selection, normalization, and parameter handling across schemes.
  • Documentation
    • Added a descriptive docstring describing supported endpoint schemes and compatibility notes.

✏️ Tip: You can customize this high-level summary in your review settings.

@CLAassistant
Copy link

CLAassistant commented Nov 30, 2025

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link

coderabbitai bot commented Nov 30, 2025

Walkthrough

The PR changes init_spans_exporter to parse API endpoints and select HTTP or gRPC OTLP exporters based on URL scheme (http/https/grpc/grpcs or scheme-less), normalizing endpoints and insecure flags. It also adds tests validating scheme handling and endpoint normalization.

Changes

Cohort / File(s) Change Summary
Exporter selection logic
packages/traceloop-sdk/traceloop/sdk/tracing/tracing.py
Reworked init_spans_exporter to parse the API endpoint with urlparse and dispatch by scheme: http/https → HTTP exporter with /v1/traces normalization; grpc → gRPC exporter using netloc, insecure=True; grpcs → gRPC exporter, insecure=False; no scheme → default to insecure gRPC using trimmed input. Added docstring.
URL scheme tests
packages/traceloop-sdk/tests/test_sdk_initialization.py
Added TestInitSpansExporter with parameterized tests: test_http_schemes, test_http_endpoint_construction, and test_grpc_schemes. Tests validate HTTP(S) normalization, gRPC/grpcs handling, trimming/whitespace, and mock OTLPSpanExporter.__init__ to assert endpoint, headers, and insecure arguments. Added patch import for mocking.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant init_spans_exporter
    participant urlparse
    participant HTTPExporter
    participant GRPCExporter

    Client->>init_spans_exporter: init_spans_exporter(api_endpoint, headers)
    init_spans_exporter->>urlparse: parse(api_endpoint)
    urlparse-->>init_spans_exporter: parsed(scheme, netloc, path)

    alt scheme is http or https
        init_spans_exporter->>HTTPExporter: instantiate(endpoint=normalized+"/v1/traces", headers)
        HTTPExporter-->>init_spans_exporter: return OTLPSpanExporter
    else scheme is grpc
        init_spans_exporter->>GRPCExporter: instantiate(endpoint=netloc, headers, insecure=true)
        GRPCExporter-->>init_spans_exporter: return OTLPSpanExporter
    else scheme is grpcs
        init_spans_exporter->>GRPCExporter: instantiate(endpoint=netloc, headers, insecure=false)
        GRPCExporter-->>init_spans_exporter: return OTLPSpanExporter
    else no scheme
        init_spans_exporter->>GRPCExporter: instantiate(endpoint=trimmed_input, headers, insecure=true)
        GRPCExporter-->>init_spans_exporter: return OTLPSpanExporter
    end

    init_spans_exporter-->>Client: SpanExporter instance
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Review focus:
    • tracing.py: scheme matching, trimming, /v1/traces normalization, and netloc extraction (ports/credentials).
    • Tests: correctness of mocked OTLPSpanExporter.__init__ assertions and coverage of whitespace/case variants.

Possibly related issues

Poem

🐰 I nibbled at endpoints, neat and spry,

http or grpc — I'll give it a try.
I trim the spaces, add v1 with care,
flag insecure when the scheme is bare.
Hop, trace, deliver — logs float on the air.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main fix: enabling correct gRPC exporter initialization with insecure OTLP by properly parsing URL schemes and setting the insecure flag.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@LeHyperion
Copy link

Hi @nirga, could you please take a look at this PR when you have a moment? Thanks!

@nirga
Copy link
Member

nirga commented Dec 1, 2025

Thanks @boscoraju-snyk & @LeHyperion - can you change the PR to ready for review and sign the CLA?

@boscoraju-snyk boscoraju-snyk marked this pull request as ready for review December 1, 2025 18:20
@boscoraju-snyk
Copy link
Contributor Author

Thanks @boscoraju-snyk & @LeHyperion - can you change the PR to ready for review and sign the CLA?

Sure!

Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed everything up to 386ebc4 in 2 minutes and 18 seconds. Click for details.
  • Reviewed 106 lines of code in 2 files
  • Skipped 0 files when reviewing.
  • Skipped posting 3 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. packages/traceloop-sdk/tests/test_sdk_initialization.py:15
  • Draft comment:
    The parameterized tests for init_spans_exporter are clear and comprehensive, covering both HTTP and gRPC URL formats (with case-insensitive schemes and whitespace).
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
2. packages/traceloop-sdk/traceloop/sdk/tracing/tracing.py:315
  • Draft comment:
    When constructing the HTTP exporter endpoint (appending '/v1/traces'), consider handling potential trailing slashes to avoid double slashes in the URL.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 40% vs. threshold = 50% The comment is about code that was changed in the diff (the HTTP exporter endpoint construction). The suggestion to use .rstrip('/') is reasonable and would prevent double slashes. However, I need to consider: 1) Is this actually a problem? Double slashes in URL paths are typically normalized by HTTP clients and shouldn't cause issues. 2) Is this an edge case that's unlikely to occur? 3) The comment is making a suggestion for code quality improvement, which according to the rules is good if actionable and clear. The suggestion is clear and actionable. But is it necessary? Most HTTP libraries handle double slashes gracefully. This feels like a minor code quality suggestion rather than a critical bug. While double slashes might look inelegant, most HTTP clients and servers handle them correctly by normalizing the path. This might be an overly cautious suggestion that doesn't address a real problem. The comment also doesn't provide evidence that this is actually causing issues or that users commonly pass endpoints with trailing slashes. Even if HTTP clients handle double slashes, it's still better practice to construct clean URLs. The fix is trivial (adding .rstrip('/')) and prevents potential edge cases. The comment is actionable, clear, and improves code quality without being overly pedantic. It's a reasonable defensive programming practice. This is a reasonable code quality suggestion that's actionable and clear. While double slashes may not cause actual failures, preventing them is a simple improvement. However, without evidence that this is a real problem users face, it's borderline whether this meets the threshold of "clearly a code change required."
3. packages/traceloop-sdk/traceloop/sdk/tracing/tracing.py:313
  • Draft comment:
    The match/case logic clearly differentiates URL schemes and correctly defaults empty/unsupported schemes to insecure gRPC. Ensure this behavior remains documented and tested.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None

Workflow ID: wflow_vt3HGnwuy9K8zxsH

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
packages/traceloop-sdk/traceloop/sdk/tracing/tracing.py (1)

294-330: Consider adding URL validation and error handling.

The function doesn't validate whether the parsed URL is well-formed or handle potential parsing errors. While urlparse is generally permissive, it's good practice to validate critical inputs, especially for security-sensitive configuration like endpoint URLs.

Consider adding validation:

 def init_spans_exporter(api_endpoint: str, headers: Dict[str, str]) -> SpanExporter:
     """
     Initialize a span exporter based on the endpoint URL scheme.
 
     Supported schemes:
         - http:// or https:// → HTTP exporter
         - grpc:// → gRPC exporter (insecure)
         - grpcs:// → gRPC exporter (secure/TLS)
         - No scheme → gRPC exporter (insecure, for backward compatibility)
 
     Args:
         api_endpoint: The endpoint URL (with or without scheme)
         headers: Headers to include with the exporter requests
 
     Returns:
         SpanExporter: Configured HTTP or gRPC exporter
+
+    Raises:
+        ValueError: If the endpoint URL is invalid
     """
+    if not api_endpoint or not api_endpoint.strip():
+        raise ValueError("api_endpoint cannot be empty")
+    
     parsed = urlparse(api_endpoint.strip())
+    
+    # Validate netloc is present for schemes that require it
+    if parsed.scheme in ("http", "https", "grpc", "grpcs") and not parsed.netloc:
+        raise ValueError(f"Invalid endpoint URL: {api_endpoint}")
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between bc97e56 and 386ebc4.

📒 Files selected for processing (2)
  • packages/traceloop-sdk/tests/test_sdk_initialization.py (2 hunks)
  • packages/traceloop-sdk/traceloop/sdk/tracing/tracing.py (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Store API keys only in environment variables/secure vaults; never hardcode secrets in code
Use Flake8 for code linting and adhere to its rules

Files:

  • packages/traceloop-sdk/tests/test_sdk_initialization.py
  • packages/traceloop-sdk/traceloop/sdk/tracing/tracing.py
🧬 Code graph analysis (1)
packages/traceloop-sdk/tests/test_sdk_initialization.py (1)
packages/traceloop-sdk/traceloop/sdk/tracing/tracing.py (1)
  • init_spans_exporter (294-330)
🔇 Additional comments (4)
packages/traceloop-sdk/traceloop/sdk/tracing/tracing.py (2)

4-4: LGTM!

The import of urlparse is appropriate for parsing endpoint URLs and determining the scheme.


313-330: No action needed—Python version requirement is already satisfied.

The project requires Python >= 3.10, which fully supports the match/case syntax. This code change is compatible with the project's minimum supported Python version and does not introduce any compatibility issues.

Likely an incorrect or invalid review comment.

packages/traceloop-sdk/tests/test_sdk_initialization.py (2)

2-2: LGTM!

The patch import is appropriately used for mocking the gRPC exporter initialization in the tests.


25-39: LGTM!

The test provides comprehensive coverage of gRPC endpoint handling:

  • Tests both grpc:// and grpcs:// schemes
  • Verifies case-insensitive scheme handling
  • Tests whitespace trimming
  • Verifies the default behavior for endpoints without a scheme (backward compatibility)
  • Correctly validates that netloc is extracted and the insecure flag is set appropriately

…p#3480)

fix(sdk): ensures correct HTTP endpoint construction
@boscoraju-snyk
Copy link
Contributor Author

@nirga Could you please take another look at this when you have a moment?

Copy link
Member

@nirga nirga left a comment

Choose a reason for hiding this comment

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

@nirga
Copy link
Member

nirga commented Dec 2, 2025

@boscoraju-snyk - can you fix the lint issues?

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/traceloop-sdk/tests/test_sdk_initialization.py (1)

2-38: HTTP exporter tests look good; wrap patch/assert lines to satisfy Flake8

The HTTP tests nicely cover scheme handling, endpoint normalization (/v1/traces, trailing slash, whitespace) and type selection, and they correctly patch OTLPSpanExporter.__init__ to assert the constructed endpoint and headers. To avoid Flake8 line-length violations in the with patch.object and assert_called_once_with lines, consider breaking them like this:

-        with patch.object(OTLPSpanExporter, "__init__", return_value=None) as mock:
-            init_spans_exporter(endpoint, {})
-            mock.assert_called_once_with(endpoint=expected_endpoint, headers={})
+        with patch.object(
+            OTLPSpanExporter,
+            "__init__",
+            return_value=None,
+        ) as mock:
+            init_spans_exporter(endpoint, {})
+            mock.assert_called_once_with(
+                endpoint=expected_endpoint,
+                headers={},
+            )

This keeps behavior the same while making the tests lint‑friendly.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 8fcdfca and 6428155.

📒 Files selected for processing (1)
  • packages/traceloop-sdk/tests/test_sdk_initialization.py (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Store API keys only in environment variables/secure vaults; never hardcode secrets in code
Use Flake8 for code linting and adhere to its rules

Files:

  • packages/traceloop-sdk/tests/test_sdk_initialization.py
🧬 Code graph analysis (1)
packages/traceloop-sdk/tests/test_sdk_initialization.py (1)
packages/traceloop-sdk/traceloop/sdk/tracing/tracing.py (1)
  • init_spans_exporter (294-333)

@boscoraju-snyk
Copy link
Contributor Author

boscoraju-snyk commented Dec 2, 2025

@boscoraju-snyk - can you fix the lint issues?

@nirga Sure, I have resolved the lint issues now.

@nirga nirga merged commit f782741 into traceloop:main Dec 3, 2025
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants