Skip to content

Settings comments not propagated when using #[serde(flatten)] #42

@hgmich

Description

@hgmich

In a shared workspace of several crates, I am sharing a common settings struct like this:

use foundations::settings::settings;
use std::path::PathBuf;

#[settings]
pub struct NatsSettings {
    /// NATS server URL.
    #[serde(default = "NatsSettings::default_url")]
    pub url: String,
    /// NATS credentials file. Set to null to disable authentication.
    #[serde(default = "NatsSettings::default_creds_file")]
    pub credentials_file: Option<PathBuf>,
}

impl NatsSettings {
    fn default_url() -> String {
        "nats://localhost:4222".into()
    }

    fn default_creds_file() -> Option<PathBuf> {
        Some("/etc/nats/creds".into())
    }
}

Since these services all connect to NATS, it makes sense to have a common section for these. However, some services make use of additional features, such as NATS' key-value store. Similar to how one might "extend" traits locally, I adopted a pattern somewhat like this:

use foundations::settings::settings;
use foundations::telemetry::settings::TelemetrySettings;

use workspace_utils::settings::NatsSettings;

#[settings]
pub(crate) struct ServiceSettings {
    /// Telemetry settings.
    pub(crate) telemetry: TelemetrySettings,
    /// NATS client configuration.
    pub(crate) nats: NatsSettingsExt,
}

#[settings]
pub(crate) struct NatsSettingsExt {
    #[serde(flatten)]
    pub(crate) core: NatsSettings,

    /// NATS KV bucket name.
    pub(crate) kv_bucket: String,
}

This actually mostly works as expected - the only thing to note is that in the generated config, the doc comments in NatsSettings are not propagated into the generated config file:

---
# Telemetry settings.
telemetry:
  # Distributed tracing settings
  tracing:
    # Enables tracing.
    enabled: true
    # The address of the Jaeger Thrift (UDP) agent.
    jaeger_tracing_server_addr: "127.0.0.1:6831"
    # Overrides the bind address for the reporter API.
    # By default, the reporter API is only exposed on the loopback
    # interface. This won't work in environments where the
    # Jaeger agent is on another host (for example, Docker).
    # Must have the same address family as `jaeger_tracing_server_addr`.
    jaeger_reporter_bind_addr: ~
    # Sampling ratio.
    #
    # This can be any fractional value between `0.0` and `1.0`.
    # Where `1.0` means "sample everything", and `0.0` means "don't sample anything".
    sampling_ratio: 1.0
    # Settings for rate limiting emission of traces
    rate_limit:
      # Whether to enable rate limiting of events
      enabled: false
      # Maximum number of events that can be emitted per second
      max_events_per_second: 0
  # Logging settings.
  logging:
    # Specifies log output.
    output: terminal
    # The format to use for log messages.
    format: text
    # Set the logging verbosity level.
    verbosity: INFO
    # A list of field keys to redact when emitting logs.
    #
    # This might be useful to hide certain fields in production logs as they may
    # contain sensitive information, but allow them in testing environment.
    redact_keys: []
    # Settings for rate limiting emission of log events
    rate_limit:
      # Whether to enable rate limiting of events
      enabled: false
      # Maximum number of events that can be emitted per second
      max_events_per_second: 0
    # Configure log volume metrics.
    log_volume_metrics:
      # Whether to enable log volume metrics
      enabled: false
  # Metrics settings.
  metrics:
    # How the metrics service identifier defined in `ServiceInfo` is used
    # for this service.
    service_name_format: metric_prefix
    # Whether to report optional metrics in the telemetry server.
    report_optional: false
  # Server settings.
  server:
    # Enables telemetry server
    enabled: true
    # Telemetry server address.
    addr: "127.0.0.1:0"
# NATS client configuration.
nats:
  url: "nats://localhost:4222"
  credentials_file: /etc/nats/creds
  # NATS KV bucket name.
  kv_bucket: ""

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions