cmd/options.rs
1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use clap::Parser;
16use common_config::Configurable;
17use common_options::plugin_options::PluginOptionsDeserializer;
18use common_runtime::global::RuntimeOptions;
19use plugins::PluginOptions;
20use plugins::options::PluginOptionsDeserializerImpl;
21use serde::{Deserialize, Serialize};
22use serde_json::Value;
23
24#[derive(Parser, Default, Debug, Clone)]
25pub struct GlobalOptions {
26 #[clap(long, value_name = "LOG_DIR")]
27 #[arg(global = true)]
28 pub log_dir: Option<String>,
29
30 #[clap(long, value_name = "LOG_LEVEL")]
31 #[arg(global = true)]
32 pub log_level: Option<String>,
33
34 #[cfg(feature = "tokio-console")]
35 #[clap(long, value_name = "TOKIO_CONSOLE_ADDR")]
36 #[arg(global = true)]
37 pub tokio_console_addr: Option<String>,
38}
39
40// TODO(LFC): Move logging and tracing options into global options, like the runtime options.
41/// All the options of GreptimeDB.
42#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
43#[serde(default)]
44pub struct GreptimeOptions<T> {
45 /// The runtime options.
46 pub runtime: RuntimeOptions,
47 /// The plugin options.
48 ///
49 /// Deserialized leniently via [`deserialize_plugin_options`]: plugin
50 /// options not recognized by the current build are dropped (with a deferred
51 /// warning) instead of aborting startup, while malformed payloads for known
52 /// variants still error.
53 #[serde(default, deserialize_with = "deserialize_plugin_options")]
54 pub plugins: Vec<PluginOptions>,
55
56 /// The options of each component (like Datanode or Standalone) of GreptimeDB.
57 #[serde(flatten)]
58 pub component: T,
59}
60
61impl<T> Configurable for GreptimeOptions<T>
62where
63 T: Configurable,
64{
65 fn env_list_keys() -> Option<&'static [&'static str]> {
66 T::env_list_keys()
67 }
68}
69
70/// A serde `deserialize_with` helper that parses the `plugins` field leniently.
71///
72/// It delegates to the plugin crate's deserializer (`PluginOptionsDeserializerImpl`),
73/// which knows the recognized variants: unknown options are dropped while
74/// malformed known options still error. Keeping the variant-aware logic in the
75/// `plugins` crate avoids duplicating it and avoids introducing a new symbol on
76/// the replaceable `plugins` crate.
77fn deserialize_plugin_options<'de, D>(deserializer: D) -> Result<Vec<PluginOptions>, D::Error>
78where
79 D: serde::Deserializer<'de>,
80{
81 let values = Vec::<Value>::deserialize(deserializer)?;
82 if values.is_empty() {
83 return Ok(vec![]);
84 }
85 let payload = serde_json::to_string(&values).map_err(serde::de::Error::custom)?;
86 PluginOptionsDeserializerImpl
87 .deserialize(&payload)
88 .map_err(serde::de::Error::custom)
89}
90
91/// Emits the plugin options that were dropped during config loading (because
92/// they were not recognized by the current build) as warnings.
93///
94/// Config loading runs before the global tracing subscriber is installed, so
95/// the warnings are buffered and must be flushed once logging is initialized.
96/// Each server's `build` method calls this right after initializing logging.
97pub(crate) fn flush_dropped_plugin_warnings() {
98 let tags = common_options::plugin_options::take_dropped_plugin_warnings();
99 for tag in tags {
100 common_telemetry::warn!(
101 "Ignoring unrecognized plugin option `{tag}` in the config; \
102 it likely belongs to a plugin that is not compiled into this build."
103 );
104 }
105}