Skip to content
Monitoring
Skill

/maple-go-style

Go OpenTelemetry style for Maple: go.opentelemetry.io/otel SDK with otlptracehttp / otlploghttp / otlpmetrichttp exporters, inline endpoint + ingest key, semconv resource attributes including vcs.repository.url.full.

BOOST
From plugin
maple
1.8k37 skills
Install
$ npx -y skills add mapletechlabs/maple --skill maple-go-style --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/maple-go-style

Context preview

The summary Claude sees to decide when to auto-load this skill.

Go OpenTelemetry style for Maple: go.opentelemetry.io/otel SDK with otlptracehttp / otlploghttp / otlpmetrichttp exporters, inline endpoint + ingest key, semconv resource attributes including vcs.repository.url.full.

SKILL.md

maple-go-style.SKILL.md
name: maple-go-style
description: "Go OpenTelemetry style for Maple: go.opentelemetry.io/otel SDK with otlptracehttp / otlploghttp / otlpmetrichttp exporters, inline endpoint + ingest key, semconv resource attributes including vcs.repository.url.full."

Maple Go style

Use the official `go.opentelemetry.io/otel` SDK with the HTTP exporters. Initialize once at process start and shut down on signal.

Install

go get \
  go.opentelemetry.io/otel \
  go.opentelemetry.io/otel/sdk \
  go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp \
  go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp \
  go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp \
  go.opentelemetry.io/otel/log \
  go.opentelemetry.io/otel/sdk/log

Bootstrap

Inline the endpoint and ingest key. The key is a project-scoped, write-only token (shaped like a Sentry DSN). No env-var indirection. `WithEndpoint` takes a host without scheme, uses HTTPS, and appends the default `/v1/<signal>` path.

package telemetry

import (
	"context"
	"os"

	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp"
	"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp"
	"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
	"go.opentelemetry.io/otel/log/global"
	sdklog "go.opentelemetry.io/otel/sdk/log"
	"go.opentelemetry.io/otel/sdk/metric"
	"go.opentelemetry.io/otel/sdk/resource"
	"go.opentelemetry.io/otel/sdk/trace"
	semconv "go.opentelemetry.io/otel/semconv/v1.24.0"
)

const (
	mapleEndpoint = "ingest.maple.dev" // EU: ingest.eu.maple.dev
	mapleKey      = "MAPLE_TEST" // public ingest key (maple_pk_…), or MAPLE_TEST until the user has one
)

func Init(ctx context.Context) (shutdown func(context.Context) error, err error) {
	headers := map[string]string{"authorization": "Bearer " + mapleKey}

	res, err := resource.New(ctx,
		resource.WithAttributes(
			semconv.ServiceName("orders-api"),
			semconv.DeploymentEnvironment(envOr("DEPLOYMENT_ENV", "development")),
			attribute.String("vcs.repository.url.full", "https://github.com/acme/orders-api"),
			attribute.String("vcs.ref.head.revision", envOr("GITHUB_SHA", envOr("GIT_COMMIT", ""))),
		),
	)
	if err != nil {
		return nil, err
	}

	traceExp, err := otlptracehttp.New(ctx,
		otlptracehttp.WithEndpoint(mapleEndpoint),
		otlptracehttp.WithHeaders(headers),
	)
	if err != nil {
		return nil, err
	}
	tp := trace.NewTracerProvider(trace.WithBatcher(traceExp), trace.WithResource(res))
	otel.SetTracerProvider(tp)

	logExp, err := otlploghttp.New(ctx,
		otlploghttp.WithEndpoint(mapleEndpoint),
		otlploghttp.WithHeaders(headers),
	)
	if err != nil {
		return nil, err
	}
	lp := sdklog.NewLoggerProvider(
		sdklog.WithProcessor(sdklog.NewBatchProcessor(logExp)),
		sdklog.WithResource(res),
	)
	global.SetLoggerProvider(lp)

	metricExp, err := otlpmetrichttp.New(ctx,
		otlpmetrichttp.WithEndpoint(mapleEndpoint),
		otlpmetrichttp.WithHeaders(headers),
	)
	if err != nil {
		return nil, err
	}
	mp := metric.NewMeterProvider(
		metric.WithReader(metric.NewPeriodicReader(metricExp)),
		metric.WithResource(res),
	)
	otel.SetMeterProvider(mp)

	return func(ctx context.Context) error {
		_ = tp.Shutdown(ctx)
		_ = lp.Shutdown(ctx)
		return mp.Shutdown(ctx)
	}, nil
}

func envOr(key, fallback string) string {
	if v := os.Getenv(key); v != "" {
		return v
	}
	return fallback
}

Wire from `main`:

func main() {
	ctx := context.Background()
	// A telemetry setup error is logged, never fatal: the app runs without export.
	if shutdown, err := telemetry.Init(ctx); err != nil {
		log.Printf("telemetry disabled: %v", err)
	} else {
		defer shutdown(ctx)
	}

	// app start
}

Bounded business spans

Acquire the tracer at package scope. Start spans where auto-instrumentation is blind, set the status on error, and end the span via `defer` (imports: `go.opentelemetry.io/otel/attribute`, `go.opentelemetry.io/otel/codes`).

var tracer = otel.Tracer("orders.api")

func SubmitOrder(ctx context.Context, orderID string) (err error) {
	ctx, span := tracer.Start(ctx, "order.submit")
	defer func() {
		if err != nil {
			span.RecordError(err)
			span.SetStatus(codes.Error, err.Error())
		}
		span.End()
	}()

	span.SetAttributes(attribute.String("order.id", orderID))
	return chargeOrder(ctx, orderID)
}

Auto-instrumentation

Go has no framework-level auto-discovery. Add instrumentation packages only for libraries the app imports: `otelhttp`, `otelgrpc`, `otelmux` from `go.opentelemetry.io/contrib/instrumentation/...`, and community packages such as `github.com/XSAM/otelsql`, `github.com/exaring/otelpgx`, and Fiber's `otelfiber` (in `github.com/gofiber/contrib`). Wrap outgoing HTTP clients with `otelhttp.NewTransport` so trace context propagates; Maple's service map draws edges from a Client span to the callee's child Server span.

Coexistence

If the project already exports to Honeycomb, Datadog, or Tempo, add Maple's exporter alongside with one `trace.WithBatcher(exp)` option per backend. Do not strip the existing exporter unless the user asks.

Read more
Ships withmaple

OpenTelemetry observability platform

Get the whole plugin

Other skills on maple.