Skip to content

Commit 2b617df

Browse files
committed
container meta lazy client to avoid block_on
1 parent 361d79c commit 2b617df

File tree

3 files changed

+64
-38
lines changed

3 files changed

+64
-38
lines changed

runtimes/core/src/metadata/mod.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,44 @@ use std::collections::HashMap;
22

33
use crate::encore::runtime::v1::{environment::Cloud, Environment};
44
use anyhow::Context;
5+
use tokio::sync::OnceCell;
56

67
mod gce;
78

9+
#[derive(Debug)]
10+
pub struct ContainerMetaClient {
11+
cell: OnceCell<ContainerMetadata>,
12+
env: Environment,
13+
http_client: reqwest::Client,
14+
fallback: ContainerMetadata,
15+
}
16+
17+
impl ContainerMetaClient {
18+
pub fn new(env: Environment, http_client: reqwest::Client) -> Self {
19+
Self {
20+
cell: OnceCell::new(),
21+
fallback: ContainerMetadata {
22+
env_name: env.env_name.clone(),
23+
..Default::default()
24+
},
25+
env,
26+
http_client,
27+
}
28+
}
29+
30+
pub async fn collect(&self) -> &ContainerMetadata {
31+
self.cell
32+
.get_or_try_init(|| async {
33+
ContainerMetadata::collect(&self.env, &self.http_client).await
34+
})
35+
.await
36+
.unwrap_or_else(|err| {
37+
log::warn!("failed to fetch container metadata: {err}");
38+
&self.fallback
39+
})
40+
}
41+
}
42+
843
#[derive(Debug, Clone, Default)]
944
pub struct ContainerMetadata {
1045
pub service_id: String,

runtimes/core/src/metrics/exporter/gcp.rs

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::metadata::ContainerMetadata;
1+
use crate::metadata::ContainerMetaClient;
22
use crate::metrics::exporter::Exporter;
33
use crate::metrics::{CollectedMetric, MetricValue};
44
use anyhow::Context;
@@ -17,7 +17,7 @@ pub struct Gcp {
1717
monitored_resource_type: String,
1818
monitored_resource_labels: HashMap<String, String>,
1919
metric_names: HashMap<String, String>,
20-
container_meta: ContainerMetadata,
20+
container_meta_client: Arc<ContainerMetaClient>,
2121
}
2222

2323
#[derive(Debug)]
@@ -51,15 +51,15 @@ impl Gcp {
5151
monitored_resource_type: String,
5252
monitored_resource_labels: HashMap<String, String>,
5353
metric_names: HashMap<String, String>,
54-
container_meta: ContainerMetadata,
54+
container_meta_client: ContainerMetaClient,
5555
) -> Self {
5656
Self {
5757
client: Arc::new(LazyMonitoringClient::new()),
5858
project_id,
5959
monitored_resource_type,
6060
monitored_resource_labels,
6161
metric_names,
62-
container_meta,
62+
container_meta_client: Arc::new(container_meta_client),
6363
}
6464
}
6565

@@ -82,7 +82,7 @@ impl Gcp {
8282
self.project_id
8383
);
8484

85-
let time_series = self.get_metric_data(metrics);
85+
let time_series = self.get_metric_data(metrics).await;
8686

8787
// Send metrics in batches (Google Cloud allows up to 200 time series per request)
8888
for batch in time_series.chunks(200) {
@@ -94,12 +94,14 @@ impl Gcp {
9494
Ok(())
9595
}
9696

97-
fn get_metric_data(&self, collected: Vec<CollectedMetric>) -> Vec<TimeSeries> {
97+
async fn get_metric_data(&self, collected: Vec<CollectedMetric>) -> Vec<TimeSeries> {
9898
let end_time = SystemTime::now();
9999
let ts_end_time: google_cloud_wkt::Timestamp = end_time.try_into().unwrap_or_default();
100100

101101
let mut data: Vec<TimeSeries> = Vec::with_capacity(collected.len());
102102

103+
let container_meta = self.container_meta_client.collect().await;
104+
103105
for metric in collected {
104106
let cloud_metric_name = match self.metric_names.get(metric.key.name()) {
105107
Some(name) => name,
@@ -112,11 +114,11 @@ impl Gcp {
112114
}
113115
};
114116

115-
let container_labels = self.container_meta.labels();
117+
let container_labels = container_meta.labels();
116118
let container_labels_len = container_labels.len();
117119
let mut labels =
118120
HashMap::with_capacity(container_labels_len + metric.key.labels().len());
119-
labels.extend(container_labels);
121+
labels.extend(container_labels.clone());
120122
labels.extend(
121123
metric
122124
.key
@@ -171,6 +173,18 @@ impl Gcp {
171173
),
172174
};
173175

176+
// Add container instance ID to node_id if present
177+
let mut monitored_resource_labels = self.monitored_resource_labels.clone();
178+
if let Some(node_id) = monitored_resource_labels.get("node_id") {
179+
monitored_resource_labels.insert(
180+
"node_id".to_string(),
181+
format!("{}-{}", node_id, container_meta.instance_id),
182+
);
183+
}
184+
185+
let mut mr = MonitoredResource::new().set_type(&self.monitored_resource_type);
186+
mr.labels = monitored_resource_labels;
187+
174188
data.push(
175189
TimeSeries::new()
176190
.set_metric_kind(kind)
@@ -179,11 +193,7 @@ impl Gcp {
179193
.set_type(format!("custom.googleapis.com/{}", cloud_metric_name))
180194
.set_labels(labels),
181195
)
182-
.set_resource(
183-
MonitoredResource::new()
184-
.set_type(&self.monitored_resource_type)
185-
.set_labels(&self.monitored_resource_labels),
186-
)
196+
.set_resource(mr)
187197
.set_value_type(value_type)
188198
.set_points(vec![Point::new()
189199
.set_interval(interval)

runtimes/core/src/metrics/manager.rs

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
22
encore::runtime::v1::{self as pb, Environment},
3-
metadata::{process_env_substitution, ContainerMetadata},
3+
metadata::{process_env_substitution, ContainerMetaClient},
44
metrics::{
55
exporter::{self, Exporter},
66
registry::Registry,
@@ -37,45 +37,30 @@ impl ProviderType {
3737
&self,
3838
env: &Environment,
3939
http_client: &reqwest::Client,
40-
runtime_handle: tokio::runtime::Handle,
4140
) -> Arc<dyn Exporter + Send + Sync> {
4241
match self {
4342
Self::Gcp(config) | Self::EncoreCloud(config) => {
44-
runtime_handle.block_on(Self::create_gcp_exporter(config, env, http_client))
43+
Self::create_gcp_exporter(config, env, http_client)
4544
}
4645
}
4746
}
4847

49-
async fn create_gcp_exporter(
48+
fn create_gcp_exporter(
5049
provider_cfg: &pb::metrics_provider::GcpCloudMonitoring,
5150
env: &Environment,
5251
http_client: &reqwest::Client,
5352
) -> Arc<dyn Exporter + Send + Sync> {
54-
let container_meta = ContainerMetadata::collect(env, http_client)
55-
.await
56-
.unwrap_or_else(|_| ContainerMetadata {
57-
env_name: env.env_name.clone(),
58-
..Default::default()
59-
});
53+
let container_meta_client = ContainerMetaClient::new(env.clone(), http_client.clone());
6054

6155
let mut labels = provider_cfg.monitored_resource_labels.clone();
62-
63-
// Add container instance ID to node_id if present
64-
if let Some(node_id) = labels.get("node_id").cloned() {
65-
labels.insert(
66-
"node_id".to_string(),
67-
format!("{}-{}", node_id, container_meta.instance_id),
68-
);
69-
}
70-
7156
process_env_substitution(&mut labels);
7257

7358
Arc::new(exporter::Gcp::new(
7459
provider_cfg.project_id.clone(),
7560
provider_cfg.monitored_resource_type.clone(),
7661
labels,
7762
provider_cfg.metric_names.clone(),
78-
container_meta,
63+
container_meta_client,
7964
))
8065
}
8166
}
@@ -110,11 +95,7 @@ impl Manager {
11095

11196
for metrics_provider in &observability.metrics {
11297
if let Some(provider_type) = ProviderType::from_config(metrics_provider) {
113-
manager.exporter = Some(provider_type.create_exporter(
114-
environment,
115-
http_client,
116-
runtime_handle.clone(),
117-
));
98+
manager.exporter = Some(provider_type.create_exporter(environment, http_client));
11899
break; // Take the first valid provider
119100
}
120101
}

0 commit comments

Comments
 (0)