zooqueenandhanzo-dev a403f49d40
CI / Security Scan (push) Successful in 1m27s
CI / Test (1.26.4) (push) Successful in 6m9s
CI / Build (1.26.4, macos-latest) (push) Failing after 0s
CI / Build (1.26.4, windows-latest) (push) Failing after 0s
CI / Build (1.26.4, ubuntu-latest) (push) Canceled after 0s
otel: move the OpenTelemetry bridge out of the root package
exporter_otelzap.go was the only file in the root package importing
go.opentelemetry.io, and it made the root package link 34 OpenTelemetry SDK
packages. Nothing else in the root package wants them: the registry, the text
encoder and the ZAP exporter are pure luxfi/zap.

That cost was not paid by the root package alone. github.com/zap-proto/zip
imports this module for the registry, EncodeText and NewZAPExporter, and passes
on whatever the root package links to each of the 125 programs built on it. The
ruling is native ZAP only, so nothing a plugin inherits may carry the
OpenTelemetry SDK.

The adapter is now package github.com/luxfi/metric/otel, and the two symbols it
exports lose the prefixes that only existed to disambiguate them inside the root
package:

  metric.NewOTelZAPExporter(cfg)  ->  otel.New(cfg)
  *metric.OTelZAPExporter         ->  *otel.Exporter

The configuration type stays metric.ZAPExporterConfig, since it belongs to the
ZAP exporter this adapter builds on. No alias is left behind in the root package
— one that re-imported the moved package would link the SDK again and undo the
change. Callers of the adapter add the otel import and drop the prefixes.

Proof, rather than a grep for import lines:

  go list -deps . | grep -c go.opentelemetry.io    ->  0
  go list -deps ./otel | grep -c go.opentelemetry.io  ->  34

0 holds under the default tags, -tags metrics and -tags metrics_noop alike. A
program importing zip v1.25.0 against this module resolves 0 as well, measured
with a replace directive.

The conversion had no tests, so the move now pins it: counter and gauge shapes,
the drop of an aggregation these shapes cannot carry, and the arithmetic that
matters — OpenTelemetry reports a count per bucket where Prometheus reports a
running total.

The metrics_noop defaults are untouched; recording stays the default and the
no-op stays opt-in. Build, vet and test -race are green under all three tag
sets.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-08-04 22:03:23 -07:00
2026-08-03 21:02:04 -07:00
2026-02-13 16:09:16 -08:00
2026-02-13 16:09:16 -08:00
2026-07-26 21:12:24 -07:00
2025-09-24 09:55:53 +00:00

metric

Lux Metrics Library

github.com/luxfi/metric is the native metrics library for Lux. It produces a scrape-compatible text exposition format and is designed for low overhead in hot paths.

Features

  • Single, native API for counters, gauges, histograms, summaries, and vectors
  • Scrape-compatible text format encoder and HTTP handler
  • Registry + gatherer model for composition
  • Optional no-op build for benchmark runs (build-tagged swap)

Installation

go get github.com/luxfi/metric@latest

Quick Start

package main

import (
	"net/http"

	"github.com/luxfi/metric"
)

func main() {
	m := metric.New("myapp")

	requests := m.NewCounter("requests_total", "Total requests")
	latency := m.NewHistogram("request_seconds", "Request latency (s)", metric.DefBuckets)

	requests.Inc()
	latency.Observe(0.123)

	http.Handle("/metrics", metric.Handler())
	_ = http.ListenAndServe(":8080", nil)
}

Custom Registry

reg := metric.NewRegistry()
m := metric.NewWithRegistry("myapp", reg)

requests := m.NewCounter("requests_total", "Total requests")
requests.Inc()

handler := metric.NewHTTPHandler(reg, metric.HandlerOpts{})

Vector Metrics

m := metric.New("myapp")
byRoute := m.NewCounterVec("requests_total", "Requests by route", []string{"method", "route"})

byRoute.WithLabelValues("GET", "/").Inc()

Metrics Off Build

Metrics record for real in an ordinary build. For benchmark runs you can swap the entire package to no-op implementations with a build tag, which keeps call sites unchanged while minimizing overhead.

go test -tags metrics_noop ./...

Built with the metrics_noop tag, metric.NewRegistry() and the package defaults return no-op implementations that record nothing — every counter reads zero — so use it only where that is what you want. Pre-bind label values in hot paths to avoid argument construction overhead.

S
Description
Prometheus metrics helpers: standard counters, gauges, histograms, and instrumentation conventions for all Lux components.
Readme BSD-3-Clause
887 KiB
Languages
Go 88.4%
HTML 10.2%
Makefile 1.4%