Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.logwiz.io/llms.txt

Use this file to discover all available pages before exploring further.

The opentelemetry-sdk for Zig is in alpha (v0.1.1, Zig 0.15.2). It has not been battle-tested in production environments. Expect breaking changes between releases.
Logwiz accepts OpenTelemetry logs over OTLP HTTP. The Zig SDK’s std.log bridge routes all standard library log calls to OpenTelemetry without changing a single call site. Records land in the OTEL logs index pinned by your ingest token (default: otel-logs-v0_9).

Setup

1

Add the SDK to your project

Requires Zig ≥ 0.15.2. Run this in your project root:
zig fetch --save "git+https://github.com/zig-o11y/opentelemetry-sdk#v0.1.1"
Then add these lines to build.zig after your exe declaration:
const otel_sdk = b.dependency("opentelemetry", .{
    .target = target,
    .optimize = optimize,
});
exe.root_module.addImport("opentelemetry-sdk", otel_sdk.module("sdk"));
The dependency key opentelemetry matches the SDK’s package name in its build.zig.zon; the import alias opentelemetry-sdk is what your code will @import.
2

Set environment variables

export OTEL_SERVICE_NAME=my-zig-service
export OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://<your-logwiz>/api/otlp/v1/logs
export OTEL_EXPORTER_OTLP_LOGS_HEADERS=Authorization=Bearer%20<your-ingest-token>
The %20 after Bearer is required — OTEL expects URL-encoded header values.
3

Minimal working example

const std = @import("std");
const sdk = @import("opentelemetry-sdk");

pub const std_options: std.Options = .{
    .logFn = sdk.logs.std_log_bridge.logFn,
};

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    // OTLP exporter — reads OTEL_EXPORTER_OTLP_* env vars
    var otlp_config = try sdk.otlp.ConfigOptions.init(allocator);
    defer otlp_config.deinit();

    var otlp_exporter = try sdk.logs.OTLPExporter.init(allocator, otlp_config);
    defer otlp_exporter.deinit();
    const exporter = otlp_exporter.asLogRecordExporter();

    // Wire the exporter into a processor
    var simple_processor = sdk.logs.SimpleLogRecordProcessor.init(allocator, exporter);
    const processor = simple_processor.asLogRecordProcessor();

    // Logger provider with the processor attached
    var provider = try sdk.logs.LoggerProvider.init(allocator, null);
    defer provider.deinit();
    try provider.addLogRecordProcessor(processor);

    // Route std.log calls through OpenTelemetry
    try sdk.logs.std_log_bridge.configure(.{
        .provider = provider,
        .also_log_to_stderr = true,
    });
    defer sdk.logs.std_log_bridge.shutdown();

    std.log.info("Hello from Zig to Logwiz", .{});

    try provider.shutdown();
}
Save as src/main.zig and run zig build run. The bridge reads the endpoint and auth header from the environment variables above.
4

Verify in Logwiz

Open Search, filter on service_name:my-zig-service, and your record should appear within ~2 seconds.

Structured logging

The std.log bridge maps Zig log levels to OpenTelemetry severity numbers automatically:
Zig levelOTel severity
debugDEBUG (5)
infoINFO (9)
warnWARN (13)
errERROR (17)
Log messages and their format arguments become the log record body. Unlike Go’s slog.With, the std.log API does not support structured key/value attributes — format args are interpolated into the message string.
std.log.info("user signed up: {s} plan={s}", .{ user_id, plan });
For structured attributes, use the direct SDK API — see the examples/logs/ folder in the SDK repository.