<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: She11 QA</title>
    <description>The latest articles on DEV Community by She11 QA (@she11_qa).</description>
    <link>https://dev.to/she11_qa</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4079421%2Fd58c59f2-4f10-4f9e-b125-7dc79f2166db.png</url>
      <title>DEV Community: She11 QA</title>
      <link>https://dev.to/she11_qa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/she11_qa"/>
    <language>en</language>
    <item>
      <title>Organizing Application-Specific Artifacts in Automation Frameworks</title>
      <dc:creator>She11 QA</dc:creator>
      <pubDate>Thu, 27 Aug 2026 07:09:49 +0000</pubDate>
      <link>https://dev.to/she11_qa/organizing-application-specific-artifacts-in-automation-frameworks-57ga</link>
      <guid>https://dev.to/she11_qa/organizing-application-specific-artifacts-in-automation-frameworks-57ga</guid>
      <description>&lt;p&gt;Maintaining a clean and modular repository structure is essential when scaling test automation frameworks across multiple applications. A core practice is isolating &lt;strong&gt;application-specific artifacts&lt;/strong&gt; from shared resources.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Folder Purpose&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The HL-RLS_SpecificArtifacts directory stores files dedicated strictly to an individual application. This includes app-specific configurations, test data, documentation, and automation scripts directly tied to that project.&lt;/p&gt;

&lt;p&gt;Separating these assets ensures independence, allowing teams to work autonomously without breaking global configurations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to Include vs. What to Exclude&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Include (Application-Specific)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configuration Files:&lt;/strong&gt; Settings unique to the application (e.g., environment variables, app-specific configurations).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Test Data:&lt;/strong&gt; Datasets used solely by this application's test cases (e.g., custom mock data).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Documentation:&lt;/strong&gt; Workflows, setup guides, or instructions exclusive to the app.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automation Artifacts:&lt;/strong&gt; Unique test suites, helper scripts, or framework extensions tailored to this application.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Exclude (Move to Shared Directories)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Global/Shared Configurations:&lt;/strong&gt; Store multi-app settings in Shared Resources/Configs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Generic Test Data:&lt;/strong&gt; Place reusable mock data in Shared Resources/Reusable-Test-Data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Shared Libraries &amp;amp; Utilities:&lt;/strong&gt; Move general helper scripts or shared libraries to Shared Resources/Libraries or Automated-Utilities.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Temporary Files:&lt;/strong&gt; Avoid committing draft logs, unreviewed code, or personal developer files.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good Examples&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ApplicationConfig.yml – Defines app-specific deployment variables, URLs, or API keys.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TestData-SpecificApp.json – A mock dataset simulating specific user behavior for this application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CustomScripts.sh – Tailored automation steps for server setup or specific integrations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Anti-Examples (Belong in Shared Folders)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;GlobalConfig.json – Shared config file across all projects (move to Shared Resources/Configs).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CommonLoggingLibrary.js – Reusable logging utility (move to Shared Resources/Libraries).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TestData-Common.json – Generic test dataset used across multiple test suites (move to Shared Resources/Reusable-Test-Data).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaways &amp;amp; Best Practices&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Isolation:&lt;/strong&gt; Keep global and application-level concerns separate so teams can work independently without cross-contaminating shared logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Maintenance:&lt;/strong&gt; Regularly review and purge outdated, unused, or draft files to preserve workspace clarity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Exclusivity:&lt;/strong&gt; Only keep files in this directory if they apply exclusively to the target application.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;HL-RLS ( High-Level Release-Specific artifacts/configurations.)&lt;/p&gt;

</description>
      <category>bestpractices</category>
      <category>devops</category>
      <category>testing</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Building an AI Engineering Observability Platform for Test Automation</title>
      <dc:creator>She11 QA</dc:creator>
      <pubDate>Wed, 26 Aug 2026 06:57:58 +0000</pubDate>
      <link>https://dev.to/she11_qa/building-an-ai-engineering-observability-platform-for-test-automation-31em</link>
      <guid>https://dev.to/she11_qa/building-an-ai-engineering-observability-platform-for-test-automation-31em</guid>
      <description>&lt;p&gt;&lt;strong&gt;Building an AI Engineering Observability Platform for Test Automation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tracking static productivity percentages (e.g., 75%–80% savings) is no longer enough to prove real enterprise value. To provide transparency, governance, and business ROI, you must convert your AI-driven test automation framework into an &lt;strong&gt;AI Engineering Observability Platform.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Current Gap in the Model&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Many teams showcase an agentic setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;✅ Context Agent&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ Test Case Agent&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ Feature File Agent&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ Page Object Agent&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ Step Definition Agent&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While this tracks estimated effort reduction (e.g., 45 hrs → 9.5 hrs), stakeholders often ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;"How do we know AI actually did the work?"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"How many tokens were consumed?"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"What was generated daily?"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"What was the total cost?"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"How much effort did we save?"&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key Metrics to Track&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Agent Utilization Metrics&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Agent&lt;/th&gt;
