metricsx

package
v0.1.15 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 29, 2026 License: MIT Imports: 18 Imported by: 0

README

metricsx

metricsx is the Aisphere Kernel metrics package. It is the recommended package for registering and recording metrics (counters, up-down counters, histograms, gauges) in business code. It wraps go.opentelemetry.io/otel/metric with a simpler API and built-in safety: nil-safe, low-cardinality validation, automatic system metrics, Prometheus one-liner.

新手上路:只看本文件即可上手。需要深度细节时再翻其他文档(见末尾"文档地图")。


1. 为什么需要 metricsx

Before metricsx, business code used otel/metric directly:

  • Verbose registration (meter.Int64Counter(name, metric.WithDescription(desc)))
  • No nil safety — passing nil meter panicked
  • No cardinality validation — easy to cause Prometheus label explosion
  • No system metrics — had to manually register goroutine/memory gauges
  • No Prometheus one-liner — had to wire exporter + meter provider + handler

metricsx provides a Manager interface with clean methods, nil safety, cardinality warnings, and a NewPrometheusManager one-liner.

metricsx (only defines metric registration/recording)
  ↓ stable contract (Manager interface)
handler   → IncrementCounter(ctx, "requests_total", "method", "GET")
service   → RecordHistogram(ctx, "query_seconds", latency, "op", "find")
worker    → SetGauge("queue_depth", 42, "queue", "publish")
startup   → NewPrometheusManager + GetHandler → /metrics endpoint

metricsx itself does not do logging, tracing, or transport middleware. It only manages metric instruments.


2. 30-second quickstart

package main

import (
    "net/http"

    "github.com/aisphereio/kernel/metricsx"
)

func main() {
    // Bootstrap: Prometheus-backed Manager in one call
    m := metricsx.NewPrometheusManager("aihub", "v1.0.0", logger)

    // Register metrics at startup
    metricsx.RegisterSystemMetrics(m)  // goroutines, memory, GC
    m.NewCounter("skill_create_total", "Total skills created")
    m.NewHistogram("skill_query_seconds", "Skill query latency",
        metricsx.DefaultBuckets...)
    m.NewGauge("active_sessions", "Active sessions")

    // Expose /metrics + /debug/pprof/*
    http.Handle("/metrics", metricsx.GetHandler(m))
    go http.ListenAndServe(":9000", nil)

    // In business code:
    m.IncrementCounter(ctx, "skill_create_total", "tenant", "t_acme")
    m.RecordHistogram(ctx, "skill_query_seconds", 0.042, "operation", "find")
    m.SetGauge("active_sessions", 42, "tenant", "t_acme")
}

3. Manager API cheatsheet

Bootstrap
Function Use for
NewPrometheusManager(app, ver, logger) One-liner Prometheus Manager
NewPrometheusMeter(app, ver) Just the otel Meter (use with NewManager)
NewManager(meter, logger) Wrap any otel Meter
Noop() Discard all metrics (tests, disabled features)
Registration (call at startup)
Method Instrument type
m.NewCounter(name, desc) Monotonic int64 counter
m.NewUpDownCounter(name, desc) float64, can go up or down
m.NewHistogram(name, desc, buckets...) float64 distribution
m.NewGauge(name, desc) float64 current value
Recording (call in business code)
Method What it does
m.IncrementCounter(ctx, name, labels...) +1
m.DeltaUpDownCounter(ctx, name, value, labels...) +/- value
m.RecordHistogram(ctx, name, value, labels...) Observe value
m.SetGauge(name, value, labels...) Set current value

Labels are key-value pairs: "key1", "value1", "key2", "value2".


4. Instrument types

Counter (monotonic)
m.NewCounter("requests_total", "Total requests")
m.IncrementCounter(ctx, "requests_total", "method", "GET", "status", "200")

Use for: request counts, event counts, error counts. Never decreases.

