Skip to content

test: add FastStream integration test#2070

Merged
strawgate merged 2 commits into
mainfrom
docs/example-verification
Jul 13, 2026
Merged

test: add FastStream integration test#2070
strawgate merged 2 commits into
mainfrom
docs/example-verification

Conversation

@strawgate

@strawgate strawgate commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds an integration test for FastStream, the one documented integration that emits real spans but had no test coverage. It exercises FastStream's OpenTelemetry RedisTelemetryMiddleware against the in-memory TestRedisBroker (no real Redis) and asserts the publish/process message spans plus their OpenTelemetry messaging semantic-convention attributes — mirroring docs/integrations/event-streams/faststream.md.

Context

Came out of a cross-reference of every integration guide against the SDK's test suite (checking each doc's instrument_* call and span-name claims against what the tests actually assert). Result: the docs are well-rooted — of ~32 integrations with tests, all primary instrumentation methods and span-name claims match; the only genuine span-emitting integration with zero coverage was FastStream, which this fills.

Test plan

  • tests/otel_integrations/test_faststream.py passes deterministically (asserts span names + stable messaging attributes; skips the non-deterministic message IDs / timing metrics).
  • Adds faststream[redis] to the dev dependency group; test_redis.py / test_celery.py still pass with it installed.

Follow-ups

  • The remaining untested guides are either non-span-emitting (gunicorn delegates to the web-framework instrumentation; airflow/bigquery are native-OTel config) or LLM frameworks (magentic, mirascope, llamaindex) that would need recorded VCR cassettes — a natural follow-up.

Review in cubic

FastStream was the one documented integration with real span-emitting
instrumentation but no test coverage. Exercise its RedisTelemetryMiddleware
against the in-memory TestRedisBroker and assert the message spans and their
OTel messaging attributes, mirroring the docs example.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Added faststream[redis]>=0.5.0 to the development dependencies. Added an async integration test that configures FastStream Redis with OpenTelemetry middleware, registers handlers, publishes through TestRedisBroker, exports spans, checks expected span names, and validates Redis messaging semantic-convention attributes.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: adding a FastStream integration test.
Description check ✅ Passed The description is directly related to the FastStream test and dependency update.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/example-verification

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

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found across 3 files

Confidence score: 5/5

  • In tests/otel_integrations/test_faststream.py, the sorted({span['name'] for span in spans}) set-based assertion can mask duplicate span names, so a regression that emits extra spans could still pass and reduce test sensitivity; this is low merge risk but worth tightening by asserting counts (or avoiding set deduplication) before/soon after merge.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="tests/otel_integrations/test_faststream.py">

<violation number="1" location="tests/otel_integrations/test_faststream.py:42">
P3: The test is well-constructed and matches FastStream's actual OTel middleware behavior. One subtle maintainability concern: the test uses `sorted({span['name'] for span in spans})` with a set comprehension (line 39), which deduplicates span names. If the middleware were to accidentally emit duplicate span names (e.g., two `test-channel process` spans), the assertion would silently pass since sets collapse duplicates. Using a list comprehension would surface unexpected duplicates and make the assertion stricter: `sorted([span['name'] for span in spans])`.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

spans = exporter.exported_spans_as_dict()

