blob: 9ca35c8c3aafe0f7df92f4927d5b5c780868c61b [file] [log] [blame]
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package event
import (
"fmt"
"time"
)
type Metric interface {
Descriptor() MetricDescriptor
}
type MetricDescriptor struct {
namespace string
name string
Description string
// For unit, follow otel, or define Go types for common units? We don't need
// a time unit because we'll use time.Duration, and the only other unit otel
// currently defines (besides dimensionless) is bytes.
}
// TODO: how to force a non-empty namespace?
func NewMetricDescriptor(name string) MetricDescriptor {
if name == "" {
panic("name cannot be empty")
}
m := MetricDescriptor{name: name}
// TODO: make this work right whether called from in this package or externally.
// Set namespace to the caller's import path.
// Depth:
// 0 runtime.Callers
// 1 importPath
// 2 this function
// 3 caller of this function (one of the NewXXX methods in this package)
// 4 caller's caller
m.namespace = importPath(4, nil)
return m
}
func (m *MetricDescriptor) String() string {
return fmt.Sprintf("Metric(\"%s/%s\")", m.namespace, m.name)
}
func (m *MetricDescriptor) WithNamespace(ns string) *MetricDescriptor {
if ns == "" {
panic("namespace cannot be empty")
}
m.namespace = ns
return m
}
func (m MetricDescriptor) Name() string { return m.name }
func (m MetricDescriptor) Namespace() string { return m.namespace }
// A counter is a metric that counts something cumulatively.
type Counter struct {
MetricDescriptor
}
func NewCounter(name string) *Counter {
return &Counter{NewMetricDescriptor(name)}
}
func (c *Counter) Descriptor() MetricDescriptor {
return c.MetricDescriptor
}
type MetricValue struct {
m Metric
v Value
}
func (c *Counter) Record(v uint64) MetricValue {
return MetricValue{c, Uint64Of(v)}
}
// A FloatGauge records a single floating-point value that may go up or down.
// TODO(generics): Gauge[T]
type FloatGauge struct {
MetricDescriptor
}
func NewFloatGauge(name string) *FloatGauge {
return &FloatGauge{NewMetricDescriptor(name)}
}
func (g *FloatGauge) Descriptor() MetricDescriptor {
return g.MetricDescriptor
}
func (g *FloatGauge) Record(v float64) MetricValue {
return MetricValue{g, Float64Of(v)}
}
// A Duration records a distribution of durations.
// TODO(generics): Distribution[T]
type Duration struct {
MetricDescriptor
}
func NewDuration(name string) *Duration {
return &Duration{NewMetricDescriptor(name)}
}
func (d *Duration) Descriptor() MetricDescriptor {
return d.MetricDescriptor
}
func (d *Duration) Record(v time.Duration) MetricValue {
return MetricValue{d, DurationOf(v)}
}