119 lines
4.2 KiB
Go
119 lines
4.2 KiB
Go
// Copyright 2014 The Prometheus 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 prometheus_test
|
|
|
|
import "github.com/prometheus/client_golang/prometheus"
|
|
|
|
// ClusterManager is an example for a system that might have been built without
|
|
// Prometheus in mind. It models a central manager of jobs running in a
|
|
// cluster. To turn it into something that collects Prometheus metrics, we
|
|
// simply add the two methods required for the Collector interface.
|
|
//
|
|
// An additional challenge is that multiple instances of the ClusterManager are
|
|
// run within the same binary, each in charge of a different zone. We need to
|
|
// make use of ConstLabels to be able to register each ClusterManager instance
|
|
// with Prometheus.
|
|
type ClusterManager struct {
|
|
Zone string
|
|
OOMCountDesc *prometheus.Desc
|
|
RAMUsageDesc *prometheus.Desc
|
|
// ... many more fields
|
|
}
|
|
|
|
// ReallyExpensiveAssessmentOfTheSystemState is a mock for the data gathering a
|
|
// real cluster manager would have to do. Since it may actually be really
|
|
// expensive, it must only be called once per collection. This implementation,
|
|
// obviously, only returns some made-up data.
|
|
func (c *ClusterManager) ReallyExpensiveAssessmentOfTheSystemState() (
|
|
oomCountByHost map[string]int, ramUsageByHost map[string]float64,
|
|
) {
|
|
// Just example fake data.
|
|
oomCountByHost = map[string]int{
|
|
"foo.example.org": 42,
|
|
"bar.example.org": 2001,
|
|
}
|
|
ramUsageByHost = map[string]float64{
|
|
"foo.example.org": 6.023e23,
|
|
"bar.example.org": 3.14,
|
|
}
|
|
return
|
|
}
|
|
|
|
// Describe simply sends the two Descs in the struct to the channel.
|
|
func (c *ClusterManager) Describe(ch chan<- *prometheus.Desc) {
|
|
ch <- c.OOMCountDesc
|
|
ch <- c.RAMUsageDesc
|
|
}
|
|
|
|
// Collect first triggers the ReallyExpensiveAssessmentOfTheSystemState. Then it
|
|
// creates constant metrics for each host on the fly based on the returned data.
|
|
//
|
|
// Note that Collect could be called concurrently, so we depend on
|
|
// ReallyExpensiveAssessmentOfTheSystemState to be concurrency-safe.
|
|
func (c *ClusterManager) Collect(ch chan<- prometheus.Metric) {
|
|
oomCountByHost, ramUsageByHost := c.ReallyExpensiveAssessmentOfTheSystemState()
|
|
for host, oomCount := range oomCountByHost {
|
|
ch <- prometheus.MustNewConstMetric(
|
|
c.OOMCountDesc,
|
|
prometheus.CounterValue,
|
|
float64(oomCount),
|
|
host,
|
|
)
|
|
}
|
|
for host, ramUsage := range ramUsageByHost {
|
|
ch <- prometheus.MustNewConstMetric(
|
|
c.RAMUsageDesc,
|
|
prometheus.GaugeValue,
|
|
ramUsage,
|
|
host,
|
|
)
|
|
}
|
|
}
|
|
|
|
// NewClusterManager creates the two Descs OOMCountDesc and RAMUsageDesc. Note
|
|
// that the zone is set as a ConstLabel. (It's different in each instance of the
|
|
// ClusterManager, but constant over the lifetime of an instance.) Then there is
|
|
// a variable label "host", since we want to partition the collected metrics by
|
|
// host. Since all Descs created in this way are consistent across instances,
|
|
// with a guaranteed distinction by the "zone" label, we can register different
|
|
// ClusterManager with the same registry.
|
|
func NewClusterManager(zone string) *ClusterManager {
|
|
return &ClusterManager{
|
|
Zone: zone,
|
|
OOMCountDesc: prometheus.NewDesc(
|
|
"clustermanager_oom_count",
|
|
"Number of OOM crashes.",
|
|
[]string{"host"},
|
|
prometheus.Labels{"zone": zone},
|
|
),
|
|
RAMUsageDesc: prometheus.NewDesc(
|
|
"clustermanager_ram_usage_bytes",
|
|
"RAM usage as reported to the cluster manager.",
|
|
[]string{"host"},
|
|
prometheus.Labels{"zone": zone},
|
|
),
|
|
}
|
|
}
|
|
|
|
func ExampleCollector_clustermanager() {
|
|
workerDB := NewClusterManager("db")
|
|
workerCA := NewClusterManager("ca")
|
|
|
|
// Since we are dealing with custom Collector implementations, it might
|
|
// be a good idea to try it out with a pedantic registry.
|
|
reg := prometheus.NewPedanticRegistry()
|
|
prometheus.MustRegisterWith(reg, workerDB)
|
|
prometheus.MustRegisterWith(reg, workerCA)
|
|
}
|