Line data Source code
1 : use crate::metrics::PageserverRequestLabelGroup;
2 : use safekeeper_api::models::{SafekeeperUtilization, TimelineCreateRequest, TimelineStatus};
3 : use safekeeper_client::mgmt_api::{Client, Result};
4 : use utils::{
5 : id::{NodeId, TenantId, TimelineId},
6 : logging::SecretString,
7 : };
8 :
9 : /// Thin wrapper around [`safekeeper_client::mgmt_api::Client`]. It allows the storage
10 : /// controller to collect metrics in a non-intrusive manner.
11 : ///
12 : /// Analogous to [`crate::pageserver_client::PageserverClient`].
13 : #[derive(Debug, Clone)]
14 : pub(crate) struct SafekeeperClient {
15 : inner: Client,
16 : node_id_label: String,
17 : }
18 :
19 : macro_rules! measured_request {
20 : ($name:literal, $method:expr, $node_id: expr, $invoke:expr) => {{
21 : let labels = PageserverRequestLabelGroup {
22 : pageserver_id: $node_id,
23 : path: $name,
24 : method: $method,
25 : };
26 :
27 : let latency = &crate::metrics::METRICS_REGISTRY
28 : .metrics_group
29 : .storage_controller_safekeeper_request_latency;
30 : let _timer_guard = latency.start_timer(labels.clone());
31 :
32 : let res = $invoke;
33 :
34 : if res.is_err() {
35 : let error_counters = &crate::metrics::METRICS_REGISTRY
36 : .metrics_group
37 : .storage_controller_pageserver_request_error;
38 : error_counters.inc(labels)
39 : }
40 :
41 : res
42 : }};
43 : }
44 :
45 : impl SafekeeperClient {
46 : #[allow(dead_code)]
47 0 : pub(crate) fn new(
48 0 : node_id: NodeId,
49 0 : mgmt_api_endpoint: String,
50 0 : jwt: Option<SecretString>,
51 0 : ) -> Self {
52 0 : Self {
53 0 : inner: Client::from_client(reqwest::Client::new(), mgmt_api_endpoint, jwt),
54 0 : node_id_label: node_id.0.to_string(),
55 0 : }
56 0 : }
57 :
58 0 : pub(crate) fn from_client(
59 0 : node_id: NodeId,
60 0 : raw_client: reqwest::Client,
61 0 : mgmt_api_endpoint: String,
62 0 : jwt: Option<SecretString>,
63 0 : ) -> Self {
64 0 : Self {
65 0 : inner: Client::from_client(raw_client, mgmt_api_endpoint, jwt),
66 0 : node_id_label: node_id.0.to_string(),
67 0 : }
68 0 : }
69 :
70 : #[allow(dead_code)]
71 0 : pub(crate) async fn create_timeline(
72 0 : &self,
73 0 : req: &TimelineCreateRequest,
74 0 : ) -> Result<TimelineStatus> {
75 0 : measured_request!(
76 0 : "create_timeline",
77 0 : crate::metrics::Method::Post,
78 0 : &self.node_id_label,
79 0 : self.inner.create_timeline(req).await
80 0 : )
81 0 : }
82 :
83 : #[allow(dead_code)]
84 0 : pub(crate) async fn delete_timeline(
85 0 : &self,
86 0 : tenant_id: TenantId,
87 0 : timeline_id: TimelineId,
88 0 : ) -> Result<TimelineStatus> {
89 0 : measured_request!(
90 0 : "delete_timeline",
91 0 : crate::metrics::Method::Delete,
92 0 : &self.node_id_label,
93 0 : self.inner.delete_timeline(tenant_id, timeline_id).await
94 0 : )
95 0 : }
96 :
97 0 : pub(crate) async fn get_utilization(&self) -> Result<SafekeeperUtilization> {
98 0 : measured_request!(
99 0 : "utilization",
100 0 : crate::metrics::Method::Get,
101 0 : &self.node_id_label,
102 0 : self.inner.utilization().await
103 0 : )
104 0 : }
105 : }
|