Skip to content

Instantly share code, notes, and snippets.

@Apurer
Created October 31, 2025 22:51
Show Gist options
  • Select an option

  • Save Apurer/66545bd58e17bb9e304a71bda656d801 to your computer and use it in GitHub Desktop.

Select an option

Save Apurer/66545bd58e17bb9e304a71bda656d801 to your computer and use it in GitHub Desktop.
package main
import (
"context"
"fmt"
"log/slog"
"os"
"time"
"go.opentelemetry.io/contrib/bridges/otelslog"
"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp"
"go.opentelemetry.io/otel/log/global"
sdklog "go.opentelemetry.io/otel/sdk/log"
"go.opentelemetry.io/otel/sdk/resource"
"go.opentelemetry.io/otel/semconv/v1.24.0"
"go.temporal.io/sdk/client"
workerlog "go.temporal.io/sdk/worker/log"
)
func main() {
ctx := context.Background()
// --- Initialize OpenTelemetry logging ---
provider, err := initOTELLogging(ctx)
if err != nil {
panic(fmt.Errorf("failed to init OTEL logging: %w", err))
}
defer func() {
_ = provider.Shutdown(context.Background())
}()
// --- Run the main application logic ---
runApp(ctx)
}
// initOTELLogging sets up and globally registers the OTEL log pipeline.
func initOTELLogging(ctx context.Context) (*sdklog.LoggerProvider, error) {
// Create OTLP HTTP exporter (insecure)
exporter, err := otlploghttp.New(ctx,
otlploghttp.WithInsecure(), // no TLS
otlploghttp.WithEndpoint("localhost:4318"),
)
if err != nil {
return nil, fmt.Errorf("failed to create OTLP exporter: %w", err)
}
// Create a logger provider with resource info
provider := sdklog.NewLoggerProvider(
sdklog.WithResource(resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceName("temporal-client"),
semconv.ServiceVersion("1.0.0"),
semconv.DeploymentEnvironment("development"),
)),
sdklog.WithProcessor(sdklog.NewBatchProcessor(exporter)),
)
// Register globally
global.SetLoggerProvider(provider)
return provider, nil
}
// runApp creates the Temporal client and emits logs.
func runApp(ctx context.Context) {
// Retrieve the global provider explicitly
provider := global.GetLoggerProvider()
// Create a slog.Logger backed by OTEL
otelSlog := otelslog.NewLogger(
"example/temporal",
otelslog.WithLoggerProvider(provider),
)
// Log to both stdout and OTEL
handler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo})
logger := slog.New(slog.NewMultiHandler(handler, otelSlog.Handler()))
// Temporal StructuredLogger adapter
temporalLogger := workerlog.NewStructuredLogger(logger)
// --- Connect to Temporal ---
c, err := client.Dial(client.Options{
HostPort: "localhost:7233",
Namespace: "default",
Logger: temporalLogger,
})
if err != nil {
panic(fmt.Errorf("unable to create Temporal client: %w", err))
}
defer c.Close()
// Emit logs
logger.Info("Temporal client started")
runWorkflowExample(ctx, c, logger)
}
// Example fake workflow logic
func runWorkflowExample(ctx context.Context, c client.Client, logger *slog.Logger) {
logger.Info("Running fake workflow", "workflow", "ExampleWorkflow")
time.Sleep(2 * time.Second)
logger.Info("Workflow completed successfully")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment