feat: Add Groq instrumentation package - #368
Conversation
Pull request dashboard statusClosed · refreshed 2026-08-09 19:26 UTC Status above doesn't look right?
|
There was a problem hiding this comment.
Pull request overview
Adds a new opentelemetry-instrumentation-genai-groq package to instrument the official Groq Python client (groq) in this monorepo, including tests (unit + conformance), VCR cassettes, and runnable examples, plus workspace/tox wiring.
Changes:
- Introduces a new Groq instrumentation package (instrumentor, patching, streaming wrappers, helpers).
- Adds Groq test suite (unit + conformance), VCR cassettes, and example apps (manual + zero-code).
- Wires the package into the repo’s workspace/lockfile and
toxenv matrix.
Reviewed changes
Copilot reviewed 36 out of 37 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| uv.lock | Adds the new Groq instrumentation package to the workspace lock and includes groq as a dependency. |
| tox.ini | Adds Groq test/lint/conformance envs and editable install wiring for the new package. |
| instrumentation/opentelemetry-instrumentation-genai-groq/pyproject.toml | Defines the new package metadata, dependencies, extras, and instrumentor entry point. |
| instrumentation/opentelemetry-instrumentation-genai-groq/README.rst | Documents installation, usage, content capture, and upload hook behavior for the new package. |
| instrumentation/opentelemetry-instrumentation-genai-groq/.changelog/313.added | Towncrier fragment announcing the new instrumentation package. |
| instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/init.py | Implements GroqInstrumentor and documents usage/configuration in the module docstring. |
| instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/package.py | Declares the instrumented library requirement string for the instrumentor. |
| instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/version.py | Adds the package version (1.0b0.dev). |
| instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/patch.py | Wraps Groq chat completions create/parse methods to create invocations and wrap streams. |
| instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/utils.py | Extracts request/response fields into util-genai invocation models and message/tool models. |
| instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/chat_wrappers.py | Adds sync/async stream wrappers built on util-genai stream wrappers to finalize telemetry on drain/close/error. |
| instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/chat_buffers.py | Buffers streamed content/tool-call fragments to build final output messages. |
| instrumentation/opentelemetry-instrumentation-genai-groq/tests/conftest.py | Sets up Groq clients, VCR scrubbing, and shared instrumentation fixtures for tests. |
| instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_chat_completions.py | Adds sync/async + streaming/non-streaming + error-path coverage for Groq chat completions. |
| instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_conformance.py | Runs scenario-based semantic-conventions conformance checks via weaver live-check. |
| instrumentation/opentelemetry-instrumentation-genai-groq/tests/init.py | Marks the Groq tests package. |
| instrumentation/opentelemetry-instrumentation-genai-groq/tests/conformance/init.py | Marks the conformance scenarios package. |
| instrumentation/opentelemetry-instrumentation-genai-groq/tests/conformance/inference.py | Adds a conformance scenario for a non-streaming chat completion (inference). |
| instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.oldest.txt | Adds oldest-factor test-only pin(s). |
| instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.latest.txt | Adds latest-factor test dependency list. |
| instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_basic.yaml | Adds a VCR cassette for basic sync chat completion. |
| instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_async_chat_completions_basic.yaml | Adds a VCR cassette for basic async chat completion. |
| instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_streaming.yaml | Adds a VCR cassette for sync streaming chat completion. |
| instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_async_chat_completions_streaming.yaml | Adds a VCR cassette for async streaming chat completion. |
| instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_provider_error.yaml | Adds a VCR cassette for a provider error path. |
| instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_caller_side_error.yaml | Adds a VCR cassette used by the caller-side error-in-stream test. |
| instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_stream_side_error.yaml | Adds a VCR cassette used by the stream-side error injection test. |
| instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/inference_conformance.yaml | Adds a VCR cassette for the inference conformance scenario. |
| instrumentation/opentelemetry-instrumentation-genai-groq/examples/zero-code/README.rst | Documents running Groq with opentelemetry-instrument (zero-code) for this package. |
| instrumentation/opentelemetry-instrumentation-genai-groq/examples/zero-code/main.py | Zero-code example app that calls Groq chat completions. |
| instrumentation/opentelemetry-instrumentation-genai-groq/examples/zero-code/requirements.txt | Dependencies for the zero-code example environment. |
| instrumentation/opentelemetry-instrumentation-genai-groq/examples/zero-code/.env | Example env vars for running the zero-code example. |
| instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/README.rst | Documents running Groq with manual SDK configuration and optional custom completion hook. |
| instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/main.py | Manual example wiring OTel SDK + instrumentor and calling Groq. |
| instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/custom_hook.py | Manual example demonstrating a programmatic CompletionHook. |
| instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/requirements.txt | Dependencies for the manual example environment. |
| instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/.env | Example env vars for running the manual example. |
Suppressed comments (4)
instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/patch.py:54
Error.typemust be a string (seeopentelemetry.util.genai.types.Error), but this passes an exception class. Passing the original exception lets the util deriveerror.typecorrectly and preserves the exception reference.
chat_invocation.fail(Error(type=type(error), message=str(error)))
instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/patch.py:91
Error.typemust be a string (seeopentelemetry.util.genai.types.Error), but this passes an exception class. Pass the original exception soinvocation.fail()can derive the correct low-cardinalityerror.type.
chat_invocation.fail(Error(type=type(error), message=str(error)))
raise
instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_chat_completions.py:72
- This assertion is non-deterministic (
GEN_AI_SYSTEMvsgen_ai.provider.name) and allows tests to pass even if the wrong attribute is emitted. Prefer asserting the exactgen_ai.provider.nameattribute for Groq spans.
instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_chat_completions.py:102 - This assertion is non-deterministic (
GEN_AI_SYSTEMvsgen_ai.provider.name) and allows tests to pass even if the wrong attribute is emitted. Prefer asserting the exactgen_ai.provider.nameattribute for Groq spans.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| import logging | ||
|
|
||
| from opentelemetry.util.genai.handler import TelemetryHandler | ||
| from opentelemetry.util.genai.invocation import ( | ||
| InferenceInvocation, | ||
| ) | ||
| from opentelemetry.util.genai.types import ( | ||
| Error, | ||
| ) | ||
|
|
||
| from .chat_wrappers import AsyncChatStreamWrapper, ChatStreamWrapper | ||
| from .utils import ( | ||
| _prepare_output_messages, | ||
| create_chat_invocation, | ||
| is_streaming, | ||
| ) | ||
|
|
||
| _logger = logging.getLogger(__name__) |
| result = wrapped(*args, **kwargs) | ||
| if hasattr(result, "parse"): | ||
| # result is of type LegacyAPIResponse, call parse to get the actual response | ||
| parsed_result = result.parse() | ||
| else: | ||
| parsed_result = result | ||
| if is_streaming(kwargs): | ||
| return ChatStreamWrapper( | ||
| parsed_result, chat_invocation, capture_content | ||
| ) |
| result = await wrapped(*args, **kwargs) | ||
| if hasattr(result, "parse"): | ||
| # result is of type LegacyAPIResponse, calling parse to get the actual response | ||
| parsed_result = result.parse() | ||
| else: | ||
| parsed_result = result | ||
| if is_streaming(kwargs): | ||
| return AsyncChatStreamWrapper( | ||
| parsed_result, chat_invocation, capture_content | ||
| ) |
| test-instrumentation-genai-anthropic-conformance: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-anthropic/tests/test_conformance.py --vcr-record=none {posargs} | ||
| lint-instrumentation-genai-anthropic: sh -c "cd instrumentation && ruff check opentelemetry-instrumentation-genai-anthropic" | ||
|
|
||
| test-instrumentation-genai-groq-{oldest,latest}: pytest --ignore={toxinidir}/instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_conformance.py {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-groq/tests {posargs} |
| assert ( | ||
| span.attributes.get(GEN_AI_SYSTEM) == "groq" | ||
| or span.attributes.get("gen_ai.provider.name") == "groq" | ||
| ) |
| See the `opentelemetry-util-genai README | ||
| <https://github.com/open-telemetry/opentelemetry-python-contrib/blob/main/util/opentelemetry-util-genai/README.rst>`_ | ||
| for the full list of GenAI configuration variables. |
|
I realized having two open PRs at the same time might be overwhelming to review. I am closing this feature PR for now so we can focus solely on getting the global test-matrix and linter fixes merged first in PR #313 . Once those infrastructure fixes are merged into main, I will reopen this PR so it's completely clean and easy to review. |
Description
Please include a summary of the change and which issue, if any, is fixed.
Include the motivation and context for the change.
Fixes # (issue)
Type of change
Please delete options that are not relevant.
How has this been tested?
Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. List any relevant details for your test
configuration.
Checklist
See CONTRIBUTING.md
for the style guide, changelog guidance, and more.