Table of contents
Part of nurago, a collection of independent Go packages for backend services.
import "github.com/tecnickcom/nurago/pkg/sleuth"
Write-side client for the Sleuth.io API, covering four registration workflows.
c, err := sleuth.New(addr, org, apiKey)
err = c.SendDeployRegistration(ctx, &sleuth.DeployRegistrationRequest{...})
err = c.SendManualChange(ctx, &sleuth.ManualChangeRequest{...})
err = c.SendCustomIncidentImpactRegistration(ctx, &sleuth.CustomIncidentImpactRegistrationRequest{...})
err = c.SendCustomMetricImpactRegistration(ctx, &sleuth.CustomMetricImpactRegistrationRequest{...})
Four workflows, and what separates them
Deploy registration reports a code deployment: the ordinary case, where a pipeline ships a build.
Manual change reports something that changed production without going through a deployment. A feature flag flipped, a configuration value edited, a database migration run by hand. These cause incidents at a rate comparable to deployments and are invisible to a tool that only watches your pipeline, which makes change failure rate look better than it is.
Custom incident impact reports an incident from a source Sleuth does not integrate with directly.
Custom metric impact feeds an arbitrary metric, for tracking something specific to your system against deployments.
The org slug is a constructor argument because Sleuth’s URLs are organisation-scoped. New builds the endpoint templates once from the base URL and slug, so each send is a substitution rather than string assembly per call.
Validation before the network call
Every request struct is validated through validator before anything is sent.
A metrics ingestion endpoint accepts a payload and returns success; whether the payload was usable surfaces later as a gap in a dashboard. Local validation turns that into an error at the call site, where you can see which request was malformed.
API keys stay out of error text
Like slack, this client wraps its errors so the configured address is replaced with REDACTED in the message, while Unwrap returns the original error so errors.Is and errors.As keep working.
Go’s net/http puts the request URL into transport error messages. Logging a raw transport error from an authenticated client is a routine way for credentials and internal endpoints to reach a log aggregator.
Options
| Option | Effect |
|---|---|
WithTimeout | request timeout |
WithPingTimeout | health-check timeout |
WithPingURL | health-check target |
WithHTTPClient | inject a transport or a mock |
WithRetryAttempts | retries per send |
Wiring
Each send is a synchronous call to an external service from the path that just deployed or just detected an incident. Register deployments from the pipeline rather than from service startup, and register incidents after your own system of record has the incident, so a Sleuth outage costs a metric rather than the event itself.
WithTimeout and WithRetryAttempts bound how long a failing send holds the caller.
Example
c, err := sleuth.New("https://app.sleuth.io", "my-org", "api-key")
if err != nil {
log.Fatal(err)
}
err = c.HealthCheck(context.Background())
fmt.Println(err)
Full source is in example_sleuth_test.go. More runnable examples are on pkg.go.dev.
Dependencies
Reaches the validation stack through validator.
Links
- Reference documentation
- Source code
- The same job for DevLake: devlake
- Payload validation: validator
- All nurago packages