feat: support reporting env vars in heartbeat messages to metasrv#8084
feat: support reporting env vars in heartbeat messages to metasrv#8084v0y4g3r wants to merge 6 commits intoGreptimeTeam:mainfrom
Conversation
Add `heartbeat_env_vars` config option for datanode and frontend. When configured, the specified environment variable values are read at startup and sent to metasrv in every heartbeat via the `extensions` map. Metasrv extracts and stores them in `NodeInfo` for use in routing decisions (e.g. AZ-aware region placement). - Add `EnvVars` helper in `common/meta/src/datanode.rs` following the existing `GcStat` extension pattern with `into_extensions`/`from_extensions` - Add `env_vars: HashMap<String, String>` field to `NodeInfo` in `common/meta/src/cluster.rs` with `#[serde(default)]` for backward compat - Add `heartbeat_env_vars: Vec<String>` config field to `DatanodeOptions`, `FrontendOptions`, and `StandaloneOptions` - Inject env vars into heartbeat `extensions` in both datanode and frontend heartbeat tasks (`datanode/src/heartbeat.rs`, `frontend/src/heartbeat.rs`) - Extract env vars from `req.extensions` in all three metasrv `CollectXxxClusterInfoHandler`s - Update `NodeInfo` construction sites in `meta-client`, `discovery/lease.rs`, and `standalone/information_extension.rs` - Update expected TOML output in `tests-integration/tests/http.rs` - Add unit tests for `EnvVars` round-trip and `NodeInfo` backward compat Signed-off-by: Lei, HUANG <leih@nvidia.com> Signed-off-by: Lei, HUANG <mrsatangel@gmail.com>
Signed-off-by: Lei, HUANG <mrsatangel@gmail.com>
Signed-off-by: Lei, HUANG <mrsatangel@gmail.com>
Signed-off-by: Lei, HUANG <mrsatangel@gmail.com>
Signed-off-by: Lei, HUANG <mrsatangel@gmail.com>
Signed-off-by: Lei, HUANG <mrsatangel@gmail.com>
There was a problem hiding this comment.
Code Review
This pull request implements a mechanism for nodes to report specific environment variables to the meta service via heartbeat messages. It adds a heartbeat_env_vars configuration to Datanode, Frontend, and Standalone components, updates the NodeInfo structure to include an env_vars field, and modifies heartbeat handlers to propagate this data through request extensions. Feedback highlights an opportunity to refactor duplicated mapping logic in the meta-client and notes that environment variables are currently not populated in standalone mode, which affects the consistency of the information_schema.nodes table.
| cpu_usage_millicores: node_info.cpu_usage_millicores, | ||
| memory_usage_bytes: node_info.memory_usage_bytes, | ||
| hostname: node_info.hostname, | ||
| env_vars: Default::default(), |
There was a problem hiding this comment.
The mapping logic from the Protobuf NodeInfo to the internal NodeInfo struct is duplicated multiple times in this file (e.g., lines 460-463, 476-480, 494-498, 510-514). This violates the general rule of refactoring duplicated logic into shared helper functions to improve maintainability. Consider creating a helper method to handle this conversion, which would also make it easier to propagate env_vars if they are added to the Protobuf definition in the future.
References
- Refactor duplicated logic (like environment variable extraction) into shared helper functions to improve maintainability and reduce code duplication.
| .unwrap_or_default() | ||
| .to_string_lossy() | ||
| .to_string(), | ||
| env_vars: Default::default(), |
There was a problem hiding this comment.
In standalone mode, the env_vars field is hardcoded to Default::default(). This means that environment variables configured via heartbeat_env_vars will not be visible in the information_schema.nodes table when running in standalone mode. To ensure consistency across deployment modes and provide a complete view of node metadata, this extension should be updated to populate env_vars from the process environment based on the configured keys.
There was a problem hiding this comment.
Pull request overview
Adds a configurable mechanism for datanode/frontend (and standalone via option propagation) to report selected environment variable values to metasrv via heartbeat extensions, and persists them into NodeInfo for later routing/placement decisions (e.g., AZ-aware logic).
Changes:
- Introduces
heartbeat_env_vars: Vec<String>in datanode/frontend/standalone options and wires it into env-based config loading. - Implements
EnvVars(serialize into / deserialize from heartbeatextensionsunder__env_vars) and stores extracted values incommon_meta::cluster::NodeInfo. - Updates heartbeat senders (datanode/frontend) and metasrv heartbeat handlers to populate/extract the env-var extension; expands tests for config loading and serialization/backward-compat.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests-integration/tests/http.rs | Updates /config expected output to include heartbeat_env_vars = []. |
| src/standalone/src/options.rs | Adds heartbeat_env_vars to standalone config and propagates into frontend/datanode options. |
| src/standalone/src/information_extension.rs | Updates standalone NodeInfo construction for the new env_vars field. |
| src/meta-srv/src/handler/collect_cluster_info_handler.rs | Extracts __env_vars from heartbeat extensions and stores into NodeInfo. |
| src/meta-srv/src/discovery/lease.rs | Updates metasrv discovery tests to populate NodeInfo.env_vars. |
| src/meta-client/src/client/util.rs | Updates meta-client test helpers for the new NodeInfo.env_vars field. |
| src/meta-client/src/client.rs | Ensures metasrv node info construction populates env_vars (default). |
| src/frontend/src/heartbeat.rs | Reads configured env vars once at startup and injects into heartbeat extensions. |
| src/frontend/src/frontend.rs | Adds heartbeat_env_vars to frontend options and env list parsing keys. |
| src/datanode/src/heartbeat.rs | Reads configured env vars once at startup and injects into heartbeat extensions (alongside existing GC stat extension). |
| src/datanode/src/config.rs | Adds heartbeat_env_vars to datanode options and env list parsing keys. |
| src/common/meta/src/datanode.rs | Adds EnvVars helper + unit tests for extension round-trip behavior. |
| src/common/meta/src/cluster.rs | Adds NodeInfo.env_vars with serde default + tests for backward compatibility and round-trip. |
| src/cmd/tests/load_config_test.rs | Adds env-based config loading test for heartbeat_env_vars across components. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| pub memory: MemoryOptions, | ||
| /// The event recorder options. | ||
| pub event_recorder: EventRecorderOptions, | ||
| /// Environment variable keys to read and report in heartbeat messages. |
| pub slow_query: SlowQueryOptions, | ||
| pub query: QueryOptions, | ||
| pub memory: MemoryOptions, | ||
| /// Environment variable keys to read and report in heartbeat messages. |
| let env_vars = EnvVars::from_extensions(&request.extensions) | ||
| .inspect_err(|e| { | ||
| warn!(e; | ||
| "Failed to deserialize __env_vars from heartbeat extensions, peer: {}", peer |
Summary
heartbeat_env_varsconfig option for datanode and frontend to specify environment variable keys whose values should be reported to metasrv in heartbeat messagesNodeInfo, enabling routing decisions like AZ-aware region placementGcStatextension pattern using theHeartbeatRequest.extensionsmap with key__env_varsChanges
heartbeat_env_vars: Vec<String>toDatanodeOptions,FrontendOptions, andStandaloneOptionsEnvVarshelper incommon/meta/src/datanode.rswithfrom_config/into_extensions/from_extensionsenv_vars: HashMap<String, String>field toNodeInfoincommon/meta/src/cluster.rswith#[serde(default)]for backward compatCollectXxxClusterInfoHandlers extract env vars fromreq.extensionsand store inNodeInfoTest plan
EnvVarsround-trip serializationNodeInfobackward compat (deserialize withoutenv_varsfield)test_config_apiupdated for new config fieldheartbeat_env_vars, verify metasrv stores values inNodeInfo