mirror of
https://github.com/SigNoz/signoz.git
synced 2026-05-10 12:20:29 +01:00
100 lines
3.0 KiB
Go
100 lines
3.0 KiB
Go
package v2
|
|
|
|
import (
|
|
"regexp"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// Code is a dotted, hierarchical identifier registered at process start. It
|
|
// encodes domain (subsystem), op (verb), optional sub (qualifier), and a
|
|
// terminal reason. Codes are values; two Codes with the same string are equal
|
|
// by value and safe to compare with ==.
|
|
type Code struct{ s string }
|
|
|
|
// String returns the dotted code as it appears on the wire. Empty for the
|
|
// zero value.
|
|
func (c Code) String() string { return c.s }
|
|
|
|
// codePattern allows 2-4 dotted segments, each starting with a lowercase
|
|
// letter and continuing with [a-z0-9_]. One segment is too broad (use a
|
|
// domain prefix); five or more means the domain should be split.
|
|
var codePattern = regexp.MustCompile(`^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*){1,3}$`)
|
|
|
|
// Meta is the per-code default envelope applied by constructors before
|
|
// per-call options. Every field has a natural per-code default — an auth
|
|
// code always wants Reauthenticate, every documented code wants its docs
|
|
// URL — so the registry is the right place to declare them once.
|
|
type Meta struct {
|
|
Category Category
|
|
Fault Fault
|
|
Retry Retry
|
|
Remediation Remediation
|
|
Refs map[RefKind]string
|
|
}
|
|
|
|
// Retry tells the caller how and when to retry. After is meaningful only
|
|
// when Policy == RetryAfter.
|
|
type Retry struct {
|
|
Policy RetryPolicy
|
|
After time.Duration
|
|
}
|
|
|
|
var (
|
|
registryMu sync.RWMutex
|
|
registry = map[string]Meta{}
|
|
)
|
|
|
|
// Register installs a code with its default Meta and returns the Code value.
|
|
// It panics on a malformed code string or a duplicate registration — both
|
|
// indicate a programming error that must be caught at boot, not at first
|
|
// failure.
|
|
//
|
|
// Call from the owning domain's package init or top-level var block:
|
|
//
|
|
// var CodeUnknownFunction = errors.Register("query.parse.unknown_function", errors.Meta{
|
|
// Category: errors.CategoryInvalidInput,
|
|
// Fault: errors.FaultCaller,
|
|
// Retry: errors.Retry{Policy: errors.RetryAfterFix},
|
|
// })
|
|
func Register(s string, meta Meta) Code {
|
|
if !codePattern.MatchString(s) {
|
|
panic("errors/v2: malformed code: " + s)
|
|
}
|
|
registryMu.Lock()
|
|
defer registryMu.Unlock()
|
|
if _, ok := registry[s]; ok {
|
|
panic("errors/v2: duplicate code: " + s)
|
|
}
|
|
registry[s] = meta
|
|
return Code{s: s}
|
|
}
|
|
|
|
// MetaOf returns the Meta a code was registered with. Returns the zero Meta
|
|
// and false for unregistered or zero codes.
|
|
func MetaOf(c Code) (Meta, bool) {
|
|
if c.s == "" {
|
|
return Meta{}, false
|
|
}
|
|
registryMu.RLock()
|
|
defer registryMu.RUnlock()
|
|
m, ok := registry[c.s]
|
|
return m, ok
|
|
}
|
|
|
|
// registerOrGet is the internal idempotent register used by adapters that
|
|
// may see the same code (e.g. legacy.<v1>) more than once across the process
|
|
// lifetime. It panics on malformed codes — duplicate codes silently keep the
|
|
// existing Meta.
|
|
func registerOrGet(s string, meta Meta) Code {
|
|
if !codePattern.MatchString(s) {
|
|
panic("errors/v2: malformed code: " + s)
|
|
}
|
|
registryMu.Lock()
|
|
defer registryMu.Unlock()
|
|
if _, ok := registry[s]; !ok {
|
|
registry[s] = meta
|
|
}
|
|
return Code{s: s}
|
|
}
|