Skip to content

Commit d4e820a

Browse files
committed
Add a command audit log
Signed-off-by: Didier Wenzek <[email protected]>
1 parent 3521388 commit d4e820a

File tree

9 files changed

+73
-15
lines changed

9 files changed

+73
-15
lines changed

Cargo.lock

+13
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ toml = "0.8"
191191
tower = "0.4"
192192
tower-http = "0.5"
193193
tracing = { version = "0.1", features = ["attributes", "log"] }
194+
tracing-appender = "0.2"
194195
tracing-subscriber = { version = "0.3", features = ["time", "env-filter"] }
195196
try-traits = "0.1"
196197
url = "2.3"

crates/common/tedge_config/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ thiserror = { workspace = true }
3535
tokio = { workspace = true }
3636
toml = { workspace = true }
3737
tracing = { workspace = true }
38+
tracing-appender = { workspace = true }
3839
tracing-subscriber = { workspace = true }
3940
url = { workspace = true }
4041
which = { workspace = true }

crates/common/tedge_config/src/system_toml/log_level.rs

+43-15
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ use super::SystemTomlError;
55
use crate::cli::LogConfigArgs;
66
use std::io::IsTerminal;
77
use std::str::FromStr;
8+
use tracing::metadata::LevelFilter;
9+
use tracing_appender::rolling::*;
10+
use tracing_subscriber::filter::filter_fn;
11+
use tracing_subscriber::layer::SubscriberExt;
12+
use tracing_subscriber::util::SubscriberInitExt;
13+
use tracing_subscriber::Layer;
814

915
/// Configures and enables logging taking into account flags, env variables and file config.
1016
///
@@ -19,7 +25,8 @@ pub fn log_init(
1925
flags: &LogConfigArgs,
2026
config_dir: &Utf8Path,
2127
) -> Result<(), SystemTomlError> {
22-
let subscriber = tracing_subscriber::fmt()
28+
// General logging
29+
let log_layer = tracing_subscriber::fmt::layer()
2330
.with_writer(std::io::stderr)
2431
.with_ansi(std::io::stderr().is_terminal())
2532
.with_timer(tracing_subscriber::fmt::time::UtcTime::rfc_3339());
@@ -28,22 +35,43 @@ pub fn log_init(
2835
.log_level
2936
.or(flags.debug.then_some(tracing::Level::DEBUG));
3037

31-
if let Some(log_level) = log_level {
32-
subscriber.with_max_level(log_level).init();
33-
return Ok(());
34-
}
35-
36-
if std::env::var("RUST_LOG").is_ok() {
37-
subscriber
38-
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
38+
let log_layer = if let Some(log_level) = log_level {
39+
log_layer
40+
.with_filter(LevelFilter::from_level(log_level))
41+
.boxed()
42+
} else if std::env::var("RUST_LOG").is_ok() {
43+
log_layer
3944
.with_file(true)
4045
.with_line_number(true)
41-
.init();
42-
return Ok(());
43-
}
44-
45-
let log_level = get_log_level(sname, config_dir)?;
46-
subscriber.with_max_level(log_level).init();
46+
.with_filter(tracing_subscriber::EnvFilter::from_default_env())
47+
.boxed()
48+
} else {
49+
let log_level = get_log_level(sname, config_dir)?;
50+
log_layer
51+
.with_filter(LevelFilter::from_level(log_level))
52+
.boxed()
53+
};
54+
55+
// Audit journal
56+
let audit_appender = RollingFileAppender::builder()
57+
.rotation(Rotation::DAILY)
58+
.filename_prefix("tedge.audit.log")
59+
.max_log_files(7);
60+
let audit_layer = audit_appender
61+
.build("/var/log/tedge")
62+
.ok()
63+
.map(|audit_appender| {
64+
tracing_subscriber::fmt::layer()
65+
.with_writer(audit_appender)
66+
.with_timer(tracing_subscriber::fmt::time::UtcTime::rfc_3339())
67+
.with_filter(LevelFilter::INFO)
68+
.with_filter(filter_fn(|metadata| metadata.target() == "Audit"))
69+
});
70+
71+
tracing_subscriber::registry()
72+
.with(audit_layer)
73+
.with(log_layer)
74+
.init();
4775

4876
Ok(())
4977
}

crates/core/tedge/src/cli/config/commands/add.rs

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ impl Command for AddConfigCommand {
2727
})
2828
.await
2929
.map_err(anyhow::Error::new)?;
30+
tracing::info!(target: "Audit", "tedge config add {} {}", &self.key, &self.value);
3031
Ok(())
3132
}
3233
}

crates/core/tedge/src/cli/config/commands/remove.rs

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ impl Command for RemoveConfigCommand {
2323
})
2424
.await
2525
.map_err(anyhow::Error::new)?;
26+
tracing::info!(target: "Audit", "tedge config remove {} {}", &self.key, &self.value);
2627
Ok(())
2728
}
2829
}

crates/core/tedge/src/cli/config/commands/set.rs

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ impl Command for SetConfigCommand {
2727
})
2828
.await
2929
.map_err(anyhow::Error::new)?;
30+
tracing::info!(target: "Audit", "tedge config set {} {}", &self.key, &self.value);
3031
Ok(())
3132
}
3233
}

crates/core/tedge/src/cli/config/commands/unset.rs

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ impl Command for UnsetConfigCommand {
1919
.update_toml(&|dto, _reader| Ok(dto.try_unset_key(&self.key)?))
2020
.await
2121
.map_err(anyhow::Error::new)?;
22+
tracing::info!(target: "Audit", "tedge config unset {}", &self.key);
2223
Ok(())
2324
}
2425
}

crates/core/tedge_agent/src/operation_workflows/actor.rs

+11
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ impl Actor for WorkflowActor {
6565
}
6666

6767
async fn run(mut self) -> Result<(), RuntimeError> {
68+
tracing::info!(target: "Audit", "tedge-agent started");
6869
self.workflow_repository.load().await;
6970
self.publish_operation_capabilities().await?;
7071
self.load_command_board().await?;
@@ -95,11 +96,15 @@ impl Actor for WorkflowActor {
9596
)
9697
.await
9798
{
99+
tracing::info!(target: "Audit", "Updated capability {}",
100+
updated_capability.topic.as_ref(),
101+
);
98102
self.mqtt_publisher.send(updated_capability).await?
99103
}
100104
}
101105
}
102106
}
107+
tracing::info!(target: "Audit", "tedge-agent stopped");
103108
Ok(())
104109
}
105110
}
@@ -159,6 +164,7 @@ impl WorkflowActor {
159164
Ok(Some(new_state)) => {
160165
self.persist_command_board().await?;
161166
if new_state.is_init() {
167+
tracing::info!(target: "Audit", "Execute {operation} command, log = {}", log_file.path);
162168
self.process_command_update(new_state.with_log_path(&log_file.path))
163169
.await?;
164170
}
@@ -211,6 +217,11 @@ impl WorkflowActor {
211217

212218
match action {
213219
OperationAction::Clear => {
220+
tracing::info!(
221+
target: "Audit",
222+
"{} {operation} command",
223+
if state.is_successful() {"Executed"} else { "Failed"},
224+
);
214225
if let Some(invoking_command) =
215226
self.workflow_repository.invoking_command_state(&state)
216227
{

0 commit comments

Comments
 (0)