UpDownCounter (can decrease)
m.NewUpDownCounter("active_sessions", "Active sessions")
m.DeltaUpDownCounter(ctx, "active_sessions", 1, "tenant", "t_acme")   // +1
m.DeltaUpDownCounter(ctx, "active_sessions", -1, "tenant", "t_acme")  // -1

Use for: active sessions, in-flight requests, queue size (when you need the delta pattern rather than absolute set).

Histogram (distribution)
m.NewHistogram("request_seconds", "Request latency",
    metricsx.DefaultBuckets...)  // 0.005, 0.01, 0.025, ..., 10
m.RecordHistogram(ctx, "request_seconds", 0.042, "operation", "find")

Use for: latencies, payload sizes, any distribution. Buckets define the boundaries for aggregation.

Gauge (current value)
m.NewGauge("queue_depth", "Current queue depth")
m.SetGauge("queue_depth", 42, "queue", "skill_publish")

Use for: current state that can go up or down (queue depth, connection count, memory usage). Each SetGauge replaces the previous value.


5. nil safety

A nil Manager is a valid no-op. All methods are safe to call on nil:

var m metricsx.Manager  // nil
m.IncrementCounter(ctx, "test")  // no-op, no panic
m.SetGauge("test", 1.0)          // no-op, no panic

This happens when NewManager(nil, nil) is called (e.g. metrics disabled in config). Business code can pass the Manager through without nil-checks.

Use Noop() explicitly for tests:

func TestCreateSkill(t *testing.T) {
    svc := NewService(metricsx.Noop())  // discard metrics in tests
    // ...
}

6. Labels and cardinality

Labels are key-value pairs passed as varargs:

m.IncrementCounter(ctx, "requests_total",
    "method", "GET",        // label 1
    "status", "200",        // label 2
    "tenant", "t_acme",     // label 3
)

Cardinality warning: metricsx logs a warning if you pass more than 20 labels (potential Prometheus cardinality explosion). The metric is still recorded, but you'll see a warning in logs.

Best practices:

  • Keep label count under 10
  • Never put dynamic IDs (user_id, request_id, skill_id) in labels — use metricsx only for low-cardinality dimensions (method, status, tenant, operation, error_code)
  • For high-cardinality data, use logs (logx) or tracing (otel), not metrics

7. System metrics

RegisterSystemMetrics(m) registers 5 standard Go runtime gauges:

Metric Description
app_go_goroutines Number of goroutines
app_sys_memory_alloc Allocated memory in bytes
app_sys_total_alloc Total allocated memory in bytes
app_go_num_gc Number of GC cycles
app_go_sys Memory obtained from OS in bytes

These are auto-updated on each /metrics scrape via GetHandler.


8. /metrics endpoint

