sourcegraph/lib
Robert Lin 294d4b47f8
telemetry-gateway: wrap publish errors in error details for Sentry (#61895)
We aggregate all errors on a single log entry to get accurate representations of issues in Sentry, while not generating thousands of log entries at the same time. Because this means we only get higher-level logger context, we must annotate the errors directly with some hidden details to preserve Sentry grouping while adding context for diagnostics.

We do this by using CockroachDB error's `WithSafeDetails` helper, which annotates an error with details that are _not_ rendered by `err.Error()` but _are_ included in Sentry reports (via the `Message` field). Currently, we annotate the event ID, feature, action, and source (see example output below)

Context on this request: https://sourcegraph.slack.com/archives/C06CCJR4K9R/p1713054354443579

## Test plan

_Super_ jank unit tests that try to emulate how we build Sentry reports, relying on knowledge of how our Sentry report building works internally. I opened https://github.com/sourcegraph/log/issues/65 in case there are new use cases for this in the future. Running the test with `-v` demonstrates the output:

```
$ go test -timeout 30s -run ^TestSummarizeFailedEvents$ github.com/sourcegraph/sourcegraph/cmd/telemetry-gateway/internal/server -v
=== RUN   TestSummarizeFailedEvents
=== RUN   TestSummarizeFailedEvents/all_failed
=== RUN   TestSummarizeFailedEvents/all_failed/Sentry_report
    publish_events_test.go:83: Sentry Error message for field "error.0":
        
        publish_events_test.go:38: event publish failed
        (1) feature:"feature_0" action:"action_0" id:"id_0" server:{version:"TestSummarizeFailedEvents/all_failed"}  client:{name:"test_client"}
        Wraps: (2) attached stack trace
          -- stack trace:
          | github.com/sourcegraph/sourcegraph/cmd/telemetry-gateway/internal/server.TestSummarizeFailedEvents.func1
          |     /Users/robert@sourcegraph.com/Projects/sourcegraph/sourcegraph/cmd/telemetry-gateway/internal/server/publish_events_test.go:38
          | testing.tRunner
          |     /Users/robert@sourcegraph.com/.asdf/installs/golang/1.22.1/go/src/testing/testing.go:1689
          | runtime.goexit
          |     /Users/robert@sourcegraph.com/.asdf/installs/golang/1.22.1/go/src/runtime/asm_arm64.s:1222
        Wraps: (3) event publish failed
        Error types: (1) *safedetails.withSafeDetails (2) *withstack.withStack (3) *errutil.leafError
        -- report composition:
        *errutil.leafError: event publish failed
        publish_events_test.go:38: *withstack.withStack (top exception)
        *safedetails.withSafeDetails: feature:"feature_0" action:"action_0" id:"id_0" server:{version:"TestSummarizeFailedEvents/all_failed"}  client:{name:"test_client"}
        
    publish_events_test.go:83: Sentry Error message for field "error.1":
        
        publish_events_test.go:38: event publish failed
        (1) feature:"feature_1" action:"action_1" id:"id_1" server:{version:"TestSummarizeFailedEvents/all_failed"}
        Wraps: (2) attached stack trace
          -- stack trace:
          | github.com/sourcegraph/sourcegraph/cmd/telemetry-gateway/internal/server.TestSummarizeFailedEvents.func1
          |     /Users/robert@sourcegraph.com/Projects/sourcegraph/sourcegraph/cmd/telemetry-gateway/internal/server/publish_events_test.go:38
          | testing.tRunner
          |     /Users/robert@sourcegraph.com/.asdf/installs/golang/1.22.1/go/src/testing/testing.go:1689
          | runtime.goexit
          |     /Users/robert@sourcegraph.com/.asdf/installs/golang/1.22.1/go/src/runtime/asm_arm64.s:1222
        Wraps: (3) event publish failed
        Error types: (1) *safedetails.withSafeDetails (2) *withstack.withStack (3) *errutil.leafError
        -- report composition:
        *errutil.leafError: event publish failed
        publish_events_test.go:38: *withstack.withStack (top exception)
        *safedetails.withSafeDetails: feature:"feature_1" action:"action_1" id:"id_1" server:{version:"TestSummarizeFailedEvents/all_failed"}
        
    publish_events_test.go:83: Sentry Error message for field "error.2":
        
        publish_events_test.go:38: event publish failed
        (1) feature:"feature_2" action:"action_2" id:"id_2" server:{version:"TestSummarizeFailedEvents/all_failed"}  client:{name:"test_client"}
        Wraps: (2) attached stack trace
          -- stack trace:
          | github.com/sourcegraph/sourcegraph/cmd/telemetry-gateway/internal/server.TestSummarizeFailedEvents.func1
          |     /Users/robert@sourcegraph.com/Projects/sourcegraph/sourcegraph/cmd/telemetry-gateway/internal/server/publish_events_test.go:38
          | testing.tRunner
          |     /Users/robert@sourcegraph.com/.asdf/installs/golang/1.22.1/go/src/testing/testing.go:1689
          | runtime.goexit
          |     /Users/robert@sourcegraph.com/.asdf/installs/golang/1.22.1/go/src/runtime/asm_arm64.s:1222
        Wraps: (3) event publish failed
        Error types: (1) *safedetails.withSafeDetails (2) *withstack.withStack (3) *errutil.leafError
        -- report composition:
        *errutil.leafError: event publish failed
        publish_events_test.go:38: *withstack.withStack (top exception)
        *safedetails.withSafeDetails: feature:"feature_2" action:"action_2" id:"id_2" server:{version:"TestSummarizeFailedEvents/all_failed"}  client:{name:"test_client"}
        
    publish_events_test.go:83: Sentry Error message for field "error.3":
        
        publish_events_test.go:38: event publish failed
        (1) feature:"feature_3" action:"action_3" id:"id_3" server:{version:"TestSummarizeFailedEvents/all_failed"}
        Wraps: (2) attached stack trace
          -- stack trace:
          | github.com/sourcegraph/sourcegraph/cmd/telemetry-gateway/internal/server.TestSummarizeFailedEvents.func1
          |     /Users/robert@sourcegraph.com/Projects/sourcegraph/sourcegraph/cmd/telemetry-gateway/internal/server/publish_events_test.go:38
          | testing.tRunner
          |     /Users/robert@sourcegraph.com/.asdf/installs/golang/1.22.1/go/src/testing/testing.go:1689
          | runtime.goexit
          |     /Users/robert@sourcegraph.com/.asdf/installs/golang/1.22.1/go/src/runtime/asm_arm64.s:1222
        Wraps: (3) event publish failed
        Error types: (1) *safedetails.withSafeDetails (2) *withstack.withStack (3) *errutil.leafError
        -- report composition:
        *errutil.leafError: event publish failed
        publish_events_test.go:38: *withstack.withStack (top exception)
        *safedetails.withSafeDetails: feature:"feature_3" action:"action_3" id:"id_3" server:{version:"TestSummarizeFailedEvents/all_failed"}
        
    publish_events_test.go:83: Sentry Error message for field "error.4":
        
        publish_events_test.go:38: event publish failed
        (1) feature:"feature_4" action:"action_4" id:"id_4" server:{version:"TestSummarizeFailedEvents/all_failed"}  client:{name:"test_client"}
        Wraps: (2) attached stack trace
          -- stack trace:
          | github.com/sourcegraph/sourcegraph/cmd/telemetry-gateway/internal/server.TestSummarizeFailedEvents.func1
          |     /Users/robert@sourcegraph.com/Projects/sourcegraph/sourcegraph/cmd/telemetry-gateway/internal/server/publish_events_test.go:38
          | testing.tRunner
          |     /Users/robert@sourcegraph.com/.asdf/installs/golang/1.22.1/go/src/testing/testing.go:1689
          | runtime.goexit
          |     /Users/robert@sourcegraph.com/.asdf/installs/golang/1.22.1/go/src/runtime/asm_arm64.s:1222
        Wraps: (3) event publish failed
        Error types: (1) *safedetails.withSafeDetails (2) *withstack.withStack (3) *errutil.leafError
        -- report composition:
        *errutil.leafError: event publish failed
        publish_events_test.go:38: *withstack.withStack (top exception)
        *safedetails.withSafeDetails: feature:"feature_4" action:"action_4" id:"id_4" server:{version:"TestSummarizeFailedEvents/all_failed"}  client:{name:"test_client"}
        
=== RUN   TestSummarizeFailedEvents/some_failed
=== RUN   TestSummarizeFailedEvents/all_succeeded
=== RUN   TestSummarizeFailedEvents/all_succeeded_(large_set)
--- PASS: TestSummarizeFailedEvents (0.23s)
    --- PASS: TestSummarizeFailedEvents/all_failed (0.22s)
        --- PASS: TestSummarizeFailedEvents/all_failed/Sentry_report (0.00s)
    --- PASS: TestSummarizeFailedEvents/some_failed (0.00s)
    --- PASS: TestSummarizeFailedEvents/all_succeeded (0.00s)
    --- PASS: TestSummarizeFailedEvents/all_succeeded_(large_set) (0.00s)
PASS
ok      github.com/sourcegraph/sourcegraph/cmd/telemetry-gateway/internal/server        (cached)
```
2024-04-15 23:19:29 +00:00
..
api enterprise: Move last directory out (#57392) 2023-10-05 20:15:40 +00:00
background Replace all traditional for-loops (#60988) 2024-03-11 16:05:47 +02:00
batches code-search: handle changeset fork when creating a batch change via src-cli (#58156) 2023-11-08 09:55:05 +01:00
cliutil sg: improve positional completions (#58569) 2023-11-27 16:30:59 -08:00
codeintel Add syntax highlighting for Pkl files (#61478) 2024-04-04 12:28:35 -04:00
errors telemetry-gateway: wrap publish errors in error details for Sentry (#61895) 2024-04-15 23:19:29 +00:00
gitservice Replace all traditional for-loops (#60988) 2024-03-11 16:05:47 +02:00
iterator ci: re-enable race detection (#52776) 2023-06-05 20:41:47 +02:00
managedservicesplatform msp/opentelemetry: fix metrics export instrumentation (#61649) 2024-04-05 19:00:19 +00:00
output rfc795: new release process foundations (#60962) 2024-03-12 17:12:22 +01:00
pointers msp: add monitoring stack (#58816) 2023-12-13 19:40:57 +00:00
process vcssyncer: Move clone implementation details into syncer (#57688) 2023-10-27 20:55:59 +02:00
servicecatalog Remove GitHub proxy service (#56485) 2023-09-14 19:43:40 +02:00
go.mod bump to Go 1.22.1 (#60902) 2024-03-06 17:38:43 -07:00
go.sum bump to Go 1.22.1 (#60902) 2024-03-06 17:38:43 -07:00
README.md lib: Introduce non-enterprise lib directory (#18992) 2021-03-10 19:41:33 -06:00
tools.go bump to Go 1.22.1 (#60902) 2024-03-06 17:38:43 -07:00

Sourcegraph lib module

This directory is the root of a separate go module from the primary module rooted at sourcegraph/sourcegraph. This module exists to hold code that we want to reuse outside of the sourcegraph/sourcegraph repo.

Code in this module should not import from sourcegraph/sourcegraph or from other Sourcegraph repositories to avoid complicated dependency relationships. Instead consider moving code from elsewhere into this module.