howdy/trace
Tracing with OpenTelemetry.
Howdy and its packages open a span around each request, database query, remote call and email, and your code can add its own:
import howdy/trace
pub fn checkout(cart: Cart) {
use <- trace.span("checkout", [trace.int("cart.items", cart.count)])
...
}
Nothing is recorded or sent anywhere until an OpenTelemetry SDK is
running. Without one every function here does next to nothing, so
instrumented code costs almost nothing in an app that does not collect
telemetry. Add howdy_telemetry to switch it on; see its docs.
Spans nest by process: a span opened while another is running in the
same process becomes its child. Other Gleam libraries built on
opentelemetry_api, such as opengleametry, share the same context, so
their spans nest under Howdy’s and the other way round. Work handed to
another process starts a new trace unless you carry the context across
with context and within.
Types
A key and value recorded on a span or event. Use the OpenTelemetry
semantic convention names where one fits, such as http.route or
db.system.name.
pub opaque type Attribute
A span waiting to be run. Build one with new when you need more than
span offers.
pub opaque type Builder
The tracing context of a process, to carry into another process with
within.
pub opaque type Context
What a span represents. Tracing backends use it to recognise requests,
so the request Howdy serves is a Server span and a call out to another
service is a Client span.
pub type Kind {
Internal
Server
Client
Producer
Consumer
}
Constructors
-
Internal -
Server -
Client -
Producer -
Consumer
Values
pub fn attributes(
builder: Builder,
attributes: List(Attribute),
) -> Builder
Add attributes to the span when it starts. Samplers only see attributes
given here, not ones added later with set_attributes.
pub fn continue_from(
builder: Builder,
headers: List(#(String, String)),
) -> Builder
Continue the trace described by the traceparent and tracestate
headers of an incoming request, if they are there. Header names must be
lowercase, as they are in a gleam/http request. Without trace headers
the span starts a new trace, or continues the current one.
pub fn event(name: String, attributes: List(Attribute)) -> Nil
Record that something happened at this moment in the current span.
pub fn inject(
headers: List(#(String, String)),
) -> List(#(String, String))
Add the current trace’s traceparent and tracestate headers to
headers, so a service you call can continue the trace. Returns
headers unchanged outside a span.
pub fn is_recording() -> Bool
Whether the current span is being recorded. Use it to skip work that only feeds a span, such as formatting a large attribute.
pub fn link_to(traceparent: String) -> Result(Link, Nil)
A link to the span a traceparent value describes.
pub fn new(name: String) -> Builder
Start building a span called name. It is an Internal span with no
attributes until you say otherwise.
pub fn run(builder: Builder, body: fn() -> a) -> a
Run run inside the span and return what it returns.
pub fn set_attributes(attributes: List(Attribute)) -> Nil
Add attributes to the current span. Does nothing outside a span.
pub fn set_error(message: String) -> Nil
Mark the current span as failed, with a short description of what went wrong. A span that panics is marked for you.
pub fn span(
name: String,
with: List(Attribute),
body: fn() -> a,
) -> a
Run run inside a span called name, and return what it returns.
The span ends when run returns. If run panics, the panic is recorded
on the span, the span is marked as failed, and the panic carries on.
pub fn strings(key: String, values: List(String)) -> Attribute
A list of strings, such as the tags on a message.
pub fn trace_id() -> option.Option(String)
The current trace’s id as 32 lowercase hex characters, if the current span is being recorded. Show it on an error page or in a log line so the trace can be found later.
pub fn traceparent() -> option.Option(String)
The current span as a W3C traceparent header value, if it is being
recorded. Store it alongside work queued for later, then link_to it.