summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-23 22:08:13 +0300
committerPaul Buetow <paul@buetow.org>2026-05-23 22:08:13 +0300
commit1179c247afbc815a664e26fd58a52f75bec15ccd (patch)
tree9b79f99970b9d9223483ca3610a70b996dd49905
parent2da5b82874549a4406b30dd9b29f5835102c2969 (diff)
doc: document MetricRegistry pointer safety guarantees
Add explicit documentation to Find, FindCaseInsensitive, FindWithAliases, List, and ListByCategory clarifying that returned *Metric pointers are safe to hold across concurrent Unregister calls. Metric objects are immutable after registration: Register panics on duplicate names (no in-place mutation), Unregister only deletes entries from the map (never modifies the Metric struct), and no mutator methods exist on the Metric type. The sync.RWMutex protects the map structures, while the immutability invariant protects the returned pointers.
-rw-r--r--internal/rpn/metric_registry.go15
1 files changed, 14 insertions, 1 deletions
diff --git a/internal/rpn/metric_registry.go b/internal/rpn/metric_registry.go
index 7a8b9aa..2c89b11 100644
--- a/internal/rpn/metric_registry.go
+++ b/internal/rpn/metric_registry.go
@@ -53,6 +53,11 @@ func (r *MetricRegistry) Register(m *Metric) {
}
// Find looks up a metric by name (case-sensitive).
+// The returned *Metric pointer is safe to hold across concurrent Unregister
+// calls: Metric objects are never mutated after registration (Register panics
+// on duplicates, and Unregister only deletes entries from the map without
+// modifying the objects), so the pointer always refers to a valid, immutable
+// value even after the metric is unregistered from the registry.
func (r *MetricRegistry) Find(name string) (*Metric, bool) {
r.mu.RLock()
defer r.mu.RUnlock()
@@ -62,6 +67,8 @@ func (r *MetricRegistry) Find(name string) (*Metric, bool) {
// FindCaseInsensitive looks up a metric by name ignoring case.
// Returns the canonical name match.
+// The returned *Metric pointer is safe to hold across concurrent operations
+// (see MetricRegistry.Find for details).
func (r *MetricRegistry) FindCaseInsensitive(name string) (*Metric, bool) {
r.mu.RLock()
defer r.mu.RUnlock()
@@ -105,6 +112,8 @@ func (r *MetricRegistry) MarkExactMatch(names ...string) {
// FindWithAliases looks up a metric by name, resolving aliases.
// Checks exact match first, then aliases, then case-insensitive (unless exact-match).
+// The returned *Metric pointer is safe to hold across concurrent operations
+// (see MetricRegistry.Find for details).
func (r *MetricRegistry) FindWithAliases(name string) (*Metric, bool) {
r.mu.RLock()
defer r.mu.RUnlock()
@@ -137,7 +146,9 @@ func (r *MetricRegistry) FindWithAliases(name string) (*Metric, bool) {
return nil, false
}
-// List returns all registered metrics.
+// List returns all registered metrics as a slice of pointers.
+// The returned pointers are safe to hold across concurrent Unregister calls
+// (see MetricRegistry.Find for details).
func (r *MetricRegistry) List() []*Metric {
r.mu.RLock()
defer r.mu.RUnlock()
@@ -149,6 +160,8 @@ func (r *MetricRegistry) List() []*Metric {
}
// ListByCategory returns all metrics in the given category.
+// The returned pointers are safe to hold across concurrent Unregister calls
+// (see MetricRegistry.Find for details).
func (r *MetricRegistry) ListByCategory(cat Category) []*Metric {
r.mu.RLock()
defer r.mu.RUnlock()