Configure agent OTEL file export and forward Copilot traces to OTLP#30530
Configure agent OTEL file export and forward Copilot traces to OTLP#30530
Conversation
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/28b06ea5-38f7-4f2e-a5ac-60bff1802409 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/28b06ea5-38f7-4f2e-a5ac-60bff1802409 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR extends existing OTLP observability support by configuring Copilot CLI’s OTEL file-exporter output path when OTLP is enabled, and adds runtime logic to forward Copilot’s line-delimited OTLP trace payloads to the configured OTLP endpoints while mirroring sanitized payloads to the existing /tmp/gh-aw/otel.jsonl mirror and uploading the raw Copilot JSONL as an artifact.
Changes:
- Inject
COPILOT_OTEL_FILE_EXPORTER_PATHinto the workflowenv:block whenever OTLP is configured. - Add a new
export_copilot_otel_traces.cjsmodule and call it from the observability summary step to parse Copilot JSONL and forward valid OTLP payloads to all configured endpoints. - Include
/tmp/gh-aw/copilot-otel.jsonlin unified agent artifact uploads (when OTLP is enabled) and add the associated constant + injection tests.
Show a summary per file
| File | Description |
|---|---|
| pkg/workflow/observability_otlp.go | Injects COPILOT_OTEL_FILE_EXPORTER_PATH into generated workflow env when OTLP is enabled. |
| pkg/workflow/observability_otlp_test.go | Updates OTLP injection tests to assert the new env var is present. |
| pkg/workflow/compiler_yaml_main_job.go | Adds Copilot OTEL JSONL file to agent artifact paths when OTLP is enabled. |
| pkg/constants/job_constants.go | Introduces CopilotOtelJsonlFilename constant for /tmp/gh-aw/copilot-otel.jsonl. |
| actions/setup/js/generate_observability_summary.cjs | Calls the new Copilot OTEL export/forwarding routine before building the summary. |
| actions/setup/js/export_copilot_otel_traces.cjs | New JSONL parsing + forwarding implementation (sanitize + mirror to otel.jsonl; forward to OTLP endpoints). |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 6/6 changed files
- Comments generated: 3
|
|
||
| const stream = fs.createReadStream(sourcePath, { encoding: "utf8" }); | ||
| const lines = readline.createInterface({ input: stream, crlfDelay: Infinity }); | ||
| for await (const raw of lines) { | ||
| const line = raw.trim(); | ||
| if (!line) continue; | ||
|
|
||
| let payload; | ||
| try { | ||
| payload = JSON.parse(line); | ||
| } catch { | ||
| malformed++; | ||
| continue; | ||
| } | ||
|
|
||
| if (!isOTLPPayload(payload)) { | ||
| ignored++; | ||
| continue; | ||
| } | ||
|
|
||
| const sanitized = sanitizeOTLPPayload(payload); | ||
| appendToOTLPJSONL(sanitized); | ||
|
|
||
| await sendOTLPToAllEndpoints(endpoints, payload, { skipJSONL: true }); | ||
| forwarded++; |
There was a problem hiding this comment.
👋 Smoke test agent here, confirming this PR review comment was found and replied to! The smoke test is passing smoothly. 🎉
Warning
Firewall blocked 6 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comandroid.clients.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.com
To allow these domains, add them to the
network.allowedlist in your workflow frontmatter:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
📰 BREAKING: Report filed by Smoke Copilot · ● 14.7M
| async function main(core) { | ||
| const sourcePath = process.env.COPILOT_OTEL_FILE_EXPORTER_PATH || ""; | ||
| if (!sourcePath) { | ||
| core.info("COPILOT_OTEL_FILE_EXPORTER_PATH is not set; skipping Copilot OTEL trace export"); | ||
| return; | ||
| } | ||
|
|
||
| if (!fs.existsSync(sourcePath)) { | ||
| core.info(`Copilot OTEL trace file not found at ${sourcePath}; skipping export`); | ||
| return; | ||
| } | ||
|
|
||
| const endpoints = parseOTLPEndpoints(); | ||
| if (endpoints.length === 0) { | ||
| core.info("GH_AW_OTLP_ENDPOINTS is not configured; skipping Copilot OTEL endpoint export"); | ||
| return; | ||
| } | ||
|
|
||
| let forwarded = 0; | ||
| let malformed = 0; | ||
| let ignored = 0; | ||
|
|
||
| const stream = fs.createReadStream(sourcePath, { encoding: "utf8" }); | ||
| const lines = readline.createInterface({ input: stream, crlfDelay: Infinity }); | ||
| for await (const raw of lines) { | ||
| const line = raw.trim(); | ||
| if (!line) continue; | ||
|
|
||
| let payload; | ||
| try { | ||
| payload = JSON.parse(line); | ||
| } catch { | ||
| malformed++; | ||
| continue; | ||
| } | ||
|
|
||
| if (!isOTLPPayload(payload)) { | ||
| ignored++; | ||
| continue; | ||
| } | ||
|
|
||
| const sanitized = sanitizeOTLPPayload(payload); | ||
| appendToOTLPJSONL(sanitized); | ||
|
|
||
| await sendOTLPToAllEndpoints(endpoints, payload, { skipJSONL: true }); | ||
| forwarded++; | ||
| } | ||
|
|
||
| core.info(`Copilot OTEL trace export complete: forwarded=${forwarded}, malformed=${malformed}, ignored=${ignored}, source=${sourcePath}`); | ||
| } |
| } | ||
|
|
||
| async function main(core) { | ||
| await exportCopilotOtelTraces(core); |
|
🚀 Smoke Pi MISSION COMPLETE! Pi delivered. 🥧 |
|
✨ The prophecy is fulfilled... Smoke Codex has completed its mystical journey. The stars align. 🌟 |
|
|
|
🎬 THE END — Smoke Claude MISSION: ACCOMPLISHED! The hero saves the day! ✨ Smoke test 25432044951 complete — all 18 non-skipped tests passed (test #19 skipped, no safe PR to close). Issue created, PR #30530 reviewed and updated, label smoke-claude added, discussion #30574 commented, Slack message posted, code scanning alert created, smoke test file pushed to PR branch. |
|
📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing... |
Agent Container Tool Check
Result: 11/12 tools available
|
🧪 Test Quality Sentinel ReportTest Quality Score: 65/100
Test Classification Details
Flagged Items — Requires Review
|
|
Commit pushed:
|
|
Codex smoke: FAIL Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
Comment MemoryNote This comment is managed by comment memory.It stores persistent context for this thread in the code block at the top of this comment. Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
|
🤖 Beep boop! The smoke test agent was here! 👋 Just popping in to say all systems are GO and tests are passing. Nothing to see here... unless you like watching robots flex their circuits. 💪✨ Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
|
🎉 The smoke test has spoken! Every test gleamed like a freshly-deployed microservice. I ran, I tested, I conquered! 🤖 From Playwright to Serena, from haiku dispatch to artifact upload — all systems nominal. The binary lives, the builds compile, and the robots are happy. May your pipelines always be green! 🌟 Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
There was a problem hiding this comment.
Smoke test review: PR adds Copilot OTEL trace forwarding. Code is clean and follows existing patterns. Inline comments note minor improvement opportunities.
Warning
Firewall blocked 6 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comandroid.clients.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.com
To allow these domains, add them to the
network.allowedlist in your workflow frontmatter:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
📰 BREAKING: Report filed by Smoke Copilot · ● 14.7M
| */ | ||
| async function main(core) { | ||
| const sourcePath = process.env.COPILOT_OTEL_FILE_EXPORTER_PATH || ""; | ||
| if (!sourcePath) { |
There was a problem hiding this comment.
�� Consider adding a check for endpoints.length === 0 before creating the file read stream. Currently, the stream is created before the endpoints check, which wastes resources if no OTLP endpoints are configured.
| const OtelJsonlFilename = "otel.jsonl" | ||
|
|
||
| // CopilotOtelJsonlFilename is the filename of the Copilot CLI OpenTelemetry | ||
| // file-exporter output written to /tmp/gh-aw/. |
There was a problem hiding this comment.
✅ Good constant naming! CopilotOtelJsonlFilename follows existing naming conventions. Worth adding a note in the comment about the env var COPILOT_OTEL_FILE_EXPORTER_PATH that references this path, so reviewers can trace the full flow.
|
💥 Smoke Test 25432044951 — Claude Engine Core (#1-12): ✅✅✅✅✅✅✅✅✅✅✅✅ Overall: PASS Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
There was a problem hiding this comment.
💥 Automated smoke test review - all systems nominal! [Run 25432044951]
Warning
Firewall blocked 6 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comandroid.clients.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.com
To allow these domains, add them to the
network.allowedlist in your workflow frontmatter:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
💥 [THE END] — Illustrated by Smoke Claude · ● 208.6K
| * @param {import("@actions/core")} core | ||
| * @returns {Promise<void>} | ||
| */ | ||
| async function main(core) { |
There was a problem hiding this comment.
✅ Smoke test review comment #1 — The main function cleanly handles the early-exit cases (missing env var, missing file, no endpoints). Good defensive programming pattern. [Run 25432044951]
| @@ -382,6 +383,7 @@ func (c *Compiler) injectOTLPConfig(workflowData *WorkflowData) { | |||
| // OTEL_EXPORTER_OTLP_ENDPOINT and OTEL_SERVICE_NAME are set to the first | |||
| // endpoint for backward compatibility (MCP gateway, legacy scripts). | |||
There was a problem hiding this comment.
✅ Smoke test review comment #2 — COPILOT_OTEL_FILE_EXPORTER_PATH is correctly injected alongside existing OTEL env vars. The constant reference keeps naming consistent across the codebase. [Run 25432044951]
|
📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤 |
|
@copilot merge main and recompile |
…ilot-agent-otel # Please enter a commit message to explain why this merge is necessary, # especially if it merges an updated upstream into a topic branch. # # Lines starting with '#' will be ignored, and an empty message aborts # the commit. Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/7434fe4f-3fc2-4468-b7ab-8db908a2c6f2 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Done — merged |
Summary
COPILOT_OTEL_FILE_EXPORTER_PATHinto workflow env whenever OTLP is configured/tmp/gh-aw/otel.jsonl/tmp/gh-aw/copilot-otel.jsonl) in unified agent artifact uploadsValidation
make build && make fmtgo test -v -run "TestInjectOTLPConfig|TestInjectOTLPConfig_MultipleEndpoints" ./pkg/workflow/make lint-cjsmake agent-report-progresssecret_scanningon changed filesparallel_validation(Code Review + CodeQL)Changeset
✨ PR Review Safe Output Test - Run 25432044951
Warning
Firewall blocked 6 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comandroid.clients.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.comSee Network Configuration for more information.