otel

OpenTelemetry observability for Kit — metrics, traces, and log correlation

Files

FileDescription
.editorconfigEditor formatting configuration
.gitignoreGit ignore rules for build artifacts and dependencies
.tool-versionsasdf tool versions (Zig, Kit)
LICENSEMIT license file
README.mdThis file
examples/basic-metrics.kitExample: basic metrics
kit.tomlPackage manifest with metadata and dependencies
src/exporter-otlp.kitOTLP/HTTP JSON Exporter
src/exporter-prometheus.kitPrometheus Text Format Exporter
src/main.kitKit OTel — OpenTelemetry for Kit
src/meter.kitOpenTelemetry Meter Provider
src/metrics.kitOpenTelemetry Metric Instruments
src/tracer.kitOpenTelemetry Tracer Provider
src/traces.kitOpenTelemetry Trace Spans
src/types.kitOpenTelemetry Core Types
tests/metrics.test.kitTests for metrics
tests/traces.test.kitTests for traces

Dependencies

No Kit package dependencies.

Installation

kit add gitlab.com/kit-lang/packages/kit-otel.git

Usage

import Kit.OTel as OTel

main = fn(-env) =>
  # Create a meter to group metrics
  meter = OTel.create-meter "my-service"{version: "1.0.0"}

  # Counter (monotonically increasing)
  counter = OTel.create-counter "http.requests.total"{
    description: "Total HTTP requests", 
    unit: "requests"
  }
  counter = OTel.increment counter {method: "GET"}

  # Histogram (distribution of values)
  latency = OTel.create-histogram "http.request.duration"{
    description: "Request latency in milliseconds", 
    unit: "ms", 
    buckets: [5, 10, 25, 50, 100, 250, 500, 1000]
  }
  latency = OTel.record latency 42{method: "GET"}

  # Gauge (point-in-time value)
  depth = OTel.create-gauge "actor.mailbox.depth"{
    description: "Actor mailbox depth", 
    unit: "messages"
  }
  depth = OTel.set-gauge depth 127{actor: "worker-1"}

  # UpDownCounter (can increase or decrease)
  active = OTel.create-up-down-counter "http.connections.active"{
    description: "Active HTTP connections", 
    unit: "connections"
  }
  active = OTel.add active 1{}
  active = OTel.add active -1{}

  # Register metrics with the meter
  meter = OTel.register-metric meter counter
  meter = OTel.register-metric meter latency

  # Traces
  tracer = OTel.create-tracer "my-service"{version: "1.0.0"}
  span = OTel.start-span tracer "handle-request"{kind: OTel.SpanServer, attributes: {}}
  tracer = OTel.finish-span tracer span OTel.SpanOk

  # Export via OTLP/HTTP
  exporter = OTel.create-otlp-exporter {
    endpoint: "http://localhost:4318", 
    headers: [], 
    timeout-ms: 5000
  }
  OTel.export-metrics exporter meter
  OTel.export-spans exporter tracer

  # Or export as Prometheus text format
  prom-text = OTel.format-prometheus meter
  println prom-text

main

Development

Running Examples

Run examples with the interpreter:

kit run examples/basic-metrics.kit

Compile examples to a native binary:

kit build examples/basic-metrics.kit && ./basic-metrics

Running Tests

Run the test suite:

kit test

Run the test suite with coverage:

kit test --coverage

Running kit dev

Run the standard development workflow (format, check, test):

kit dev

This will:

  1. Format and check source files in src/
  2. Run tests in tests/ with coverage

Generating Documentation

Generate API documentation from doc comments:

kit doc

