Skip to content

feat(error-tracking): add ambient trace IDs to exceptions - #262

Merged
pauldambra merged 3 commits into
mainfrom
posthog/exception-trace-context
Oct 19, 2026
Merged

pauldambra merged 3 commits into
mainfrom
posthog/exception-trace-context

Conversation

@pauldambra

@pauldambra pauldambra commented Oct 16, 2026 •

Copy link
Copy Markdown
Member

[Robot] Draft prepared with Codex.

💡 Motivation and Context

Developers need to find the trace for a captured error. PHP exception events do not include IDs from the active OpenTelemetry span.

  • Add $trace_id and $span_id to manual and automatic exception events when the application provides a valid active span.
  • Preserve leading zeros, unsampled spans, and caller property precedence. Failed lookups still capture the exception.
  • Use OpenTelemetry as a development-only test dependency. Add a minor release intent and regenerate the API snapshot for the internal helper.

This draft implements the proposed exception trace contract and waits for agreement there before merge.

💚 How did you test it?

  • Reproduced missing IDs and request-property overrides before their fixes, then ran the complete PHPUnit suite on PHP 8.5.
  • Added parameterized tests for real OpenTelemetry spans, invalid IDs, event and request property precedence, empty caller values, and context cleanup.
  • Tested missing API and autoload failures in separate processes, plus context read failure and automatic capture.
  • Passed all 16 compliance-adapter tests, Composer validation, public API snapshot check, and PHP formatting.
  • PHP_CodeSniffer reports no errors. Existing line-length warnings and PHP/PHPUnit deprecations remain non-blocking.

📝 Checklist

  • I reviewed the submitted code.
  • I added tests to verify the changes.
  • I updated the docs if needed. Usage documentation lives on posthog.com; no scoped document exists in this repository.
  • No breaking change or entry added to the changelog.

If releasing new changes

  • Ran pnpm change to generate a change intent file. Added the change intent directly because the pinned pnpm download failed certificate validation.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Codex (gpt-6) used shell commands, Git, Composer, PHPUnit, PHP_CodeSniffer, and the GitHub CLI. The change uses one shared internal helper for manual and automatic capture. OpenTelemetry remains optional at runtime. Human review is required. Skills: writing-tests and writing-pr-descriptions.


Created with PostHog Desktop

Generated-By: PostHog Desktop
Task-Id: 5681be44-4986-48db-b140-1bda88f75f96
@pauldambra pauldambra self-assigned this Oct 16, 2026

@posthog posthog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

PostHog Review · Standard · reviewed e0f393c: 1 Should fix.

This is the only automatic review while this pull request is a draft. Comment @posthog review to review new changes sooner. Otherwise, a review of the new changes runs when you mark it ready for review.

Comment thread lib/Client.php
@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

posthog-php-fork_curl Compliance Report

Date: 2026-10-19T11:28:09.790243+00:00
Duration: 112942ms

⚠️ Some Tests Failed

36/47 tests passed, 11 failed


Capture Tests

⚠️ 19/30 tests passed, 11 failed

View Details
Test Status Duration
Format Validation.Event Has Required Fields ✅ 35ms
Format Validation.Event Has Uuid ✅ 530ms
Format Validation.Event Has Lib Properties ✅ 531ms
Format Validation.Distinct Id Is String ✅ 530ms
Format Validation.Token Is Present ✅ 530ms
Format Validation.Custom Properties Preserved ✅ 533ms
Format Validation.Event Has Timestamp ✅ 531ms
Format Validation.Non Utc Event Timestamp Is Converted To Utc ✅ 531ms
Retry Behavior.Retries On 503 ❌ 5532ms
Retry Behavior.Does Not Retry On 400 ✅ 2536ms
Retry Behavior.Does Not Retry On 401 ✅ 2532ms
Retry Behavior.Respects Retry After Header ❌ 5537ms
Retry Behavior.Implements Backoff ❌ 15548ms
Retry Behavior.Retries On 500 ❌ 5536ms
Retry Behavior.Retries On 502 ❌ 5538ms
Retry Behavior.Retries On 504 ❌ 5540ms
Retry Behavior.Max Retries Respected ❌ 15545ms
Deduplication.Generates Unique Uuids ✅ 539ms
Deduplication.Preserves Uuid On Retry ❌ 5536ms
Deduplication.Preserves Uuid And Timestamp On Retry ❌ 10544ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry ❌ 5538ms
Deduplication.No Duplicate Events In Batch ✅ 541ms
Deduplication.Different Events Have Different Uuids ✅ 534ms
Compression.Sends Gzip When Enabled ✅ 533ms
Batch Format.Uses Proper Batch Structure ✅ 531ms
Batch Format.Flush With No Events Sends Nothing ✅ 519ms
Batch Format.Multiple Events Batched Together ✅ 521ms
Error Handling.Does Not Retry On 403 ✅ 2533ms
Error Handling.Does Not Retry On 413 ✅ 2535ms
Error Handling.Retries On 408 ❌ 5531ms

Failures

retry_behavior.retries_on_503

Expected at least 3 requests, got 1

retry_behavior.respects_retry_after_header

Expected at least 2 requests, got 1

retry_behavior.implements_backoff

Expected at least 3 requests, got 1

retry_behavior.retries_on_500

Expected at least 2 requests, got 1

retry_behavior.retries_on_502

Expected at least 2 requests, got 1

retry_behavior.retries_on_504

Expected at least 2 requests, got 1

retry_behavior.max_retries_respected

Expected 4 requests, got 1

deduplication.preserves_uuid_on_retry

Need at least 2 requests to check retry

deduplication.preserves_uuid_and_timestamp_on_retry

Expected at least 3 requests, got 1

deduplication.preserves_uuid_and_timestamp_on_batch_retry

Expected at least 2 requests, got 1

error_handling.retries_on_408

Expected at least 2 requests, got 1

Feature_Flags Tests

✅ 17/17 tests passed

View Details
Test Status Duration
Request Payload.Request With Person Properties Device Id ✅ 528ms
Request Payload.Flags Request Uses V2 Query Param ✅ 522ms
Request Payload.Flags Request Hits Flags Path Not Decide ✅ 522ms
Request Payload.Flags Request Omits Authorization Header ✅ 523ms
Request Payload.Token In Flags Body Matches Init ✅ 522ms
Request Payload.Groups Round Trip ✅ 521ms
Request Payload.Groups Default To Empty Object ✅ 522ms
Request Payload.Disable Geoip False Propagates As Geoip Disable False ✅ 521ms
Request Payload.Disable Geoip Omitted Defaults To False ✅ 522ms
Request Payload.Flag Keys To Evaluate Contains Only Requested Key ✅ 522ms
Request Lifecycle.No Flags Request On Init Alone ✅ 517ms
Request Lifecycle.No Flags Request On Normal Capture ✅ 517ms
Request Lifecycle.Two Flag Calls Produce Two Remote Requests ✅ 524ms
Request Lifecycle.Mock Response Value Is Returned To Caller ✅ 524ms
Retry Behavior.Retries Flags On 502 ✅ 626ms
Retry Behavior.Retries Flags On 504 ✅ 624ms
Side Effect Events.Get Feature Flag Captures Feature Flag Called Event ✅ 532ms

@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

posthog-php-lib_curl Compliance Report

Date: 2026-10-19T11:27:58.320958+00:00
Duration: 118858ms

✅ All Tests Passed!

47/47 tests passed


Capture Tests

✅ 30/30 tests passed

View Details
Test Status Duration
Format Validation.Event Has Required Fields ✅ 29ms
Format Validation.Event Has Uuid ✅ 523ms
Format Validation.Event Has Lib Properties ✅ 525ms
Format Validation.Distinct Id Is String ✅ 525ms
Format Validation.Token Is Present ✅ 525ms
Format Validation.Custom Properties Preserved ✅ 524ms
Format Validation.Event Has Timestamp ✅ 525ms
Format Validation.Non Utc Event Timestamp Is Converted To Utc ✅ 525ms
Retry Behavior.Retries On 503 ✅ 5834ms
Retry Behavior.Does Not Retry On 400 ✅ 2526ms
Retry Behavior.Does Not Retry On 401 ✅ 2529ms
Retry Behavior.Respects Retry After Header ✅ 8534ms
Retry Behavior.Implements Backoff ✅ 16248ms
Retry Behavior.Retries On 500 ✅ 5635ms
Retry Behavior.Retries On 502 ✅ 5633ms
Retry Behavior.Retries On 504 ✅ 5632ms
Retry Behavior.Max Retries Respected ✅ 17048ms
Deduplication.Generates Unique Uuids ✅ 234ms
Deduplication.Preserves Uuid On Retry ✅ 5631ms
Deduplication.Preserves Uuid And Timestamp On Retry ✅ 10842ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry ✅ 5637ms
Deduplication.No Duplicate Events In Batch ✅ 531ms
Deduplication.Different Events Have Different Uuids ✅ 526ms
Compression.Sends Gzip When Enabled ✅ 525ms
Batch Format.Uses Proper Batch Structure ✅ 525ms
Batch Format.Flush With No Events Sends Nothing ✅ 520ms
Batch Format.Multiple Events Batched Together ✅ 514ms
Error Handling.Does Not Retry On 403 ✅ 2528ms
Error Handling.Does Not Retry On 413 ✅ 2526ms
Error Handling.Retries On 408 ✅ 5634ms