# A publish and a process span for each channel the message flows through (plus the initial create).
assert sorted({span['name'] for span in spans}) == snapshot(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3: The test is well-constructed and matches FastStream's actual OTel middleware behavior. One subtle maintainability concern: the test uses sorted({span['name'] for span in spans}) with a set comprehension (line 39), which deduplicates span names. If the middleware were to accidentally emit duplicate span names (e.g., two test-channel process spans), the assertion would silently pass since sets collapse duplicates. Using a list comprehension would surface unexpected duplicates and make the assertion stricter: sorted([span['name'] for span in spans]).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tests/otel_integrations/test_faststream.py, line 42:

<comment>The test is well-constructed and matches FastStream's actual OTel middleware behavior. One subtle maintainability concern: the test uses `sorted({span['name'] for span in spans})` with a set comprehension (line 39), which deduplicates span names. If the middleware were to accidentally emit duplicate span names (e.g., two `test-channel process` spans), the assertion would silently pass since sets collapse duplicates. Using a list comprehension would surface unexpected duplicates and make the assertion stricter: `sorted([span['name'] for span in spans])`.</comment>

<file context>
@@ -0,0 +1,56 @@
+    spans = exporter.exported_spans_as_dict()
+
+    # A publish and a process span for each channel the message flows through (plus the initial create).
+    assert sorted({span['name'] for span in spans}) == snapshot(
+        [
+            'another-channel process',
</file context>
Suggested change
assert sorted({span['name'] for span in spans}) == snapshot(
assert sorted([span['name'] for span in spans]) == snapshot(

@strawgate strawgate enabled auto-merge (squash) July 13, 2026 12:39
@strawgate strawgate merged commit 65d5688 into main Jul 13, 2026
16 of 17 checks passed
@strawgate strawgate deleted the docs/example-verification branch July 13, 2026 12:45

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pyproject.toml`:
- Line 165: Update the FastStream dependency entry in pyproject.toml to include
the otel extra alongside redis, ensuring
faststream.redis.opentelemetry.RedisTelemetryMiddleware is available when
dependencies are installed while preserving the existing minimum version.

In `@tests/otel_integrations/test_faststream.py`:
- Around line 42-50: Update the span-name assertion to sort the full list of
span names directly instead of constructing a set, preserving duplicate
publish/process spans while retaining the existing snapshot comparison.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1e63e30e-08a0-42d7-bfd2-cd4143aa744e

📥 Commits

Reviewing files that changed from the base of the PR and between 2717a25 and ca2018d.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (2)
  • pyproject.toml
  • tests/otel_integrations/test_faststream.py
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • pydantic/logfire (manual)
  • pydantic/pydantic-ai (manual)
  • pydantic/pydantic (auto-detected)

Comment thread pyproject.toml
"sqlmodel>=0.0.15",
"mypy>=1.10.0",
"celery>=5.4.0",
"faststream[redis]>=0.5.0",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== pyproject references =="
rg -n "faststream(\[.*\])?>=|RedisTelemetryMiddleware|opentelemetry|faststream.redis" pyproject.toml tests src docs || true

echo
echo "== files mentioning RedisTelemetryMiddleware =="
rg -n "RedisTelemetryMiddleware" . || true

echo
echo "== list candidate files =="
fd -a "faststream" . || true
fd -a "pyproject.toml" . || true

Repository: pydantic/logfire

Length of output: 50372


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Focus on the files that can justify the dependency claim.
git ls-files | rg '(^|/)(pyproject\.toml|tests?/|docs?/).*' || true

echo
echo "== mentions of faststream in repo =="
rg -n "faststream" . || true

echo
echo "== mentions of RedisTelemetryMiddleware in repo =="
rg -n "RedisTelemetryMiddleware" . || true

Repository: pydantic/logfire

Length of output: 26920


🌐 Web query:

FastStream RedisTelemetryMiddleware first release opentelemetry 0.5.7

💡 Result:

The RedisTelemetryMiddleware component in FastStream is used for integrating OpenTelemetry tracing and metrics with the Redis broker [1][2][3]. While FastStream version 0.5.7 exists, it is not specifically identified as the first release of this middleware in available documentation [4]. The middleware is a standard part of the FastStream Redis integration and is used by passing an instance of it to the middlewares parameter when initializing a RedisBroker [2][3]. Key details regarding this component include: - Functionality: It provides telemetry for Redis operations, including support for custom tracer and meter providers [1][5]. - Usage: Developers typically initialize it within the RedisBroker configuration, for example: broker = RedisBroker(middlewares=(RedisTelemetryMiddleware(),)) [2][3]. - Evolution: FastStream has undergone significant changes in versions 0.6.x and 0.7.x, including updates to middleware handling and the removal of deprecated features (e.g., publisher/subscriber-level middlewares were removed in favor of broker-level or app-level usage in 0.7.0) [6][7][8]. If you are looking for the exact version where RedisTelemetryMiddleware was first introduced, it is recommended to review the pull requests and commit history on the official FastStream GitHub repository [9].

Citations:


🌐 Web query:

site:dummy.faststream.airt.ai 0.5 release opentelemetry faststream.redis.opentelemetry

💡 Result:

In FastStream version 0.5, OpenTelemetry support is integrated as a core feature, allowing for the collection and exporting of telemetry data such as traces across your messaging infrastructure [1][2]. While there is no specific, isolated package named faststream.redis.opentelemetry, OpenTelemetry functionality is provided through the base FastStream OpenTelemetry middleware [3]. Users can implement telemetry for Redis brokers by utilizing the standard FastStream OpenTelemetry integration, which is designed to work with supported brokers including Redis [2][4]. The 0.5 release cycle significantly expanded these observability capabilities, with documentation explicitly noting that by version 0.5.28, the planned OpenTelemetry features were completed [1]. You can access these tools by importing them from the faststream.opentelemetry module and applying them to your broker configurations [2][3].

Citations:


Add FastStream's otel extra. faststream[redis]>=0.5.0 doesn't cover faststream.redis.opentelemetry.RedisTelemetryMiddleware; the test needs the OpenTelemetry extra at install time.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pyproject.toml` at line 165, Update the FastStream dependency entry in
pyproject.toml to include the otel extra alongside redis, ensuring
faststream.redis.opentelemetry.RedisTelemetryMiddleware is available when
dependencies are installed while preserving the existing minimum version.

Comment on lines +42 to +50
assert sorted({span['name'] for span in spans}) == snapshot(
[
'another-channel process',
'another-channel publish',
'test-channel create',
'test-channel process',
'test-channel publish',
]
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve duplicate spans in the assertion.

The set comprehension discards multiplicity, so duplicate publish/process spans with the same name would still pass. Compare the sorted list directly.

Proposed fix
-    assert sorted({span['name'] for span in spans}) == snapshot(
+    assert sorted(span['name'] for span in spans) == snapshot(
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
assert sorted({span['name'] for span in spans}) == snapshot(
[
'another-channel process',
'another-channel publish',
'test-channel create',
'test-channel process',
'test-channel publish',
]
)
assert sorted(span['name'] for span in spans) == snapshot(
[
'another-channel process',
'another-channel publish',
'test-channel create',
'test-channel process',
'test-channel publish',
]
)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/otel_integrations/test_faststream.py` around lines 42 - 50, Update the
span-name assertion to sort the full list of span names directly instead of
constructing a set, preserving duplicate publish/process spans while retaining
the existing snapshot comparison.

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.

1 participant