&lt;th&gt;Executions&lt;/th&gt;
&lt;th&gt;Success Rate&lt;/th&gt;
&lt;th&gt;Avg Runtime&lt;/th&gt;
&lt;th&gt;Tokens Used&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Context Agent&lt;/td&gt;
&lt;td&gt;45&lt;/td&gt;
&lt;td&gt;98%&lt;/td&gt;
&lt;td&gt;35 sec&lt;/td&gt;
&lt;td&gt;120K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test Case Agent&lt;/td&gt;
&lt;td&gt;60&lt;/td&gt;
&lt;td&gt;95%&lt;/td&gt;
&lt;td&gt;50 sec&lt;/td&gt;
&lt;td&gt;850K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Feature Agent&lt;/td&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;99%&lt;/td&gt;
&lt;td&gt;20 sec&lt;/td&gt;
&lt;td&gt;150K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Page Object Agent&lt;/td&gt;
&lt;td&gt;35&lt;/td&gt;
&lt;td&gt;96%&lt;/td&gt;
&lt;td&gt;45 sec&lt;/td&gt;
&lt;td&gt;400K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Step Definition Agent&lt;/td&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;97%&lt;/td&gt;
&lt;td&gt;30 sec&lt;/td&gt;
&lt;td&gt;300K&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;2. Daily Productivity Output&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Manual&lt;/th&gt;
&lt;th&gt;AI&lt;/th&gt;
&lt;th&gt;Savings&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Test Cases Created&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;6.6X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Feature Files Created&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;td&gt;10X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Step Definitions&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;10X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Page Objects&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;8X&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;3. Time Savings Calculation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Log every LLM execution with telemetry attributes:&lt;br&gt;
{&lt;br&gt;
  "user": "Tester1",&lt;br&gt;
  "agent": "Test Case Agent",&lt;br&gt;
  "input_tokens": 3500,&lt;br&gt;
  "output_tokens": 6500,&lt;br&gt;
  "model": "GPT-4o",&lt;br&gt;
  "execution_time": "42 sec"&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Effort Comparison Example:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Context Generation:&lt;/strong&gt; 4 hrs (Manual) vs. 30 mins (AI)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Test Case Creation:&lt;/strong&gt; 8 hrs (Manual) vs. 1 hr (AI)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Feature File Creation:&lt;/strong&gt; 4 hrs (Manual) vs. 20 mins (AI)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Total Manual Effort:&lt;/strong&gt; 16 hrs | AI Effort: 1.8 hrs | Net Time Saved: 14.2 hrs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Quality Improvements&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;KPI&lt;/th&gt;
&lt;th&gt;Before AI&lt;/th&gt;
&lt;th&gt;After AI&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Test Coverage&lt;/td&gt;
&lt;td&gt;65%&lt;/td&gt;
&lt;td&gt;90%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Automation Coverage&lt;/td&gt;
&lt;td&gt;50%&lt;/td&gt;
&lt;td&gt;85%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Defect Leakage&lt;/td&gt;
&lt;td&gt;12%&lt;/td&gt;
&lt;td&gt;5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rework Rate&lt;/td&gt;
&lt;td&gt;18%&lt;/td&gt;
&lt;td&gt;7%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Future-State Architecture (MCP-Enabled)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Implement the Model Context Protocol (MCP) and telemetry to route logs from your agents directly to visualization tools like Power BI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Azure OpenAI -&amp;gt; Orchestrator&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Agents&lt;/strong&gt;: Context, Test Case, Feature, Step, Page Object&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Telemetry Layer:&lt;/strong&gt; Logs Prompts, Token Usage, Runtime Metrics, Cost Metrics, User Metrics, Generated Assets&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dashboard&lt;/strong&gt;: Power BI / Custom Observability Suite&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Core Steering Committee KPIs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When presenting to stakeholders, focus on these 8 KPIs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI Adoption Rate&lt;/strong&gt; (% of automation work generated by AI)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tokens Consumed&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cost per Story&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automation Assets Generated&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hours Saved&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Productivity Improvement %&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automation Coverage Increase&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Defect Reduction %&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Executive Summary Example:&lt;/strong&gt;&lt;br&gt;
"During July, the AI Automation Factory executed 5,200 agent workflows, consumed 42M tokens, generated 3,800 automation assets, reduced manual effort by 78%, saved 620 engineering hours, and improved automation coverage from 58% to 86%."&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>testing</category>
      <category>ai</category>
      <category>devops</category>
      <category>architecture</category>
    </item>
    <item>
      <title>A Unified KPI Framework for Automation Testing with Playwright &amp; JavaScript</title>
      <dc:creator>She11 QA</dc:creator>
      <pubDate>Wed, 26 Aug 2026 06:48:04 +0000</pubDate>
      <link>https://dev.to/she11_qa/a-unified-kpi-framework-for-automation-testing-with-playwright-javascript-2oce</link>
      <guid>https://dev.to/she11_qa/a-unified-kpi-framework-for-automation-testing-with-playwright-javascript-2oce</guid>
      <description>&lt;p&gt;Measuring the impact of test automation goes beyond simple pass/fail ratios. To demonstrate real engineering excellence and business value, automation metrics must capture execution speed, suite stability, test coverage, maintenance cost, and CI/CD integration.&lt;/p&gt;

&lt;p&gt;Here is a comprehensive, unified KPI framework designed specifically for &lt;strong&gt;Playwright &amp;amp; JavaScript&lt;/strong&gt; automation suites.&lt;/p&gt;




&lt;h3&gt;
  
  
  📊 Executive KPI Targets
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Target&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Execution Speed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Runtime Reduction&lt;/td&gt;
&lt;td&gt;50% ↓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Efficiency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Throughput&lt;/td&gt;
&lt;td&gt;+40% ↑&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Flaky Tests&lt;/td&gt;
&lt;td&gt;&amp;lt; 3%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reliability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Retry Dependency&lt;/td&gt;
&lt;td&gt;&amp;lt; 5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Coverage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Automation Coverage&lt;/td&gt;
&lt;td&gt;80%+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Quality&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Defect Leakage&lt;/td&gt;
&lt;td&gt;20–30% ↓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Productivity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Script Dev Time&lt;/td&gt;
&lt;td&gt;30% ↓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CI/CD&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Pipeline Time&lt;/td&gt;
&lt;td&gt;40% ↓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ROI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Automation ROI&lt;/td&gt;
&lt;td&gt;Positive (3–6 months)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual Effort Reduction&lt;/td&gt;
&lt;td&gt;30–50% ↓&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  1. Execution Efficiency &amp;amp; Speed
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Test Execution Time Reduction:&lt;/strong&gt; Target 40–60% reduction vs legacy frameworks like Selenium.
$$\text{Reduction \%} = \frac{\text{Old Time} - \text{New Time}}{\text{Old Time}} \times 100$$&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parallel Execution Efficiency:&lt;/strong&gt; Measure tests executed per hour and parallel thread utilization.
$$\text{Efficiency \%} = \frac{\text{Sequential Time} - \text{Parallel Time}}{\text{Sequential Time}} \times 100$$&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test Throughput:&lt;/strong&gt; Maximize total test cases executed per CI window.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD Pipeline Cycle Time:&lt;/strong&gt; Aim for a 30–40% total reduction in build + test execution duration.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Stability &amp;amp; Reliability
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flaky Test Rate:&lt;/strong&gt; Keep flaky tests under 2–3% by leveraging Playwright's native auto-waiting and resilient locators.
$$\text{Flakiness \%} = \frac{\text{Flaky Tests}}{\text{Total Tests}} \times 100$$&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retry Dependency Ratio:&lt;/strong&gt; Track the percentage of tests passing only after retries to minimize false positives.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Failure Root Cause Accuracy:&lt;/strong&gt; Target &amp;gt;90% of test failures pointing directly to genuine application defects rather than script instability.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Coverage Metrics
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automation Coverage:&lt;/strong&gt; Maintain 80%+ regression coverage across all functional scenarios.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-Browser &amp;amp; Device Coverage:&lt;/strong&gt; Measure test runs across Chromium, Firefox, and WebKit using Playwright’s native multi-browser support and device emulation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API + UI Balance:&lt;/strong&gt; Track distribution across API-level setup and UI assertion layers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Quality &amp;amp; Defect Metrics
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Defect Detection Efficiency (DDE):&lt;/strong&gt;
$$\text{DDE \%} = \frac{\text{Defects Found in Testing}}{\text{Total Defects}} \times 100$$&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Defect Leakage Reduction:&lt;/strong&gt; Target a 20–30% reduction in production defects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mean Time to Detect (MTTD):&lt;/strong&gt; Catch defects post-commit within minutes, not hours.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Productivity &amp;amp; Maintainability
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Script Development Time:&lt;/strong&gt; Aim for ~30% faster scripting using Playwright Codegen and concise JS APIs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reusability Index:&lt;/strong&gt; Track percentage of shared fixtures, hooks, and Page Object components.
$$\text{Reusability \%} = \frac{\text{Reusable Components}}{\text{Total Code}} \times 100$$&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintenance Effort:&lt;/strong&gt; Monitor hours spent updating selectors and test logic per sprint.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. Cost &amp;amp; ROI Calculation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automation ROI:&lt;/strong&gt;
$$\text{ROI} = \frac{\text{Manual Effort Saved} - \text{Automation Cost}}{\text{Automation Cost}}$$&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Optimization:&lt;/strong&gt; Target a 30–50% reduction in manual regression QA effort, achieving positive ROI within 3 to 6 months.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🚀 Why Playwright Delivers High ROI
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Faster execution&lt;/strong&gt; through isolated browser contexts and parallel execution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stable test runs&lt;/strong&gt; via auto-waiting and built-in network mocking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplified debugging&lt;/strong&gt; using Trace Viewer, automated video capture, and step-by-step DOM snapshots.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native CI/CD integration&lt;/strong&gt; designed for continuous delivery setups.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>testing</category>
      <category>playwright</category>
      <category>javascript</category>
      <category>devops</category>
    </item>
    <item>
      <title>Building an Automated QA KPI Dashboard for Playwright &amp; BDD Pipelines</title>
      <dc:creator>She11 QA</dc:creator>
      <pubDate>Wed, 26 Aug 2026 06:41:36 +0000</pubDate>
      <link>https://dev.to/she11_qa/building-an-automated-qa-kpi-dashboard-for-playwright-bdd-pipelines-31p7</link>
      <guid>https://dev.to/she11_qa/building-an-automated-qa-kpi-dashboard-for-playwright-bdd-pipelines-31p7</guid>
      <description>&lt;p&gt;Tracking test automation metrics manually often leads to outdated figures and missed engineering gaps. To solve this, automated reporting directly from your test suites—such as Playwright and Cucumber—provides clear visibility into health, execution speed, and coverage.&lt;/p&gt;

&lt;p&gt;Below is a breakdown of how to structure an &lt;strong&gt;Automation KPI Dashboard&lt;/strong&gt; to streamline test metrics, track trends, and establish actionable engineering goals.&lt;/p&gt;




&lt;h3&gt;
  
  
  Executive Summary Dashboard
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;KPI Metric&lt;/th&gt;
&lt;th&gt;Target&lt;/th&gt;
&lt;th&gt;Current Value&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Trend&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total Test Cases&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;100% coverage&lt;/td&gt;
&lt;td&gt;85%&lt;/td&gt;
&lt;td&gt;🟡 Partial&lt;/td&gt;
&lt;td&gt;↗️ Up&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Automated Test Coverage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;90%+&lt;/td&gt;
&lt;td&gt;78%&lt;/td&gt;
&lt;td&gt;🟡 Partial&lt;/td&gt;
&lt;td&gt;↗️ Up&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pass Rate (Last Run)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;95%+&lt;/td&gt;
&lt;td&gt;92%&lt;/td&gt;
&lt;td&gt;🟡 Partial&lt;/td&gt;
&lt;td&gt;↔️ Stable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Avg. Execution Time&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&amp;lt; 30 min&lt;/td&gt;
&lt;td&gt;28 min&lt;/td&gt;
&lt;td&gt;🟢 Good&lt;/td&gt;
&lt;td&gt;↘️ Down&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Flaky Test Rate&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&amp;lt; 2%&lt;/td&gt;
&lt;td&gt;1.5%&lt;/td&gt;
&lt;td&gt;🟢 Good&lt;/td&gt;
&lt;td&gt;↔️ Stable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Defects Detected&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;🟡 Review&lt;/td&gt;
&lt;td&gt;↔️ Stable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CI/CD Pipeline Success&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;td&gt;98%&lt;/td&gt;
&lt;td&gt;🟡 Partial&lt;/td&gt;
&lt;td&gt;↗️ Up&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  Key Metric Breakdowns
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Coverage &amp;amp; Execution
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Total Test Suite:&lt;/strong&gt; 120 tests (94 Automated, 26 Manual).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Latest Run (2026-05-29):&lt;/strong&gt; 94 executed — 87 passed, 7 failed, 0 skipped.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. Flakiness Tracking
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flaky Tests (Last 10 Runs):&lt;/strong&gt; 2 scenarios identified.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Top Offenders:&lt;/strong&gt;

&lt;ol&gt;
&lt;li&gt;Scenario A: UI timeout issues.&lt;/li&gt;
&lt;li&gt;Scenario B: Data synchronization lag.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. Defect Detection &amp;amp; CI/CD Performance
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Defect Lifecycle:&lt;/strong&gt; 3 opened, 1 closed (Avg. resolution time: 2 days).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pipeline Health:&lt;/strong&gt; 98% success rate, 12 min average build time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Primary Cause of Pipeline Failure:&lt;/strong&gt; Dependency resolution errors.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Execution &amp;amp; Pass Rate Trends (Last 6 Runs)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Run Date&lt;/th&gt;
&lt;th&gt;Pass %&lt;/th&gt;
&lt;th&gt;Fail %&lt;/th&gt;
&lt;th&gt;Flaky %&lt;/th&gt;
&lt;th&gt;Duration (min)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;2026-05-29&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;92%&lt;/td&gt;
&lt;td&gt;8%&lt;/td&gt;
&lt;td&gt;2%&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;2026-05-28&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;91%&lt;/td&gt;
&lt;td&gt;9%&lt;/td&gt;
&lt;td&gt;2%&lt;/td&gt;
&lt;td&gt;29&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;2026-05-27&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;90%&lt;/td&gt;
&lt;td&gt;10%&lt;/td&gt;
&lt;td&gt;3%&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;2026-05-26&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;89%&lt;/td&gt;
&lt;td&gt;11%&lt;/td&gt;
&lt;td&gt;3%&lt;/td&gt;
&lt;td&gt;31&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;2026-05-25&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;88%&lt;/td&gt;
&lt;td&gt;12%&lt;/td&gt;
&lt;td&gt;4%&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;2026-05-24&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;87%&lt;/td&gt;
&lt;td&gt;13%&lt;/td&gt;
&lt;td&gt;4%&lt;/td&gt;
&lt;td&gt;33&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  Next Engineering Action Items
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Automation Expansion:&lt;/strong&gt; Push total automated coverage past 90%.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flakiness Mitigation:&lt;/strong&gt; Refactor explicit waits and isolation for UI timeout and data sync scenarios.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pipeline Stability:&lt;/strong&gt; Resolve dependency caching errors to bring CI/CD success to 100%.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimization:&lt;/strong&gt; Lower execution suite duration below 25 minutes using parallel run setups.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Implementation Note:&lt;/strong&gt; This dashboard context can be auto-generated by parsing execution JSON outputs (from frameworks like Playwright or Cucumber BDD) directly into your CI/CD reporting artifacts after every major test cycle or sprint.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>testing</category>
      <category>automation</category>
      <category>devops</category>
      <category>javascript</category>
    </item>
    <item>
      <title>GenAI in Test Automation: Accelerating Testing with GitHub Copilot &amp; Agentic Solutions</title>
      <dc:creator>She11 QA</dc:creator>
      <pubDate>Tue, 25 Aug 2026 08:48:23 +0000</pubDate>
      <link>https://dev.to/she11_qa/genai-in-test-automation-accelerating-testing-with-github-copilot-agentic-solutions-1pj</link>
      <guid>https://dev.to/she11_qa/genai-in-test-automation-accelerating-testing-with-github-copilot-agentic-solutions-1pj</guid>
      <description>&lt;h1&gt;
  
  
  GenAI in Test Automation: Accelerating Testing with GitHub Copilot &amp;amp; Agentic Solutions
&lt;/h1&gt;

&lt;p&gt;Generative AI is shifting how quality assurance teams design, generate, and maintain test automation suites. By using GitHub Copilot (GHCP) alongside agentic workflows, software teams can significantly cut setup time while maintaining production-grade standards.&lt;/p&gt;

&lt;p&gt;Here is a practical framework for leveraging GenAI and agentic solutions to accelerate test automation.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Tooling &amp;amp; Core Capabilities
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Primary Tool:&lt;/strong&gt; GitHub Copilot (GHCP)&lt;/p&gt;

&lt;h3&gt;
  
  
  Framework &amp;amp; Language Support
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frameworks:&lt;/strong&gt; Selenium, Playwright, Cypress&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Languages:&lt;/strong&gt; Java, JavaScript, Python&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scope:&lt;/strong&gt; Web &amp;amp; API application testing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architectural Patterns:&lt;/strong&gt; Generates modular scripts using Page Object Model (POM), BDD, and Data-Driven Testing paradigms.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚡ Modes of Operation
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Mode:&lt;/strong&gt; Human-in-the-loop workflow tailored for prompt refinement and continuous validation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agentic Mode:&lt;/strong&gt; Autonomous end-to-end test generation, execution, and reporting pipeline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edit Mode:&lt;/strong&gt; Quick prompt-driven corrections and inline code modifications.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Crucial Rule:&lt;/strong&gt; Human-in-the-loop oversight is mandatory to validate, monitor, and correct generated outputs against real-world domain requirements.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  📋 Implementation Workflow
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Pre-requisites &amp;amp; Setup
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Configure &lt;strong&gt;GitHub Copilot, GHCP&lt;/strong&gt;, and relevant automation-oriented VSIX extensions in your IDE.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Format test cases in Markdown (Test ID, Objective, Steps, Expected Results, Test Data). Keep individual files under 20 MB.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Collect element locators (JSON, Excel, or Markdown format) and application configurations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: Prompt Engineering &amp;amp; Execution
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use prompt templates populated with your framework details, target language, and app context.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set explicit constraints, rules, and coding style guides within the prompt.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Process prompts through GHCP agentic workflows to generate test cases and code scripts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Execute generated test suites, evaluate performance metrics, and iteratively refine prompts.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Key Use Cases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scenario &amp;amp; Case Generation:&lt;/strong&gt; Automatically derive BDD or non-BDD user stories, scenarios, and test cases.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Manual to Automated Scripting:&lt;/strong&gt; Rapidly translate manual test documentation into executable code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Suite Maintenance:&lt;/strong&gt; Automate locator fixes and script updates whenever application flows change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Intelligent Prioritization:&lt;/strong&gt; Target tests based on risk, business criticality, and execution frequency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data &amp;amp; Reporting:&lt;/strong&gt; Automate test data creation and post-execution reporting.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📌 Best Practices Checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Human Oversight:&lt;/strong&gt; Always inspect AI-generated code for edge cases, logical errors, and adherence to company coding standards.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Track Impact Metrics:&lt;/strong&gt; Measure success by tracking output accuracy, test coverage improvements, bug reduction rates, and overall engineering time saved.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Document Structured Inputs:&lt;/strong&gt; Provide clean input context (BRD documents, locator files, code samples) to minimize hallucination risks during script generation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>testing</category>
      <category>ai</category>
      <category>githubcopilot</category>
      <category>automation</category>
    </item>
    <item>
      <title>Essential Git Commands for Feature Branch Workflow</title>
      <dc:creator>She11 QA</dc:creator>
      <pubDate>Tue, 25 Aug 2026 08:40:14 +0000</pubDate>
      <link>https://dev.to/she11_qa/essential-git-commands-for-feature-branch-workflow-2e13</link>
      <guid>https://dev.to/she11_qa/essential-git-commands-for-feature-branch-workflow-2e13</guid>
      <description>&lt;h1&gt;
  
  
  How to Switch, Sync, and Merge Git Branches in VS Code
&lt;/h1&gt;

&lt;p&gt;Keeping your feature or QA branch up to date with the main codebase is essential for preventing merge conflicts later down the line. Here is a quick reference guide on how to switch branches, fetch new remotes, and pull the latest changes into your branch using VS Code and Git terminal.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. How to Switch Branches in VS Code
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Using the Command Palette:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Press Ctrl + Shift + P (Windows/Linux) or Cmd + Shift + P (Mac).&lt;/li&gt;
&lt;li&gt;Type and select &lt;strong&gt;Git: Checkout to...&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select your target branch (e.g., your-feature-branch).&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Using the Terminal:
&lt;/h3&gt;

&lt;p&gt;If the branch hasn't been fetched locally yet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Fetch the specific branch from remote&lt;/span&gt;
git fetch origin your-feature-branch

&lt;span class="c"&gt;# Switch to the branch&lt;/span&gt;
git checkout your-feature-branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Syncing Your Branch with the Latest Main Code
&lt;/h2&gt;

&lt;p&gt;Follow these 5 steps to update your local working branch with the latest upstream code from main:&lt;/p&gt;

&lt;p&gt;Step 1: Switch to the Main Branch&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Pull Remote Changes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git pull origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 3: Return to Your Feature Branch&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout your-feature-branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 4: Merge Main into Your Branch&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git merge main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Handling Conflicts: If VS Code highlights merge conflicts, edit the files to resolve them, then stage and commit:&lt;br&gt;
git add .&lt;br&gt;
git commit -m "Merge main into your-feature-branch"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Step 5: Push Updates to Remote&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push origin your-feature-branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Quick Summary Checklist&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;git checkout main → Jump to main&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;git pull origin main → Get latest changes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;git checkout  → Return to your working branch&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;git merge main → Bring latest main changes into your branch&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;git push origin  → Push updated work to remote&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
      <category>vscode</category>
      <category>developer</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Setting Up a Playwright JavaScript BDD Automation Framework with Cucumber</title>
      <dc:creator>She11 QA</dc:creator>
      <pubDate>Tue, 25 Aug 2026 08:31:19 +0000</pubDate>
      <link>https://dev.to/she11_qa/setting-up-a-playwright-javascript-bdd-automation-framework-with-cucumber-1779</link>
      <guid>https://dev.to/she11_qa/setting-up-a-playwright-javascript-bdd-automation-framework-with-cucumber-1779</guid>
      <description>&lt;p&gt;Setting up a scalable test automation framework using Playwright JavaScript with BDD (Behavior-Driven Development) via Cucumber helps streamline testing and maintain consistency across complex test suites. &lt;/p&gt;

&lt;p&gt;Here is a step-by-step guide to onboarding and initializing this test environment.&lt;/p&gt;




&lt;h3&gt;
  
  
  Prerequisites &amp;amp; Tools
&lt;/h3&gt;

&lt;p&gt;Make sure you have the following software installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Recommended VS Code Extensions
&lt;/h3&gt;

&lt;p&gt;Open the Extensions tab in VS Code (Ctrl + Shift + X / Cmd + Shift + X) and install:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cucumber (Gherkin) Support&lt;/strong&gt; — Syntax highlighting and step definition navigation for .feature files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript / TypeScript Support&lt;/strong&gt; — Auto-completion and language tooling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ESLint&lt;/strong&gt; (Optional) — Code linting to maintain style rules and clean syntax.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Setup &amp;amp; Initialization Commands
&lt;/h3&gt;

&lt;p&gt;Clone the repository, navigate to your root workspace, and execute the following commands in your integrated terminal:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Install required project dependencies
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Download and configure required Playwright browser binaries
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx playwright &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--with-deps&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. Install Excel utility packages for handling test data
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;exceljs &lt;span class="nt"&gt;--save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. Optional security/vulnerability audit
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm audit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  5. Launch tests in Playwright's UI Mode for debugging
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run &lt;span class="nb"&gt;test&lt;/span&gt;/ui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Best Practices for BDD Automation Suites&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Align Feature Files with Test Specifications:&lt;/strong&gt; Always map .feature Gherkin steps directly against your functional requirements sheet to prevent missing coverage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Centralize Documentation:&lt;/strong&gt; Keep detailed architecture notes and setup guides inside the README.md file and a dedicated /doc folder for faster onboarding.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data Handling:&lt;/strong&gt; Use structured files (such as Excel via exceljs or JSON) to separate test scripts from dynamic test data.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>playwright</category>
      <category>testing</category>
      <category>bdd</category>
    </item>
    <item>
      <title>Fixing PowerShell Script Execution Policy Issue When Activating Python venv</title>
      <dc:creator>She11 QA</dc:creator>
      <pubDate>Tue, 25 Aug 2026 08:26:09 +0000</pubDate>
      <link>https://dev.to/she11_qa/fixing-powershell-script-execution-policy-issue-when-activating-python-venv-582j</link>
      <guid>https://dev.to/she11_qa/fixing-powershell-script-execution-policy-issue-when-activating-python-venv-582j</guid>
      <description>&lt;p&gt;When setting up a Python virtual environment on Windows, running .\venv\Scripts\activate in PowerShell often throws a script execution policy error (such as PSSecurityException or cannot be loaded because running scripts is disabled on this system).&lt;/p&gt;

&lt;p&gt;Here is a quick walkthrough to resolve this issue safely without disabling your system's global security policies.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Cause
&lt;/h3&gt;

&lt;p&gt;Windows PowerShell restricts script execution by default under the Restricted policy to prevent malicious scripts from executing. Because virtual environment activation scripts (Activate.ps1) are local scripts, PowerShell blocks them.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step-by-Step Fix
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Open PowerShell
&lt;/h4&gt;

&lt;p&gt;Launch PowerShell (or your integrated terminal in VS Code).&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Update Execution Policy for Current User
&lt;/h4&gt;

&lt;p&gt;Run the following command to allow locally generated scripts to execute for your Windows profile only:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Set-ExecutionPolicy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ExecutionPolicy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;RemoteSigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Scope&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CurrentUser&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why -Scope CurrentUser?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Scope limiting ensures you only grant permission to your current user session, eliminating the need to alter global system policies or risk security system-wide.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verification Workflow&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once the policy is set, you can create and activate your environment seamlessly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# 1. Create your virtual environment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-m&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;venv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;venv&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# 2. Activate the virtual environment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;\venv\Scripts\activate&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Output: Your prompt will now show the environment prefix:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# (.venv) PS C:\your-project-path&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error&lt;/strong&gt;: PowerShell blocks Activate.ps1.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fix&lt;/strong&gt;: Set -ExecutionPolicy RemoteSigned scoped to -Scope CurrentUser.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security&lt;/strong&gt;: Keeps remote unsigned scripts blocked while allowing local development tools to function smoothly.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>powershell</category>
      <category>windows</category>
      <category>developers</category>
    </item>
    <item>
      <title>Setting Up Playwright with JavaScript for Test Automation: Prerequisites &amp; VS Code Extensions</title>
      <dc:creator>She11 QA</dc:creator>
      <pubDate>Tue, 25 Aug 2026 08:20:04 +0000</pubDate>
      <link>https://dev.to/she11_qa/setting-up-playwright-with-javascript-for-test-automation-prerequisites-vs-code-extensions-181c</link>
      <guid>https://dev.to/she11_qa/setting-up-playwright-with-javascript-for-test-automation-prerequisites-vs-code-extensions-181c</guid>
      <description>&lt;p&gt;Setting up a new test automation framework can be tricky if you miss essential tools and extensions. Below is a structured checklist to get your environment fully prepared for automation testing using &lt;strong&gt;Playwright with JavaScript&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. Framework &amp;amp; Core Requirements
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Framework Type:&lt;/strong&gt; Playwright (JavaScript)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration:&lt;/strong&gt; settings.xml (shared via your internal communications channel)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repository:&lt;/strong&gt; xlc-portfolio-tech-shared-services/xlc-app-kc-test-automation&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2. Development Environment Setup
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;IDE:&lt;/strong&gt; Install &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration Files:&lt;/strong&gt; Ensure settings.xml and Framework.zip are downloaded and properly configured in your root workspace.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  3. Recommended VS Code Extensions
&lt;/h3&gt;

&lt;p&gt;To streamline writing BDD-style tests, running Playwright suites, and debugging, install the following extensions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Playwright &amp;amp; Testing:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Playwright Test Runner&lt;/li&gt;
&lt;li&gt;Playwright Test for VSCode&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BDD &amp;amp; Gherkin / Cucumber Support:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Cucumber&lt;/li&gt;
&lt;li&gt;Cucumber (Gherkin) Full Support&lt;/li&gt;
&lt;li&gt;Snippets and Syntax Highlight for Gherkin (Cucumber)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI &amp;amp; GitHub Integration:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;GitHub Copilot&lt;/li&gt;
&lt;li&gt;GitHub Copilot Chat&lt;/li&gt;
&lt;li&gt;GitHub Actions&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Quality &amp;amp; Utilities:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;ESLint&lt;/li&gt;
&lt;li&gt;XML Tools&lt;/li&gt;
&lt;li&gt;Rainbow CSV&lt;/li&gt;
&lt;li&gt;Excel Viewer&lt;/li&gt;
&lt;li&gt;Microsoft Edge Tools for VS Code&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  💡 Pro Tip
&lt;/h3&gt;

&lt;p&gt;Make sure all team members maintain identical VS Code extension sets to prevent formatting inconsistencies and ensure smooth local test runs!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>playwright</category>
      <category>testing</category>
      <category>automation</category>
    </item>
    <item>
      <title>Building an AI Test Automation Factory: How We Reduced Automation Effort by 78% with Multi-Agent Systems &amp; MCP</title>
      <dc:creator>She11 QA</dc:creator>
      <pubDate>Sat, 22 Aug 2026 09:25:45 +0000</pubDate>
      <link>https://dev.to/she11_qa/building-an-ai-test-automation-factory-how-we-reduced-automation-effort-by-78-with-multi-agent-45h3</link>
      <guid>https://dev.to/she11_qa/building-an-ai-test-automation-factory-how-we-reduced-automation-effort-by-78-with-multi-agent-45h3</guid>
      <description>&lt;p&gt;Traditional test automation frameworks often carry heavy maintenance costs, slow release cycles, and high knowledge dependency. By transitioning from standard script creation to a governed &lt;strong&gt;AI Test Automation Factory&lt;/strong&gt;, engineering teams can shift their focus from writing boilerplate code to high-value validation and architectural optimization.&lt;/p&gt;

&lt;p&gt;Here is an architectural breakdown of how multi-agent AI systems, governed telemetry, and Model Context Protocol (MCP) transform enterprise quality engineering.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem: The 45-Hour Manual Bottleneck&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Building a end-to-end BDD automation suite manually requires significant time per user story—often taking up to 45 hours across five distinct steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Context Generation &amp;amp; Requirements Review&lt;/strong&gt; (~8 hrs)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Manual Test Case Design&lt;/strong&gt; (~9 hrs)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cucumber Feature File Creation&lt;/strong&gt; (~8 hrs)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Page Object Model Generation&lt;/strong&gt; (~8 hrs)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Step Definition Implementation&lt;/strong&gt; (~10 hrs)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This traditional workflow creates coverage gaps, inconsistent code quality, and defect leakage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution: Multi-Agent AI Automation Pipeline&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of relying on single prompts, an AI Test Automation Factory routes requirement artifacts (BRDs / User Stories) through specialized agents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
[BRD / User Story] 
       │
       ▼
[Context Agent] ──► [Test Case Agent] ──► [Feature File Agent]
                                                  │
[Automation Suite] ◄── [Step Definition Agent] ◄── [Page Object Agent]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Context Agent:&lt;/strong&gt; Parses acceptance criteria and enterprise domain knowledge.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Test Case Agent:&lt;/strong&gt; Auto-generates exhaustive test scenario matrices.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Feature File Agent:&lt;/strong&gt; Drafts standardized BDD Cucumber feature files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Page Object &amp;amp; Step Def Agents:&lt;/strong&gt; Constructs clean design patterns (POM) and matching step implementations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Measurable ROI: Before vs. After AI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By replacing manual generation with agentic workflows, the effort to automate a scenario drops from &lt;strong&gt;45 hours to 9.5 hours:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;Manual Effort&lt;/th&gt;
&lt;th&gt;AI-Driven Effort&lt;/th&gt;
&lt;th&gt;Time Saved&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Context Generation&lt;/td&gt;
&lt;td&gt;8 hrs&lt;/td&gt;
&lt;td&gt;2 hrs&lt;/td&gt;
&lt;td&gt;75%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test Design&lt;/td&gt;
&lt;td&gt;9 hrs&lt;/td&gt;
&lt;td&gt;2 hrs&lt;/td&gt;
&lt;td&gt;78%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Feature File Creation&lt;/td&gt;
&lt;td&gt;8 hrs&lt;/td&gt;
&lt;td&gt;0.5 hrs&lt;/td&gt;
&lt;td&gt;94%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Page Object Creation&lt;/td&gt;
&lt;td&gt;8 hrs&lt;/td&gt;
&lt;td&gt;2 hrs&lt;/td&gt;
&lt;td&gt;75%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Step Definitions&lt;/td&gt;
&lt;td&gt;10 hrs&lt;/td&gt;
&lt;td&gt;3 hrs&lt;/td&gt;
&lt;td&gt;70%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total Effort&lt;/td&gt;
&lt;td&gt;45 hrs&lt;/td&gt;
&lt;td&gt;9.5 hrs&lt;/td&gt;
&lt;td&gt;78% Reduction&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Key Business Metrics:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Productivity Multiplier:&lt;/strong&gt; 4X Faster Delivery&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Test Coverage:&lt;/strong&gt; Increased from 65% to 90%&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Defect Leakage:&lt;/strong&gt; Reduced from 12% to 5%&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Overall Cost Footprint:&lt;/strong&gt; Scaled down to 22% of original baseline&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;AI Governance &amp;amp; Observability&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Enterprise deployment requires strict guardrails around LLM usage. A telemetry layer sits between the agents and executive reporting dashboards to monitor performance in real time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Token &amp;amp; Usage Tracking:&lt;/strong&gt; Daily audit trails for prompt/completion token consumption.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cost &amp;amp; Adoption Monitoring:&lt;/strong&gt; Sprint-by-sprint metrics tracking user engagement vs. API spend.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Executive Visibility:&lt;/strong&gt; Real-time Power BI reporting reflecting total hours saved and generated code assets.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Future: Autonomous Testing via MCP&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The future of QA lies in moving from &lt;strong&gt;AI-Assisted&lt;/strong&gt; generation to &lt;strong&gt;Autonomous Self-Healing Execution&lt;/strong&gt;. Leveraging the Model Context Protocol (MCP) enables seamless enterprise knowledge integration, allowing agents to directly query system context, adjust broken locators automatically, and deliver a fully autonomous QA pipeline.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>ai</category>
      <category>automation</category>
      <category>devops</category>
    </item>
    <item>
      <title>How to Configure Full Parallel Execution in TestNG via Maven (with Dynamic Thread Control)</title>
      <dc:creator>She11 QA</dc:creator>
      <pubDate>Sat, 22 Aug 2026 09:16:16 +0000</pubDate>
      <link>https://dev.to/she11_qa/how-to-configure-full-parallel-execution-in-testng-via-maven-with-dynamic-thread-control-o86</link>
      <guid>https://dev.to/she11_qa/how-to-configure-full-parallel-execution-in-testng-via-maven-with-dynamic-thread-control-o86</guid>
      <description>&lt;p&gt;Running automation test suites sequentially can quickly become a bottleneck in CI/CD pipelines. To optimize execution efficiency, you can enable full parallel execution using TestNG and Maven, allowing you to control thread counts dynamically right from the command line without modifying XML files every time.&lt;/p&gt;

&lt;p&gt;Here is a step-by-step guide on how to configure your framework for flexible parallel execution, along with a comparison of native TestNG execution versus custom Allocator/Run Manager approaches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step-by-Step Configuration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Update testng_regression.xml&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Modify the  tag to set your default parallel mode and thread count. You can set parallel to methods, classes, tests, or instances based on your architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;
&lt;span class="nt"&gt;&amp;lt;suite&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Regression"&lt;/span&gt; &lt;span class="na"&gt;parallel=&lt;/span&gt;&lt;span class="s"&gt;"methods"&lt;/span&gt; &lt;span class="na"&gt;thread-count=&lt;/span&gt;&lt;span class="s"&gt;"10"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Configure pom.xml for Dynamic Control&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To override these settings at runtime without touching the codebase, map properties inside the  block of the maven-surefire-plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;
&lt;span class="nt"&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;parallel&amp;gt;&lt;/span&gt;${parallel}&lt;span class="nt"&gt;&amp;lt;/parallel&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;threadCount&amp;gt;&lt;/span&gt;${threadCount}&lt;span class="nt"&gt;&amp;lt;/threadCount&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Command-Line Usage Examples&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once configured, you can pass parameters dynamically via Maven:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Default Run (10 threads):&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   mvn clean &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-P&lt;/span&gt; runTestNGTests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Thread Count (15 threads):&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
   mvn clean &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-P&lt;/span&gt; runTestNGTests &lt;span class="nt"&gt;-DthreadCount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Change Parallel Mode at Runtime:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
   mvn clean &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-P&lt;/span&gt; runTestNGTests &lt;span class="nt"&gt;-Dparallel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;classes &lt;span class="nt"&gt;-DthreadCount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;High-Throughput Run (Match CPU cores, e.g., 24 threads):&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
   mvn clean &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-P&lt;/span&gt; runTestNGTests &lt;span class="nt"&gt;-DthreadCount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;24
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Comparison: Native TestNG vs. Custom Excel Allocator&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If your framework currently uses a custom Excel-based Run Manager alongside native TestNG, here is how the two approaches compare:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature / Aspect&lt;/th&gt;
&lt;th&gt;Custom Allocator (Run Manager)&lt;/th&gt;
&lt;th&gt;Native TestNG&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Entry Point&lt;/td&gt;
&lt;td&gt;allocator.Allocator.main() via Maven exec plugin&lt;/td&gt;
&lt;td&gt;maven-surefire-plugin running testng.xml&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test Selection&lt;/td&gt;
&lt;td&gt;Reads Excel sheets via custom properties&lt;/td&gt;
&lt;td&gt;Reads testng_regression.xml classes/methods&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Thread Management&lt;/td&gt;
&lt;td&gt;Managed via custom ExecutorService&lt;/td&gt;
&lt;td&gt;Native TestNG thread pool (parallel + thread-count)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Execution Command&lt;/td&gt;
&lt;td&gt;mvn clean test -P runAllocator&lt;/td&gt;
&lt;td&gt;mvn clean test -P runTestNGTests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pros&lt;/td&gt;
&lt;td&gt;Data-driven via Excel; multi-sheet aggregation support&lt;/td&gt;
&lt;td&gt;Lightweight, faster startup, zero Excel dependencies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cons&lt;/td&gt;
&lt;td&gt;Requires global property tuning; code changes for structural updates&lt;/td&gt;
&lt;td&gt;Restricted to TestNG parallel modes (methods/classes)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Which Approach Should You Choose?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Choose Custom Allocator&lt;/strong&gt; if your suite relies heavily on fine-grained Excel-driven iteration control or multi-sheet test scheduling.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Choose Native TestNG&lt;/strong&gt; if you want a cleaner footprint, faster execution loops without file-parsing overhead, and straightforward CLI thread scaling.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>testing</category>
      <category>automation</category>
      <category>java</category>
      <category>devops</category>
    </item>
    <item>
      <title>Complete End-to-End OpenTelemetry Setup Guide for AI Agents &amp; Power BI Observability</title>
      <dc:creator>She11 QA</dc:creator>
      <pubDate>Fri, 21 Aug 2026 09:14:14 +0000</pubDate>
      <link>https://dev.to/she11_qa/complete-end-to-end-opentelemetry-setup-guide-for-ai-agents-power-bi-observability-4p66</link>
      <guid>https://dev.to/she11_qa/complete-end-to-end-opentelemetry-setup-guide-for-ai-agents-power-bi-observability-4p66</guid>
      <description>&lt;p&gt;&lt;strong&gt;OpenTelemetry E2E Setup Guide for AI Agents&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This guide shows how to set up end-to-end OpenTelemetry observability for AI agents, from local tracing to production export. It covers the OpenTelemetry Collector, Python and Node.js instrumentation, agent-specific spans, LLM and tool-call tracing, validation, and production recommendations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. What You Are Instrumenting&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For an AI agent, the most useful trace structure is a top-level agent run with child spans for every meaningful operation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
agent.run
|-- agent.plan
|-- llm.chat
|-- tool.call: knowledge_search
|-- retrieval.query
|-- memory.read
|-- llm.chat
|-- memory.write
`-- agent.finalize

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At minimum, trace these operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;agent.run : one full user request or autonomous task&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;llm.chat : each model call&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tool.call : each tool invocation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;retrieval.query : vector search, database lookup, or document retrieval&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;memory.read : agent memory lookup&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;memory.write : agent memory update&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;agent.handoff : transfer to another agent or human&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;agent.finalize : final response construction&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Recommended Architecture&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Agent Application
|
v
OTLP traces, metrics, logs
|
v
OpenTelemetry Collector
|
v Exporter
v
Observability Backend

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Common observability backends include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Jaeger&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Grafana Tempo&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Honeycomb&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Datadog&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New Relic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Azure Monitor&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AWS X-Ray&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Google Cloud Trace&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Elastic Observability&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For local development, you can start with the OpenTelemetry Collector plus a logging exporter. For production, send data from the Collector to your preferred backend.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Local OpenTelemetry Collector Setup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a file named otel-collector-config.yaml:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="na"&gt;receivers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;otlp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;protocols&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.0.0.0:4318&lt;/span&gt;
      &lt;span class="na"&gt;grpc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.0.0.0:4317&lt;/span&gt;

&lt;span class="na"&gt;processors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;batch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;exporters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;logging&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;verbosity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;detailed&lt;/span&gt;

&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pipelines&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;traces&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;receivers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;otlp&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;processors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;batch&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;exporters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;logging&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the Collector with Docker on Windows PowerShell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--rm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;4317:4317&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;4318:4318&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;-v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;${PWD}&lt;/span&gt;&lt;span class="s2"&gt;/otel-collector-config.yaml:/etc/otelcol/config.yaml"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nx"&gt;otel/opentelemetry-collector:latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the Collector on macOS or Linux:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 4317:4317 &lt;span class="nt"&gt;-p&lt;/span&gt; 4318:4318 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;&lt;span class="s2"&gt;/otel-collector-config.yaml:/etc/otelcol/config.yaml"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  otel/opentelemetry-collector:latest

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The local OTLP endpoints are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;HTTP: &lt;a href="http://localhost:4318/v1/traces" rel="noopener noreferrer"&gt;http://localhost:4318/v1/traces&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;gRPC: localhost:4317&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Python Agent Setup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Install dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create telemetry.py:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;opentelemetry&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;trace&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;opentelemetry.exporter.otlp.proto.http.trace_exporter&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OTLPSpanExporter&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;opentelemetry.sdk.resources&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Resource&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;opentelemetry.sdk.trace&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TracerProvider&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;opentelemetry.sdk.trace.export&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BatchSpanProcessor&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;configure_telemetry&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;service.name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent-service&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;service.version&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.0.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;deployment.environment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;local&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TracerProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;exporter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OTLPSpanExporter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:4318/v1/traces&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_span_processor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BatchSpanProcessor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exporter&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_tracer_provider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instrument the agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;opentelemetry&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;trace&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;opentelemetry.trace&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;StatusCode&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;telemetry&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;configure_telemetry&lt;/span&gt;

&lt;span class="nf"&gt;configure_telemetry&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;tracer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_tracer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent-service&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_as_current_span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent.run&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent.name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;support-agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent.version&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.0.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent.input.length&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_as_current_span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent.plan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;plan_span&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;plan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_plan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;plan_span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent.plan.steps&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_as_current_span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llm.chat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;llm_span&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;llm_span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gen_ai.system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;llm_span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gen_ai.operation.name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;chat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;llm_span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gen_ai.request.model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4.1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="n"&gt;llm_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;call_llm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="n"&gt;llm_span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gen_ai.response.model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4.1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;llm_span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gen_ai.usage.input_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;llm_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_tokens&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;llm_span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gen_ai.usage.output_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;llm_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output_tokens&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_as_current_span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool.call&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;tool_span&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;tool_span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool.name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;knowledge_search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;tool_span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool.call_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;llm_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tool_call_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="n"&gt;documents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;search_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;llm_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tool_query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="n"&gt;tool_span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool.success&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;tool_span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;retrieval.document_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_as_current_span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent.finalize&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;final_span&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;final_answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;produce_answer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;llm_response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;final_span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent.output.length&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;final_answer&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;final_answer&lt;/span&gt;

        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;record_exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;StatusCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Node.js or TypeScript Agent Setup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Install dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; @opentelemetry/api @opentelemetry/sdk-node @opentelemetry/exporter-trace-otlp-http
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create telemetry.ts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NodeSDK&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@opentelemetry/sdk-node&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;OTLPTraceExporter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@opentelemetry/exporter-trace-otlp-http&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;telemetrySdk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NodeSDK&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;agent-service&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;traceExporter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OTLPTraceExporter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:4318/v1/traces&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;startTelemetry&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;telemetrySdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;stopTelemetry&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;telemetrySdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instrument the agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SpanStatusCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;trace&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@opentelemetry/api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;startTelemetry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stopTelemetry&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./telemetry&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tracer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTracer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;agent-service&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;runAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userInput&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startActiveSpan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;agent.run&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;span&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;agent.name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;support-agent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;agent.version&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;agent.input.length&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;plan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startActiveSpan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;agent.plan&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;planSpan&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createPlan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userInput&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;planSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;agent.plan.steps&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;planSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;llmResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startActiveSpan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;llm.chat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;llmSpan&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;llmSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gen_ai.system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;openai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;llmSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gen_ai.operation.name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;chat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;llmSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gen_ai.request.model&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gpt-4.1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;callLlm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userInput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nx"&gt;llmSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gen_ai.response.model&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gpt-4.1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;llmSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gen_ai.usage.input_tokens&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inputTokens&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;llmSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gen_ai.usage.output_tokens&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;outputTokens&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;llmSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;documents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startActiveSpan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tool.call&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;toolSpan&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;toolSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tool.name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;knowledge_search&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;toolSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tool.call_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;llmResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toolCallId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;searchDocuments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;llmResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toolQuery&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nx"&gt;toolSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tool.success&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;toolSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;retrieval.document_count&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;toolSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;finalAnswer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startActiveSpan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;agent.finalize&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;finalSpan&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;produceAnswer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;llmResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;finalSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;agent.output.length&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;finalSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="nx"&gt;span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;finalAnswer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recordException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SpanStatusCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="nx"&gt;span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;startTelemetry&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;runAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;How do I reset my password?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;stopTelemetry&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;6. Recommended Span Attributes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use OpenTelemetry semantic conventions where possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GenAI Attributes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;gen_ai.system&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;gen_ai.operation.name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;gen_ai.request.model&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;gen_ai.response.model&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;gen_ai.request.temperature&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;gen_ai.request.max_tokens&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;gen_ai.usage.input_tokens&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;gen_ai.usage.output_tokens&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Agent Attributes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;agent.name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;agent.version&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;agent.run_id&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;agent.session_id&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;agent.step.name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;agent.step.index&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;agent.output.length&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;agent.input.length&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tool Attributes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;tool.name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tool.call_id&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tool.success&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tool.error.type&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tool.retry_count&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Retrieval Attributes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;retrieval.system&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;retrieval.index.name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;retrieval.query_count&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;retrieval.document_count&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;retrieval.top_k&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Memory Attributes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;memory.operation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;memory.scope&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;memory.result_count&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;7. What Not To Capture&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Do not capture sensitive or high-risk data as span attributes unless your organization has explicit approval, redaction, access control, and retention policies.&lt;/p&gt;

&lt;p&gt;Avoid storing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Full prompts&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Full model responses&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;User secrets&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;API keys or tokens&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Raw documents&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Email addresses&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Payment information&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Health data&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Authentication headers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Full tool outputs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Prefer safe metadata:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;prompt length&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;response length&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;token counts&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;model name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tool name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;status&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;latency&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;retry count&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;document count&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;8. Metrics To Add&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Traces show what happened for one request. Metrics show aggregate behavior.&lt;/p&gt;

&lt;p&gt;Recommended metrics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;agent.run.count&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;agent.run.duration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;agent.run.error.count&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;llm.request.count&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;llm.request.duration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;llm.token.input.count&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;llm.token.output.count&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tool.call.count&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tool.call.duration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tool.call.error.count&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;retrieval.query.count&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;retrieval.document.count&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;agent.handoff.count&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Start with traces first, then add metrics once your span structure is stable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9. Logging Setup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use logs for discrete application events, but correlate them with traces.&lt;/p&gt;

&lt;p&gt;Recommended log fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;trace_id&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;span_id&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;agent_run_id&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;agent.name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;event.name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;status&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;error.type&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;error.message&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep logs redacted. Avoid logging raw prompts, completions, credentials, or document bodies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;10. Validation Checklist&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use this checklist to verify the setup end to end.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Start the OpenTelemetry Collector.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run one local agent request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Confirm the Collector receives spans.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Confirm the root span is named agent.run.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Confirm LLM calls appear as llm.chat child spans.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Confirm tool calls appear as tool.call child spans.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Confirm errors are recorded on failed spans.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Confirm token usage attributes appear when available.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Confirm sensitive content is not exported.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Confirm traces reach your observability backend.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;11. Production Collector Example&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For production, route data through the Collector and export to your backend.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="na"&gt;otlp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;protocols&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;grpc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;processors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;batch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;memory_limiter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;check_interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1s&lt;/span&gt;
    &lt;span class="na"&gt;limit_mib&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;512&lt;/span&gt;
    &lt;span class="na"&gt;spike_limit_mib&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;128&lt;/span&gt;

&lt;span class="na"&gt;exporters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;otlphttp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://your-observability-backend.example.com&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;api-key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${OBSERVABILITY_API_KEY}&lt;/span&gt;

&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pipelines&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;traces&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;receivers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;otlp&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;processors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;memory_limiter&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;batch&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;exporters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;otlphttp&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set environment variables securely through your deployment platform, secret manager, or CI/CD system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;12. Production Hardening&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before production rollout:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add sampling if trace volume is high.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Redact sensitive inputs and outputs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add service names and versions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add deployment environment attributes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use secure OTLP endpoints.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Store backend API keys in a secret manager.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure retention policies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add alerts for agent error rate and high latency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Track model cost through token metrics.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Validate compliance requirements before exporting AI data.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;13. Sampling Guidance&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For development, sample everything.&lt;/p&gt;

&lt;p&gt;For production, consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;100% sampling for errors&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;100% sampling for low-volume critical workflows&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lower probabilistic sampling for high-volume successful requests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tail sampling when supported by your backend or Collector distribution&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example parent-based trace ID ratio sampling in Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;opentelemetry.sdk.trace&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TracerProvider&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;opentelemetry.sdk.trace.sampling&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ParentBased&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TraceIdRatioBased&lt;/span&gt;

&lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TracerProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;sampler&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;ParentBased&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TraceIdRatioBased&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This samples roughly 10% of new traces while preserving parent-child trace consistency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;14. Framework-Specific Notes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LangChain&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instrument the chain or agent executor as agent.run, then wrap model calls, retrievers, and tools as child spans. If you use callbacks, create spans inside callback handlers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Semantic Kernel&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Trace kernel invocation as agent.run, function calls as tool.call, planner execution as agent.plan, and AI service calls as llm.chat.&lt;br&gt;
AutoGen or Multi-Agent Systems&lt;br&gt;
Use one trace for the full multi-agent workflow. Each agent turn can be represented as agent.run or agent.step, with agent.name distinguishing participants. Handoffs should be explicit spans named agent.handoff.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custom Agents&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create spans directly around your orchestration code. This usually gives the best signal because you know where planning, memory, retrieval, tool execution, and finalization happen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;15. Minimal Rollout Plan&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add the OpenTelemetry SDK to the agent service.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Send traces to a local Collector.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a root agent.run span.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add child spans for LLM calls and tool calls.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Validate trace shape locally.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add retrieval and memory spans.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add token and latency attributes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add redaction rules.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Export from the Collector to your observability backend.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add dashboards and alerts.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;16. Example Dashboard Panels&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Useful panels for agent operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Agent run count by agent name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Agent error rate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Agent p50, p95, and p99 latency&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;LLM latency by model&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Input and output tokens by model&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tool call failure rate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Retrieval document count&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Handoff count&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Estimated model cost&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Top failing tools&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;17. Power BI Dashboard For Usage And Tokens&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Power BI should usually read from a queryable store, not directly from raw OpenTelemetry traces. Use OpenTelemetry for observability, then write a normalized usage table for reporting.&lt;/p&gt;

&lt;p&gt;Recommended flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Agent Application
|
v
OpenTelemetry traces and metrics
|
v
OpenTelemetry Collector
|
v Export
v
Azure Monitor, Log Analytics, SQL, Fabric Lakehouse, or Data Warehouse
|
v Power BI semantic model
v
Power BI dashboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Recommended Data Source Options&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use one of these patterns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Azure Monitor or Log Analytics if your traces already go to Azure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Application Insights if your application telemetry is already centralized there.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Azure SQL Database if you want simple relational reporting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Microsoft Fabric Lakehouse or Warehouse if you want scalable analytics.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Databricks, Snowflake, or BigQuery if your organization already uses one of them.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For most teams, the easiest production setup is to store one row per LLM request in a table named agent_llm_usage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Usage Table Schema&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a reporting table with stable, low-cardinality columns.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;agent_llm_usage&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;usage_id&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;trace_id&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;span_id&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;timestamp_utc&lt;/span&gt; &lt;span class="n"&gt;DATETIME2&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;environment&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;service_name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;agent_name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;agent_version&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;session_id&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_id_hash&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model_provider&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model_name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;operation_name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;input_tokens&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;output_tokens&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;total_tokens&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_tokens&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;output_tokens&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;estimated_cost_usd&lt;/span&gt; &lt;span class="nb"&gt;DECIMAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;duration_ms&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;error_type&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tool_name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;retrieval_document_count&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not store raw prompts, raw completions, secrets, full document text, or emails in this table. Use hashed user identifiers if user-level reporting is required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Writing Usage Records&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;OpenTelemetry spans should still include token attributes such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
gen_ai.usage.input_tokens
gen_ai.usage.output_tokens
gen_ai.request.model
gen_ai.system
agent.name
agent.session_id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Power BI, also write a compact business reporting event when each LLM call finishes. In Python, the event can be inserted into SQL, sent to Event Hubs, or written to your analytics pipeline.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;record_llm_usage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;usage_record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;usage_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usage_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trace_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trace_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;span_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;span_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timestamp_utc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamp_utc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;environment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;service_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent-service&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agent_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent_version&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agent_version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;session_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user_id_hash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_id_hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model_provider&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;operation_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;chat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;estimated_cost_usd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;estimated_cost_usd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;duration_ms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;duration_ms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;success&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;insert_usage_record&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;usage_record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Cost Calculation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Keep model pricing in a separate table so costs can be updated without changing historical usage records.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;model_pricing&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model_provider&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model_name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;effective_from_utc&lt;/span&gt; &lt;span class="n"&gt;DATETIME2&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;input_cost_per_1k_tokens&lt;/span&gt; &lt;span class="nb"&gt;DECIMAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;output_cost_per_1k_tokens&lt;/span&gt; &lt;span class="nb"&gt;DECIMAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The estimated cost formula is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
estimated_cost = (input_tokens / 1000 * input_price) + (output_tokens / 1000 * output_price)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can calculate this in the ingestion pipeline, SQL view, Fabric notebook, or Power BI semantic model. Pipeline or SQL calculation is usually better because all reports use the same cost logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Power BI Data Model&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use a simple star schema.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fact table:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;agent_llm_usage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Dimension tables:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;dim_date&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;dim_agent&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;dim_model&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;dim_environment&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;dim_tool&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Relationships:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;dim_date[date] -&amp;gt; agent_llm_usage[date]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;dim_agent[agent_name] -&amp;gt; agent_llm_usage[agent_name]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;dim_model[model_name] -&amp;gt; agent_llm_usage[model_name]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;dim_environment[environment] -&amp;gt; agent_llm_usage[environment]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;dim_tool[tool_name] -&amp;gt; agent_llm_usage[tool_name]&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Core DAX Measures&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create these measures in Power BI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Total Requests = 
COUNTROWS(agent_llm_usage)

Successful Requests = 
CALCULATE(
    COUNTROWS(agent_llm_usage),
    agent_llm_usage[status] = "success"
)

Failed Requests = 
CALCULATE(
    COUNTROWS(agent_llm_usage),
    agent_llm_usage[status] &amp;lt;&amp;gt; "success"
)

Failure Rate = 
DIVIDE([Failed Requests], [Total Requests])

Input Tokens = 
SUM(agent_llm_usage[input_tokens])

Output Tokens = 
SUM(agent_llm_usage[output_tokens])

Total Tokens = 
[Input Tokens] + [Output Tokens]

Estimated Cost USD = 
SUM(agent_llm_usage[estimated_cost_usd])

Average Duration MS = 
AVERAGE(agent_llm_usage[duration_ms])

Average Tokens Per Request = 
DIVIDE([Total Tokens], [Total Requests])

P95 Duration MS = 
PERCENTILEX.INC(
    agent_llm_usage,
    agent_llm_usage[duration_ms],
    0.95
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Recommended Power BI Pages&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create these report pages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Executive Overview&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Token Usage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cost Analysis&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Agent Performance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Model Performance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tool And Retrieval Usage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Errors And Reliability&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Recommended visuals for the Executive Overview page:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Card: total requests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Card: total tokens&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Card: estimated cost&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Card: failure rate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Line chart: requests by day&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Line chart: tokens by day&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bar chart: cost by agent&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bar chart: tokens by model&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Table: top agents by cost, tokens, and failures&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Recommended visuals for the Token Usage page:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Line chart: input tokens and output tokens over time&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stacked column chart: tokens by model&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Matrix: agent name by model name with total tokens&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Slicer: date range&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Recommended visuals for the Cost Analysis page:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Slicer: environment&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Slicer: agent name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Slicer: model name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Line chart: estimated cost by day&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bar chart: estimated cost by model&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bar chart: estimated cost by agent&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Table: session or hashed user groups by cost&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;KPI: cost per request&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Recommended visuals for the Errors And Reliability page:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Card: failed requests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Card: failure rate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Line chart: failures by day&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bar chart: errors by model&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bar chart: errors by tool&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Table: error type, agent name, model name, and count&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Refresh And Governance&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Recommended refresh setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Development: manual refresh&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Small production workload: scheduled refresh every 1 to 4 hours&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;High-volume production workload: Direct Lake, DirectQuery, or incremental refresh&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Governance recommendations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use row-level security if teams should only see their own agents.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Store only hashed user IDs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep prompt and completion content out of the reporting model.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Certify the semantic model once measures are validated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document model pricing assumptions and update them when provider pricing changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;18. Troubleshooting&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No Spans In Collector&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Collector is running.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;App exports to &lt;a href="http://localhost:4318/v1/traces" rel="noopener noreferrer"&gt;http://localhost:4318/v1/traces&lt;/a&gt; for OTLP HTTP.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Port 4318 is reachable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The SDK is initialized before the agent runs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The app shuts down cleanly so batch spans are flushed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Root Span Exists But Child Spans Are Missing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Child spans are created inside the active context.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Async operations preserve context.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Spans are ended after work completes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Exceptions do not skip span.end() in TypeScript.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Too Much Sensitive Data&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;No full prompts are added as attributes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No raw tool outputs are added as attributes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Logs do not contain secrets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Collector processors or backend rules redact known sensitive fields.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;High Trace Volume&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add sampling.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reduce span count for noisy internal steps.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep attributes low-cardinality.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Avoid unique values such as full user IDs, emails, or raw queries in indexed attributes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;19. Final Recommended Baseline&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A practical first production baseline is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Root span:
agent.run

Child spans:
agent.plan
llm.chat
tool.call
retrieval.query
memory.read
memory.write
agent.finalize

Required attributes:
service.name
deployment.environment
agent.name
agent.version
gen_ai.system
gen_ai.request.model
gen_ai.usage.input_tokens
gen_ai.usage.output_tokens
tool.name
tool.success
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives enough visibility to answer the most important operational questions: what happened, where time was spent, which model and tools were used, whether the run failed, and how much token usage it consumed.&lt;/p&gt;

</description>
      <category>opentelemetry</category>
      <category>python</category>
      <category>typescript</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
