1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Copyright (c) 2021, Facebook, Inc. and its affiliates
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

use prometheus::{
    register_histogram_vec_with_registry, register_int_counter_vec_with_registry,
    register_int_counter_with_registry, register_int_gauge_with_registry, HistogramVec, IntCounter,
    IntCounterVec, IntGauge, Registry,
};

use mysten_metrics::histogram::Histogram;

const FINALITY_LATENCY_SEC_BUCKETS: &[f64] = &[
    0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85,
    0.9, 0.95, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6,
    2.7, 2.8, 2.9, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5,
    7.0, 7.5, 8.0, 8.5, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0,
    25.0,
];

#[derive(Clone)]
pub struct QuorumDriverMetrics {
    pub(crate) total_requests: IntCounter,
    pub(crate) total_enqueued: IntCounter,
    pub(crate) total_ok_responses: IntCounter,
    pub(crate) total_err_responses: IntCounterVec,
    pub(crate) attempt_times_ok_response: Histogram,

    // TODO: add histogram of attempt that tx succeeds
    pub(crate) current_requests_in_flight: IntGauge,

    pub(crate) total_err_process_tx_responses_with_nonzero_conflicting_transactions: IntCounter,
    pub(crate) total_attempts_retrying_conflicting_transaction: IntCounter,
    pub(crate) total_successful_attempts_retrying_conflicting_transaction: IntCounter,
    pub(crate) total_times_conflicting_transaction_already_finalized_when_retrying: IntCounter,
    pub(crate) total_retryable_overload_errors: IntCounter,
    pub(crate) transaction_retry_count: Histogram,
    pub(crate) current_transactions_in_retry: IntGauge,

    pub(crate) settlement_finality_latency: HistogramVec,
}

impl QuorumDriverMetrics {
    pub fn new(registry: &Registry) -> Self {
        Self {
            total_requests: register_int_counter_with_registry!(
                "quorum_driver_total_requests",
                "Total number of requests received",
                registry,
            )
            .unwrap(),
            total_enqueued: register_int_counter_with_registry!(
                "quorum_driver_total_enqueued",
                "Total number of requests enqueued",
                registry,
            )
            .unwrap(),
            total_ok_responses: register_int_counter_with_registry!(
                "quorum_driver_total_ok_responses",
                "Total number of requests processed with Ok responses",
                registry,
            )
            .unwrap(),
            total_err_responses: register_int_counter_vec_with_registry!(
                "quorum_driver_total_err_responses",
                "Total number of requests returned with Err responses, grouped by error type",
                &["error"],
                registry,
            )
            .unwrap(),
            attempt_times_ok_response: Histogram::new_in_registry(
                "quorum_driver_attempt_times_ok_response",
                "Total attempt times of ok response",
                registry,
            ),
            current_requests_in_flight: register_int_gauge_with_registry!(
                "current_requests_in_flight",
                "Current number of requests being processed in QuorumDriver",
                registry,
            )
            .unwrap(),
            total_err_process_tx_responses_with_nonzero_conflicting_transactions: register_int_counter_with_registry!(
                "quorum_driver_total_err_process_tx_responses_with_nonzero_conflicting_transactions",
                "Total number of err process_tx responses with non empty conflicting transactions",
                registry,
            )
            .unwrap(),
            total_attempts_retrying_conflicting_transaction: register_int_counter_with_registry!(
                "quorum_driver_total_attempts_trying_conflicting_transaction",
                "Total number of attempts to retry a conflicting transaction",
                registry,
            )
            .unwrap(),
            total_successful_attempts_retrying_conflicting_transaction: register_int_counter_with_registry!(
                "quorum_driver_total_successful_attempts_trying_conflicting_transaction",
                "Total number of successful attempts to retry a conflicting transaction",
                registry,
            )
            .unwrap(),
            total_times_conflicting_transaction_already_finalized_when_retrying: register_int_counter_with_registry!(
                "quorum_driver_total_times_conflicting_transaction_already_finalized_when_retrying",
                "Total number of times the conflicting transaction is already finalized when retrying",
                registry,
            )
            .unwrap(),
            total_retryable_overload_errors: register_int_counter_with_registry!(
                "quorum_driver_total_retryable_overload_errors",
                "Total number of transactions experiencing retryable overload error",
                registry,
            )
            .unwrap(),
            transaction_retry_count: Histogram::new_in_registry(
                "quorum_driver_transaction_retry_count",
                "Histogram of transaction retry count",
                registry,
            ),
            current_transactions_in_retry: register_int_gauge_with_registry!(
                "current_transactions_in_retry",
                "Current number of transactions in retry loop in QuorumDriver",
                registry,
            )
            .unwrap(),
            settlement_finality_latency: register_histogram_vec_with_registry!(
                "quorum_driver_settlement_finality_latency",
                "Settlement finality latency observed from quorum driver",
                &["tx_type"],
                FINALITY_LATENCY_SEC_BUCKETS.to_vec(),
                registry,
            )
            .unwrap(),
        }
    }

    pub fn new_for_tests() -> Self {
        let registry = Registry::new();
        Self::new(&registry)
    }
}