Note: Kit sources with doc comments (##) will generate HTML documents in docs/*.html

Cleaning Build Artifacts

Remove generated files, caches, and build artifacts:

kit task clean

Note: Defined in kit.toml.

Local Installation

To install this package locally for development:

kit install

This installs the package to ~/.kit/packages/@kit/otel/, making it available for import as Kit.OTel in other projects.

License

This package is released under the MIT License - see LICENSE for details.

Exported Functions & Types

create-tracer

Create a new tracer for grouping related spans.

Parameters:

Returns:

String -> Record -> Record

tracer = create-tracer "my-service" {version: "1.0.0"}

start-span

Start a new root span via this tracer.

Parameters:

Returns:

Record -> String -> Record -> Record

span = start-span tracer "handle-request" {kind: SpanServer, attributes: {}}

start-child-span

Start a child span via this tracer.

Parameters:

Returns:

Record -> Record -> String -> Record -> Record

finish-span

End a span and add it to the tracer's collection.

Parameters:

Returns:

Record -> Record -> SpanStatus -> Record

tracer = finish-span tracer span SpanOk

collect-spans

Collect all completed spans as a list.

Parameters:

Returns:

Record -> List Record

reset

Reset the tracer, clearing all collected spans.

Useful after a successful export.

Record -> Record

span-count

Get the number of collected spans.

Record -> Int

generate-trace-id

Generate a 32-character hex trace ID.

Uses UUID.v4 with dashes stripped to produce a 32-hex-char string conforming to the W3C Trace Context specification.

Returns:

String

tid = generate-trace-id
println tid  # e.g., "550e8400e29b41d4a716446655440000"

generate-span-id

Generate a 16-character hex span ID.

Uses the first 16 characters of a stripped UUID.v4.

Returns:

String

sid = generate-span-id
println sid  # e.g., "550e8400e29b41d4"

create-span

Create a root span (no parent).

Parameters:

Returns:

String -> Record -> Record

span = create-span "handle-request" {kind: SpanServer, attributes: {}}

create-child-span

Create a child span linked to a parent span.

Inherits the parent's trace-id and sets parent-span-id.

Parameters:

Returns:

Record -> String -> Record -> Record

child = create-child-span parent "db-query" {kind: SpanClient, attributes: {}}

end-span

End a span by setting its end-time and status.

Parameters:

Returns:

Record -> SpanStatus -> Record

span = end-span span SpanOk
span = end-span span (SpanError {message: "connection refused"})

add-event

Add an event to a span.

Events are timestamped annotations that record notable moments during a span's lifetime (e.g., cache misses, retries, exceptions).

Parameters:

Returns:

Record -> String -> Record -> Record

span = add-event span "cache-miss" {key: "user:42"}

set-attribute

Set an attribute on a span.

Parameters:

Returns:

Record -> String -> a -> Record

duration

Get the duration of a completed span in milliseconds.

Returns 0 if the span has not been ended yet.

Record -> Int

is-ended?

Check if a span has been ended.

Record -> Bool

Counter

Counter metric kind.

MetricKind

Histogram

Histogram metric kind.

MetricKind

Gauge

Gauge metric kind.

MetricKind

UpDownCounter

UpDownCounter metric kind.

MetricKind

SpanClient

Client span kind.

SpanKind

SpanServer

Server span kind.

SpanKind

SpanProducer

Producer span kind.

SpanKind

SpanConsumer

Consumer span kind.

SpanKind

SpanInternal

Internal span kind.

SpanKind

SpanOk

Ok span status.

SpanStatus

SpanError

Error span status.

String -> SpanStatus

SpanUnset

Unset span status.

SpanStatus

StringAttr

String attribute value.

String -> AttributeValue

IntAttr

Integer attribute value.

Int -> AttributeValue

FloatAttr

Float attribute value.

Float -> AttributeValue

BoolAttr

Boolean attribute value.

Bool -> AttributeValue

ExportError

Export error.

{message: String} -> OTelError

ConfigError

Configuration error.

{message: String} -> OTelError

InvalidMetric

Invalid metric error.

{message: String} -> OTelError

create-counter

Create a counter metric instrument.

String -> Record -> Record

create-histogram

Create a histogram metric instrument.

String -> Record -> Record

create-gauge

Create a gauge metric instrument.

String -> Record -> Record

create-up-down-counter

Create an up-down counter metric instrument.

String -> Record -> Record

increment

Increment a counter by 1.

Record -> Record -> Record

add

Add a value to a counter or up-down counter.

Record -> Int -> Record -> Record

record

Record a value in a histogram.

Record -> Int -> Record -> Record

set-gauge

Set the current value of a gauge.

Record -> Int -> Record -> Record

get-value

Get the current value of a metric.

Record -> Int

create-meter

Create a new meter for grouping related metrics.

String -> Record -> Record

register-metric

Register a metric instrument with a meter.

Record -> Record -> Record

get-metric

Get a registered metric by name.

Record -> String -> Option Record

update-metric

Update a registered metric in the meter.

Record -> Record -> Record

collect-metrics

Collect all registered metrics as a list.

Record -> List Record

reset-meter

Reset the meter.

Record -> Record

generate-trace-id

Generate a 32-character hex trace ID.

String

generate-span-id

Generate a 16-character hex span ID.

String

create-span

Create a root span.

String -> Record -> Record

create-child-span

Create a child span linked to a parent span.

Record -> String -> Record -> Record

end-span

End a span with a status.

Record -> SpanStatus -> Record

add-event

Add an event to a span.

Record -> String -> Record -> Record

set-attribute

Set an attribute on a span.

Record -> String -> a -> Record

duration

Get the duration of a completed span in milliseconds.

Record -> Int

is-ended?

Check if a span has been ended.

Record -> Bool

create-tracer

Create a new tracer for grouping related spans.

String -> Record -> Record

start-span

Start a new root span via a tracer.

Record -> String -> Record -> Record

start-child-span

Start a child span via a tracer.

Record -> Record -> String -> Record -> Record

finish-span

End a span and add it to the tracer.

Record -> Record -> SpanStatus -> Record

collect-spans

Collect all completed spans from a tracer.

Record -> List Record

reset-tracer

Reset the tracer.

Record -> Record

create-otlp-exporter

Create an OTLP/HTTP exporter.

Record -> Record

export-metrics

Export metrics to an OTLP collector.

Record -> Record -> Result String OTelError

export-spans

Export spans to an OTLP collector.

Record -> Record -> Result String OTelError

format-prometheus

Format metrics as Prometheus exposition text.

Record -> String

metric-kind-to-string

Convert a MetricKind to its string representation.

MetricKind -> String

span-kind-to-int

Convert a SpanKind to its OTLP numeric value.

SpanKind -> Int

span-kind-to-string

Convert a SpanKind to its string representation.

SpanKind -> String

span-status-to-int

Convert a SpanStatus to its OTLP status code integer.

SpanStatus -> Int

attribute-value-to-string

Convert an AttributeValue to a display string.

AttributeValue -> String

create-meter

Create a new meter for grouping related metrics.

Parameters:

Returns:

String -> Record -> Record

meter = create-meter "my-service" {version: "1.0.0"}

register-metric

Register a metric instrument with a meter.

Parameters:

Returns:

Record -> Record -> Record

meter = register-metric meter counter

get-metric

Get a registered metric by name.

Parameters:

Returns:

Record -> String -> Option Record

match get-metric meter "http.requests.total"
  | Some m -> println "Found metric"
  | None -> println "Not found"

update-metric

Update a registered metric in the meter.

Replaces the metric with the same name in the meter's collection.

Parameters:

Returns:

Record -> Record -> Record

updated-counter = Metrics.increment counter {method: "GET"}
meter = update-metric meter updated-counter

collect

Collect all registered metrics as a list.

Returns a snapshot of all current metric values for export.

Parameters:

Returns:

Record -> List Record

metrics = collect meter
List.map metrics fn(m) => println "${m.name}: ${to-string (Metrics.get-value m)}"

reset

Reset the meter, clearing all registered metrics.

Creates a fresh meter with the same name and version but no metrics. Useful after a successful export to start fresh.

Parameters:

Returns:

Record -> Record

metric-count

Get the number of registered metrics.

Record -> Int

create-otlp-exporter

Create an OTLP/HTTP exporter.

Parameters:

  • - endpoint - Base URL of the OTel collector (e.g., "http://localhost:4318")
  • - headers - List of {name, value} header records
  • - timeout-ms - Request timeout in milliseconds

Returns:

Record -> Record

exporter = create-otlp-exporter {
  endpoint: "http://localhost:4318",
  headers: [],
  timeout-ms: 5000
}

export-metrics

Export metrics from a meter to the OTLP collector.

Serializes all registered metrics to OTLP JSON format and sends via HTTP POST.

Parameters:

Returns:

Record -> Record -> Result String OTelError

export-spans

Export spans from a tracer to the OTLP collector.

Serializes all collected spans to OTLP JSON format and sends via HTTP POST.

Parameters:

Returns:

Record -> Record -> Result String OTelError

create-counter

Create a counter metric instrument.

Counters are monotonically increasing and track cumulative totals.

Parameters:

Returns:

String -> Record -> Record

counter = create-counter "http.requests.total" {
  description: "Total HTTP requests",
  unit: "requests"
}

create-histogram

Create a histogram metric instrument.

Histograms track the distribution of values across configurable buckets.

Parameters:

Returns:

String -> Record -> Record

latency = create-histogram "http.request.duration" {
  description: "Request latency in ms",
  unit: "ms",
  buckets: [5, 10, 25, 50, 100, 250, 500, 1000]
}

create-gauge

Create a gauge metric instrument.

Gauges record a point-in-time value that can go up or down.

Parameters:

Returns:

String -> Record -> Record

depth = create-gauge "actor.mailbox.depth" {
  description: "Actor mailbox depth",
  unit: "messages"
}

create-up-down-counter

Create an up-down counter metric instrument.

Up-down counters can increase or decrease, tracking values like active connections.

Parameters:

Returns:

String -> Record -> Record

active = create-up-down-counter "http.connections.active" {
  description: "Active HTTP connections",
  unit: "connections"
}

increment

Increment a counter by 1.

Parameters:

Returns:

Record -> Record -> Record

updated = increment counter {method: "GET", path: "/api"}

add

Add a value to a counter or up-down counter.

Parameters:

Returns:

Record -> Int -> Record -> Record

updated = add counter 5 {method: "POST"}
updated2 = add up-down -1 {}

record

Record a value in a histogram.

Updates the histogram's count, total, and bucket counts.

Parameters:

Returns:

Record -> Int -> Record -> Record

updated = record latency 42 {method: "GET"}

set-gauge

Set the current value of a gauge.

Parameters:

Returns:

Record -> Int -> Record -> Record

updated = set-gauge depth 127 {actor: "worker-1"}

get-value

Get the current value of a metric.

For counters and gauges, returns the value directly. For histograms, returns the count of observations.

Parameters:

Returns:

Record -> Int

val = get-value counter

get-labels

Get the labels map for a metric.

Record -> Map

MetricKind

The kind of metric instrument.

- Counter: Monotonically increasing value (e.g., request count) - Histogram: Distribution of values (e.g., latency) - Gauge: Point-in-time value (e.g., queue depth) - UpDownCounter: Value that can increase or decrease (e.g., active connections)

Variants

Counter
Histogram
Gauge
UpDownCounter

Counter

Counter metric kind constructor.

MetricKind

Histogram

Histogram metric kind constructor.

MetricKind

Gauge

Gauge metric kind constructor.

MetricKind

UpDownCounter

UpDownCounter metric kind constructor.

MetricKind

SpanKind

The kind of span in a trace.

- SpanClient: Outgoing request (e.g., HTTP client call) - SpanServer: Incoming request (e.g., HTTP server handler) - SpanProducer: Message producer (e.g., publishing to a queue) - SpanConsumer: Message consumer (e.g., reading from a queue) - SpanInternal: Internal operation (default)

Variants

SpanClient
SpanServer
SpanProducer
SpanConsumer
SpanInternal

SpanClient

Client span kind constructor.

SpanKind

SpanServer

Server span kind constructor.

SpanKind

SpanProducer

Producer span kind constructor.

SpanKind

SpanConsumer

Consumer span kind constructor.

SpanKind

SpanInternal

Internal span kind constructor.

SpanKind

SpanStatus

The status of a completed span.

- SpanOk: Operation completed successfully - SpanError: Operation failed with an error message - SpanUnset: Status not explicitly set (default)

Variants

SpanOk
SpanError {message}
SpanUnset

SpanOk

Ok span status constructor.

SpanStatus

SpanError

Error span status constructor.

String -> SpanStatus

SpanUnset

Unset span status constructor.

SpanStatus

AttributeValue

A typed attribute value for spans and metrics.

OpenTelemetry attributes are key-value pairs where values have specific types. - StringAttr: String value - IntAttr: Integer value - FloatAttr: Floating-point value - BoolAttr: Boolean value

Variants

StringAttr {String}
IntAttr {Int}
FloatAttr {Float}
BoolAttr {Bool}

StringAttr

String attribute value constructor.

String -> AttributeValue

IntAttr

Integer attribute value constructor.

Int -> AttributeValue

FloatAttr

Float attribute value constructor.

Float -> AttributeValue

BoolAttr

Boolean attribute value constructor.

Bool -> AttributeValue

OTelError

Error types for OpenTelemetry operations.

- ExportError: Failed to export telemetry data - ConfigError: Invalid configuration - InvalidMetric: Invalid metric operation

Variants

ExportError {message}
ConfigError {message}
InvalidMetric {message}

metric-kind-to-string

Convert a MetricKind to its string representation.

MetricKind -> String

span-kind-to-int

Convert a SpanKind to its OTLP numeric value.

SpanKind -> Int

span-kind-to-string

Convert a SpanKind to its string representation.

SpanKind -> String

span-status-to-int

Convert a SpanStatus to its OTLP status code integer.

SpanStatus -> Int

attribute-value-to-string

Convert an AttributeValue to a display string.

AttributeValue -> String

format-metrics

Format all metrics in a meter as Prometheus exposition text.

Parameters:

Returns:

Record -> String

text = format-metrics meter
println text

format-single-metric

Format a single metric as Prometheus text lines.

Record -> String