package metrics import ( "encoding/json" "github.com/prometheus/client_golang/prometheus" dto "github.com/prometheus/client_model/go" ) var appMetricsDesc = map[string]map[string]Description{ poolSubsystem: { overallErrorsMetric: Description{ Type: dto.MetricType_GAUGE, Namespace: namespace, Subsystem: poolSubsystem, Name: overallErrorsMetric, Help: "Total number of errors in pool", }, overallNodeErrorsMetric: Description{ Type: dto.MetricType_GAUGE, Namespace: namespace, Subsystem: poolSubsystem, Name: overallNodeErrorsMetric, Help: "Total number of errors for connection in pool", VariableLabels: []string{"node"}, }, overallNodeRequestsMetric: Description{ Type: dto.MetricType_GAUGE, Namespace: namespace, Subsystem: poolSubsystem, Name: overallNodeRequestsMetric, Help: "Total number of requests to specific node in pool", VariableLabels: []string{"node"}, }, currentErrorMetric: Description{ Type: dto.MetricType_GAUGE, Namespace: namespace, Subsystem: poolSubsystem, Name: currentErrorMetric, Help: "Number of errors on current connections that will be reset after the threshold", VariableLabels: []string{"node"}, }, avgRequestDurationMetric: Description{ Type: dto.MetricType_GAUGE, Namespace: namespace, Subsystem: poolSubsystem, Name: avgRequestDurationMetric, Help: "Average request duration (in milliseconds) for specific method on node in pool", VariableLabels: []string{"node", "method"}, }, }, stateSubsystem: { healthMetric: Description{ Type: dto.MetricType_GAUGE, Namespace: namespace, Subsystem: stateSubsystem, Name: healthMetric, Help: "Current HTTP gateway state", }, versionInfoMetric: Description{ Type: dto.MetricType_GAUGE, Namespace: namespace, Subsystem: stateSubsystem, Name: versionInfoMetric, Help: "Version of current FrostFS HTTP Gate instance", VariableLabels: []string{"version"}, }, }, } type Description struct { Type dto.MetricType Namespace string Subsystem string Name string Help string ConstantLabels []KeyValue VariableLabels []string } type KeyValue struct { Key string `json:"key"` Value string `json:"value"` } func (d *Description) MarshalJSON() ([]byte, error) { return json.Marshal(&struct { Type string `json:"type"` FQName string `json:"name"` Help string `json:"help"` ConstantLabels []KeyValue `json:"constant_labels"` VariableLabels []string `json:"variable_labels"` }{ Type: d.Type.String(), FQName: d.BuildFQName(), Help: d.Help, ConstantLabels: d.ConstantLabels, VariableLabels: d.VariableLabels, }) } func (d *Description) BuildFQName() string { return prometheus.BuildFQName(d.Namespace, d.Subsystem, d.Name) } func (d *Description) ConstLabelsMap() map[string]string { constsLabels := make(map[string]string, len(d.ConstantLabels)) for _, kv := range d.ConstantLabels { constsLabels[kv.Key] = kv.Value } return constsLabels } // DescribeAll returns descriptions for metrics. func DescribeAll() []Description { var list []Description for _, m := range appMetricsDesc { for _, description := range m { list = append(list, description) } } return list } func newOpts(description Description) prometheus.Opts { return prometheus.Opts{ Namespace: description.Namespace, Subsystem: description.Subsystem, Name: description.Name, Help: description.Help, ConstLabels: description.ConstLabelsMap(), } } func mustNewGauge(description Description) prometheus.Gauge { if description.Type != dto.MetricType_GAUGE { panic("invalid metric type") } return prometheus.NewGauge( prometheus.GaugeOpts(newOpts(description)), ) } func mustNewGaugeVec(description Description) *prometheus.GaugeVec { if description.Type != dto.MetricType_GAUGE { panic("invalid metric type") } return prometheus.NewGaugeVec( prometheus.GaugeOpts(newOpts(description)), description.VariableLabels, ) }