221 lines
12 KiB
Go
221 lines
12 KiB
Go
|
// Copyright (C) 2020 Storj Labs, Inc.
|
||
|
// See LICENSE for copying information.
|
||
|
|
||
|
package main
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
// Note to readers: All of the tag iteration and field searching code does not bother to
|
||
|
// handle escaped spaces or commas because all of the keys we intend to migrate do not
|
||
|
// contain them. In particular, we have no package import paths with spaces or commas and
|
||
|
// it is impossible to have a function name with a space or comma in it. Additionally, all
|
||
|
// of the monkit/v3 field names do not have spaces or commas. This could become invalid if
|
||
|
// someone decides to break it, but this code is also temporary.
|
||
|
|
||
|
// MetricDowngrade downgrades known v3 metrics into v2 versions for backwards compat.
|
||
|
type MetricDowngrade struct {
|
||
|
dest MetricDest
|
||
|
}
|
||
|
|
||
|
// NewMetricDowngrade constructs a MetricDowngrade that passes known v3 metrics as
|
||
|
// v2 metrics to the provided dest.
|
||
|
func NewMetricDowngrade(dest MetricDest) *MetricDowngrade {
|
||
|
return &MetricDowngrade{
|
||
|
dest: dest,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Metric implements MetricDest
|
||
|
func (k *MetricDowngrade) Metric(application, instance string, key []byte, val float64, ts time.Time) error {
|
||
|
comma := bytes.IndexByte(key, ',')
|
||
|
if comma < 0 {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
if string(key[:comma]) == "function_times" {
|
||
|
return k.handleFunctionTimes(application, instance, key[comma+1:], val, ts)
|
||
|
}
|
||
|
if string(key[:comma]) == "function" {
|
||
|
return k.handleFunction(application, instance, key[comma+1:], val, ts)
|
||
|
}
|
||
|
|
||
|
v2key, ok := knownMetrics[string(key[:comma])]
|
||
|
if !ok {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
space := bytes.LastIndexByte(key, ' ')
|
||
|
if space < 0 {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
out := make([]byte, 0, len(v2key)+1+len(key)-space)
|
||
|
out = append(out, v2key...)
|
||
|
out = append(out, '.')
|
||
|
out = append(out, key[space+1:]...)
|
||
|
|
||
|
return k.dest.Metric(application, instance, out, val, ts)
|
||
|
}
|
||
|
|
||
|
func (k *MetricDowngrade) handleFunctionTimes(application, instance string, key []byte, val float64, ts time.Time) error {
|
||
|
var name, kind, scope string
|
||
|
iterateTags(key, func(tag []byte) {
|
||
|
if len(tag) < 6 {
|
||
|
return
|
||
|
}
|
||
|
switch {
|
||
|
case string(tag[:5]) == "name=":
|
||
|
name = string(tag[5:])
|
||
|
case string(tag[:5]) == "kind=":
|
||
|
kind = string(tag[5:])
|
||
|
case string(tag[:6]) == "scope=":
|
||
|
scope = string(tag[6:])
|
||
|
}
|
||
|
})
|
||
|
|
||
|
if name == "" || kind == "" || scope == "" {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
space := bytes.LastIndexByte(key, ' ')
|
||
|
if space < 0 {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
out := make([]byte, 0, len(scope)+1+len(name)+1+len(kind)+7+(len(key)-space))
|
||
|
out = append(out, scope...)
|
||
|
out = append(out, '.')
|
||
|
out = append(out, name...)
|
||
|
out = append(out, '.')
|
||
|
out = append(out, kind...)
|
||
|
out = append(out, "_times_"...)
|
||
|
out = append(out, key[space+1:]...)
|
||
|
|
||
|
return k.dest.Metric(application, instance, out, val, ts)
|
||
|
}
|
||
|
|
||
|
func (k *MetricDowngrade) handleFunction(application, instance string, key []byte, val float64, ts time.Time) error {
|
||
|
var name, scope string
|
||
|
iterateTags(key, func(tag []byte) {
|
||
|
if len(tag) < 6 {
|
||
|
return
|
||
|
}
|
||
|
switch {
|
||
|
case string(tag[:5]) == "name=":
|
||
|
name = string(tag[5:])
|
||
|
case string(tag[:6]) == "scope=":
|
||
|
scope = string(tag[6:])
|
||
|
}
|
||
|
})
|
||
|
|
||
|
if name == "" || scope == "" {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
space := bytes.LastIndexByte(key, ' ')
|
||
|
if space < 0 {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
out := make([]byte, 0, len(scope)+1+len(name)+1+(len(key)-space))
|
||
|
out = append(out, scope...)
|
||
|
out = append(out, '.')
|
||
|
out = append(out, name...)
|
||
|
out = append(out, '.')
|
||
|
out = append(out, key[space+1:]...)
|
||
|
|
||
|
return k.dest.Metric(application, instance, out, val, ts)
|
||
|
}
|
||
|
|
||
|
func iterateTags(key []byte, cb func([]byte)) {
|
||
|
for len(key) > 0 {
|
||
|
comma := bytes.IndexByte(key, ',')
|
||
|
if comma == -1 {
|
||
|
break
|
||
|
}
|
||
|
cb(key[:comma])
|
||
|
key = key[comma+1:]
|
||
|
}
|
||
|
space := bytes.IndexByte(key, ' ')
|
||
|
if space >= 0 {
|
||
|
cb(key[:space])
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var knownMetrics = map[string]string{
|
||
|
"total.bytes": "storj.io/storj/satellite/accounting/tally.total.bytes",
|
||
|
"total.inline_bytes": "storj.io/storj/satellite/accounting/tally.total.inline_bytes",
|
||
|
"total.inline_segments": "storj.io/storj/satellite/accounting/tally.total.inline_segments",
|
||
|
"total.objects": "storj.io/storj/satellite/accounting/tally.total.objects",
|
||
|
"total.remote_bytes": "storj.io/storj/satellite/accounting/tally.total.remote_bytes",
|
||
|
"total.remote_segments": "storj.io/storj/satellite/accounting/tally.total.remote_segments",
|
||
|
"total.segments": "storj.io/storj/satellite/accounting/tally.total.segments",
|
||
|
"audit_contained_nodes": "storj.io/storj/satellite/audit.audit_contained_nodes",
|
||
|
"audit_contained_nodes_global": "storj.io/storj/satellite/audit.audit_contained_nodes_global",
|
||
|
"audit_contained_percentage": "storj.io/storj/satellite/audit.audit_contained_percentage",
|
||
|
"audit_fail_nodes": "storj.io/storj/satellite/audit.audit_fail_nodes",
|
||
|
"audit_fail_nodes_global": "storj.io/storj/satellite/audit.audit_fail_nodes_global",
|
||
|
"audit_failed_percentage": "storj.io/storj/satellite/audit.audit_failed_percentage",
|
||
|
"audit_offline_nodes": "storj.io/storj/satellite/audit.audit_offline_nodes",
|
||
|
"audit_offline_nodes_global": "storj.io/storj/satellite/audit.audit_offline_nodes_global",
|
||
|
"audit_offline_percentage": "storj.io/storj/satellite/audit.audit_offline_percentage",
|
||
|
"audit_success_nodes": "storj.io/storj/satellite/audit.audit_success_nodes",
|
||
|
"audit_success_nodes_global": "storj.io/storj/satellite/audit.audit_success_nodes_global",
|
||
|
"audit_successful_percentage": "storj.io/storj/satellite/audit.audit_successful_percentage",
|
||
|
"audit_total_nodes": "storj.io/storj/satellite/audit.audit_total_nodes",
|
||
|
"audit_total_nodes_global": "storj.io/storj/satellite/audit.audit_total_nodes_global",
|
||
|
"audit_total_pointer_nodes": "storj.io/storj/satellite/audit.audit_total_pointer_nodes",
|
||
|
"audit_total_pointer_nodes_global": "storj.io/storj/satellite/audit.audit_total_pointer_nodes_global",
|
||
|
"audit_unknown_nodes": "storj.io/storj/satellite/audit.audit_unknown_nodes",
|
||
|
"audit_unknown_nodes_global": "storj.io/storj/satellite/audit.audit_unknown_nodes_global",
|
||
|
"audit_unknown_percentage": "storj.io/storj/satellite/audit.audit_unknown_percentage",
|
||
|
"audited_percentage": "storj.io/storj/satellite/audit.audited_percentage",
|
||
|
"reverify_contained": "storj.io/storj/satellite/audit.reverify_contained",
|
||
|
"reverify_contained_global": "storj.io/storj/satellite/audit.reverify_contained_global",
|
||
|
"reverify_contained_in_segment": "storj.io/storj/satellite/audit.reverify_contained_in_segment",
|
||
|
"reverify_fails": "storj.io/storj/satellite/audit.reverify_fails",
|
||
|
"reverify_fails_global": "storj.io/storj/satellite/audit.reverify_fails_global",
|
||
|
"reverify_offlines": "storj.io/storj/satellite/audit.reverify_offlines",
|
||
|
"reverify_offlines_global": "storj.io/storj/satellite/audit.reverify_offlines_global",
|
||
|
"reverify_successes": "storj.io/storj/satellite/audit.reverify_successes",
|
||
|
"reverify_successes_global": "storj.io/storj/satellite/audit.reverify_successes_global",
|
||
|
"reverify_total_in_segment": "storj.io/storj/satellite/audit.reverify_total_in_segment",
|
||
|
"reverify_unknown": "storj.io/storj/satellite/audit.reverify_unknown",
|
||
|
"reverify_unknown_global": "storj.io/storj/satellite/audit.reverify_unknown_global",
|
||
|
"graceful_exit_fail_max_failures_percentage": "storj.io/storj/satellite/gracefulexit.graceful_exit_fail_max_failures_percentage",
|
||
|
"graceful_exit_fail_validation": "storj.io/storj/satellite/gracefulexit.graceful_exit_fail_validation",
|
||
|
"graceful_exit_final_bytes_transferred": "storj.io/storj/satellite/gracefulexit.graceful_exit_final_bytes_transferred",
|
||
|
"graceful_exit_final_pieces_failed": "storj.io/storj/satellite/gracefulexit.graceful_exit_final_pieces_failed",
|
||
|
"graceful_exit_final_pieces_succeess": "storj.io/storj/satellite/gracefulexit.graceful_exit_final_pieces_succeess",
|
||
|
"graceful_exit_init_node_age_seconds": "storj.io/storj/satellite/gracefulexit.graceful_exit_init_node_age_seconds",
|
||
|
"graceful_exit_init_node_audit_success_count": "storj.io/storj/satellite/gracefulexit.graceful_exit_init_node_audit_success_count",
|
||
|
"graceful_exit_init_node_audit_total_count": "storj.io/storj/satellite/gracefulexit.graceful_exit_init_node_audit_total_count",
|
||
|
"graceful_exit_init_node_piece_count": "storj.io/storj/satellite/gracefulexit.graceful_exit_init_node_piece_count",
|
||
|
"graceful_exit_success": "storj.io/storj/satellite/gracefulexit.graceful_exit_success",
|
||
|
"graceful_exit_successful_pieces_transfer_ratio": "storj.io/storj/satellite/gracefulexit.graceful_exit_successful_pieces_transfer_ratio",
|
||
|
"graceful_exit_transfer_piece_fail": "storj.io/storj/satellite/gracefulexit.graceful_exit_transfer_piece_fail",
|
||
|
"graceful_exit_transfer_piece_success": "storj.io/storj/satellite/gracefulexit.graceful_exit_transfer_piece_success",
|
||
|
"download_failed_not_enough_pieces_uplink": "storj.io/storj/satellite/orders.download_failed_not_enough_pieces_uplink",
|
||
|
"checker_segment_age": "storj.io/storj/satellite/repair/checker.checker_segment_age",
|
||
|
"checker_segment_healthy_count": "storj.io/storj/satellite/repair/checker.checker_segment_healthy_count",
|
||
|
"checker_segment_time_until_irreparable": "storj.io/storj/satellite/repair/checker.checker_segment_time_until_irreparable",
|
||
|
"checker_segment_total_count": "storj.io/storj/satellite/repair/checker.checker_segment_total_count",
|
||
|
"remote_files_checked": "storj.io/storj/satellite/repair/checker.remote_files_checked",
|
||
|
"remote_files_lost": "storj.io/storj/satellite/repair/checker.remote_files_lost",
|
||
|
"remote_segments_checked": "storj.io/storj/satellite/repair/checker.remote_segments_checked",
|
||
|
"remote_segments_lost": "storj.io/storj/satellite/repair/checker.remote_segments_lost",
|
||
|
"remote_segments_needing_repair": "storj.io/storj/satellite/repair/checker.remote_segments_needing_repair",
|
||
|
"download_failed_not_enough_pieces_repair": "storj.io/storj/satellite/repair/repairer.download_failed_not_enough_pieces_repair",
|
||
|
"audit_reputation_alpha": "storj.io/storj/satellite/satellitedb.audit_reputation_alpha",
|
||
|
"audit_reputation_beta": "storj.io/storj/satellite/satellitedb.audit_reputation_beta",
|
||
|
"open_file_in_trash": "storj.io/storj/storage/filestore.open_file_in_trash",
|
||
|
"satellite_contact_request": "storj.io/storj/storagenode/contact.satellite_contact_request",
|
||
|
"satellite_gracefulexit_request": "storj.io/storj/storagenode/gracefulexit.satellite_gracefulexit_request",
|
||
|
"allocated_bandwidth": "storj.io/storj/storagenode/monitor.allocated_bandwidth",
|
||
|
"used_bandwidth": "storj.io/storj/storagenode/monitor.used_bandwidth",
|
||
|
"download_stripe_failed_not_enough_pieces_uplink": "storj.io/storj/uplink/eestream.download_stripe_failed_not_enough_pieces_uplink",
|
||
|
}
|