feat: add manual rust error tracking#129
Conversation
posthog-rs-v0 Compliance ReportDate: 2026-06-12 12:43:54 UTC
|
| Test | Status | Duration |
|---|---|---|
| Format Validation.Event Has Required Fields | ✅ | 134ms |
| Format Validation.Event Has Uuid | ✅ | 135ms |
| Format Validation.Event Has Lib Properties | ✅ | 132ms |
| Format Validation.Distinct Id Is String | ✅ | 133ms |
| Format Validation.Token Is Present | ✅ | 124ms |
| Format Validation.Custom Properties Preserved | ✅ | 129ms |
| Format Validation.Event Has Timestamp | ✅ | 133ms |
| Retry Behavior.Retries On 503 | ✅ | 5731ms |
| Retry Behavior.Does Not Retry On 400 | ✅ | 2134ms |
| Retry Behavior.Does Not Retry On 401 | ✅ | 2126ms |
| Retry Behavior.Respects Retry After Header | ✅ | 8090ms |
| Retry Behavior.Implements Backoff | ✅ | 15697ms |
| Retry Behavior.Retries On 500 | ✅ | 5289ms |
| Retry Behavior.Retries On 502 | ✅ | 5288ms |
| Retry Behavior.Retries On 504 | ✅ | 5288ms |
| Retry Behavior.Max Retries Respected | ✅ | 16492ms |
| Deduplication.Generates Unique Uuids | ✅ | 87ms |
| Deduplication.Preserves Uuid On Retry | ✅ | 5219ms |
| Deduplication.Preserves Uuid And Timestamp On Retry | ✅ | 10635ms |
| Deduplication.Preserves Uuid And Timestamp On Batch Retry | ✅ | 5228ms |
| Deduplication.No Duplicate Events In Batch | ✅ | 87ms |
| Deduplication.Different Events Have Different Uuids | ✅ | 52ms |
| Compression.Sends Gzip When Enabled | ✅ | 47ms |
| Batch Format.Uses Proper Batch Structure | ✅ | 37ms |
| Batch Format.Flush With No Events Sends Nothing | ✅ | 21ms |
| Batch Format.Multiple Events Batched Together | ✅ | 68ms |
| Error Handling.Does Not Retry On 403 | ✅ | 2036ms |
| Error Handling.Does Not Retry On 413 | ✅ | 2047ms |
| Error Handling.Retries On 408 | ✅ | 5240ms |
Feature_Flags Tests
View Details
| Test | Status | Duration |
|---|---|---|
| Request Payload.Request With Person Properties Device Id | ❌ | 13ms |
| Request Payload.Flags Request Uses V2 Query Param | ❌ | 12ms |
| Request Payload.Flags Request Hits Flags Path Not Decide | ❌ | 13ms |
| Request Payload.Flags Request Omits Authorization Header | ❌ | 12ms |
| Request Payload.Token In Flags Body Matches Init | ❌ | 13ms |
| Request Payload.Groups Round Trip | ❌ | 12ms |
| Request Payload.Groups Default To Empty Object | ❌ | 12ms |
| Request Payload.Person Properties Distinct Id Auto Populated When Caller Omits It | ❌ | 13ms |
| Request Payload.Disable Geoip False Propagates As Geoip Disable False | ❌ | 12ms |
| Request Payload.Disable Geoip Omitted Defaults To False | ❌ | 13ms |
| Request Payload.Flag Keys To Evaluate Contains Only Requested Key | ❌ | 12ms |
| Request Lifecycle.No Flags Request On Init Alone | ✅ | 11ms |
| Request Lifecycle.No Flags Request On Normal Capture | ✅ | 17ms |
| Request Lifecycle.Two Flag Calls Produce Two Remote Requests | ❌ | 13ms |
| Request Lifecycle.Mock Response Value Is Returned To Caller | ❌ | 12ms |
| Side Effect Events.Get Feature Flag Captures Feature Flag Called Event | ❌ | 14ms |
Failures
request_payload.request_with_person_properties_device_id
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-2d8bfde4-31c5-4949-af01-a7f43f60976e'
request_payload.flags_request_uses_v2_query_param
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-48c4cf30-e2ac-43e0-9809-85f05e3d7e23'
request_payload.flags_request_hits_flags_path_not_decide
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-4b3b8af8-ac1c-4806-857e-572124505d16'
request_payload.flags_request_omits_authorization_header
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-06cf4be3-3713-4b4d-a093-f4e384d7eb2b'
request_payload.token_in_flags_body_matches_init
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-19edf4bf-bf67-4848-ab7c-aba8f6bb78ff'
request_payload.groups_round_trip
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-4db23368-62ae-4103-8d88-a6b5ef8ba0e7'
request_payload.groups_default_to_empty_object
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-44e6b68e-a5d8-4ee8-a8cc-d3dca2bb4f1e'
request_payload.person_properties_distinct_id_auto_populated_when_caller_omits_it
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-2ea806b1-8925-4472-aa64-1706d1458493'
request_payload.disable_geoip_false_propagates_as_geoip_disable_false
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-d26ea810-b6d9-4882-9aca-59edd3c97476'
request_payload.disable_geoip_omitted_defaults_to_false
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-5be64f83-24d5-4f8b-97bc-8884ff2db50e'
request_payload.flag_keys_to_evaluate_contains_only_requested_key
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-567f9034-41aa-4cef-8118-3db8dd1dee1a'
request_lifecycle.two_flag_calls_produce_two_remote_requests
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-94f228b5-49df-4f42-a59a-02d8a4ffb9f8'
request_lifecycle.mock_response_value_is_returned_to_caller
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-58867a46-8aaf-407b-a435-903492d59bfa'
side_effect_events.get_feature_flag_captures_feature_flag_called_event
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-f18a9a81-1f89-462f-9a4a-ef5cc6a1121f'
posthog-rs-v1 Compliance ReportDate: 2026-06-12 12:44:11 UTC
|
| Test | Status | Duration |
|---|---|---|
| Endpoint And Method.Targets V1 Endpoint | ✅ | 130ms |
| Endpoint And Method.Does Not Use Legacy Endpoints | ✅ | 132ms |
| Required Headers.Has Authorization Bearer Header | ✅ | 133ms |
| Required Headers.Has Content Type Json | ✅ | 128ms |
| Required Headers.Has Posthog Sdk Info Format | ✅ | 131ms |
| Required Headers.Has Posthog Attempt Header | ✅ | 135ms |
| Required Headers.Has Posthog Request Id | ✅ | 128ms |
| Required Headers.Has Posthog Request Timestamp | ✅ | 132ms |
| Required Headers.Has User Agent | ✅ | 134ms |
| Body Format.Body Has Created At And Batch | ✅ | 131ms |
| Body Format.No Api Key In Body | ✅ | 127ms |
| Body Format.No Sent At In Body | ✅ | 125ms |
| Event Format.Event Has Required Root Fields | ✅ | 130ms |
| Event Format.Event Uuid Is Valid | ✅ | 129ms |
| Event Format.Event Timestamp Is Rfc3339 | ✅ | 122ms |
| Event Format.Distinct Id Is String | ✅ | 120ms |
| Event Format.Distinct Id At Root Not Properties | ✅ | 124ms |
| Event Format.Custom Properties Preserved | ✅ | 125ms |
| Event Format.Set Properties Preserved | ✅ | 126ms |
| Event Format.Set Once Properties Preserved | ✅ | 126ms |
| Event Format.Groups Properties Preserved | ✅ | 119ms |
| Event Format.Sdk Generates Uuid If Not Provided | ✅ | 123ms |
| Event Format.Event Has Required Root Fields Batch | ✅ | 142ms |
| Event Format.Event Uuid Is Valid Batch | ✅ | 134ms |
| Event Format.Event Timestamp Is Rfc3339 Batch | ✅ | 159ms |
| Event Format.Distinct Id Is String Batch | ✅ | 139ms |
| Event Format.Distinct Id At Root Not Properties Batch | ✅ | 137ms |
| Event Format.Custom Properties Preserved Batch | ✅ | 156ms |
| Event Format.Set Properties Preserved Batch | ✅ | 165ms |
| Event Format.Set Once Properties Preserved Batch | ✅ | 154ms |
| Event Format.Groups Properties Preserved Batch | ✅ | 141ms |
| Event Format.Sdk Generates Uuid If Not Provided Batch | ✅ | 138ms |
| Batch Behavior.Multiple Events In Single Batch | ✅ | 200ms |
| Batch Behavior.Batch Envelope Smoke | ✅ | 181ms |
| Batch Behavior.Flush With No Events Sends Nothing | ✅ | 78ms |
| Batch Behavior.Flush At Triggers Batch | ✅ | 1107ms |
| Batch Behavior.Created At Reflects Batch Creation Time | ✅ | 122ms |
| Deduplication.Generates Unique Uuids | ✅ | 173ms |
| Deduplication.Different Events Same Content Different Uuids | ✅ | 126ms |
| Deduplication.Preserves Uuid On Retry | ✅ | 6122ms |
| Deduplication.Preserves Timestamp On Retry | ✅ | 6107ms |
| Deduplication.Preserves Uuid And Timestamp On Batch Retry | ✅ | 6096ms |
| Deduplication.No Duplicate Events In Batch | ✅ | 128ms |
| Header Behavior On Retry.Attempt Header Starts At One | ✅ | 78ms |
| Header Behavior On Retry.Attempt Header Increments On Retry | ✅ | 12071ms |
| Header Behavior On Retry.Request Id Preserved On Retry | ✅ | 6054ms |
| Header Behavior On Retry.Different Requests Have Different Request Ids | ✅ | 2059ms |
| Header Behavior On Retry.Request Timestamp Changes On Retry | ✅ | 6059ms |
| Response Format Validation.Success Response Has Uuid Keyed Results | ✅ | 39ms |
| Response Format Validation.Success Response Has Ok For Each Event | ✅ | 29ms |
| Response Format Validation.Success No Retry After When All Ok | ✅ | 30ms |
| Response Format Validation.Success Retry After Present When Retry Events | ✅ | 1031ms |
| Response Format Validation.Success No Retry After When Drop Only | ✅ | 18ms |
| Response Format Validation.Response Echoes Request Id | ✅ | 15ms |
| Retry Behavior.Retries On 408 | ✅ | 6018ms |
| Retry Behavior.Retries On 500 | ✅ | 6020ms |
| Retry Behavior.Retries On 503 | ✅ | 7021ms |
| Retry Behavior.Retries On 504 | ✅ | 6021ms |
| Retry Behavior.Retryable Errors Have Retry After | ✅ | 3019ms |
| Retry Behavior.Respects Retry After On Retryable Error | ✅ | 11019ms |
| Retry Behavior.Does Not Retry On 400 | ✅ | 2016ms |
| Retry Behavior.Does Not Retry On 401 | ✅ | 2015ms |
| Retry Behavior.Does Not Retry On 402 | ✅ | 2016ms |
| Retry Behavior.Does Not Retry On 413 | ✅ | 2016ms |
| Retry Behavior.Does Not Retry On 415 | ✅ | 2019ms |
| Retry Behavior.Non Retryable Errors Have No Retry After | ✅ | 2017ms |
| Retry Behavior.Implements Backoff | ✅ | 17025ms |
| Retry Behavior.Max Retries Respected | ✅ | 18034ms |
| Partial Batch Handling.Handles 200 Full Success | ✅ | 2023ms |
| Partial Batch Handling.Handles 200 With All Ok | ✅ | 3018ms |
| Partial Batch Handling.Does Not Retry Dropped Events | ✅ | 3018ms |
| Partial Batch Handling.Does Not Retry Limited Events | ✅ | 3019ms |
| Partial Batch Handling.Prunes Ok Events On Partial Retry | ✅ | 6023ms |
| Partial Batch Handling.Prunes Dropped Events On Partial Retry | ✅ | 6023ms |
| Partial Batch Handling.Retries Only Retry Events From Partial | ✅ | 6022ms |
| Partial Batch Handling.Partial Retry Preserves Uuids | ✅ | 6021ms |
| Partial Batch Handling.Partial Retry Attempt Header Increments | ✅ | 6020ms |
| Partial Batch Handling.Partial Retry Request Id Preserved | ✅ | 6024ms |
| Partial Batch Handling.Respects Retry After On Partial | ✅ | 8021ms |
| Partial Batch Handling.Unknown Result Treated As Terminal | ✅ | 3019ms |
| Partial Batch Handling.Mixed Ok Drop Limited No Retry | ✅ | 3021ms |
| Compression.Sends Gzip Content Encoding | ✅ | 16ms |
| Compression.No Content Encoding When Disabled | ✅ | 14ms |
| Compression.Compressed Body Is Decompressible | ✅ | 15ms |
| Error Handling.Does Not Retry On Unknown 4Xx | ✅ | 2015ms |
| Event Options.Cookieless Mode Override | ✅ | 17ms |
| Event Options.Disable Skew Correction Override | ✅ | 14ms |
| Event Options.Process Person Profile Override | ✅ | 15ms |
| Event Options.Product Tour Id Override | ✅ | 14ms |
| Event Options.Unset Options Omitted | ✅ | 15ms |
| Event Options.Options Override In Batch | ✅ | 17ms |
| Geoip And Historical Migration.Geoip Disable Injected Into Properties | ✅ | 15ms |
| Geoip And Historical Migration.Historical Migration Set In Body | ✅ | 15ms |
| Geoip And Historical Migration.Historical Migration Absent By Default | ✅ | 15ms |
Feature_Flags Tests
View Details
| Test | Status | Duration |
|---|---|---|
| Request Payload.Request With Person Properties Device Id | ❌ | 12ms |
| Request Payload.Flags Request Uses V2 Query Param | ❌ | 12ms |
| Request Payload.Flags Request Hits Flags Path Not Decide | ❌ | 22ms |
| Request Payload.Flags Request Omits Authorization Header | ❌ | 22ms |
| Request Payload.Token In Flags Body Matches Init | ❌ | 15ms |
| Request Payload.Groups Round Trip | ❌ | 21ms |
| Request Payload.Groups Default To Empty Object | ❌ | 36ms |
| Request Payload.Person Properties Distinct Id Auto Populated When Caller Omits It | ❌ | 41ms |
| Request Payload.Disable Geoip False Propagates As Geoip Disable False | ❌ | 23ms |
| Request Payload.Disable Geoip Omitted Defaults To False | ❌ | 23ms |
| Request Payload.Flag Keys To Evaluate Contains Only Requested Key | ❌ | 31ms |
| Request Lifecycle.No Flags Request On Init Alone | ✅ | 40ms |
| Request Lifecycle.No Flags Request On Normal Capture | ✅ | 51ms |
| Request Lifecycle.Two Flag Calls Produce Two Remote Requests | ❌ | 33ms |
| Request Lifecycle.Mock Response Value Is Returned To Caller | ❌ | 23ms |
| Side Effect Events.Get Feature Flag Captures Feature Flag Called Event | ❌ | 19ms |
Failures
request_payload.request_with_person_properties_device_id
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-e8b1b380-261a-4896-a7bc-363e4b989b9e'
request_payload.flags_request_uses_v2_query_param
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-cef71ab1-4b85-4e91-b028-9c6f016f8ba3'
request_payload.flags_request_hits_flags_path_not_decide
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-05afa8f5-de1e-4058-898a-3d609f33a46c'
request_payload.flags_request_omits_authorization_header
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-e0c6f4bd-01e7-4af3-9977-8569b24c0eba'
request_payload.token_in_flags_body_matches_init
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-80b8e818-9ab2-41e9-8fad-453bad638ed2'
request_payload.groups_round_trip
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-4dae55b0-901e-4bfe-ad8e-01ed1f1926f3'
request_payload.groups_default_to_empty_object
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-775444cd-ac60-4979-be88-d322c14cd8c8'
request_payload.person_properties_distinct_id_auto_populated_when_caller_omits_it
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-b0095556-4438-41f4-a048-57721ff08cc8'
request_payload.disable_geoip_false_propagates_as_geoip_disable_false
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-56e765f1-9d44-4269-8da7-c078d597a6bb'
request_payload.disable_geoip_omitted_defaults_to_false
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-76f83e9c-0ef7-4653-b5ea-16714d311087'
request_payload.flag_keys_to_evaluate_contains_only_requested_key
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-b70d9276-f175-42ba-8d80-c008a4db92a1'
request_lifecycle.two_flag_calls_produce_two_remote_requests
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-c13ec4aa-1470-49b4-bb09-7b509718a4b0'
request_lifecycle.mock_response_value_is_returned_to_caller
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-613ac576-be71-4131-8444-a72a10558ba1'
side_effect_events.get_feature_flag_captures_feature_flag_called_event
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag?test_id=t-08ad4304-9c2f-4459-9a2d-1183bad726bd'
Prompt To Fix All With AIFix the following 4 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 4
src/client/blocking.rs:294-297
Stale doc-comment line on `capture_exception`. The first line was copied from the `capture_batch` doc that sits just below it, so the rendered API docs would describe this method as "Capture a collection of events with a single request." The same issue appears on the async counterpart at `src/client/async_client.rs` line 310.
```suggestion
/// Capture an exception event, sending it to PostHog Error Tracking.
#[cfg(feature = "error-tracking")]
pub fn capture_exception(&self, exception: ExceptionCapture) -> Result<(), Error> {
```
### Issue 2 of 4
src/client/async_client.rs:310-313
Same stale doc-comment line as in the blocking client — first line is leftover from the `capture_batch` doc above it.
```suggestion
/// Capture an exception event, sending it to PostHog Error Tracking.
#[cfg(feature = "error-tracking")]
pub async fn capture_exception(&self, exception: ExceptionCapture) -> Result<(), Error> {
```
### Issue 3 of 4
src/error_tracking.rs:426-429
`"DefaultStackTraceExtractor::capture"` doesn't correspond to any type or function in this codebase, so this branch can never match. It looks like it was carried over from a previous design that was later removed, leaving a superfluous predicate.
```suggestion
fn is_internal_capture_frame(function: &str) -> bool {
function.starts_with("backtrace::")
|| function.contains("capture_frames_current_first")
```
### Issue 4 of 4
tests/test_error_tracking.rs:61-203
**Blocking / async test modules are near-identical**
Every test case in `mod blocking` (lines 62–203) is duplicated almost verbatim in `mod async_client` (lines 205–351), differing only in `async fn` / `.await` and a single extra `.await` on `create_test_client`. This violates OnceAndOnlyOnce and works against the team preference for parameterised tests. A macro, a shared test-helper trait, or a code-generation pattern could drive both client flavours from a single body of test logic.
Reviews (1): Last reviewed commit: "test: align error tracking payload asser..." | Re-trigger Greptile |
Prompt To Fix All With AIFix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
README.md:23
The README version was bumped from `0.3.7` to `0.8.0`, but `Cargo.toml` currently declares `version = "0.10.0"`. Under Cargo's caret requirement, `"0.8.0"` resolves to `>= 0.8.0, < 0.9.0`, which will never pull in `0.10.x` or whatever version is published after this changeset. A user following the Quickstart and then enabling `error-tracking` would get an old version that doesn't have the feature at all.
```suggestion
posthog-rs = "0.10.0"
```
Reviews (2): Last reviewed commit: "feat: add anonymous error capture helper" | Re-trigger Greptile |
240d4dd to
a89e17f
Compare
|
how does auto capture work here? can we hook up the PanicHookInfo? |
|
yep for auto capture, I have a separate draft stacked PR, was just testing it now: #130 |
|
What if the final bundle is optimized and stripped of debug symbols? Do we intend to offer a tool for uploading debug symbols and symbolication? not a blocker since this can be done later |
|
absolutely, that's up next, I have to add support in cymbal too, and then want to add uploading debug symbols + symbolication 😁 |
Callers build payloads with ExceptionCapture::from_error directly; capture_error/capture_error_anon keep applying client-level Error Tracking options internally.
…ture Exceptions are now plain events: Exception holds only exception-specific data (items, fingerprint, level) and converts into an Event via into_event/into_event_anon, so distinct ID, props, groups, flags, and timestamps use the standard Event API instead of duplicated builders. Raw frames are captured unclassified at construction and client-level ErrorTrackingOptions (stacktrace opt-out, in-app classification, frame and source limits) are applied at capture time in the v0/v1 prep paths, so free-standing constructors always honor the capturing client's configuration.
Replace capture_error/capture_error_anon and the personless capture_exception(Exception) with capture_exception(&error, distinct_id) and capture_exception_anon(&error) across the async, blocking, and global APIs, matching the capture_exception entry point of other PostHog SDKs. Built Exception payloads now go through Exception::into_event + capture.
capture_exception(&error) now captures personlessly, and capture_exception_with(&error, CaptureExceptionOptions) carries the optional context: distinct_id, custom properties, groups, fingerprint, and severity level. capture_exception_anon is removed, and the Exception payload type with its into_event conversions is no longer exported - python/node expose no payload tier either, keeping the public surface to two methods plus one options struct.
Resolves capture-pipeline conflicts: keep finalize-at-capture (prepare_event/ build_events on &ClientOptions, fallible) while adopting main's before_send hooks, runtime context properties, and empty-batch no-op semantics.
Exception construction is now reachable only through client methods that hold the client's ErrorTrackingOptions, so client policy (stack walk gating, in-app classification, frame and source-chain limits, reserved $exception_* properties) is applied when the event is built instead of at capture time. Disabling capture_stacktrace now skips the stack walk entirely rather than discarding the captured frames at send. This removes the pending-exception staging field from Event and reverts prepare_event/build_events to main's exception-agnostic shapes.
max_frames and max_error_sources leave ErrorTrackingOptions: no other SDK exposes them, nobody asked for tunability, and the configurable source cap silently clamped to the build-time bound anyway. The caps remain as MAX_FRAMES/MAX_ERROR_SOURCES; re-adding knobs later is non-breaking.
resolve_frame yields a symbol per logical layer when the compiler inlined functions into a physical frame; the previous first-symbol-only guard kept the innermost layer and silently dropped the inline ancestry, which exists in no other frame. Emit each layer as its own frame (innermost first, matching current-first capture order), like the Go runtime does for our Go SDK. MAX_FRAMES now counts logical frames.
The error_tracking module is private, so these were never reachable, but the bare pub kept reading as public API in review diffs. Make the crate-internal surface explicit; the public ET API stays exactly capture_exception/_with, CaptureExceptionOptions, and ErrorTrackingOptions.
/// docs with examples on capture_exception/_with, CaptureExceptionOptions, and every ErrorTrackingOptions field (derive_builder copies field docs onto the generated setters), including the capture-site-vs-origin stacktrace caveat and crate-prefix in-app patterns. README gains the configuration example and a captured-properties table.
dustinbyrne
left a comment
There was a problem hiding this comment.
this is test failing when combined with the capture-v1 feature - we should either add this combo to the matrix or I strongly suggest including this as a default feature
test_error_tracking.rs asserts the V0 wire shape, so it is gated out under capture-v1; test_error_tracking_v1.rs adds V1-envelope twins (single-attempt clients against an empty-results 2xx, asserting one well-formed request). Fixes the error-tracking + capture-v1 combo failing with 404s against v0-shaped mocks.
before_send on the flag-event hosts is only read by the v0 ship path, so scope a dead_code allow under capture-v1 (the v1 flag path does not apply before_send hooks today). Restructure the blocking capture cfg splits as tail blocks so needless_return doesn't fire under capture-v1.
The matrix never enabled error-tracking, so every ET test compiled to nothing in CI; cover it alone and combined with capture-v1, on both clients.
The pin guarded the declared 1.78 MSRV, but every toolchain it could help (1.78-1.84) is already locked out by edition-2024 transitive manifests (idna_adapter via reqwest->url, present on main's lockfile too), so it protects nothing reachable while exporting =0.3.74 resolution conflicts to any consumer tree wanting backtrace ^0.3.75. Verified against 0.3.76 across all feature combos. Whether to restore the 1.78 floor or bump rust-version is left as a separate decision.
Every other PostHog SDK ships error tracking in the box; with the backtrace pin gone there is no resolution cost to carry it as a default feature, and capture_exception works out of the box. Opt out with default-features = false. The CI matrix collapses accordingly: the default and capture-v1 steps now cover error tracking on the async client, keeping explicit steps only for the blocking client.
|
yea good spot, updated, thanks! |
…g-manual # Conflicts: # .github/workflows/ci.yaml
| } | ||
| ``` | ||
|
|
||
| ## Error Tracking |
There was a problem hiding this comment.
@cat-ph too late to the party but see this comment
see #140
lets avoid docs in those files
lets move those docs to the oficial docs under https://posthog.com/docs/libraries/rust or the official error tracking rust docs
that should be the canonical docs
💡 Motivation and Context
Adds a manual Error tracking v1 for the Rust SDK behind the
error-trackingfeature. The API supports building exception payloads from Rust errors, capturing exception events, optional stacktrace capture via thebacktracecrate, and client-level stacktrace/in-app frame options.💚 How did you test it?
cargo generate-lockfilecargo fmt --all -- --checkcargo check --features error-trackingcargo clippy --all-targets --features error-tracking -- -D warningscargo test --features error-trackingcargo test --no-default-features --features error-trackingalso went through with a local project sending a test stacktrace:
📝 Checklist
If releasing new changes
sampo addto generate a changeset file