Tilebox can export workflow telemetry to Axiom through OTLP. Use this when your team already analyzes logs and traces in Axiom or wants long-term telemetry in Axiom datasets.
Built-in Tilebox Console observability does not require Axiom. Axiom export is optional and additive.
Configure Axiom export
Section titled “Configure Axiom export”Create Axiom datasets for logs and traces and an API key with ingest permissions. Then configure export when the runner process starts.
from tilebox.workflows import Clientfrom tilebox.workflows.observability.logging import configure_otel_logging_axiomfrom tilebox.workflows.observability.tracing import configure_otel_tracing_axiom
from my_workflow import ProcessScene
configure_otel_tracing_axiom( service="sentinel-2-runner", dataset="workflow-traces", api_key="<axiom-api-key>",)configure_otel_logging_axiom( service="sentinel-2-runner", dataset="workflow-logs", api_key="<axiom-api-key>",)
client = Client(name="sentinel-2-runner")runner = client.runner(tasks=[ProcessScene])runner.run_forever()package main
import ( "context" "log/slog"
"github.com/tilebox/tilebox-go/observability" "github.com/tilebox/tilebox-go/observability/logger" "github.com/tilebox/tilebox-go/observability/tracer" "github.com/tilebox/tilebox-go/workflows/v1" "go.opentelemetry.io/otel")
type ProcessScene struct{}
func (t *ProcessScene) Execute(ctx context.Context) error { slog.InfoContext(ctx, "processing scene") return nil}
func main() { ctx := context.Background() service := &observability.Service{Name: "sentinel-2-runner"} apiKey := "<axiom-api-key>"
traceProvider, shutdownTracer, err := tracer.NewAxiomProvider(ctx, service, "workflow-traces", apiKey) if err != nil { slog.ErrorContext(ctx, "failed to configure Axiom tracing", slog.Any("error", err)) return } defer shutdownTracer(ctx) otel.SetTracerProvider(traceProvider)
logHandler, shutdownLogger, err := logger.NewAxiomHandler(ctx, service, "workflow-logs", apiKey, logger.WithLevel(slog.LevelInfo), ) if err != nil { slog.ErrorContext(ctx, "failed to configure Axiom logging", slog.Any("error", err)) return } defer shutdownLogger(ctx) slog.SetDefault(logger.New(logHandler))
client := workflows.NewClient() runner, err := client.NewTaskRunner(ctx) if err != nil { slog.ErrorContext(ctx, "failed to create runner", slog.Any("error", err)) return }
if err := runner.RegisterTasks(&ProcessScene{}); err != nil { slog.ErrorContext(ctx, "failed to register tasks", slog.Any("error", err)) return }
runner.Run(ctx)}Environment variables
Section titled “Environment variables”You can omit credentials from code by setting environment variables:
| Variable | Used by |
|---|---|
AXIOM_API_KEY | log and trace export |
AXIOM_LOGS_DATASET | configure_otel_logging_axiom() |
AXIOM_TRACES_DATASET | configure_otel_tracing_axiom() |
configure_otel_tracing_axiom(service="sentinel-2-runner")configure_otel_logging_axiom(service="sentinel-2-runner")traceProvider, shutdownTracer, err := tracer.NewAxiomProviderFromEnv(ctx, service)if err != nil { slog.ErrorContext(ctx, "failed to configure Axiom tracing", slog.Any("error", err)) return}defer shutdownTracer(ctx)otel.SetTracerProvider(traceProvider)
logHandler, shutdownLogger, err := logger.NewAxiomHandlerFromEnv(ctx, service, logger.WithLevel(slog.LevelInfo),)if err != nil { slog.ErrorContext(ctx, "failed to configure Axiom logging", slog.Any("error", err)) return}defer shutdownLogger(ctx)slog.SetDefault(logger.New(logHandler))Existing Axiom screenshots
Section titled “Existing Axiom screenshots”
