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