forked from marktoda/uniswapx-artemis
-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathcloudwatch_utils.rs
238 lines (217 loc) · 7.52 KB
/
cloudwatch_utils.rs
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
use std::{future::Future, pin::Pin, sync::Arc};
use aws_sdk_cloudwatch::Client as CloudWatchClient;
use aws_sdk_cloudwatch::{
config::http::HttpResponse,
error::SdkError,
operation::put_metric_data::{PutMetricDataError, PutMetricDataOutput},
types::Dimension,
};
/// Constants for dimension names and values
pub const SERVICE_DIMENSION: &str = "Service";
pub const ROUTER02: &str = "Router02";
pub const PRIORITY_EXECUTOR: &str = "PriorityExecutor";
pub const V2_EXECUTOR: &str = "V2Executor";
pub const V3_EXECUTOR: &str = "V3Executor";
/// Constants for metric names
pub const ROUTING_MS: &str = "RoutingMs";
pub const TX_SUCCEEDED_METRIC: &str = "TransactionSucceeded";
pub const TX_REVERTED_METRIC: &str = "TransactionReverted";
pub const TX_SUBMITTED_METRIC: &str = "TransactionSubmitted";
pub const TX_STATUS_UNKNOWN_METRIC: &str = "TransactionStatusUnknown";
pub const LATEST_BLOCK: &str = "LatestBlock";
pub const EXECUTION_ATTEMPTED_METRIC: &str = "ExecutionAttempted";
pub const EXECUTION_SKIPPED_ALREADY_FILLED_METRIC: &str = "ExecutionSkippedAlreadyFilled";
pub const EXECUTION_SKIPPED_PAST_DEADLINE_METRIC: &str = "ExecutionSkippedPastDeadline";
pub const UNPROFITABLE_METRIC: &str = "Unprofitable";
pub const TARGET_BLOCK_DELTA: &str = "TargetBlockDelta";
pub const REVERT_CODE_METRIC: &str = "RevertCode";
pub enum DimensionName {
Service,
}
impl AsRef<str> for DimensionName {
fn as_ref(&self) -> &str {
match self {
DimensionName::Service => SERVICE_DIMENSION,
}
}
}
impl From<DimensionName> for String {
fn from(dimension: DimensionName) -> Self {
match dimension {
DimensionName::Service => SERVICE_DIMENSION.to_string(),
}
}
}
pub enum DimensionValue {
PriorityExecutor,
V2Executor,
V3Executor,
Router02,
}
impl From<DimensionValue> for String {
fn from(value: DimensionValue) -> Self {
match value {
DimensionValue::PriorityExecutor => PRIORITY_EXECUTOR.to_string(),
DimensionValue::V2Executor => V2_EXECUTOR.to_string(),
DimensionValue::V3Executor => V3_EXECUTOR.to_string(),
DimensionValue::Router02 => ROUTER02.to_string(),
}
}
}
impl AsRef<str> for DimensionValue {
fn as_ref(&self) -> &str {
match self {
DimensionValue::PriorityExecutor => PRIORITY_EXECUTOR,
DimensionValue::V2Executor => V2_EXECUTOR,
DimensionValue::V3Executor => V3_EXECUTOR,
DimensionValue::Router02 => ROUTER02,
}
}
}
pub enum CwMetrics {
RoutingMs(u64),
Unprofitable(u64),
ExecutionAttempted(u64),
ExecutionSkippedAlreadyFilled(u64),
ExecutionSkippedPastDeadline(u64),
TxSucceeded(u64),
TxReverted(u64),
TxSubmitted(u64),
TxStatusUnknown(u64),
LatestBlock(u64),
RevertCode(u64, String), // chain_id and revert code string
/// Balance for individual address
Balance(String),
// negative is too early, positive is too late
TargetBlockDelta(u64),
}
impl From<CwMetrics> for String {
fn from(metric: CwMetrics) -> Self {
match metric {
CwMetrics::RoutingMs(chain_id) => format!("{}-{}", chain_id, ROUTING_MS),
CwMetrics::Unprofitable(chain_id) => format!("{}-{}", chain_id, UNPROFITABLE_METRIC),
CwMetrics::ExecutionAttempted(chain_id) => {
format!("{}-{}", chain_id, EXECUTION_ATTEMPTED_METRIC)
}
CwMetrics::ExecutionSkippedAlreadyFilled(chain_id) => {
format!("{}-{}", chain_id, EXECUTION_SKIPPED_ALREADY_FILLED_METRIC)
}
CwMetrics::ExecutionSkippedPastDeadline(chain_id) => {
format!("{}-{}", chain_id, EXECUTION_SKIPPED_PAST_DEADLINE_METRIC)
}
CwMetrics::TxSucceeded(chain_id) => format!("{}-{}", chain_id, TX_SUCCEEDED_METRIC),
CwMetrics::TxReverted(chain_id) => format!("{}-{}", chain_id, TX_REVERTED_METRIC),
CwMetrics::TxSubmitted(chain_id) => format!("{}-{}", chain_id, TX_SUBMITTED_METRIC),
CwMetrics::TxStatusUnknown(chain_id) => {
format!("{}-{}", chain_id, TX_STATUS_UNKNOWN_METRIC)
}
CwMetrics::Balance(val) => format!("Bal-{}", val),
CwMetrics::LatestBlock(chain_id) => format!("{}-{}", chain_id, LATEST_BLOCK),
CwMetrics::TargetBlockDelta(chain_id) => format!("{}-{}", chain_id, TARGET_BLOCK_DELTA),
CwMetrics::RevertCode(chain_id, code) => format!("{}-{}-{}", chain_id, REVERT_CODE_METRIC, code),
}
}
}
pub const ARTEMIS_NAMESPACE: &str = "Artemis";
pub struct MetricBuilder {
metric_name: String,
dimensions: Vec<Dimension>,
value: f64,
}
// TODO: TxStatus type metrics => TxStatus(u32)
impl MetricBuilder {
pub fn new(metric: CwMetrics) -> Self {
match metric {
CwMetrics::Balance(val) => Self {
metric_name: format!("Bal-{}", val),
dimensions: Vec::new(),
value: 0.0,
},
_ => Self {
metric_name: metric.into(),
dimensions: Vec::new(),
value: 1.0,
},
}
}
pub fn add_dimension(mut self, name: &str, value: &str) -> Self {
self.dimensions
.push(Dimension::builder().name(name).value(value).build());
self
}
pub fn with_value(mut self, value: f64) -> Self {
self.value = value;
self
}
pub fn build(self) -> aws_sdk_cloudwatch::types::MetricDatum {
aws_sdk_cloudwatch::types::MetricDatum::builder()
.metric_name(self.metric_name)
.value(self.value)
.set_dimensions(Some(self.dimensions))
.build()
}
}
pub fn receipt_status_to_metric(status: bool, chain_id: u64) -> CwMetrics {
match status {
true => CwMetrics::TxSucceeded(chain_id),
false => CwMetrics::TxReverted(chain_id),
}
}
pub fn revert_code_to_metric(chain_id: u64, revert_code: String) -> CwMetrics {
CwMetrics::RevertCode(chain_id, revert_code)
}
pub fn build_metric_future(
cloudwatch_client: Option<Arc<CloudWatchClient>>,
dimension_value: DimensionValue,
metric: CwMetrics,
value: f64,
) -> Option<
Pin<
Box<
impl Future<
Output = Result<
PutMetricDataOutput,
SdkError<PutMetricDataError, HttpResponse>,
>,
> + Send
+ 'static,
>,
>,
> {
cloudwatch_client.map(|client| {
Box::pin(async move {
client
.put_metric_data()
.namespace(ARTEMIS_NAMESPACE)
.metric_data(
MetricBuilder::new(metric)
.add_dimension(DimensionName::Service.as_ref(), dimension_value.as_ref())
.with_value(value)
.build(),
)
.send()
.await
})
})
}
#[macro_export]
macro_rules! send_metric_with_order_hash {
($order_hash: expr, $future: expr) => {
let hash = Arc::clone($order_hash);
tokio::spawn(async move {
if let Err(e) = $future.await {
warn!("{} - error sending metric: {:?}", hash, e);
}
})
};
}
#[macro_export]
macro_rules! send_metric {
($future: expr) => {
tokio::spawn(async move {
if let Err(e) = $future.await {
warn!("error sending metric: {:?}", e);
}
})
};
}