Skip to main content

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}