Feature_Flags Tests

✅ 17/17 tests passed

View Details
Test Status Duration
Request Payload.Request With Person Properties Device Id ✅ 524ms
Request Payload.Flags Request Uses V2 Query Param ✅ 522ms
Request Payload.Flags Request Hits Flags Path Not Decide ✅ 523ms
Request Payload.Flags Request Omits Authorization Header ✅ 523ms
Request Payload.Token In Flags Body Matches Init ✅ 523ms
Request Payload.Groups Round Trip ✅ 523ms
Request Payload.Groups Default To Empty Object ✅ 523ms
Request Payload.Disable Geoip False Propagates As Geoip Disable False ✅ 522ms
Request Payload.Disable Geoip Omitted Defaults To False ✅ 523ms
Request Payload.Flag Keys To Evaluate Contains Only Requested Key ✅ 523ms
Request Lifecycle.No Flags Request On Init Alone ✅ 519ms
Request Lifecycle.No Flags Request On Normal Capture ✅ 508ms
Request Lifecycle.Two Flag Calls Produce Two Remote Requests ✅ 527ms
Request Lifecycle.Mock Response Value Is Returned To Caller ✅ 526ms
Retry Behavior.Retries Flags On 502 ✅ 626ms
Retry Behavior.Retries Flags On 504 ✅ 625ms
Side Effect Events.Get Feature Flag Captures Feature Flag Called Event ✅ 525ms

@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

posthog-php-socket Compliance Report

Date: 2026-10-19T11:28:36.265676+00:00
Duration: 148811ms

⚠️ Some Tests Failed

36/47 tests passed, 11 failed


Capture Tests

⚠️ 19/30 tests passed, 11 failed

View Details
Test Status Duration
Format Validation.Event Has Required Fields ✅ 20ms
Format Validation.Event Has Uuid ✅ 516ms
Format Validation.Event Has Lib Properties ✅ 517ms
Format Validation.Distinct Id Is String ✅ 517ms
Format Validation.Token Is Present ✅ 516ms
Format Validation.Custom Properties Preserved ✅ 518ms
Format Validation.Event Has Timestamp ✅ 516ms
Format Validation.Non Utc Event Timestamp Is Converted To Utc ✅ 518ms
Retry Behavior.Retries On 503 ❌ 9224ms
Retry Behavior.Does Not Retry On 400 ✅ 2521ms
Retry Behavior.Does Not Retry On 401 ✅ 2521ms
Retry Behavior.Respects Retry After Header ❌ 9226ms
Retry Behavior.Implements Backoff ❌ 19238ms
Retry Behavior.Retries On 500 ❌ 9225ms
Retry Behavior.Retries On 502 ❌ 8731ms
Retry Behavior.Retries On 504 ❌ 9229ms
Retry Behavior.Max Retries Respected ❌ 19238ms
Deduplication.Generates Unique Uuids ✅ 523ms
Deduplication.Preserves Uuid On Retry ❌ 9227ms
Deduplication.Preserves Uuid And Timestamp On Retry ❌ 14233ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry ❌ 9230ms
Deduplication.No Duplicate Events In Batch ✅ 523ms
Deduplication.Different Events Have Different Uuids ✅ 517ms
Compression.Sends Gzip When Enabled ✅ 518ms
Batch Format.Uses Proper Batch Structure ✅ 517ms
Batch Format.Flush With No Events Sends Nothing ✅ 515ms
Batch Format.Multiple Events Batched Together ✅ 508ms
Error Handling.Does Not Retry On 403 ✅ 2519ms
Error Handling.Does Not Retry On 413 ✅ 2519ms
Error Handling.Retries On 408 ❌ 5522ms

