Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .sce/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
"pi"
]
},
"log_file": "context/tmp/sce.log",
"log_file_mode": "append",
"log_dir": "context/tmp",
"log_level": "error",
"policies": {
"attribution_hooks": {
Expand Down
16 changes: 2 additions & 14 deletions cli/assets/generated/config/schema/sce-config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,10 @@
"json"
]
},
"log_file": {
"log_dir": {
"type": "string",
"minLength": 1
},
"log_file_mode": {
"type": "string",
"enum": [
"truncate",
"append"
]
},
"timeout_ms": {
"type": "integer",
"minimum": 0
Expand Down Expand Up @@ -358,10 +351,5 @@
"additionalProperties": false
}
},
"additionalProperties": false,
"dependentRequired": {
"log_file_mode": [
"log_file"
]
}
"additionalProperties": false
}
2 changes: 2 additions & 0 deletions cli/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ where
"sce.app.start",
"Starting command dispatch",
&[("component", services::observability::NAME)],
None,
);
let Some(command_args) = args.take() else {
return Err(ClassifiedError::runtime(REPEATED_COMMAND_DISPATCH_ERROR));
Expand All @@ -380,6 +381,7 @@ where
"sce.command.parsed",
"Command parsed",
&[("command", command.name().as_ref())],
None,
);
Ok(command)
}
7 changes: 6 additions & 1 deletion cli/src/services/app_support.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,15 @@ pub(crate) fn log_startup_configuration(
("path", loaded_path.path.to_string_lossy().as_ref()),
("source", loaded_path.source.as_str()),
],
None,
);
}
for validation_error in &observability_config.validation_errors {
logger.warn(
INVALID_CONFIG_WARNING_EVENT_ID,
"Invalid discovered config skipped; using degraded defaults",
&[("error", validation_error.as_str())],
None,
);
}
}
Expand All @@ -112,20 +114,23 @@ where
"sce.command.dispatch_start",
"Dispatching command",
&[("command", command_name.as_ref())],
None,
);
let dispatch_result = command.execute(context);
if dispatch_result.is_ok() {
logger.debug(
"sce.command.dispatch_end",
"Command dispatch completed",
&[("command", command_name.as_ref())],
None,
);
}
dispatch_result.inspect(|_payload| {
logger.info(
"sce.command.completed",
"Command completed",
&[("command", command_name.as_ref())],
None,
);
})
}
Expand All @@ -136,7 +141,7 @@ where
W: Write,
{
if let Some(log) = logger {
log.log_classified_error(error);
log.log_classified_error(error, None);
}
write_error_diagnostic(stderr, error);
ExitCode::from(error.class().exit_code())
Expand Down
13 changes: 2 additions & 11 deletions cli/src/services/config/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,7 @@ pub(super) fn format_show_output(runtime: &RuntimeConfig, report_format: ReportF
runtime.log_format.value.as_str(),
runtime.log_format.source,
),
"log_file": format_optional_resolved_value_json(&runtime.log_file),
"log_file_mode": format_resolved_value_json(
runtime.log_file_mode.value.as_str(),
runtime.log_file_mode.source,
),
"log_dir": format_optional_resolved_value_json(&runtime.log_dir),
"timeout_ms": {
"value": runtime.timeout_ms.value,
"source": runtime.timeout_ms.source.as_str(),
Expand Down Expand Up @@ -204,12 +200,7 @@ fn format_observability_text_lines(runtime: &RuntimeConfig) -> Vec<String> {
runtime.log_format.value.as_str(),
runtime.log_format.source,
),
format_optional_resolved_value_text("log_file", &runtime.log_file),
format_resolved_value_text(
"log_file_mode",
runtime.log_file_mode.value.as_str(),
runtime.log_file_mode.source,
),
format_optional_resolved_value_text("log_dir", &runtime.log_dir),
]
}

Expand Down
58 changes: 14 additions & 44 deletions cli/src/services/config/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@ use super::policy::{build_validation_warnings, resolve_bash_policy_config, BashP
use super::schema;
use super::types::{
parse_bool_value_from, ConfigPathSource, ConfigRequest, DatabaseRetryConfig, LoadedConfigPath,
LogFileMode, LogFormat, LogLevel, ReportFormat, ResolvedAuthRuntimeConfig,
ResolvedHookRuntimeConfig, ResolvedObservabilityRuntimeConfig, ResolvedOptionalValue,
ResolvedValue, ValueSource, ENV_ATTRIBUTION_HOOKS_DISABLED, ENV_LOG_FILE, ENV_LOG_FILE_MODE,
ENV_LOG_FORMAT, ENV_LOG_LEVEL,
LogFormat, LogLevel, ReportFormat, ResolvedAuthRuntimeConfig, ResolvedHookRuntimeConfig,
ResolvedObservabilityRuntimeConfig, ResolvedOptionalValue, ResolvedValue, ValueSource,
ENV_ATTRIBUTION_HOOKS_DISABLED, ENV_LOG_DIR, ENV_LOG_FORMAT, ENV_LOG_LEVEL,
};

const DEFAULT_TIMEOUT_MS: u64 = 30000;
Expand Down Expand Up @@ -58,8 +57,7 @@ pub(super) struct RuntimeConfig {
pub(super) loaded_config_paths: Vec<LoadedConfigPath>,
pub(super) log_level: ResolvedValue<LogLevel>,
pub(super) log_format: ResolvedValue<LogFormat>,
pub(super) log_file: ResolvedOptionalValue<String>,
pub(super) log_file_mode: ResolvedValue<LogFileMode>,
pub(super) log_dir: ResolvedOptionalValue<String>,
pub(super) timeout_ms: ResolvedValue<u64>,
pub(super) attribution_hooks_enabled: ResolvedValue<bool>,
pub(super) workos_client_id: ResolvedOptionalValue<String>,
Expand Down Expand Up @@ -191,8 +189,7 @@ where
Ok(ResolvedObservabilityRuntimeConfig {
log_level: runtime.log_level.value,
log_format: runtime.log_format.value,
log_file: runtime.log_file.value,
log_file_mode: runtime.log_file_mode.value,
log_dir: runtime.log_dir.value,
loaded_config_paths: runtime.loaded_config_paths,
validation_errors: runtime.validation_errors,
})
Expand Down Expand Up @@ -268,8 +265,7 @@ where
let mut file_config = schema::FileConfig {
log_level: None,
log_format: None,
log_file: None,
log_file_mode: None,
log_dir: None,
timeout_ms: None,
attribution_hooks_enabled: None,
workos_client_id: None,
Expand All @@ -295,11 +291,8 @@ where
if let Some(log_format) = layer.log_format {
file_config.log_format = Some(log_format);
}
if let Some(log_file) = layer.log_file {
file_config.log_file = Some(log_file);
}
if let Some(log_file_mode) = layer.log_file_mode {
file_config.log_file_mode = Some(log_file_mode);
if let Some(log_dir) = layer.log_dir {
file_config.log_dir = Some(log_dir);
}
if let Some(timeout_ms) = layer.timeout_ms {
file_config.timeout_ms = Some(timeout_ms);
Expand Down Expand Up @@ -364,45 +357,23 @@ where
};
}

let mut resolved_log_file = ResolvedOptionalValue {
let mut resolved_log_dir = ResolvedOptionalValue {
value: file_config
.log_file
.log_dir
.as_ref()
.map(|value| value.value.clone()),
source: file_config
.log_file
.log_dir
.as_ref()
.map(|value| ValueSource::ConfigFile(value.source)),
};
if let Some(raw) = env_lookup(ENV_LOG_FILE) {
resolved_log_file = ResolvedOptionalValue {
if let Some(raw) = env_lookup(ENV_LOG_DIR) {
resolved_log_dir = ResolvedOptionalValue {
value: Some(raw),
source: Some(ValueSource::Env),
};
}

let mut resolved_log_file_mode = ResolvedValue {
value: LogFileMode::Truncate,
source: ValueSource::Default,
};
if let Some(value) = file_config.log_file_mode {
resolved_log_file_mode = ResolvedValue {
value: value.value,
source: ValueSource::ConfigFile(value.source),
};
}
if let Some(raw) = env_lookup(ENV_LOG_FILE_MODE) {
resolved_log_file_mode = ResolvedValue {
value: LogFileMode::parse(&raw, ENV_LOG_FILE_MODE)?,
source: ValueSource::Env,
};
}
if resolved_log_file.value.is_none() && resolved_log_file_mode.source != ValueSource::Default {
bail!(
"{ENV_LOG_FILE_MODE} requires {ENV_LOG_FILE}. Try: set {ENV_LOG_FILE} to a file path or unset {ENV_LOG_FILE_MODE}."
);
}

let mut resolved_timeout_ms = ResolvedValue {
value: DEFAULT_TIMEOUT_MS,
source: ValueSource::Default,
Expand Down Expand Up @@ -468,8 +439,7 @@ where
loaded_config_paths,
log_level: resolved_log_level,
log_format: resolved_log_format,
log_file: resolved_log_file,
log_file_mode: resolved_log_file_mode,
log_dir: resolved_log_dir,
timeout_ms: resolved_timeout_ms,
attribution_hooks_enabled: resolved_attribution_hooks_enabled,
workos_client_id: resolved_workos_client_id,
Expand Down
31 changes: 8 additions & 23 deletions cli/src/services/config/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ use serde_json::Value;

use super::policy::{parse_bash_policy_presets, parse_custom_bash_policies, CustomBashPolicyEntry};
use super::types::{
ConfigPathSource, DatabaseRetryConfig, IntegrationTargetId, IntegrationsConfig, LogFileMode,
LogFormat, LogLevel,
ConfigPathSource, DatabaseRetryConfig, IntegrationTargetId, IntegrationsConfig, LogFormat,
LogLevel,
};
use crate::services::resilience::RetryPolicy;

Expand All @@ -32,16 +32,15 @@ pub(crate) const TOP_LEVEL_CONFIG_KEYS: &[&str] = &[
CONFIG_SCHEMA_DECLARATION_KEY,
"log_level",
"log_format",
"log_file",
"log_file_mode",
"log_dir",
"timeout_ms",
super::resolver::WORKOS_CLIENT_ID_KEY.config_key,
"policies",
"integrations",
];

pub(crate) const TOP_LEVEL_CONFIG_KEYS_DESCRIPTION: &str =
"$schema, log_level, log_format, log_file, log_file_mode, timeout_ms, workos_client_id, policies, integrations";
"$schema, log_level, log_format, log_dir, timeout_ms, workos_client_id, policies, integrations";

static CONFIG_SCHEMA_VALIDATOR: OnceLock<Validator> = OnceLock::new();

Expand All @@ -67,8 +66,7 @@ pub(crate) struct ParsedFileConfigDocument {
pub(crate) _schema: Option<String>,
pub(crate) log_level: Option<String>,
pub(crate) log_format: Option<String>,
pub(crate) log_file: Option<String>,
pub(crate) log_file_mode: Option<String>,
pub(crate) log_dir: Option<String>,
pub(crate) timeout_ms: Option<u64>,
pub(crate) workos_client_id: Option<String>,
pub(crate) policies: Option<ParsedPoliciesConfigDocument>,
Expand Down Expand Up @@ -143,8 +141,7 @@ pub(crate) struct FileConfigValue<T> {
pub(crate) struct FileConfig {
pub(crate) log_level: Option<FileConfigValue<LogLevel>>,
pub(crate) log_format: Option<FileConfigValue<LogFormat>>,
pub(crate) log_file: Option<FileConfigValue<String>>,
pub(crate) log_file_mode: Option<FileConfigValue<LogFileMode>>,
pub(crate) log_dir: Option<FileConfigValue<String>>,
pub(crate) timeout_ms: Option<FileConfigValue<u64>>,
pub(crate) attribution_hooks_enabled: Option<FileConfigValue<bool>>,
pub(crate) workos_client_id: Option<FileConfigValue<String>>,
Expand Down Expand Up @@ -276,18 +273,7 @@ pub(crate) fn parse_file_config(
})
})
.transpose()?;
let log_file = typed
.log_file
.map(|value| FileConfigValue { value, source });
let log_file_mode = typed
.log_file_mode
.map(|raw| -> Result<FileConfigValue<LogFileMode>> {
Ok(FileConfigValue {
value: LogFileMode::parse(&raw, &format!("config file '{}'", path.display()))?,
source,
})
})
.transpose()?;
let log_dir = typed.log_dir.map(|value| FileConfigValue { value, source });
let timeout_ms = typed
.timeout_ms
.map(|value| FileConfigValue { value, source });
Expand All @@ -301,8 +287,7 @@ pub(crate) fn parse_file_config(
Ok(FileConfig {
log_level,
log_format,
log_file,
log_file_mode,
log_dir,
timeout_ms,
attribution_hooks_enabled,
workos_client_id,
Expand Down
39 changes: 2 additions & 37 deletions cli/src/services/config/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ pub const NAME: &str = "config";

pub(crate) const ENV_LOG_LEVEL: &str = "SCE_LOG_LEVEL";
pub(crate) const ENV_LOG_FORMAT: &str = "SCE_LOG_FORMAT";
pub(crate) const ENV_LOG_FILE: &str = "SCE_LOG_FILE";
pub(crate) const ENV_LOG_FILE_MODE: &str = "SCE_LOG_FILE_MODE";
pub(crate) const ENV_LOG_DIR: &str = "SCE_LOG_DIR";
pub(crate) const ENV_ATTRIBUTION_HOOKS_DISABLED: &str = "SCE_ATTRIBUTION_HOOKS_DISABLED";

pub type ReportFormat = OutputFormat;
Expand Down Expand Up @@ -104,39 +103,6 @@ impl LogFormat {
}
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum LogFileMode {
Truncate,
Append,
}

impl LogFileMode {
pub(crate) fn parse(raw: &str, source: &str) -> anyhow::Result<Self> {
match raw {
"truncate" => Ok(Self::Truncate),
"append" => Ok(Self::Append),
_ => anyhow::bail!(
"Invalid log file mode '{raw}' from {source}. Valid values: truncate, append."
),
}
}

pub(crate) fn parse_env(raw: &str, key: &str) -> anyhow::Result<Self> {
match raw {
"truncate" => Ok(Self::Truncate),
"append" => Ok(Self::Append),
_ => anyhow::bail!("Invalid {key} '{raw}'. Valid values: truncate, append."),
}
}

pub(crate) fn as_str(self) -> &'static str {
match self {
Self::Truncate => "truncate",
Self::Append => "append",
}
}
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) enum ValueSource {
Flag,
Expand Down Expand Up @@ -230,8 +196,7 @@ pub(crate) struct ResolvedAuthRuntimeConfig {
pub(crate) struct ResolvedObservabilityRuntimeConfig {
pub(crate) log_level: LogLevel,
pub(crate) log_format: LogFormat,
pub(crate) log_file: Option<String>,
pub(crate) log_file_mode: LogFileMode,
pub(crate) log_dir: Option<String>,
pub(crate) loaded_config_paths: Vec<LoadedConfigPath>,
pub(crate) validation_errors: Vec<String>,
}
Expand Down
Loading
Loading