sleuth

sleuth provides a Go client for the Sleuth.io API, covering common write-side integrations for delivery metrics and operational signal ingestion.

Part of nurago, a collection of independent Go packages for backend services.

import "github.com/tecnickcom/nurago/pkg/sleuth"

Package sleuth provides a Go client for the Sleuth.io API, covering common write-side integrations for delivery metrics and operational signal ingestion.

This package supports four Sleuth workflows:

  • deployment registration,
  • manual change registration,
  • custom incident impact registration,
  • custom metric impact registration.

Sleuth API reference: https://help.sleuth.io/sleuth-api

How It Works

New initializes a Client with base URL, org slug, and API key, then builds the endpoint URL templates used by each API action.

For each send operation:

  1. The request struct is validated using nurago’s validator package and the tag rules declared on fields.
  2. The payload is JSON-encoded and sent as an authenticated HTTP POST (Authorization: apikey <key>).
  3. The request is executed through a write-oriented HTTP retrier.
  4. Non-200 responses are returned as errors with status details.

Health checks are implemented using Sleuth’s documented behavior in absence of a dedicated ping endpoint: the client performs a controlled registration call and verifies expected 404 semantics and response content.

Usage

c, err := sleuth.New("https://app.sleuth.io/api/1", "my-org", apiKey)
if err != nil {
    return err
}

if err := c.HealthCheck(ctx); err != nil {
    return err
}

err = c.SendDeployRegistration(ctx, &sleuth.DeployRegistrationRequest{
    Deployment: "my-service",
    Sha:        "abcdef1234567890abcdef1234567890abcdef12",
})
if err != nil {
    return err
}

When To Use

  • A deployment pipeline reports to Sleuth.
  • Manual changes such as feature-flag flips should be tracked alongside deploys.

Example

// A stand-in for https://app.sleuth.io. Real code passes the Sleuth
// base address.
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	fmt.Println(r.Method, r.URL.Path)

	w.WriteHeader(http.StatusOK)
}))

defer srv.Close()

client, err := sleuth.New(srv.URL, "example-org", "api-key")
if err != nil {
	fmt.Println(err)

	return
}

// Requests are validated before being sent, so a malformed payload
// fails locally rather than at the API.
err = client.SendDeployRegistration(context.TODO(), &sleuth.DeployRegistrationRequest{
	Deployment:        "payments-production",
	Sha:               "9f8c1b2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b",
	Environment:       "production",
	IgnoreIfDuplicate: true,
	Tags:              []string{"#payments", "#backend"},
})

fmt.Println("err:", err)

// Output:
// POST /deployments/example-org/payments-production/register_deploy
// err: <nil>

Full source is in example_sleuth_test.go. More runnable examples are on pkg.go.dev.

Dependencies

Importing this package pulls 9 external modules:

  • github.com/gabriel-vasile/mimetype
  • github.com/go-playground/locales
  • github.com/go-playground/universal-translator
  • github.com/go-playground/validator/v10
  • github.com/julienschmidt/httprouter
  • github.com/leodido/go-urn
  • golang.org/x/crypto
  • golang.org/x/sys
  • golang.org/x/text