GetHandler(m) returns an HTTP handler serving:

  • /metrics — Prometheus exposition format (with auto system metrics)
  • /debug/pprof/* — Go pprof profiling endpoints
http.Handle("/metrics", metricsx.GetHandler(m))
http.ListenAndServe(":9000", nil)

Scrape with Prometheus or curl:

curl http://localhost:9000/metrics

9. DefaultBuckets

DefaultBuckets provides sensible histogram bucket boundaries for request latency in seconds:

m.NewHistogram("request_seconds", "Request latency",
    metricsx.DefaultBuckets...)
// Buckets: 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10

For non-latency histograms, provide custom buckets:

m.NewHistogram("payload_bytes", "Payload size in bytes",
    100, 1000, 10000, 100000, 1000000,
)

10. Forbidden patterns (AI 必读)

// ❌ Use otel/metric directly in business code
meter.Int64Counter("requests_total", metric.WithDescription("..."))

// ❌ Put dynamic IDs in labels (cardinality explosion)
m.IncrementCounter(ctx, "requests_total",
    "request_id", reqID,     // ❌ high cardinality
    "user_id", userID,       // ❌ high cardinality
)

// ❌ Skip registration, then record (silently fails)
m.IncrementCounter(ctx, "never_registered")  // logs error, no-ops

// ❌ Nil-check before every call (unnecessary — nil Manager is safe)
if m != nil {
    m.IncrementCounter(ctx, "test")
}

Required:

// ✅ Register at startup, record in business code
m.NewCounter("requests_total", "Total requests")
m.IncrementCounter(ctx, "requests_total", "method", "GET", "status", "200")

// ✅ Low-cardinality labels only
m.IncrementCounter(ctx, "requests_total",
    "method", "GET",
    "status", "200",
    "tenant", "t_acme",
)

// ✅ No nil-check needed (nil Manager is no-op)
m.IncrementCounter(ctx, "test")  // safe even if m is nil

11. Integration with errorx

Count errors by error_code for alerting:

import "github.com/aisphereio/kernel/errorx"

err := h.svc.Create(ctx, req)
if err != nil {
    m.IncrementCounter(ctx, "errors_total",
        "error_code", errorx.CodeOf(err).String(),
        "http_status", fmt.Sprintf("%d", errorx.HTTPStatusOf(err)),
        "retryable", fmt.Sprintf("%t", errorx.RetryableOf(err)),
    )
    return err
}

Never put request_id / trace_id / skill_id in labels — those go in logs (logx) or tracing (otel).


12. Integration with logx

metricsx.Logger is an alias of logx.Logger — pass a logx.Logger directly:

import (
    "github.com/aisphereio/kernel/logx"
    "github.com/aisphereio/kernel/metricsx"
)

logger, _, _ := logx.New(cfg)
m := metricsx.NewPrometheusManager("aihub", "v1.0.0", logger)  // logx.Logger satisfies metricsx.Logger

metricsx reuses the Kernel logger contract instead of duplicating log methods.


13. 测试

go test ./metricsx -v
go test ./metricsx -race
go test ./metricsx -cover

go run ./examples/metricsx-basic

14. 文档地图

metricsx 的文档分为四类,按需查阅:

快速上手
├── 本文件 (metricsx/README.md)             ← 你正在看的,单一入口
├── metricsx/doc.go                         ← go doc 输出源
└── metricsx/example_test.go                ← Go 标准示例

深度规范(架构师/PR review 时看)
└── docs/contracts/metricsx.md              ← 不可破坏契约

AI 编码指南(AI 写业务代码时看)
├── docs/ai/metricsx.md                     ← 合并版 AI 指南
└── AGENTS.md                               ← 项目级 AI 规则

可运行示例
└── examples/metricsx-basic/                ← 最小示例

优先级:日常开发只看本 README + docs/ai/metricsx.md 即可。


15. Examples 索引(按场景查找)

Bootstrap
Function Example
NewManager ExampleNewManager
Noop ExampleNoop
NewPrometheusManager ExampleNewPrometheusManager
Registration
Method Example
NewCounter ExampleManager_NewCounter
NewUpDownCounter ExampleManager_NewUpDownCounter
NewHistogram ExampleManager_NewHistogram, ExampleManager_NewHistogram_defaultBuckets
NewGauge ExampleManager_NewGauge
Recording
Method Example
IncrementCounter ExampleManager_IncrementCounter
DeltaUpDownCounter ExampleManager_DeltaUpDownCounter
RecordHistogram ExampleManager_RecordHistogram
SetGauge ExampleManager_SetGauge
nil safety
Topic Example
nil Manager no-op ExampleManager_nilSafety
System metrics
Function Example
RegisterSystemMetrics ExampleRegisterSystemMetrics
GetHandler ExampleGetHandler
Constants
Topic Example
DefaultBuckets ExampleDefaultBuckets
Errors
Type Example
ErrNotRegistered ExampleErrNotRegistered
ErrAlreadyRegistered ExampleErrAlreadyRegistered
Business scenarios (in example_business_test.go)
Scenario Example
Bootstrap at startup Example_businessBootstrap
Counter — count events Example_businessCounter
Histogram — record latency Example_businessHistogram
Gauge — current state Example_businessGauge
UpDownCounter — inc/dec Example_businessUpDownCounter
nil Manager in tests Example_businessNilManagerInTests
System metrics on scrape Example_businessSystemMetrics
Multi-tenant labels Example_businessMultiTenant
Error metrics Example_businessErrorMetrics
Cardinality warning Example_businessCardinalityWarning

16. 设计哲学一句话

metricsx is the recommended metrics package. Register at startup, record in business code. nil Manager is safe. Low-cardinality labels only. If you're about to write meter.Int64Counter(...) directly or put user_id in a label — STOP, use metricsx.NewCounter and keep labels low-cardinality.

Documentation

Overview

Package metricsx provides business-facing metrics for Aisphere Kernel.

metricsx is the recommended package for registering and recording metrics (counters, up-down counters, histograms, gauges) in business code. It wraps go.opentelemetry.io/otel/metric with a simpler API and built-in safety:

  • Nil-safe: all methods on a nil Manager are no-ops
  • Low-cardinality label validation (warns on > 20 labels)
  • Standard system metrics registration helpers (goroutines, memory)
  • Prometheus exporter one-liner via NewPrometheusManager
  • Logger type reuses logx.Logger

Design principle

metricsx only DEFINES metric registration and recording. It does NOT do logging (use logx), NOT do tracing (use contrib/otel/tracing), NOT do transport middleware (use contrib/otel/metrics for that). It only manages metric instruments.

metricsx depends on logx, go.opentelemetry.io/otel/metric, the Prometheus exporter, and the Go standard library. It does NOT import errorx or transport.

30-second quickstart

// Bootstrap: create a Prometheus-backed manager
m := metricsx.NewPrometheusManager("aihub", "v1.0.0", logger)

// Register metrics at startup
m.NewCounter("skill_create_total", "Total skills created")
m.NewHistogram("skill_query_seconds", "Skill query latency", 0.01, 0.1, 1, 10)
m.NewGauge("active_sessions", "Active sessions")

// Record in business code
m.IncrementCounter(ctx, "skill_create_total", "tenant", "t_acme")
m.RecordHistogram(ctx, "skill_query_seconds", 0.042, "operation", "find")
m.SetGauge("active_sessions", 42, "tenant", "t_acme")

// Expose /metrics endpoint
http.Handle("/metrics", metricsx.GetHandler(m))

Instrument types

m.NewCounter(name, desc)                        // monotonic, int64
m.NewUpDownCounter(name, desc)                  // can go up or down, float64
m.NewHistogram(name, desc, buckets...)          // distribution, float64
m.NewGauge(name, desc)                          // current value, float64

Recording

m.IncrementCounter(ctx, name, labels...)        // +1
m.DeltaUpDownCounter(ctx, name, value, labels...) // +/- value
m.RecordHistogram(ctx, name, value, labels...)  // observe value
m.SetGauge(name, value, labels...)              // set current value

Labels are key-value pairs: "key1", "value1", "key2", "value2".

nil safety

All methods on a nil Manager are no-ops. This means you can pass a nil Manager to test code or disabled features without nil-checks everywhere:

var m metricsx.Manager  // nil
m.IncrementCounter(ctx, "x")  // no-op, no panic

Further reading

See metricsx/README.md for the single-source-of-truth user guide, and docs/ai/metricsx.md for the AI coding recipe.

Example (BusinessBootstrap)

Example_businessBootstrap shows the standard startup pattern: create a Prometheus-backed Manager, register all metrics, expose /metrics endpoint.

package main

import (
	"fmt"

	"github.com/aisphereio/kernel/metricsx"
)

func main() {
	// In real code (cannot run here due to Prometheus registry):
	//   m := metricsx.NewPrometheusManager("aihub", "v1.0.0", logger)
	//   metricsx.RegisterSystemMetrics(m)
	//   m.NewCounter("skill_create_total", "Total skills created")
	//   m.NewHistogram("skill_query_seconds", "Skill query latency", metricsx.DefaultBuckets...)
	//   m.NewGauge("active_sessions", "Active sessions")
	//   http.Handle("/metrics", metricsx.GetHandler(m))

	m := metricsx.Noop() // stand-in for example
	m.NewCounter("skill_create_total", "Total skills created")
	m.NewHistogram("skill_query_seconds", "Skill query latency", metricsx.DefaultBuckets...)
	m.NewGauge("active_sessions", "Active sessions")
	fmt.Println("ok")
}
Output:
ok
Example (BusinessCardinalityWarning)

Example_businessCardinalityWarning shows that metricsx warns when too many labels are passed (potential Prometheus cardinality explosion).

package main

import (
	"context"
	"fmt"

	"github.com/aisphereio/kernel/metricsx"
)

func main() {
	m := metricsx.Noop()
	m.NewCounter("high_cardinality_test", "test")

	// 22 labels — triggers a warning log (but still records)
	m.IncrementCounter(context.Background(), "high_cardinality_test",
		"k1", "v1", "k2", "v2", "k3", "v3", "k4", "v4", "k5", "v5",
		"k6", "v6", "k7", "v7", "k8", "v8", "k9", "v9", "k10", "v10",
		"k11", "v11",
	)
	fmt.Println("ok")
}
Output:
ok
Example (BusinessCounter)

Example_businessCounter shows counting business events with labels.

package main

import (
	"context"
	"fmt"

	"github.com/aisphereio/kernel/metricsx"
)

func main() {
	m := metricsx.Noop()
	m.NewCounter("skill_create_total", "Total skills created")
	m.NewCounter("skill_delete_total", "Total skills deleted")

	// In handler: count with labels
	m.IncrementCounter(context.Background(), "skill_create_total",
		"tenant", "t_acme",
		"visibility", "public",
	)
	m.IncrementCounter(context.Background(), "skill_delete_total",
		"tenant", "t_acme",
		"reason", "archived",
	)
	fmt.Println("ok")
}
Output:
ok
Example (BusinessErrorMetrics)

Example_businessErrorMetrics shows counting errors by error_code for alerting and dashboards.

package main

import (
	"context"
	"fmt"

	"github.com/aisphereio/kernel/metricsx"
)

func main() {
	m := metricsx.Noop()
	m.NewCounter("errors_total", "Total errors by code")

	// When business code returns an errorx error:
	//   err := errorx.NotFound("AIHUB_SKILL_NOT_FOUND", "...")
	//   m.IncrementCounter(ctx, "errors_total",
	//       "error_code", errorx.CodeOf(err).String(),
	//       "http_status", fmt.Sprintf("%d", errorx.HTTPStatusOf(err)),
	//   )

	m.IncrementCounter(context.Background(), "errors_total",
		"error_code", "AIHUB_SKILL_NOT_FOUND",
		"http_status", "404",
	)
	m.IncrementCounter(context.Background(), "errors_total",
		"error_code", "AIHUB_SKILL_QUERY_FAILED",
		"http_status", "500",
	)
	fmt.Println("ok")
}
Output:
ok
Example (BusinessGauge)

Example_businessGauge shows tracking current state (queue depth, active sessions, etc.).

package main

import (
	"fmt"

	"github.com/aisphereio/kernel/metricsx"
)

func main() {
	m := metricsx.Noop()
	m.NewGauge("queue_depth", "Current queue depth")

	// Worker reports current queue size periodically
	queueSize := 42
	m.SetGauge("queue_depth", float64(queueSize),
		"queue", "skill_publish",
	)
	fmt.Println("ok")
}
Output:
ok
Example (BusinessHistogram)

Example_businessHistogram shows recording request latency.

package main

import (
	"context"
	"fmt"
	"time"

	"github.com/aisphereio/kernel/metricsx"
)

func main() {
	m := metricsx.Noop()
	m.NewHistogram("request_seconds", "Request latency", metricsx.DefaultBuckets...)

	start := time.Now()
	// ... business logic ...
	latency := time.Since(start).Seconds()

	m.RecordHistogram(context.Background(), "request_seconds", latency,
		"operation", "find_skill",
		"status", "200",
		"tenant", "t_acme",
	)
	fmt.Println("ok")
}
Output:
ok
Example (BusinessMultiTenant)

Example_businessMultiTenant shows per-tenant metric segmentation via labels.

package main

import (
	"context"
	"fmt"

	"github.com/aisphereio/kernel/metricsx"
)

func main() {
	m := metricsx.Noop()
	m.NewCounter("api_requests_total", "Total API requests")
	m.NewHistogram("api_request_seconds", "API request latency", metricsx.DefaultBuckets...)

	// Per-tenant recording
	tenants := []string{"t_acme", "t_globex", "t_initech"}
	for _, tenant := range tenants {
		m.IncrementCounter(context.Background(), "api_requests_total",
			"tenant", tenant,
			"endpoint", "/v1/skills",
		)
		m.RecordHistogram(context.Background(), "api_request_seconds", 0.05,
			"tenant", tenant,
			"endpoint", "/v1/skills",
		)
	}
	fmt.Println("ok")
}
Output:
ok
Example (BusinessNilManagerInTests)

Example_businessNilManagerInTests shows that nil Manager is safe — tests can pass nil without nil-checks everywhere.

package main

import (
	"context"
	"fmt"

	"github.com/aisphereio/kernel/metricsx"
)

func main() {
	// Test setup: pass nil Manager
	var m metricsx.Manager // nil
	m = metricsx.NewManager(nil, nil)

	// Business code calls methods without nil-checks:
	m.IncrementCounter(context.Background(), "test_counter")
	m.RecordHistogram(context.Background(), "test_hist", 0.5)
	m.SetGauge("test_gauge", 1.0)

	fmt.Println("ok")
}
Output:
ok
Example (BusinessSystemMetrics)

Example_businessSystemMetrics shows that GetHandler auto-records Go runtime metrics (goroutines, memory) on each /metrics scrape.

package main

import (
	"fmt"

	"github.com/aisphereio/kernel/metricsx"
)

func main() {
	m := metricsx.Noop()
	metricsx.RegisterSystemMetrics(m)

	// When Prometheus scrapes /metrics, these are auto-updated:
	//   app_go_goroutines
	//   app_sys_memory_alloc
	//   app_sys_total_alloc
	//   app_go_num_gc
	//   app_go_sys

	handler := metricsx.GetHandler(m)
	fmt.Println(handler != nil)
}
Output:
true
Example (BusinessUpDownCounter)

Example_businessUpDownCounter shows tracking values that go up and down (active sessions, in-flight requests).

package main

import (
	"context"
	"fmt"

	"github.com/aisphereio/kernel/metricsx"
)

func main() {
	m := metricsx.Noop()
	m.NewUpDownCounter("active_sessions", "Active sessions")

	// Session start: +1
	m.DeltaUpDownCounter(context.Background(), "active_sessions", 1,
		"tenant", "t_acme",
	)
	// Session end: -1
	m.DeltaUpDownCounter(context.Background(), "active_sessions", -1,
		"tenant", "t_acme",
	)
	fmt.Println("ok")
}
Output:
ok

Index

Examples

Constants

This section is empty.

Variables

View Source
var DefaultBuckets = []float64{0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10}

DefaultBuckets provides sensible histogram bucket boundaries for request latency in seconds. Use with NewHistogram:

m.NewHistogram("request_seconds", "Request latency",
    metricsx.DefaultBuckets...)

Functions

func GetHandler

func GetHandler(m Manager, opts ...HandlerOption) http.Handler

GetHandler returns an HTTP handler that serves:

  • /metrics by default, or a custom path via WithMetricsPath
  • /debug/pprof/* when WithPprof(true) is used

It also records system metrics (goroutine count, memory usage, GC count) on each metrics scrape. A nil Manager is treated as a no-op Manager.

Example
package main

import (
	"fmt"

	"github.com/aisphereio/kernel/metricsx"
)

func main() {
	m := metricsx.Noop()
	handler := metricsx.GetHandler(m)
	if handler != nil {
		fmt.Println("ok")
	}
}
Output:
ok

func GetMetricsHandler added in v0.0.6

func GetMetricsHandler(m Manager) http.Handler

GetMetricsHandler returns a metrics-only handler suitable for mounting on an existing admin server. It does not expose pprof endpoints.

func Inject added in v0.0.6

func Inject(ctx context.Context, manager Manager) context.Context

Inject stores a metrics manager in ctx. Passing nil stores a no-op manager so downstream code can always call metrics methods without nil checks.

func NewPrometheusMeter

func NewPrometheusMeter(appName, appVersion string) metric.Meter

NewPrometheusMeter creates an otel Meter backed by a Prometheus exporter. Use this with NewManager to get a Manager that exposes /metrics via GetHandler.

meter := metricsx.NewPrometheusMeter("aihub", "v1.0.0")
m := metricsx.NewManager(meter, logger)
http.Handle("/metrics", metricsx.GetHandler(m))

func PromCounter

func PromCounter(name, help string) prometheus.Counter

PromCounter returns a Prometheus counter (for direct use with promhttp instrumentation, bypassing the otel layer). Advanced use only — prefer Manager.NewCounter for business code.

func RegisterSystemMetrics

func RegisterSystemMetrics(m Manager)

RegisterSystemMetrics registers the standard system metric names so they appear in the metric store before the first metrics scrape. It is safe to call multiple times with the same Manager.

Example
package main

import (
	"fmt"

	"github.com/aisphereio/kernel/metricsx"
)

func main() {
	m := metricsx.Noop()
	metricsx.RegisterSystemMetrics(m)
	// Now app_go_goroutines, app_sys_memory_alloc, etc. are registered.
	fmt.Println("ok")
}
Output:
ok

Types

type ErrAlreadyRegistered

type ErrAlreadyRegistered struct{ Name string }

ErrAlreadyRegistered is returned when a metric name is registered twice.

Example
package main

import (
	"fmt"

	"github.com/aisphereio/kernel/metricsx"
)

func main() {
	err := &metricsx.ErrAlreadyRegistered{Name: "duplicate_metric"}
	fmt.Println(err)
}
Output:
metricsx: metric "duplicate_metric" already registered

func (*ErrAlreadyRegistered) Error

func (e *ErrAlreadyRegistered) Error() string

type ErrNotRegistered

type ErrNotRegistered struct{ Name string }

ErrNotRegistered is returned when recording against an unregistered name.

Example
package main

import (
	"fmt"

	"github.com/aisphereio/kernel/metricsx"
)

func main() {
	err := &metricsx.ErrNotRegistered{Name: "missing_metric"}
	fmt.Println(err)
}
Output:
metricsx: metric "missing_metric" not registered

func (*ErrNotRegistered) Error

func (e *ErrNotRegistered) Error() string

type HandlerOption added in v0.0.6

type HandlerOption func(*handlerConfig)

HandlerOption customizes the admin handler returned by GetHandler.

func WithMetricsPath added in v0.0.6

func WithMetricsPath(path string) HandlerOption

WithMetricsPath changes the Prometheus exposition path. Empty or malformed values fall back to /metrics.

func WithPprof added in v0.0.6

func WithPprof(enabled bool) HandlerOption

WithPprof controls whether /debug/pprof/* endpoints are added to the returned handler. GetHandler defaults to true for compatibility; kernel's built-in metrics server disables pprof unless explicitly requested.

type Logger

type Logger = logx.Logger

Logger is the Kernel logger interface accepted by metricsx.

type Manager

type Manager interface {
	// Registration (call at startup, before recording)
	NewCounter(name, desc string)
	NewUpDownCounter(name, desc string)
	NewHistogram(name, desc string, buckets ...float64)
	NewGauge(name, desc string)

	// Recording (call in business code)
	IncrementCounter(ctx context.Context, name string, labels ...string)
	DeltaUpDownCounter(ctx context.Context, name string, value float64, labels ...string)
	RecordHistogram(ctx context.Context, name string, value float64, labels ...string)
	SetGauge(name string, value float64, labels ...string)
}

Manager defines the interface for registering and recording metrics. All methods are nil-safe — a nil Manager is a valid no-op implementation.

Example (NilSafety)
package main

import (
	"context"
	"fmt"

	"github.com/aisphereio/kernel/metricsx"
)

func main() {
	// A nil Manager is a valid no-op — methods don't panic.
	// This happens when NewManager(nil, nil) is called.
	m := metricsx.NewManager(nil, nil)

	m.NewCounter("test", "test")                            // no-op
	m.IncrementCounter(context.Background(), "test")        // no-op
	m.DeltaUpDownCounter(context.Background(), "test", 1.0) // no-op
	m.RecordHistogram(context.Background(), "test", 0.5)    // no-op
	m.SetGauge("test", 1.0)                                 // no-op

	fmt.Println("ok")
}
Output:
ok

func Ensure added in v0.0.6

func Ensure(manager Manager) Manager

Ensure returns manager when non-nil, otherwise a no-op Manager.

func FromContext added in v0.0.6

func FromContext(ctx context.Context) Manager

FromContext returns the metrics manager stored in ctx, or a no-op manager if none is present. This is intended for bootstrap/lifecycle hooks that receive only context.Context from kernel.App.

func FromContextOr added in v0.0.6

func FromContextOr(ctx context.Context, fallback Manager) Manager

FromContextOr returns the metrics manager stored in ctx, or fallback when ctx has no manager. If fallback is nil, a no-op manager is returned.

func NewManager

func NewManager(meter metric.Meter, logger Logger) Manager

NewManager creates a Manager backed by the given otel meter. If logger is nil, a no-op logger is used.

Example
package main

import (
	"fmt"

	"github.com/aisphereio/kernel/metricsx"
)

func main() {
	// In real code: meter := metricsx.NewPrometheusMeter("aihub", "v1.0.0")
	// Here we pass nil meter to get a no-op Manager (safe for examples).
	m := metricsx.NewManager(nil, nil)
	fmt.Println(m == nil)
}
Output:
false

func NewPrometheusManager

func NewPrometheusManager(appName, appVersion string, logger Logger) Manager

NewPrometheusManager is a convenience that creates a Prometheus-backed Meter and wraps it in a Manager in one call.

m := metricsx.NewPrometheusManager("aihub", "v1.0.0", logger)
http.Handle("/metrics", metricsx.GetHandler(m))
Example
package main

import (
	"fmt"

	"github.com/aisphereio/kernel/metricsx"
)

func main() {
	// NewPrometheusManager creates a Prometheus-backed Manager in one call.
	// (Not run in example to avoid Prometheus registry conflicts.)
	_ = metricsx.NewPrometheusManager
	fmt.Println("see signature")
}
Output:
see signature

func Noop

func Noop() Manager

Noop returns a Manager that discards all operations. Useful in tests and disabled features.

Example
package main

import (
	"context"
	"fmt"

	"github.com/aisphereio/kernel/metricsx"
)

func main() {
	// Noop returns a Manager that discards all operations.
	// Useful in tests and disabled features.
	m := metricsx.Noop()
	m.NewCounter("test", "test counter")
	m.IncrementCounter(context.Background(), "test")
	fmt.Println("ok")
}
Output:
ok

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL