Skip to content

Commit a6c5d06

Browse files
committed
custom event metadata from buckconfig
dont modify pool.rs cleanup
1 parent cbd9c9e commit a6c5d06

8 files changed

Lines changed: 128 additions & 1 deletion

File tree

app/buck2_common/src/legacy_configs.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
//! .buckconfig files as configuration)
1313
1414
mod access;
15+
pub use access::parse_buckconfig_metadata;
1516
mod aggregator;
1617
pub mod args;
1718
pub mod cells;

app/buck2_common/src/legacy_configs/access.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ use std::str::FromStr;
1212
use std::sync::Arc;
1313

1414
use buck2_error::BuckErrorContext;
15+
use buck2_hash::StdBuckHashMap;
16+
use buck2_util::env_vars::substitute_env_vars;
1517
use gazebo::eq_chain;
1618

1719
use crate::legacy_configs::configs::ConfigValue;
@@ -21,6 +23,26 @@ use crate::legacy_configs::configs::LegacyBuckConfigValue;
2123
use crate::legacy_configs::key::BuckconfigKeyRef;
2224
use crate::legacy_configs::view::LegacyBuckConfigView;
2325

26+
/// Read the `[buck2_metadata]` section from a `LegacyBuckConfig` and resolve any `$VAR`
27+
/// references. Entries whose env vars are not set are skipped with a warning.
28+
pub fn parse_buckconfig_metadata(config: &LegacyBuckConfig) -> StdBuckHashMap<String, String> {
29+
let mut map = StdBuckHashMap::default();
30+
let Some(section) = config.get_section("buck2_metadata") else {
31+
return map;
32+
};
33+
for (key, value) in section.iter() {
34+
match substitute_env_vars(value.as_str()) {
35+
Ok(resolved) => {
36+
map.insert(key.to_owned(), resolved);
37+
}
38+
Err(e) => {
39+
tracing::warn!("Skipping [buck2_metadata] key `{}`: {:#}", key, e);
40+
}
41+
}
42+
}
43+
map
44+
}
45+
2446
impl LegacyBuckConfigView for &LegacyBuckConfig {
2547
fn get(&mut self, key: BuckconfigKeyRef) -> buck2_error::Result<Option<Arc<str>>> {
2648
Ok(LegacyBuckConfig::get(self, key).map(|v| v.to_owned().into()))

app/buck2_events/src/metadata.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@ use buck2_wrapper_common::BUCK2_WRAPPER_ENV_VAR;
1919

2020
use crate::daemon_id::DaemonId;
2121

22+
/// Collects metadata from the current binary and environment, merged with any extras, suitable for telemetry purposes.
23+
pub fn collect_with_extras(
24+
daemon: &DaemonId,
25+
extras: &StdBuckHashMap<String, String>,
26+
) -> StdBuckHashMap<String, String> {
27+
let mut map = collect(daemon);
28+
map.extend(extras.iter().map(|(k, v)| (k.clone(), v.clone())));
29+
map
30+
}
31+
2232
/// Collects metadata from the current binary and environment and writes it as map, suitable for telemetry purposes.
2333
pub fn collect(daemon: &DaemonId) -> StdBuckHashMap<String, String> {
2434
facebook_only();

app/buck2_server/src/ctx.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1123,7 +1123,10 @@ impl ServerCommandContextTrait for ServerCommandContext<'_> {
11231123
// Facebook only: metadata collection for Scribe writes
11241124
facebook_only();
11251125

1126-
let mut metadata = metadata::collect(&self.base_context.daemon.daemon_id);
1126+
let mut metadata = metadata::collect_with_extras(
1127+
&self.base_context.daemon.daemon_id,
1128+
&self.base_context.daemon.buckconfig_metadata,
1129+
);
11271130

11281131
metadata.insert(
11291132
"io_provider".to_owned(),

app/buck2_server/src/daemon/state.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use buck2_common::init::Timeout;
2727
use buck2_common::invocation_paths::InvocationPaths;
2828
use buck2_common::io::IoProvider;
2929
use buck2_common::legacy_configs::cells::BuckConfigBasedCells;
30+
use buck2_common::legacy_configs::parse_buckconfig_metadata;
3031
use buck2_common::legacy_configs::key::BuckconfigKeyRef;
3132
use buck2_common::sqlite::sqlite_db::SqliteDb;
3233
use buck2_common::sqlite::sqlite_db::SqliteIdentity;
@@ -208,6 +209,8 @@ pub struct DaemonStateData {
208209
/// Semaphores for running actions locally. These need to be shared across commands.
209210
#[allocative(skip)]
210211
pub named_semaphores_for_run_actions: Arc<NamedSemaphores>,
212+
213+
pub buckconfig_metadata: StdBuckHashMap<String, String>,
211214
}
212215

213216
impl DaemonStateData {
@@ -741,6 +744,7 @@ impl DaemonState {
741744
incremental_db_state,
742745
daemon_id: daemon_id.dupe(),
743746
named_semaphores_for_run_actions: Arc::new(NamedSemaphores::new()),
747+
buckconfig_metadata: parse_buckconfig_metadata(root_config),
744748
}))
745749
};
746750
let daemon_listener_span = tracing::Span::current();

app/buck2_util/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ version = "0.1.0"
1212
[dependencies]
1313
allocative = { workspace = true }
1414
blake3 = { workspace = true }
15+
once_cell = { workspace = true }
16+
regex = { workspace = true }
1517
dupe = { workspace = true }
1618
futures = { workspace = true }
1719
pagable = { workspace = true }

app/buck2_util/src/env_vars.rs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is dual-licensed under either the MIT license found in the
5+
* LICENSE-MIT file in the root directory of this source tree or the Apache
6+
* License, Version 2.0 found in the LICENSE-APACHE file in the root directory
7+
* of this source tree. You may select, at your option, one of the
8+
* above-listed licenses.
9+
*/
10+
11+
use std::env::VarError;
12+
13+
use once_cell::sync::Lazy;
14+
use regex::Regex;
15+
16+
/// Replace occurrences of `$FOO` in a string with the value of the env var `$FOO`.
17+
/// Returns an error if any referenced variable is not set.
18+
pub fn substitute_env_vars(s: &str) -> buck2_error::Result<String> {
19+
substitute_env_vars_impl(s, |v| std::env::var(v))
20+
}
21+
22+
pub fn substitute_env_vars_impl(
23+
s: &str,
24+
getter: impl Fn(&str) -> Result<String, VarError>,
25+
) -> buck2_error::Result<String> {
26+
static ENV_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new("\\$[a-zA-Z_][a-zA-Z_0-9]*").unwrap());
27+
28+
let mut out = String::with_capacity(s.len());
29+
let mut last_idx = 0;
30+
31+
for mat in ENV_REGEX.find_iter(s) {
32+
out.push_str(&s[last_idx..mat.start()]);
33+
let var = &mat.as_str()[1..];
34+
let val = getter(var).map_err(|e| {
35+
buck2_error::buck2_error!(
36+
buck2_error::ErrorTag::Environment,
37+
"Error substituting `{}`: {}",
38+
mat.as_str(),
39+
e
40+
)
41+
})?;
42+
out.push_str(&val);
43+
last_idx = mat.end();
44+
}
45+
46+
if last_idx < s.len() {
47+
out.push_str(&s[last_idx..s.len()]);
48+
}
49+
50+
Ok(out)
51+
}
52+
53+
#[cfg(test)]
54+
mod tests {
55+
use std::env::VarError;
56+
57+
use super::*;
58+
59+
#[test]
60+
fn test_substitute_env_vars() {
61+
let getter = |s: &str| match s {
62+
"FOO" => Ok("foo_value".to_owned()),
63+
"BAR" => Ok("bar_value".to_owned()),
64+
"BAZ" => Err(VarError::NotPresent),
65+
_ => panic!("Unexpected"),
66+
};
67+
68+
assert_eq!(
69+
substitute_env_vars_impl("$FOO", getter).unwrap(),
70+
"foo_value"
71+
);
72+
assert_eq!(
73+
substitute_env_vars_impl("$FOO$BAR", getter).unwrap(),
74+
"foo_valuebar_value"
75+
);
76+
assert_eq!(
77+
substitute_env_vars_impl("some$FOO.bar", getter).unwrap(),
78+
"somefoo_value.bar"
79+
);
80+
assert_eq!(substitute_env_vars_impl("foo", getter).unwrap(), "foo");
81+
assert_eq!(substitute_env_vars_impl("FOO", getter).unwrap(), "FOO");
82+
assert!(substitute_env_vars_impl("$FOO$BAZ", getter).is_err());
83+
}
84+
}

app/buck2_util/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#![feature(used_with_arg)]
1515

1616
pub mod arc_str;
17+
pub mod env_vars;
1718
pub mod async_move_clone;
1819
pub mod commas;
1920
pub mod cycle_detector;

0 commit comments

Comments
 (0)