storj/cmd/statreceiver/downgrade.go

244 lines
13 KiB
Go
Raw Normal View History

// 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.total.bytes",
"total.inline_bytes": "storj.io/storj/satellite/accounting.total.inline_bytes",
"total.inline_segments": "storj.io/storj/satellite/accounting.total.inline_segments",
"total.objects": "storj.io/storj/satellite/accounting.total.objects",
"total.remote_bytes": "storj.io/storj/satellite/accounting.total.remote_bytes",
"total.remote_segments": "storj.io/storj/satellite/accounting.total.remote_segments",
"total.segments": "storj.io/storj/satellite/accounting.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",
"healthy_ratio_after_repair": "storj.io/storj/satellite/repair/repairer.healthy_ratio_after_repair",
"healthy_ratio_before_repair": "storj.io/storj/satellite/repair/repairer.healthy_ratio_before_repair",
"repair_attempts": "storj.io/storj/satellite/repair/repairer.repair_attempts",
"repair_failed": "storj.io/storj/satellite/repair/repairer.repair_failed",
"repair_nodes_unavailable": "storj.io/storj/satellite/repair/repairer.repair_nodes_unavailable",
"repair_partial": "storj.io/storj/satellite/repair/repairer.repair_partial",
"repair_segment_pieces_canceled": "storj.io/storj/satellite/repair/repairer.repair_segment_pieces_canceled",
"repair_segment_pieces_failed": "storj.io/storj/satellite/repair/repairer.repair_segment_pieces_failed",
"repair_segment_pieces_successful": "storj.io/storj/satellite/repair/repairer.repair_segment_pieces_successful",
"repair_segment_pieces_total": "storj.io/storj/satellite/repair/repairer.repair_segment_pieces_total",
"repair_segment_size": "storj.io/storj/satellite/repair/repairer.repair_segment_size",
"repair_success": "storj.io/storj/satellite/repair/repairer.repair_success",
"repair_unnecessary": "storj.io/storj/satellite/repair/repairer.repair_unnecessary",
"segment_repair_count": "storj.io/storj/satellite/repair/repairer.segment_repair_count",
"segment_time_until_repair": "storj.io/storj/satellite/repair/repairer.segment_time_until_repair",
"time_for_repair": "storj.io/storj/satellite/repair/repairer.time_for_repair",
"time_since_checker_queue": "storj.io/storj/satellite/repair/repairer.time_since_checker_queue",
"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",
}