Failures

retry_behavior.retries_on_503

Expected at least 3 requests, got 1

retry_behavior.respects_retry_after_header

Expected at least 2 requests, got 1

retry_behavior.implements_backoff

Expected at least 3 requests, got 1

retry_behavior.retries_on_500

Expected at least 2 requests, got 1

retry_behavior.retries_on_502

Expected at least 2 requests, got 1

retry_behavior.retries_on_504

Expected at least 2 requests, got 1

retry_behavior.max_retries_respected

Expected 4 requests, got 1

deduplication.preserves_uuid_on_retry

Need at least 2 requests to check retry

deduplication.preserves_uuid_and_timestamp_on_retry

Expected at least 3 requests, got 1

deduplication.preserves_uuid_and_timestamp_on_batch_retry

Expected at least 2 requests, got 1

error_handling.retries_on_408

Expected at least 2 requests, got 1

Feature_Flags Tests

✅ 17/17 tests passed

View Details
Test Status Duration
Request Payload.Request With Person Properties Device Id ✅ 517ms
Request Payload.Flags Request Uses V2 Query Param ✅ 515ms
Request Payload.Flags Request Hits Flags Path Not Decide ✅ 516ms
Request Payload.Flags Request Omits Authorization Header ✅ 515ms
Request Payload.Token In Flags Body Matches Init ✅ 517ms
Request Payload.Groups Round Trip ✅ 515ms
Request Payload.Groups Default To Empty Object ✅ 516ms
Request Payload.Disable Geoip False Propagates As Geoip Disable False ✅ 516ms
Request Payload.Disable Geoip Omitted Defaults To False ✅ 514ms
Request Payload.Flag Keys To Evaluate Contains Only Requested Key ✅ 516ms
Request Lifecycle.No Flags Request On Init Alone ✅ 512ms
Request Lifecycle.No Flags Request On Normal Capture ✅ 507ms
Request Lifecycle.Two Flag Calls Produce Two Remote Requests ✅ 518ms
Request Lifecycle.Mock Response Value Is Returned To Caller ✅ 517ms
Retry Behavior.Retries Flags On 502 ✅ 616ms
Retry Behavior.Retries Flags On 504 ✅ 618ms
Side Effect Events.Get Feature Flag Captures Feature Flag Called Event ✅ 518ms

Generated-By: PostHog Desktop
Task-Id: 5681be44-4986-48db-b140-1bda88f75f96
@pauldambra
pauldambra marked this pull request as ready for review October 16, 2026 11:58
@pauldambra
pauldambra requested a review from a team as a code owner October 16, 2026 11:58
@pauldambra

Copy link
Copy Markdown
Member Author

Note

🤖 Automated comment by QA Swarm - not written by a human

Verdict: APPROVE (round 2 @ 8bbc2c9)

No new exception trace defect found. Manual and automatic capture preserve request and caller trace values. Missing or failing OpenTelemetry context does not stop exception capture.

Key findings

The earlier manual context priority finding is fixed in 8bbc2c9. Its regression cases failed before the fix and passed after it. No further defect was found in either capture path.

Convergence

The earlier finding was checked and resolved. No further quality work remains at this unchanged commit. The simplify pass proposed no change. The SDK spec agreement remains a merge hold.

Reviewer summaries

Reviewer Assessment
Router (gpt-6-sol) Low danger, medium confidence. Traced both capture and context merge paths. No new finding.
Scoped reviewer (gpt-6.1-sol) Checked the automatic provider and request merge, optional API failures, and related tests. No defect found.

The CI checks pass. The Socket and foreground ForkCurl compliance reports still show transport retry failures. Those require separate transport fixes; this verdict does not certify full SDK compliance.


Automated by QA Swarm - not a human review

@pauldambra
pauldambra merged commit b8e88a9 into main Oct 19, 2026
27 checks passed
@pauldambra
pauldambra deleted the posthog/exception-trace-context branch October 19, 2026 11:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants