-
Notifications
You must be signed in to change notification settings - Fork 3
Dev #46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dev #46
Conversation
Release/09 06 2025
[Feature] Release for Auto Instrumentation of Google ADK
WalkthroughThis update introduces new Python and TypeScript instrumentation packages and configuration files targeting AI observability and tracing. It adds OpenTelemetry-based tracing for Google ADK in Python, including instrumentor classes, wrappers, documentation, and example scripts. In TypeScript, the update refines project structure, adds changelogs, documentation, and modular TypeScript configuration files, and updates dependencies and supported versions across core, semantic conventions, OpenAI, Anthropic, and LangChain instrumentation packages. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant ExampleScript
participant TraceAIInstrumentor
participant GoogleADKAgent
participant GoogleADKRunner
participant OpenTelemetryTracer
participant ObservePlatform
User->>ExampleScript: Run instrumented example
ExampleScript->>TraceAIInstrumentor: Register and apply instrumentation
TraceAIInstrumentor->>GoogleADKAgent: Patch async methods for tracing
ExampleScript->>GoogleADKRunner: Create and run agent session
GoogleADKRunner->>OpenTelemetryTracer: Start span for run_async
GoogleADKAgent->>OpenTelemetryTracer: Start span for agent actions
OpenTelemetryTracer->>ObservePlatform: Export trace data
GoogleADKRunner-->>ExampleScript: Emit events and final response
ExampleScript->>User: Print response
Poem
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 17
🧹 Nitpick comments (22)
python/frameworks/google-adk/traceai_google_adk/version.py (1)
1-1: Single-source the version to avoid driftHard-coding the version string here duplicates the value already declared in
pyproject.toml. In practice one of the two places is forgotten during the next bump and the values diverge.Consider generating
__version__fromimportlib.metadata.version(__package__), or import the value from this file insidepyproject.tomlviapoetry-dynamic-versioning/setuptools-scmto keep a single source of truth.python/frameworks/google-adk/pyproject.toml (2)
1-6: Package metadata is inconsistent (name ↔︎ description)The package is named
traceAI-google-adkbut the description still says “Instrumentation for Anthropic”. Copy/paste artefact? Update the description so users browsing PyPI immediately know it targets Google-ADK.-description = "OpenTelemetry instrumentation for Anthropic" +description = "OpenTelemetry instrumentation for Google ADK"
12-17: Tight-pinning third-party libs hampers downstream users
google-adk = ">= 1.2.1"is flexible, but
fi-instrumentation-otel = "0.1.7"is hard-pinned. Unless you rely on an exact bug-fix release, prefer a compatible range (^0.1.7) so you automatically receive backward-compatible patches.Also double-check whether
google-genaialready depends on a narrower version ofgoogle-adkto avoid resolver conflicts.python/frameworks/google-adk/README.md (3)
10-16: Missing comma after “example” – minor readability nit“In this example we will instrument …”
Add a comma after example:
-In this example we will instrument +In this example, we will instrument🧰 Tools
🪛 LanguageTool
[typographical] ~10-~10: It appears that a comma is missing.
Context: ...or Google ADK. ## Quickstart In this example we will instrument a small program that...(DURING_THAT_TIME_COMMA)
20-33: Sample imports include unused exporters/processors
OTLPSpanExporter,ConsoleSpanExporter, andSimpleSpanProcessorare imported in the snippet but never used, which may confuse readers and encourages copy-pasting unused code.Either wire them into the example or drop the imports to keep the quick-start minimal.
105-109: Article missing before “Future AGI Platform”“send the traces to Future AGI Platform”
Kings-English: “to the Future AGI Platform”
🧰 Tools
🪛 LanguageTool
[uncategorized] ~105-~105: You might be missing the article “the” here.
Context: ...n the python file to send the traces to Future AGI Platform. ```shell python your_fil...(AI_EN_LECTOR_MISSING_DETERMINER_THE)
python/frameworks/google-adk/examples/testing_google_adk.py (1)
32-44: Eliminate the unnecessaryelseafterreturnAfter the early return the
elseblock is redundant. Micro-refactor for clarity:- else: - return { - "status": "error", - "error_message": f"Weather information for '{city}' is not available.", - } + return { + "status": "error", + "error_message": f"Weather information for '{city}' is not available.", + }🧰 Tools
🪛 Pylint (3.3.7)
[refactor] 32-44: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it
(R1705)
python/frameworks/google-adk/traceai_google_adk/__init__.py (1)
89-101: Remove duplicate imports.The
base_llm_flowmodule is imported twice in this method.def _unpatch_trace_call_llm(self) -> None: """Restore the original LLM call tracing functionality.""" from google.adk.flows.llm_flows import base_llm_flow if callable( original := getattr(base_llm_flow.trace_call_llm, "__wrapped__"), # type: ignore[attr-defined] ): - from google.adk.flows.llm_flows import ( - base_llm_flow, - ) - setattr(base_llm_flow, "trace_call_llm", original)🧰 Tools
🪛 Ruff (0.11.9)
94-94: Do not call
getattrwith a constant attribute value. It is not any safer than normal property access.Replace
getattrwith attribute access(B009)
100-100: Do not call
setattrwith a constant attribute value. It is not any safer than normal property access.Replace
setattrwith assignment(B010)
🪛 Pylint (3.3.7)
[error] 91-91: No name 'adk' in module 'google'
(E0611)
[error] 96-98: No name 'adk' in module 'google'
(E0611)
python/frameworks/google-adk/traceai_google_adk/_wrappers.py (3)
147-163: Consider capturing input values for agent runs.Unlike
_RunnerRunAsync, this wrapper doesn't capture input arguments. Consider adding input value capture for better observability.Add input value capture after line 163:
arguments = bind_args_kwargs(wrapped, *args, **kwargs) try: attributes[SpanAttributes.INPUT_VALUE] = json.dumps( arguments, default=_default, ensure_ascii=False, ) attributes[SpanAttributes.INPUT_MIME_TYPE] = FiMimeTypeValues.JSON.value except Exception: logger.exception(f"Failed to get attribute: {SpanAttributes.INPUT_VALUE}.")🧰 Tools
🪛 Pylint (3.3.7)
[refactor] 147-147: Too few public methods (1/2)
(R0903)
268-271: Address TODO for list type system instructions.The TODO comment indicates missing implementation for handling list-type system instructions.
Would you like me to implement the handling for list-type system instructions or create an issue to track this?
328-341: Simplify nested conditional.The nested if statements can be combined for better readability.
- if event := next((arg for arg in arguments.values() if isinstance(arg, Event)), None): - if responses := event.get_function_responses(): + if (event := next((arg for arg in arguments.values() if isinstance(arg, Event)), None)) and (responses := event.get_function_responses()): try: span.set_attribute( SpanAttributes.OUTPUT_VALUE, responses[0].model_dump_json(exclude_none=True), ) span.set_attribute( SpanAttributes.OUTPUT_MIME_TYPE, FiMimeTypeValues.JSON.value, ) except Exception: logger.exception(f"Failed to get attribute in {wrapped.__name__}.")🧰 Tools
🪛 Ruff (0.11.9)
328-329: Use a single
ifstatement instead of nestedifstatements(SIM102)
typescript/packages/fi-semantic-conventions/README.md (1)
1-17: Installation instructions are clear.
The README provides concise npm/yarn/pnpm commands.
Consider adding a basic usage example (e.g., code snippet demonstrating attribute import and application) and repository badges (npm version, build status) to improve discoverability and developer experience.typescript/packages/traceai_anthropic/package.json (1)
29-30: Dependency ranges should target the latest release.
You’ve pinned@traceai/fi-coreto^0.1.10, but the core package is now at0.1.11. While^0.1.10will pull in0.1.11, consider updating it to^0.1.11for clarity, or confirm that your CI matrix tests against the latest core.typescript/packages/fi-semantic-conventions/tsconfig.json (2)
7-7: Consider removing the emptyfilesarray
An empty"files": []can be omitted since"include"covers file matching. Removing it reduces clutter.
9-9: Reviewreferencesusage
An empty"references": []is a no-op; if project references aren't needed, you can remove this field. Otherwise, populate it for composite projects.typescript/packages/traceai_openai/tsconfig.json (1)
7-10: Optional: Clean up empty fields
Since"files"and"references"are empty and you’re using"include", you may remove them to reduce noise.typescript/packages/traceai_langchain/tsconfig.json (1)
7-10: Optional cleanup
Empty"files"and"references"entries can be removed for clarity when not used.typescript/packages/fi-core/package.json (1)
2-27: Optional: Addlicensefield
It’s good practice to include a"license"property inpackage.jsonto explicitly declare the package license.typescript/packages/traceai_openai/examples/manual.ts (4)
3-4: Combine imports from the same module.Multiple imports from
@traceai/fi-corecan be combined into a single import statement for better readability.-import { register } from "@traceai/fi-core"; -import { ProjectType } from "@traceai/fi-core"; +import { register, ProjectType } from "@traceai/fi-core";
10-10: Consider making the diagnostic log level configurable.The DEBUG log level is hardcoded, which might be too verbose for some use cases. Consider making it configurable via environment variables to demonstrate best practices.
-diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG); +const logLevel = process.env.OTEL_LOG_LEVEL || 'INFO'; +const diagLogLevel = DiagLogLevel[logLevel as keyof typeof DiagLogLevel] || DiagLogLevel.INFO; +diag.setLogger(new DiagConsoleLogger(), diagLogLevel);
45-45: Add type annotations for function parameters.The function parameter
promptlacks explicit type annotation. While TypeScript can infer it, explicit types improve code clarity and maintainability.-async function enhancedTextGeneration(prompt: string) { +async function enhancedTextGeneration(prompt: string): Promise<OpenAI.Chat.Completions.ChatCompletion> {
244-244: Add return type annotation for consistency.-async function testInstrumentation() { +async function testInstrumentation(): Promise<void> {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
python/frameworks/google-adk/poetry.lockis excluded by!**/*.locktypescript/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (39)
python/frameworks/google-adk/.venv/pyvenv.cfg(1 hunks)python/frameworks/google-adk/README.md(1 hunks)python/frameworks/google-adk/examples/testing_google_adk.py(1 hunks)python/frameworks/google-adk/pyproject.toml(1 hunks)python/frameworks/google-adk/traceai_google_adk/__init__.py(1 hunks)python/frameworks/google-adk/traceai_google_adk/_wrappers.py(1 hunks)python/frameworks/google-adk/traceai_google_adk/version.py(1 hunks)typescript/packages/fi-core/CHANGELOG.md(1 hunks)typescript/packages/fi-core/README.md(1 hunks)typescript/packages/fi-core/package.json(2 hunks)typescript/packages/fi-core/tsconfig.esm.json(1 hunks)typescript/packages/fi-core/tsconfig.esnext.json(1 hunks)typescript/packages/fi-core/tsconfig.json(1 hunks)typescript/packages/fi-semantic-conventions/CHANGELOG.md(1 hunks)typescript/packages/fi-semantic-conventions/README.md(1 hunks)typescript/packages/fi-semantic-conventions/package.json(1 hunks)typescript/packages/fi-semantic-conventions/tsconfig.esm.json(1 hunks)typescript/packages/fi-semantic-conventions/tsconfig.esnext.json(1 hunks)typescript/packages/fi-semantic-conventions/tsconfig.json(1 hunks)typescript/packages/traceai_anthropic/CHANGELOG.md(1 hunks)typescript/packages/traceai_anthropic/package.json(2 hunks)typescript/packages/traceai_anthropic/tsconfig.esm.json(1 hunks)typescript/packages/traceai_anthropic/tsconfig.esnext.json(1 hunks)typescript/packages/traceai_anthropic/tsconfig.json(1 hunks)typescript/packages/traceai_langchain/tsconfig.esm.json(1 hunks)typescript/packages/traceai_langchain/tsconfig.esnext.json(1 hunks)typescript/packages/traceai_langchain/tsconfig.json(1 hunks)typescript/packages/traceai_openai/CHANGELOG.md(1 hunks)typescript/packages/traceai_openai/examples/manual.ts(1 hunks)typescript/packages/traceai_openai/package.json(3 hunks)typescript/packages/traceai_openai/src/instrumentation.ts(1 hunks)typescript/packages/traceai_openai/tsconfig.esm.json(1 hunks)typescript/packages/traceai_openai/tsconfig.esnext.json(1 hunks)typescript/packages/traceai_openai/tsconfig.json(1 hunks)typescript/tsconfig.base.es5.json(1 hunks)typescript/tsconfig.base.esm.json(1 hunks)typescript/tsconfig.base.esnext.json(1 hunks)typescript/tsconfig.base.json(1 hunks)typescript/tsconfig.json(0 hunks)
💤 Files with no reviewable changes (1)
- typescript/tsconfig.json
🧰 Additional context used
🧬 Code Graph Analysis (2)
python/frameworks/google-adk/examples/testing_google_adk.py (1)
python/frameworks/google-adk/traceai_google_adk/__init__.py (1)
GoogleADKInstrumentor(22-174)
python/frameworks/google-adk/traceai_google_adk/__init__.py (1)
python/frameworks/google-adk/traceai_google_adk/_wrappers.py (5)
_BaseAgentRunAsync(147-190)_RunnerRunAsync(78-144)wrapper(347-351)_TraceCallLlm(193-283)_TraceToolCall(286-341)
🪛 Biome (1.9.4)
typescript/tsconfig.base.json
[error] 3-3: JSON standard does not allow comments.
(parse)
[error] 5-5: JSON standard does not allow comments.
(parse)
[error] 6-6: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 6-6: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 6-6: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 6-6: JSON standard does not allow comments.
(parse)
[error] 7-7: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 7-7: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 7-7: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 7-7: JSON standard does not allow comments.
(parse)
[error] 13-13: JSON standard does not allow comments.
(parse)
[error] 14-14: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 14-14: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 14-14: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 14-14: JSON standard does not allow comments.
(parse)
[error] 15-15: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 15-15: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 15-17: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 17-17: JSON standard does not allow comments.
(parse)
[error] 29-29: JSON standard does not allow comments.
(parse)
[error] 30-30: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 30-30: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 30-30: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 30-30: JSON standard does not allow comments.
(parse)
[error] 48-48: JSON standard does not allow comments.
(parse)
[error] 53-53: JSON standard does not allow comments.
(parse)
[error] 54-54: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 54-54: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 54-54: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 54-54: JSON standard does not allow comments.
(parse)
[error] 55-55: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 55-55: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 55-55: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 55-55: JSON standard does not allow comments.
(parse)
[error] 57-57: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 57-57: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 57-57: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 57-57: JSON standard does not allow comments.
(parse)
[error] 78-78: JSON standard does not allow comments.
(parse)
[error] 82-82: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 82-82: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 82-82: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 82-82: JSON standard does not allow comments.
(parse)
[error] 84-84: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 84-84: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 84-84: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 84-84: JSON standard does not allow comments.
(parse)
[error] 86-86: JSON standard does not allow comments.
(parse)
[error] 87-87: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 87-87: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 87-87: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 87-87: JSON standard does not allow comments.
(parse)
[error] 107-107: JSON standard does not allow comments.
(parse)
[error] 109-109: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 109-109: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 109-109: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 109-109: JSON standard does not allow comments.
(parse)
[error] 111-111: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 111-111: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 111-111: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 111-112: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
typescript/tsconfig.base.esnext.json
[error] 5-5: Expected a property but instead found '// target should be aligned with tsconfig.base.json'.
Expected a property here.
(parse)
[error] 6-6: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 6-6: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 6-6: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 6-6: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 7-7: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 7-7: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 7-7: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
[error] 8-9: End of file expected
Use an array for a sequence of values: [1, 2]
(parse)
🪛 LanguageTool
python/frameworks/google-adk/README.md
[typographical] ~10-~10: It appears that a comma is missing.
Context: ...or Google ADK. ## Quickstart In this example we will instrument a small program that...
(DURING_THAT_TIME_COMMA)
[uncategorized] ~105-~105: You might be missing the article “the” here.
Context: ...n the python file to send the traces to Future AGI Platform. ```shell python your_fil...
(AI_EN_LECTOR_MISSING_DETERMINER_THE)
typescript/packages/fi-core/README.md
[uncategorized] ~98-~98: Loose punctuation mark.
Context: ...agent-as-judge #### Span Types - LLM: Large Language Model operations - `AGEN...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~107-~107: Loose punctuation mark.
Context: ...tions ### Project Types - EXPERIMENT: For experimental AI development and tes...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~115-~115: Loose punctuation mark.
Context: ...# Environment Variables - FI_BASE_URL: Base URL for the TraceAI collector - `F...
(UNLIKELY_OPENING_PUNCTUATION)
🪛 Ruff (0.11.9)
python/frameworks/google-adk/examples/testing_google_adk.py
8-8: opentelemetry.exporter.otlp.proto.http.trace_exporter.OTLPSpanExporter imported but unused
Remove unused import: opentelemetry.exporter.otlp.proto.http.trace_exporter.OTLPSpanExporter
(F401)
9-9: opentelemetry.sdk.trace imported but unused
Remove unused import: opentelemetry.sdk.trace
(F401)
10-10: opentelemetry.sdk.trace.export.ConsoleSpanExporter imported but unused
Remove unused import
(F401)
10-10: opentelemetry.sdk.trace.export.SimpleSpanProcessor imported but unused
Remove unused import
(F401)
python/frameworks/google-adk/traceai_google_adk/__init__.py
82-82: Do not call setattr with a constant attribute value. It is not any safer than normal property access.
Replace setattr with assignment
(B010)
83-87: Do not call setattr with a constant attribute value. It is not any safer than normal property access.
Replace setattr with assignment
(B010)
94-94: Do not call getattr with a constant attribute value. It is not any safer than normal property access.
Replace getattr with attribute access
(B009)
100-100: Do not call setattr with a constant attribute value. It is not any safer than normal property access.
Replace setattr with assignment
(B010)
104-104: Do not call setattr with a constant attribute value. It is not any safer than normal property access.
Replace setattr with assignment
(B010)
112-112: Do not call setattr with a constant attribute value. It is not any safer than normal property access.
Replace setattr with assignment
(B010)
113-117: Do not call setattr with a constant attribute value. It is not any safer than normal property access.
Replace setattr with assignment
(B010)
124-124: Do not call getattr with a constant attribute value. It is not any safer than normal property access.
Replace getattr with attribute access
(B009)
130-130: Do not call setattr with a constant attribute value. It is not any safer than normal property access.
Replace setattr with assignment
(B010)
134-134: Do not call setattr with a constant attribute value. It is not any safer than normal property access.
Replace setattr with assignment
(B010)
145-145: Do not call setattr with a constant attribute value. It is not any safer than normal property access.
Replace setattr with assignment
(B010)
154-154: Do not call setattr with a constant attribute value. It is not any safer than normal property access.
Replace setattr with assignment
(B010)
162-162: Do not call getattr with a constant attribute value. It is not any safer than normal property access.
Replace getattr with attribute access
(B009)
165-165: Do not call setattr with a constant attribute value. It is not any safer than normal property access.
Replace setattr with assignment
(B010)
171-171: Do not call getattr with a constant attribute value. It is not any safer than normal property access.
Replace getattr with attribute access
(B009)
174-174: Do not call setattr with a constant attribute value. It is not any safer than normal property access.
Replace setattr with assignment
(B010)
python/frameworks/google-adk/traceai_google_adk/_wrappers.py
60-60: _WithTracer is an abstract base class, but it has no abstract methods or properties
(B024)
328-329: Use a single if statement instead of nested if statements
(SIM102)
🪛 Pylint (3.3.7)
python/frameworks/google-adk/examples/testing_google_adk.py
[error] 3-3: No name 'adk' in module 'google'
(E0611)
[error] 4-4: No name 'adk' in module 'google'
(E0611)
[error] 5-5: No name 'genai' in module 'google'
(E0611)
[refactor] 32-44: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it
(R1705)
python/frameworks/google-adk/traceai_google_adk/__init__.py
[error] 42-42: No name 'adk' in module 'google'
(E0611)
[error] 43-43: No name 'adk' in module 'google'
(E0611)
[error] 78-78: No name 'adk' in module 'google'
(E0611)
[error] 91-91: No name 'adk' in module 'google'
(E0611)
[error] 96-98: No name 'adk' in module 'google'
(E0611)
[error] 102-102: No name 'adk' in module 'google'
(E0611)
[error] 108-108: No name 'adk' in module 'google'
(E0611)
[error] 121-121: No name 'adk' in module 'google'
(E0611)
[error] 126-128: No name 'adk' in module 'google'
(E0611)
[error] 132-132: No name 'adk' in module 'google'
(E0611)
[error] 138-140: No name 'adk' in module 'google'
(E0611)
[error] 143-143: No name 'adk' in module 'google'
(E0611)
[error] 147-149: No name 'adk' in module 'google'
(E0611)
[error] 152-152: No name 'adk' in module 'google'
(E0611)
[error] 158-160: No name 'adk' in module 'google'
(E0611)
[error] 163-163: No name 'adk' in module 'google'
(E0611)
[error] 167-169: No name 'adk' in module 'google'
(E0611)
[error] 172-172: No name 'adk' in module 'google'
(E0611)
[refactor] 177-177: Too few public methods (1/2)
(R0903)
python/frameworks/google-adk/traceai_google_adk/_wrappers.py
[error] 19-19: No name 'adk' in module 'google'
(E0611)
[error] 20-20: No name 'adk' in module 'google'
(E0611)
[error] 21-21: No name 'adk' in module 'google'
(E0611)
[error] 22-22: No name 'adk' in module 'google'
(E0611)
[error] 23-23: No name 'adk' in module 'google'
(E0611)
[error] 24-24: No name 'adk' in module 'google'
(E0611)
[error] 25-25: No name 'adk' in module 'google'
(E0611)
[error] 26-26: No name 'adk' in module 'google'
(E0611)
[error] 27-27: No name 'genai' in module 'google'
(E0611)
[error] 28-28: No name 'genai' in module 'google'
(E0611)
[refactor] 60-60: Too few public methods (0/2)
(R0903)
[refactor] 111-111: Too few public methods (1/2)
(R0903)
[refactor] 78-78: Too few public methods (1/2)
(R0903)
[refactor] 164-164: Too few public methods (1/2)
(R0903)
[refactor] 147-147: Too few public methods (1/2)
(R0903)
[refactor] 195-195: Too many local variables (17/15)
(R0914)
[refactor] 217-279: Too many nested blocks (6/5)
(R1702)
[refactor] 195-195: Too many branches (20/12)
(R0912)
[refactor] 193-193: Too few public methods (1/2)
(R0903)
[refactor] 286-286: Too few public methods (1/2)
(R0903)
[refactor] 515-522: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it
(R1705)
🔇 Additional comments (34)
python/frameworks/google-adk/examples/testing_google_adk.py (1)
54-64: Awaitingcreate_session()without a try/except hides failures
create_sessionmakes a network call; in an example it’s fine, but in production you should wrap it so errors don’t bubble unhandled:try: await session_service.create_session(...) except Exception as exc: logger.exception("Failed to create session: %s", exc) returnpython/frameworks/google-adk/traceai_google_adk/__init__.py (4)
26-41: Well-structured instrumentation setup.The method properly handles tracer provider and config initialization with appropriate type checking.
50-62: Excellent method wrapping implementation.The approach of storing original methods for cleanup and using
wraptfor method wrapping follows best practices.
136-175: Clean tracer management implementation.The approach of disabling existing tracers with a passthrough proxy and restoring them later is well-implemented with proper type checking.
🧰 Tools
🪛 Ruff (0.11.9)
145-145: Do not call
setattrwith a constant attribute value. It is not any safer than normal property access.Replace
setattrwith assignment(B010)
154-154: Do not call
setattrwith a constant attribute value. It is not any safer than normal property access.Replace
setattrwith assignment(B010)
162-162: Do not call
getattrwith a constant attribute value. It is not any safer than normal property access.Replace
getattrwith attribute access(B009)
165-165: Do not call
setattrwith a constant attribute value. It is not any safer than normal property access.Replace
setattrwith assignment(B010)
171-171: Do not call
getattrwith a constant attribute value. It is not any safer than normal property access.Replace
getattrwith attribute access(B009)
174-174: Do not call
setattrwith a constant attribute value. It is not any safer than normal property access.Replace
setattrwith assignment(B010)
🪛 Pylint (3.3.7)
[error] 138-140: No name 'adk' in module 'google'
(E0611)
[error] 143-143: No name 'adk' in module 'google'
(E0611)
[error] 147-149: No name 'adk' in module 'google'
(E0611)
[error] 152-152: No name 'adk' in module 'google'
(E0611)
[error] 158-160: No name 'adk' in module 'google'
(E0611)
[error] 163-163: No name 'adk' in module 'google'
(E0611)
[error] 167-169: No name 'adk' in module 'google'
(E0611)
[error] 172-172: No name 'adk' in module 'google'
(E0611)
177-187: Elegant passthrough tracer implementation.The use of
wrapt.ObjectProxyto create a no-op tracer that preserves context is a clean solution for preventing double instrumentation.🧰 Tools
🪛 Pylint (3.3.7)
[refactor] 177-177: Too few public methods (1/2)
(R0903)
python/frameworks/google-adk/traceai_google_adk/_wrappers.py (2)
78-145: Robust async generator wrapper implementation.Excellent use of
ExitStackfor managing multiple contexts and comprehensive error handling for attribute serialization. The wrapper properly captures both input and output values.🧰 Tools
🪛 Pylint (3.3.7)
[refactor] 111-111: Too few public methods (1/2)
(R0903)
[refactor] 78-78: Too few public methods (1/2)
(R0903)
344-522: Well-structured attribute extraction helpers.Excellent use of the
stop_on_exceptiondecorator pattern for consistent error handling across all attribute extraction functions. The comprehensive coverage of Google ADK types ensures rich telemetry data.🧰 Tools
🪛 Pylint (3.3.7)
[refactor] 515-522: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it
(R1705)
typescript/tsconfig.base.esnext.json (1)
1-9: Comments in TSConfig are supported despite strict JSON lint warnings.
TypeScript parses tsconfig files as JSONC, so inline comments (e.g., on line 5) are valid here. You can safely ignore the parse errors from strict JSON tools.🧰 Tools
🪛 Biome (1.9.4)
[error] 5-5: Expected a property but instead found '// target should be aligned with tsconfig.base.json'.
Expected a property here.
(parse)
[error] 6-6: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 6-6: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 6-6: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 6-6: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 7-7: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 7-7: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 7-7: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 8-9: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
typescript/packages/fi-semantic-conventions/package.json (1)
3-3: Version bump aligned with ecosystem updates.
The package version has been updated from0.1.1to0.1.8to stay in sync with related TraceAI packages.typescript/packages/traceai_anthropic/CHANGELOG.md (1)
1-4: CHANGELOG entries follow Keep a Changelog format.
Versions0.1.1and0.1.0are correctly ordered with feature notes. No issues detected.typescript/packages/traceai_anthropic/package.json (1)
3-3: Package version increment is correct.
Bumped from0.1.0to0.1.1, matching the changelog.typescript/tsconfig.base.es5.json (1)
1-7: ES5 Base Config Looks Good
The new ES5-targeted base config correctly extendstsconfig.base.json, setstarget: "es5", and enablesdownlevelIterationfor proper iterator support.typescript/packages/traceai_openai/src/instrumentation.ts (1)
129-137: OpenAI v5 Support Added
Including^5.0.0alongside^4.0.0in theinit()module definition aligns with the updated peer dependency ranges. Ensure thatpackage.jsonand any documentation examples are updated to reflect support for both major versions.typescript/packages/fi-core/tsconfig.json (2)
2-6: Base Config Extension and Path Simplification
Switching to extend../../tsconfig.base.jsonand removing leading./fromoutDir/rootDirsimplifies the config and aligns with other packages.
7-9: Explicit Include of Source and Test Files
Narrowingincludetosrc/**/*.tsandtest/**/*.tsensures only relevant files are compiled. The emptyfilesandreferencesarrays are appropriate for standalone builds.typescript/packages/fi-core/tsconfig.esm.json (1)
1-10: ESM Config Correctly Extends Base ESM
The ESM-specific config properly extendstsconfig.base.esm.json, directs output todist/esm, and setstsBuildInfoFile. Including onlysrc/**/*.tsis appropriate for the ESM build.typescript/packages/traceai_openai/tsconfig.esnext.json (1)
1-10: ESNext Config Aligns with Base
Extendingtsconfig.base.esnext.jsonwith correctoutDir,rootDir, andtsBuildInfoFilefor the ESNext build ensures consistency across packages. Including only source files is appropriate.typescript/packages/traceai_openai/tsconfig.esm.json (1)
1-10: Consistent ESM build configuration applied
Extends the shared base ESM config and correctly setsoutDir,rootDir, and incrementaltsBuildInfoFile. Including onlysrc/**/*.tsis appropriate for package builds.typescript/packages/fi-semantic-conventions/tsconfig.esm.json (1)
1-10: Standardized ESM config matches project conventions
This file properly extends the base ESM config, directs output todist/esm, and scopes sources tosrc. The setup is consistent with other packages.typescript/packages/traceai_anthropic/tsconfig.esnext.json (1)
1-10: ESNext configuration aligns with monorepo standards
Extends the base ESNext config and setsoutDir,rootDir, and incremental build info correctly. Inclusion ofsrc/**/*.tsis correct.typescript/packages/fi-core/tsconfig.esnext.json (1)
1-10: Consistent ESNext build settings
Follows the same pattern as other packages: extends base ESNext config, outputs todist/esnext, and usessrcas the root.typescript/packages/traceai_anthropic/tsconfig.esm.json (1)
1-10: ESM build config is correctly defined
Extends the shared base ESM config, targetsdist/esm, and scopes source files undersrc. No project references needed here.typescript/packages/traceai_anthropic/tsconfig.json (1)
2-9: Confirm Anthropic config simplification
The TS config now extends the centralized base and removescompositeand project references. Verify thattraceai_anthropicno longer relies on project references and builds correctly in isolation or via the root-level build.typescript/packages/traceai_openai/package.json (1)
3-3: Approve version bump
Bumping from0.1.2to0.1.12follows semver and aligns with the release cadence.typescript/packages/fi-semantic-conventions/tsconfig.json (3)
2-2: Verify the base config extension path
Using"../../tsconfig.base.json"aligns with the new base config structure; confirm the path resolves correctly in the package context.
4-5: Simplified compiler paths look correct
Dropping the leading"./"inoutDirandrootDirsimplifies the paths without altering behavior.
8-8: Explicitly include tests in the build
Adding"test/**/*.ts"ensures test files are compiled and type-checked; this matches the standardized setup.typescript/tsconfig.base.esm.json (1)
2-6: Validate extension and module resolution settings
Ensure that extending./tsconfig.base.esnext.jsonis intentional for ESM targets and thatmoduleResolution: "node10"aligns with your Node.js support policy (Node.js 10 is EOL). Consider upgrading to a more recent resolution strategy (e.g.,node16ornodeNext) if applicable.typescript/packages/traceai_openai/tsconfig.json (1)
2-6: Consistent base configuration inheritance
Extending fromtsconfig.base.jsonand simplifying compiler options (outDir,rootDir) aligns this package with other monorepo packages.typescript/packages/traceai_langchain/tsconfig.json (1)
2-6: Standardized compiler options
Updating to extendtsconfig.base.jsonand normalizingoutDir/rootDirsimplifies and unifies the build across packages.typescript/packages/fi-core/package.json (3)
3-3: Version bump
Updated version to0.1.11to align with dependent packages across the monorepo.
34-37: Dependencies version pinning
Pinned@traceai/fi-semantic-conventionsto^0.1.8anduuidto^11.1.0, matching the ecosystem’s coordinated versioning strategy.
38-41: DevDependencies cleanup
Limiting devDependencies to TypeScript and Node types streamlines setup and avoids unnecessary packages.typescript/tsconfig.base.json (1)
1-112: Comprehensive base configuration
The newtsconfig.base.jsonprovides a solid foundation (incremental builds, strict checks, source maps). TS’s JSONC format supports comments—these static-analysis JSON errors can be safely ignored.🧰 Tools
🪛 Biome (1.9.4)
[error] 3-3: JSON standard does not allow comments.
(parse)
[error] 5-5: JSON standard does not allow comments.
(parse)
[error] 6-6: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 6-6: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 6-6: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 6-6: JSON standard does not allow comments.
(parse)
[error] 7-7: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 7-7: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 7-7: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 7-7: JSON standard does not allow comments.
(parse)
[error] 13-13: JSON standard does not allow comments.
(parse)
[error] 14-14: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 14-14: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 14-14: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 14-14: JSON standard does not allow comments.
(parse)
[error] 15-15: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 15-15: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 15-17: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 17-17: JSON standard does not allow comments.
(parse)
[error] 29-29: JSON standard does not allow comments.
(parse)
[error] 30-30: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 30-30: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 30-30: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 30-30: JSON standard does not allow comments.
(parse)
[error] 48-48: JSON standard does not allow comments.
(parse)
[error] 53-53: JSON standard does not allow comments.
(parse)
[error] 54-54: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 54-54: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 54-54: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 54-54: JSON standard does not allow comments.
(parse)
[error] 55-55: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 55-55: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 55-55: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 55-55: JSON standard does not allow comments.
(parse)
[error] 57-57: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 57-57: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 57-57: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 57-57: JSON standard does not allow comments.
(parse)
[error] 78-78: JSON standard does not allow comments.
(parse)
[error] 82-82: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 82-82: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 82-82: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 82-82: JSON standard does not allow comments.
(parse)
[error] 84-84: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 84-84: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 84-84: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 84-84: JSON standard does not allow comments.
(parse)
[error] 86-86: JSON standard does not allow comments.
(parse)
[error] 87-87: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 87-87: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 87-87: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 87-87: JSON standard does not allow comments.
(parse)
[error] 107-107: JSON standard does not allow comments.
(parse)
[error] 109-109: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 109-109: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 109-109: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 109-109: JSON standard does not allow comments.
(parse)
[error] 111-111: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 111-111: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 111-111: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
[error] 111-112: End of file expected
Use an array for a sequence of values:
[1, 2](parse)
| home = /opt/homebrew/opt/python@3.12/bin | ||
| include-system-site-packages = false | ||
| version = 3.12.9 | ||
| executable = /opt/homebrew/Cellar/python@3.12/3.12.9/Frameworks/Python.framework/Versions/3.12/bin/python3.12 | ||
| command = /opt/homebrew/opt/python@3.12/bin/python3.12 -m venv /Users/n.v.j.kkartik/traceAI/python/frameworks/google-adk/.venv |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don’t commit virtual-environment artefacts
python/frameworks/google-adk/.venv/pyvenv.cfg is machine-specific (absolute paths, Python installation prefix) and will quickly become stale or break CI. Virtual-envs should be excluded via .gitignore and re-created locally (python -m venv .venv or poetry env use …).
Please delete the directory from the repository and add a deny-listing rule such as:
+# Development artefacts
+python/**/.venv/Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In python/frameworks/google-adk/.venv/pyvenv.cfg lines 1 to 5, the virtual
environment configuration file contains machine-specific absolute paths that
should not be committed to the repository. Remove the entire .venv directory
from the repository and add an entry to the .gitignore file to exclude the .venv
directory from future commits. This ensures that each developer or CI
environment creates their own local virtual environment without conflicts.
| from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter | ||
| from opentelemetry.sdk import trace as trace_sdk | ||
| from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor | ||
| from fi_instrumentation import register |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Clean up unused imports to satisfy Ruff / pylint
OTLPSpanExporter, trace_sdk, ConsoleSpanExporter, and SimpleSpanProcessor are imported but not referenced, triggering F401/E0611. Remove them (or use them) to keep the example lint-clean:
-from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
-from opentelemetry.sdk import trace as trace_sdk
-from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor📝 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.
| from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter | |
| from opentelemetry.sdk import trace as trace_sdk | |
| from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor | |
| from fi_instrumentation import register | |
| from fi_instrumentation import register |
🧰 Tools
🪛 Ruff (0.11.9)
8-8: opentelemetry.exporter.otlp.proto.http.trace_exporter.OTLPSpanExporter imported but unused
Remove unused import: opentelemetry.exporter.otlp.proto.http.trace_exporter.OTLPSpanExporter
(F401)
9-9: opentelemetry.sdk.trace imported but unused
Remove unused import: opentelemetry.sdk.trace
(F401)
10-10: opentelemetry.sdk.trace.export.ConsoleSpanExporter imported but unused
Remove unused import
(F401)
10-10: opentelemetry.sdk.trace.export.SimpleSpanProcessor imported but unused
Remove unused import
(F401)
🤖 Prompt for AI Agents
In python/frameworks/google-adk/examples/testing_google_adk.py around lines 8 to
11, the imports OTLPSpanExporter, trace_sdk, ConsoleSpanExporter, and
SimpleSpanProcessor are unused and cause lint errors. Remove these unused
imports to clean up the code and satisfy Ruff/pylint checks.
| async for event in runner.run_async( | ||
| user_id=user_id, | ||
| session_id=session_id, | ||
| new_message=types.Content(role="user", parts=[ | ||
| types.Part(text="What is the weather in New York?")] | ||
| ) | ||
| ): | ||
| if event.is_final_response(): | ||
| print(event.content.parts[0].text.strip()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Loop keeps iterating after final response
Once event.is_final_response() is True the loop can break; otherwise the run_async generator will continue yielding heartbeat events and the script hangs.
- if event.is_final_response():
- print(event.content.parts[0].text.strip())
+ if event.is_final_response():
+ print(event.content.parts[0].text.strip())
+ break📝 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.
| async for event in runner.run_async( | |
| user_id=user_id, | |
| session_id=session_id, | |
| new_message=types.Content(role="user", parts=[ | |
| types.Part(text="What is the weather in New York?")] | |
| ) | |
| ): | |
| if event.is_final_response(): | |
| print(event.content.parts[0].text.strip()) | |
| async for event in runner.run_async( | |
| user_id=user_id, | |
| session_id=session_id, | |
| new_message=types.Content(role="user", parts=[ | |
| types.Part(text="What is the weather in New York?")] | |
| ) | |
| ): | |
| if event.is_final_response(): | |
| print(event.content.parts[0].text.strip()) | |
| break |
🤖 Prompt for AI Agents
In python/frameworks/google-adk/examples/testing_google_adk.py around lines 65
to 73, the async for loop continues iterating even after receiving the final
response, causing the script to hang due to ongoing heartbeat events. To fix
this, add a break statement immediately after the print statement inside the if
event.is_final_response() block to exit the loop once the final response is
received.
| def _unpatch_trace_tool_call(self) -> None: | ||
| """Restore the original tool call tracing functionality.""" | ||
| from google.adk.flows.llm_flows.base_llm_flow import functions # type: ignore[attr-defined] | ||
|
|
||
| if callable( | ||
| original := getattr(functions.trace_tool_call, "__wrapped__"), # type: ignore[attr-defined] | ||
| ): | ||
| from google.adk.flows.llm_flows.base_llm_flow import ( # type: ignore[attr-defined] | ||
| functions, | ||
| ) | ||
|
|
||
| setattr(functions, "trace_tool_call", original) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix import path inconsistency.
The import path in _unpatch_trace_tool_call differs from the one used in _patch_trace_tool_call. This inconsistency could cause the unpatch operation to fail.
def _unpatch_trace_tool_call(self) -> None:
"""Restore the original tool call tracing functionality."""
- from google.adk.flows.llm_flows.base_llm_flow import functions # type: ignore[attr-defined]
+ from google.adk.flows.llm_flows import functions
if callable(
original := getattr(functions.trace_tool_call, "__wrapped__"), # type: ignore[attr-defined]
):
- from google.adk.flows.llm_flows.base_llm_flow import ( # type: ignore[attr-defined]
- functions,
- )
-
setattr(functions, "trace_tool_call", original)📝 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.
| def _unpatch_trace_tool_call(self) -> None: | |
| """Restore the original tool call tracing functionality.""" | |
| from google.adk.flows.llm_flows.base_llm_flow import functions # type: ignore[attr-defined] | |
| if callable( | |
| original := getattr(functions.trace_tool_call, "__wrapped__"), # type: ignore[attr-defined] | |
| ): | |
| from google.adk.flows.llm_flows.base_llm_flow import ( # type: ignore[attr-defined] | |
| functions, | |
| ) | |
| setattr(functions, "trace_tool_call", original) | |
| def _unpatch_trace_tool_call(self) -> None: | |
| """Restore the original tool call tracing functionality.""" | |
| from google.adk.flows.llm_flows import functions # type: ignore[attr-defined] | |
| if callable( | |
| original := getattr(functions.trace_tool_call, "__wrapped__"), # type: ignore[attr-defined] | |
| ): | |
| setattr(functions, "trace_tool_call", original) |
🧰 Tools
🪛 Ruff (0.11.9)
124-124: Do not call getattr with a constant attribute value. It is not any safer than normal property access.
Replace getattr with attribute access
(B009)
130-130: Do not call setattr with a constant attribute value. It is not any safer than normal property access.
Replace setattr with assignment
(B010)
🪛 Pylint (3.3.7)
[error] 121-121: No name 'adk' in module 'google'
(E0611)
[error] 126-128: No name 'adk' in module 'google'
(E0611)
🤖 Prompt for AI Agents
In python/frameworks/google-adk/traceai_google_adk/__init__.py around lines 119
to 131, the import path used in the _unpatch_trace_tool_call method is
inconsistent with the one in _patch_trace_tool_call, which may cause the unpatch
operation to fail. To fix this, update the import statement in
_unpatch_trace_tool_call to use the exact same module path as in
_patch_trace_tool_call, ensuring both methods import from the same location to
maintain consistency and correctness.
| "extends": "../../tsconfig.base.esm.json", | ||
| "compilerOptions": { | ||
| "outDir": "dist/esm", | ||
| "rootDir": "src", | ||
| "tsBuildInfoFile": "dist/esm/tsconfig.esm.tsbuildinfo" | ||
| }, | ||
| "include": ["src/**/*.ts"], | ||
| "references": [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Verify ESM base config inheritance
The extends path and outDir, rootDir, and tsBuildInfoFile align with other packages. Confirm that tsconfig.base.esm.json includes incremental or composite flags so that the tsBuildInfoFile is utilized correctly.
🏁 Script executed:
#!/bin/bash
# Verify incremental/composite flags in the base ESM config
rg -A2 '"incremental"' typescript/tsconfig.base.esm.json
rg -A2 '"composite"' typescript/tsconfig.base.esm.jsonLength of output: 115
I’ll locate the ESM base config file and check for those flags directly.
🏁 Script executed:
#!/bin/bash
# Find the tsconfig.base.esm.json file
file_path=$(find . -type f -name 'tsconfig.base.esm.json' | head -n1)
echo "Config file found at: $file_path"
# Check for incremental and composite settings
if [[ -n "$file_path" ]]; then
echo "Searching for \"incremental\" in $file_path"
grep -n '"incremental"' "$file_path" || echo "❌ no incremental flag found"
echo
echo "Searching for \"composite\" in $file_path"
grep -n '"composite"' "$file_path" || echo "❌ no composite flag found"
else
echo "⚠️ tsconfig.base.esm.json not found"
fiLength of output: 816
Add composite and incremental flags to the ESM base config
The base ESM tsconfig (typescript/tsconfig.base.esm.json) is missing both "composite": true and "incremental": true, so the per-package tsBuildInfoFile settings won’t take effect. Please add these flags under compilerOptions.
• File needing update:
- typescript/tsconfig.base.esm.json
Suggested diff:
{
"compilerOptions": {
+ "composite": true,
+ "incremental": true,
// …existing options…
}
}🤖 Prompt for AI Agents
In typescript/tsconfig.base.esm.json, add the compilerOptions flags "composite":
true and "incremental": true to enable proper use of the tsBuildInfoFile in
extending configs like typescript/packages/traceai_langchain/tsconfig.esm.json.
Locate the "compilerOptions" section and insert these two flags to ensure
incremental builds and composite project support are enabled.
| import { register, ProjectType, EvalTag, EvalName, EvalSpanKind } from '@traceai/fi-core'; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix missing imports in documentation
Examples use EvalTagType and ModelChoices but don’t import them.
Apply:
-import { register, ProjectType, EvalTag, EvalName, EvalSpanKind } from '@traceai/fi-core';
+import { register, ProjectType, EvalTag, EvalTagType, EvalName, EvalSpanKind, ModelChoices } from '@traceai/fi-core';📝 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.
| import { register, ProjectType, EvalTag, EvalName, EvalSpanKind } from '@traceai/fi-core'; | |
| import { register, ProjectType, EvalTag, EvalTagType, EvalName, EvalSpanKind, ModelChoices } from '@traceai/fi-core'; |
🤖 Prompt for AI Agents
In typescript/packages/fi-core/README.md around lines 45 to 46, the import
statement is missing EvalTagType and ModelChoices which are used in the
examples. Update the import line to include EvalTagType and ModelChoices from
'@traceai/fi-core' to ensure all referenced types are properly imported in the
documentation.
| apiKey: process.env.OPENAI_API_KEY, | ||
| }); | ||
|
|
||
| console.log("OpenAI client initialized. Instrumentation patched:", (openaiInstrumentation as any).isPatched?.()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid accessing private properties.
The code accesses the private property isPatched using type assertion (openaiInstrumentation as any). This relies on internal implementation details that may change.
-console.log("OpenAI client initialized. Instrumentation patched:", (openaiInstrumentation as any).isPatched?.());
+console.log("OpenAI client initialized. Instrumentation registered.");📝 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.
| console.log("OpenAI client initialized. Instrumentation patched:", (openaiInstrumentation as any).isPatched?.()); | |
| console.log("OpenAI client initialized. Instrumentation registered."); |
🤖 Prompt for AI Agents
In typescript/packages/traceai_openai/examples/manual.ts at line 42, avoid
accessing the private property isPatched on openaiInstrumentation using type
assertion. Instead, refactor the code to use a public method or property
provided by the openaiInstrumentation object to check if it is patched, or add a
proper accessor if needed, to prevent reliance on internal implementation
details.
| // Give time for spans to be exported | ||
| setTimeout(async () => { | ||
| try { | ||
| await tracerProvider.shutdown(); | ||
| console.log("Tracer provider shut down successfully."); | ||
| } catch (error) { | ||
| console.error("Error shutting down tracer provider:", error); | ||
| } | ||
| }, 2000); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Improve shutdown mechanism for reliable span export.
The current setTimeout approach doesn't guarantee all spans are exported before the process exits. Consider using a more reliable shutdown pattern.
} finally {
- // Give time for spans to be exported
- setTimeout(async () => {
- try {
- await tracerProvider.shutdown();
- console.log("Tracer provider shut down successfully.");
- } catch (error) {
- console.error("Error shutting down tracer provider:", error);
- }
- }, 2000);
+ // Ensure all spans are exported before exit
+ console.log("Shutting down tracer provider...");
+ try {
+ // Give a reasonable timeout for span export
+ await Promise.race([
+ tracerProvider.shutdown(),
+ new Promise((_, reject) =>
+ setTimeout(() => reject(new Error("Shutdown timeout")), 5000)
+ )
+ ]);
+ console.log("Tracer provider shut down successfully.");
+ } catch (error) {
+ console.error("Error shutting down tracer provider:", error);
+ }
}📝 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.
| // Give time for spans to be exported | |
| setTimeout(async () => { | |
| try { | |
| await tracerProvider.shutdown(); | |
| console.log("Tracer provider shut down successfully."); | |
| } catch (error) { | |
| console.error("Error shutting down tracer provider:", error); | |
| } | |
| }, 2000); | |
| } | |
| } finally { | |
| // Ensure all spans are exported before exit | |
| console.log("Shutting down tracer provider..."); | |
| try { | |
| // Give a reasonable timeout for span export | |
| await Promise.race([ | |
| tracerProvider.shutdown(), | |
| new Promise((_, reject) => | |
| setTimeout(() => reject(new Error("Shutdown timeout")), 5000) | |
| ) | |
| ]); | |
| console.log("Tracer provider shut down successfully."); | |
| } catch (error) { | |
| console.error("Error shutting down tracer provider:", error); | |
| } | |
| } |
🤖 Prompt for AI Agents
In typescript/packages/traceai_openai/examples/manual.ts around lines 310 to
319, the current use of setTimeout to delay shutdown does not reliably ensure
all spans are exported before the process exits. Replace the setTimeout with a
proper asynchronous shutdown sequence that awaits the tracerProvider.shutdown()
call directly and only exits the process after confirming shutdown completion,
avoiding arbitrary delays and improving reliability.
| async function processWithAnalysis(prompt: string) { | ||
| return tracer.startActiveSpan("ai-processing-pipeline", async (pipelineSpan) => { | ||
| pipelineSpan.setAttribute("fi.span.kind", "chain"); | ||
|
|
||
| console.log("Starting auto-instrumented OpenAI call in processing pipeline"); | ||
|
|
||
| // Auto-instrumented OpenAI call | ||
| const response = await openai.chat.completions.create({ | ||
| messages: [{ role: "user", content: prompt }], | ||
| model: "gpt-4o-mini", | ||
| }); | ||
|
|
||
| // Get the currently active span (could be the auto-created OpenAI span) | ||
| const currentSpan = trace.getActiveSpan(); | ||
| if (currentSpan) { | ||
| console.log("Found active span, adding analysis flag"); | ||
| currentSpan.setAttribute("custom.analysis.enabled", true); | ||
| } else { | ||
| console.log("No active span found in processing pipeline"); | ||
| } | ||
|
|
||
| // Create manual analysis spans as children | ||
| const content = response.choices[0]?.message?.content || ""; | ||
|
|
||
| await tracer.startActiveSpan("content-analysis", async (analysisSpan) => { | ||
| analysisSpan.setAttribute("fi.span.kind", "tool"); | ||
| analysisSpan.setAttribute("analysis.content.length", content.length); | ||
| analysisSpan.setAttribute("analysis.word.count", content.split(' ').length); | ||
|
|
||
| // Simulate analysis work | ||
| await new Promise(resolve => setTimeout(resolve, 100)); | ||
|
|
||
| analysisSpan.addEvent("Content analysis completed", { | ||
| "sentiment": "positive", | ||
| "complexity": "medium" | ||
| }); | ||
|
|
||
| analysisSpan.end(); | ||
| }); | ||
|
|
||
| await tracer.startActiveSpan("content-validation", async (validationSpan) => { | ||
| validationSpan.setAttribute("fi.span.kind", "tool"); | ||
|
|
||
| // Simulate validation | ||
| const isValid = content.length > 10; | ||
| validationSpan.setAttribute("validation.result", isValid); | ||
| validationSpan.setAttribute("validation.criteria", "min_length_check"); | ||
|
|
||
| if (!isValid) { | ||
| validationSpan.setStatus({ | ||
| code: 2, | ||
| message: "Content validation failed" | ||
| }); | ||
| } | ||
|
|
||
| validationSpan.end(); | ||
| }); | ||
|
|
||
| pipelineSpan.end(); | ||
| return response; | ||
| }); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add error handling to ensure spans are properly closed.
The function lacks try-catch-finally blocks to ensure spans are properly closed in case of errors, which could lead to memory leaks or incomplete traces.
async function processWithAnalysis(prompt: string) {
return tracer.startActiveSpan("ai-processing-pipeline", async (pipelineSpan) => {
pipelineSpan.setAttribute("fi.span.kind", "chain");
console.log("Starting auto-instrumented OpenAI call in processing pipeline");
+ try {
// Auto-instrumented OpenAI call
const response = await openai.chat.completions.create({
messages: [{ role: "user", content: prompt }],
model: "gpt-4o-mini",
});
// ... rest of the function logic ...
- pipelineSpan.end();
return response;
+ } catch (error) {
+ pipelineSpan.recordException(error as Error);
+ pipelineSpan.setStatus({
+ code: 2,
+ message: `Processing pipeline failed: ${(error as Error).message}`
+ });
+ throw error;
+ } finally {
+ pipelineSpan.end();
+ }
});
}📝 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.
| async function processWithAnalysis(prompt: string) { | |
| return tracer.startActiveSpan("ai-processing-pipeline", async (pipelineSpan) => { | |
| pipelineSpan.setAttribute("fi.span.kind", "chain"); | |
| console.log("Starting auto-instrumented OpenAI call in processing pipeline"); | |
| // Auto-instrumented OpenAI call | |
| const response = await openai.chat.completions.create({ | |
| messages: [{ role: "user", content: prompt }], | |
| model: "gpt-4o-mini", | |
| }); | |
| // Get the currently active span (could be the auto-created OpenAI span) | |
| const currentSpan = trace.getActiveSpan(); | |
| if (currentSpan) { | |
| console.log("Found active span, adding analysis flag"); | |
| currentSpan.setAttribute("custom.analysis.enabled", true); | |
| } else { | |
| console.log("No active span found in processing pipeline"); | |
| } | |
| // Create manual analysis spans as children | |
| const content = response.choices[0]?.message?.content || ""; | |
| await tracer.startActiveSpan("content-analysis", async (analysisSpan) => { | |
| analysisSpan.setAttribute("fi.span.kind", "tool"); | |
| analysisSpan.setAttribute("analysis.content.length", content.length); | |
| analysisSpan.setAttribute("analysis.word.count", content.split(' ').length); | |
| // Simulate analysis work | |
| await new Promise(resolve => setTimeout(resolve, 100)); | |
| analysisSpan.addEvent("Content analysis completed", { | |
| "sentiment": "positive", | |
| "complexity": "medium" | |
| }); | |
| analysisSpan.end(); | |
| }); | |
| await tracer.startActiveSpan("content-validation", async (validationSpan) => { | |
| validationSpan.setAttribute("fi.span.kind", "tool"); | |
| // Simulate validation | |
| const isValid = content.length > 10; | |
| validationSpan.setAttribute("validation.result", isValid); | |
| validationSpan.setAttribute("validation.criteria", "min_length_check"); | |
| if (!isValid) { | |
| validationSpan.setStatus({ | |
| code: 2, | |
| message: "Content validation failed" | |
| }); | |
| } | |
| validationSpan.end(); | |
| }); | |
| pipelineSpan.end(); | |
| return response; | |
| }); | |
| } | |
| async function processWithAnalysis(prompt: string) { | |
| return tracer.startActiveSpan("ai-processing-pipeline", async (pipelineSpan) => { | |
| pipelineSpan.setAttribute("fi.span.kind", "chain"); | |
| console.log("Starting auto-instrumented OpenAI call in processing pipeline"); | |
| try { | |
| // Auto-instrumented OpenAI call | |
| const response = await openai.chat.completions.create({ | |
| messages: [{ role: "user", content: prompt }], | |
| model: "gpt-4o-mini", | |
| }); | |
| // Get the currently active span (could be the auto-created OpenAI span) | |
| const currentSpan = trace.getActiveSpan(); | |
| if (currentSpan) { | |
| console.log("Found active span, adding analysis flag"); | |
| currentSpan.setAttribute("custom.analysis.enabled", true); | |
| } else { | |
| console.log("No active span found in processing pipeline"); | |
| } | |
| // Create manual analysis spans as children | |
| const content = response.choices[0]?.message?.content || ""; | |
| await tracer.startActiveSpan("content-analysis", async (analysisSpan) => { | |
| analysisSpan.setAttribute("fi.span.kind", "tool"); | |
| analysisSpan.setAttribute("analysis.content.length", content.length); | |
| analysisSpan.setAttribute("analysis.word.count", content.split(' ').length); | |
| // Simulate analysis work | |
| await new Promise(resolve => setTimeout(resolve, 100)); | |
| analysisSpan.addEvent("Content analysis completed", { | |
| "sentiment": "positive", | |
| "complexity": "medium" | |
| }); | |
| analysisSpan.end(); | |
| }); | |
| await tracer.startActiveSpan("content-validation", async (validationSpan) => { | |
| validationSpan.setAttribute("fi.span.kind", "tool"); | |
| // Simulate validation | |
| const isValid = content.length > 10; | |
| validationSpan.setAttribute("validation.result", isValid); | |
| validationSpan.setAttribute("validation.criteria", "min_length_check"); | |
| if (!isValid) { | |
| validationSpan.setStatus({ | |
| code: 2, | |
| message: "Content validation failed" | |
| }); | |
| } | |
| validationSpan.end(); | |
| }); | |
| return response; | |
| } catch (error) { | |
| pipelineSpan.recordException(error as Error); | |
| pipelineSpan.setStatus({ | |
| code: 2, | |
| message: `Processing pipeline failed: ${(error as Error).message}` | |
| }); | |
| throw error; | |
| } finally { | |
| pipelineSpan.end(); | |
| } | |
| }); | |
| } |
🤖 Prompt for AI Agents
In typescript/packages/traceai_openai/examples/manual.ts between lines 116 and
177, the processWithAnalysis function lacks error handling around the span
usage, risking spans not being closed on exceptions. Wrap the main logic inside
the tracer.startActiveSpan callback in a try block, use catch to handle errors
appropriately, and ensure each span (pipelineSpan, analysisSpan, validationSpan)
is ended in a finally block to guarantee proper closure regardless of errors.
| async function chainedOperations() { | ||
| return tracer.startActiveSpan("chained-ai-operations", async (rootSpan) => { | ||
| rootSpan.setAttribute("fi.span.kind", "chain"); | ||
|
|
||
| console.log("Starting first auto-instrumented operation"); | ||
|
|
||
| // First operation - auto-instrumented | ||
| const firstResponse = await openai.chat.completions.create({ | ||
| messages: [{ role: "user", content: "Generate a creative story title" }], | ||
| model: "gpt-4o-mini", | ||
| }); | ||
|
|
||
| // Extract the title and use it in manual processing | ||
| const title = firstResponse.choices[0]?.message?.content || ""; | ||
|
|
||
| // Manual span that uses context from the auto-instrumented span | ||
| await tracer.startActiveSpan("title-processing", async (processingSpan) => { | ||
| processingSpan.setAttribute("fi.span.kind", "tool"); | ||
| processingSpan.setAttribute("processing.input", title); | ||
|
|
||
| // Get active span context for correlation | ||
| const activeSpan = trace.getActiveSpan(); | ||
| if (activeSpan) { | ||
| const spanContext = activeSpan.spanContext(); | ||
| processingSpan.setAttribute("correlation.parent.trace_id", spanContext.traceId); | ||
| processingSpan.setAttribute("correlation.parent.span_id", spanContext.spanId); | ||
| } | ||
|
|
||
| // Process the title | ||
| const processedTitle = title.toUpperCase().trim(); | ||
| processingSpan.setAttribute("processing.output", processedTitle); | ||
|
|
||
| processingSpan.end(); | ||
|
|
||
| console.log("Starting second auto-instrumented operation with processed title"); | ||
|
|
||
| // Second auto-instrumented operation using processed result | ||
| const storyResponse = await openai.chat.completions.create({ | ||
| messages: [{ | ||
| role: "user", | ||
| content: `Write a short story with the title: "${processedTitle}"` | ||
| }], | ||
| model: "gpt-4o-mini", | ||
| }); | ||
|
|
||
| // Enhance the auto-created span for the second call | ||
| const currentSpan = trace.getActiveSpan(); | ||
| if (currentSpan) { | ||
| console.log("Enhancing second auto-created span with story metadata"); | ||
| currentSpan.setAttribute("custom.story.title", processedTitle); | ||
| currentSpan.setAttribute("custom.story.word_count", | ||
| storyResponse.choices[0]?.message?.content?.split(' ').length || 0); | ||
| } else { | ||
| console.log("No active span found for second OpenAI call"); | ||
| } | ||
|
|
||
| return storyResponse; | ||
| }); | ||
|
|
||
| rootSpan.end(); | ||
| }); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix missing return statement and add error handling.
The function doesn't return the result from the inner async operation and lacks error handling.
async function chainedOperations() {
return tracer.startActiveSpan("chained-ai-operations", async (rootSpan) => {
rootSpan.setAttribute("fi.span.kind", "chain");
+ try {
console.log("Starting first auto-instrumented operation");
// ... existing code ...
// Manual span that uses context from the auto-instrumented span
- await tracer.startActiveSpan("title-processing", async (processingSpan) => {
+ const result = await tracer.startActiveSpan("title-processing", async (processingSpan) => {
// ... existing code ...
return storyResponse;
});
- rootSpan.end();
+ return result;
+ } catch (error) {
+ rootSpan.recordException(error as Error);
+ rootSpan.setStatus({
+ code: 2,
+ message: `Chained operations failed: ${(error as Error).message}`
+ });
+ throw error;
+ } finally {
+ rootSpan.end();
+ }
});
}📝 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.
| async function chainedOperations() { | |
| return tracer.startActiveSpan("chained-ai-operations", async (rootSpan) => { | |
| rootSpan.setAttribute("fi.span.kind", "chain"); | |
| console.log("Starting first auto-instrumented operation"); | |
| // First operation - auto-instrumented | |
| const firstResponse = await openai.chat.completions.create({ | |
| messages: [{ role: "user", content: "Generate a creative story title" }], | |
| model: "gpt-4o-mini", | |
| }); | |
| // Extract the title and use it in manual processing | |
| const title = firstResponse.choices[0]?.message?.content || ""; | |
| // Manual span that uses context from the auto-instrumented span | |
| await tracer.startActiveSpan("title-processing", async (processingSpan) => { | |
| processingSpan.setAttribute("fi.span.kind", "tool"); | |
| processingSpan.setAttribute("processing.input", title); | |
| // Get active span context for correlation | |
| const activeSpan = trace.getActiveSpan(); | |
| if (activeSpan) { | |
| const spanContext = activeSpan.spanContext(); | |
| processingSpan.setAttribute("correlation.parent.trace_id", spanContext.traceId); | |
| processingSpan.setAttribute("correlation.parent.span_id", spanContext.spanId); | |
| } | |
| // Process the title | |
| const processedTitle = title.toUpperCase().trim(); | |
| processingSpan.setAttribute("processing.output", processedTitle); | |
| processingSpan.end(); | |
| console.log("Starting second auto-instrumented operation with processed title"); | |
| // Second auto-instrumented operation using processed result | |
| const storyResponse = await openai.chat.completions.create({ | |
| messages: [{ | |
| role: "user", | |
| content: `Write a short story with the title: "${processedTitle}"` | |
| }], | |
| model: "gpt-4o-mini", | |
| }); | |
| // Enhance the auto-created span for the second call | |
| const currentSpan = trace.getActiveSpan(); | |
| if (currentSpan) { | |
| console.log("Enhancing second auto-created span with story metadata"); | |
| currentSpan.setAttribute("custom.story.title", processedTitle); | |
| currentSpan.setAttribute("custom.story.word_count", | |
| storyResponse.choices[0]?.message?.content?.split(' ').length || 0); | |
| } else { | |
| console.log("No active span found for second OpenAI call"); | |
| } | |
| return storyResponse; | |
| }); | |
| rootSpan.end(); | |
| }); | |
| } | |
| async function chainedOperations() { | |
| return tracer.startActiveSpan("chained-ai-operations", async (rootSpan) => { | |
| rootSpan.setAttribute("fi.span.kind", "chain"); | |
| try { | |
| console.log("Starting first auto-instrumented operation"); | |
| // First operation - auto-instrumented | |
| const firstResponse = await openai.chat.completions.create({ | |
| messages: [{ role: "user", content: "Generate a creative story title" }], | |
| model: "gpt-4o-mini", | |
| }); | |
| // Extract the title and use it in manual processing | |
| const title = firstResponse.choices[0]?.message?.content || ""; | |
| // Manual span that uses context from the auto-instrumented span | |
| const result = await tracer.startActiveSpan("title-processing", async (processingSpan) => { | |
| processingSpan.setAttribute("fi.span.kind", "tool"); | |
| processingSpan.setAttribute("processing.input", title); | |
| // Get active span context for correlation | |
| const activeSpan = trace.getActiveSpan(); | |
| if (activeSpan) { | |
| const spanContext = activeSpan.spanContext(); | |
| processingSpan.setAttribute("correlation.parent.trace_id", spanContext.traceId); | |
| processingSpan.setAttribute("correlation.parent.span_id", spanContext.spanId); | |
| } | |
| // Process the title | |
| const processedTitle = title.toUpperCase().trim(); | |
| processingSpan.setAttribute("processing.output", processedTitle); | |
| processingSpan.end(); | |
| console.log("Starting second auto-instrumented operation with processed title"); | |
| // Second auto-instrumented operation using processed result | |
| const storyResponse = await openai.chat.completions.create({ | |
| messages: [ | |
| { | |
| role: "user", | |
| content: `Write a short story with the title: "${processedTitle}"`, | |
| }, | |
| ], | |
| model: "gpt-4o-mini", | |
| }); | |
| // Enhance the auto-created span for the second call | |
| const currentSpan = trace.getActiveSpan(); | |
| if (currentSpan) { | |
| console.log("Enhancing second auto-created span with story metadata"); | |
| currentSpan.setAttribute("custom.story.title", processedTitle); | |
| currentSpan.setAttribute( | |
| "custom.story.word_count", | |
| storyResponse.choices[0]?.message?.content?.split(" ").length || 0 | |
| ); | |
| } else { | |
| console.log("No active span found for second OpenAI call"); | |
| } | |
| return storyResponse; | |
| }); | |
| return result; | |
| } catch (error) { | |
| rootSpan.recordException(error as Error); | |
| rootSpan.setStatus({ | |
| code: 2, | |
| message: `Chained operations failed: ${(error as Error).message}`, | |
| }); | |
| throw error; | |
| } finally { | |
| rootSpan.end(); | |
| } | |
| }); | |
| } |
🤖 Prompt for AI Agents
In typescript/packages/traceai_openai/examples/manual.ts around lines 180 to
241, the chainedOperations function is missing a return statement for the result
of the inner async operation inside the manual span, causing it not to return
the final storyResponse. Additionally, it lacks error handling. Fix this by
adding a return statement before the inner tracer.startActiveSpan call to return
the storyResponse, and wrap the entire function body in a try-catch block to
catch and handle errors appropriately, such as logging the error and rethrowing
or returning a fallback value.
Pull Request
Description
Describe the changes in this pull request:
Checklist
Related Issues
Closes #<issue_number>
Summary by CodeRabbit
New Features
Documentation
Chores