blob: 8b9ec7626837a6f78263d3db62894725ec9fad80 [file] [log] [blame]
// Copyright 2017 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package versions allows processes to report string-valued metrics with
// versions of various libraries they link with.
//
// The metric is named 'luci/components/version', and it has single field
// 'component' that defines the logical name of the component whose version is
// reported by the metric value.
//
// Having such metrics allows to easily detect processes that use stale code in
// production.
//
// Various go packages can register their versions during 'init' time, and all
// registered version will be flushed to monitoring whenever 'Report' is called.
package versions
import (
"context"
"sync"
"go.chromium.org/luci/common/tsmon/field"
"go.chromium.org/luci/common/tsmon/metric"
)
var registry struct {
m sync.RWMutex
r map[string]string
}
var (
versionMetric = metric.NewString(
"luci/components/version",
"Versions of LUCI components linked into the process.",
nil,
field.String("component"),
)
)
// Register tells the library to start reporting a version for given component.
//
// This should usually called during 'init' time.
//
// The component name will be used as a value of 'component' metric field, and
// the given version will become the actual reported metric value. It is a good
// idea to use a fully qualified go package name as 'component'.
func Register(component, version string) {
registry.m.Lock()
defer registry.m.Unlock()
if registry.r == nil {
registry.r = make(map[string]string, 1)
}
registry.r[component] = version
}
// Report populates 'luci/components/version' metric with versions of all
// registered components.
func Report(c context.Context) {
registry.m.RLock()
defer registry.m.RUnlock()
for component := range registry.r {
versionMetric.Set(c, registry.r[component], component)
}
}