feat: add tracing

This commit is contained in:
Alexander Navarro 2025-06-26 12:42:01 -04:00
parent f613efc882
commit 1f194ca7f1
6 changed files with 126 additions and 29 deletions

86
Cargo.lock generated
View file

@ -193,6 +193,8 @@ dependencies = [
"serde_yml", "serde_yml",
"thiserror", "thiserror",
"tokio", "tokio",
"tracing",
"tracing-subscriber",
] ]
[[package]] [[package]]
@ -615,6 +617,12 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.174" version = "0.2.174"
@ -669,6 +677,16 @@ dependencies = [
"windows-sys 0.59.0", "windows-sys 0.59.0",
] ]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
dependencies = [
"overload",
"winapi",
]
[[package]] [[package]]
name = "num-conv" name = "num-conv"
version = "0.1.0" version = "0.1.0"
@ -699,6 +717,12 @@ version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.3.1" version = "2.3.1"
@ -888,6 +912,15 @@ dependencies = [
"version_check", "version_check",
] ]
[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
"lazy_static",
]
[[package]] [[package]]
name = "shlex" name = "shlex"
version = "1.3.0" version = "1.3.0"
@ -964,6 +997,15 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "thread_local"
version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.41" version = "0.3.41"
@ -1058,9 +1100,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
dependencies = [ dependencies = [
"pin-project-lite", "pin-project-lite",
"tracing-attributes",
"tracing-core", "tracing-core",
] ]
[[package]]
name = "tracing-attributes"
version = "0.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "tracing-core" name = "tracing-core"
version = "0.1.34" version = "0.1.34"
@ -1068,6 +1122,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
dependencies = [ dependencies = [
"once_cell", "once_cell",
"valuable",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
dependencies = [
"nu-ansi-term",
"sharded-slab",
"smallvec",
"thread_local",
"tracing-core",
"tracing-log",
] ]
[[package]] [[package]]
@ -1099,6 +1179,12 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "valuable"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.5" version = "0.9.5"

View file

@ -10,3 +10,5 @@ serde = "1.0.219"
serde_yml = "0.0.12" serde_yml = "0.0.12"
thiserror = "2.0.12" thiserror = "2.0.12"
tokio = { version = "1.45.1", features = ["macros", "rt", "rt-multi-thread"] } tokio = { version = "1.45.1", features = ["macros", "rt", "rt-multi-thread"] }
tracing = "0.1.41"
tracing-subscriber = "0.3.19"

View file

@ -2,6 +2,7 @@ use bollard::models::{ContainerSummary, ContainerSummaryStateEnum, MountPoint};
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde_yml::Value; use serde_yml::Value;
use std::collections::HashMap; use std::collections::HashMap;
use tracing::field::{Field, Visit};
mod labels; mod labels;

View file

@ -1,4 +1,5 @@
use thiserror::Error; use thiserror::Error;
use tracing::dispatcher::SetGlobalDefaultError;
pub type Result<T> = std::result::Result<T, self::Error>; pub type Result<T> = std::result::Result<T, self::Error>;
@ -6,10 +7,13 @@ pub type Result<T> = std::result::Result<T, self::Error>;
pub enum Error { pub enum Error {
#[error("Unhandled error: {0}")] #[error("Unhandled error: {0}")]
Static(&'static str), Static(&'static str),
#[error("Unhandled error: {0}")] #[error("Unhandled error: {0}")]
Generic(String), Generic(String),
#[error(transparent)]
Tracing(#[from] SetGlobalDefaultError),
#[error(transparent)] #[error(transparent)]
Docker(#[from] bollard::errors::Error), Docker(#[from] bollard::errors::Error),
} }

View file

@ -4,16 +4,16 @@ use tokio;
#[tokio::main] #[tokio::main]
async fn main() -> epoch::Result<()> { async fn main() -> epoch::Result<()> {
// construct a subscriber that prints formatted traces to stdout
tracing_subscriber::fmt().with_ansi(true).compact().init();
let docker = Docker::connect_with_local_defaults()?; let docker = Docker::connect_with_local_defaults()?;
let filters: HashMap<&str, Vec<&str>> = HashMap::from( let filters: HashMap<&str, Vec<&str>> = HashMap::from([("label", vec!["epoch.manage=true"])]);
[
("label", vec!["epoch.manage=true"]),
],
);
let opts = bollard::query_parameters::ListContainersOptionsBuilder::new() let opts = bollard::query_parameters::ListContainersOptionsBuilder::new()
.filters(&filters).build(); .filters(&filters)
.build();
let containers = docker.list_containers(Some(opts)).await?; let containers = docker.list_containers(Some(opts)).await?;

View file

@ -1,7 +1,10 @@
use crate::docker::Container;
use crate::Error; use crate::Error;
use bollard::models::ContainerSummary; use bollard::models::ContainerSummary;
use bollard::Docker; use bollard::Docker;
use futures::future::try_join_all;
use std::collections::HashMap; use std::collections::HashMap;
use tracing::info;
/// Namespace to manage containers together (like compose projects) /// Namespace to manage containers together (like compose projects)
type ServiceGroup = String; type ServiceGroup = String;
@ -43,6 +46,7 @@ impl From<&Vec<ContainerSummary>> for Services {
} }
} }
#[tracing::instrument(skip(containers))]
pub async fn manage(containers: &Vec<ContainerSummary>) -> crate::Result<()> { pub async fn manage(containers: &Vec<ContainerSummary>) -> crate::Result<()> {
let services = Services::from(containers); let services = Services::from(containers);
@ -52,35 +56,35 @@ pub async fn manage(containers: &Vec<ContainerSummary>) -> crate::Result<()> {
// TODO: iterate over groups in parallel // TODO: iterate over groups in parallel
for (group, containers) in services.0.iter() { for (group, containers) in services.0.iter() {
// stop containers of service group // stop containers of service group
let stop_tasks = containers.into_iter().map(async |container| { try_join_all(containers.into_iter().map(|container | stop_container(&docker, container))).await?;
eprintln!("Stoping container: {:#?}", container.id);
let stop_opts = bollard::query_parameters::StopContainerOptionsBuilder::new().build();
docker.stop_container(&container.id, Some(stop_opts)).await?;
Ok::<(), crate::Error>(())
});
futures::future::try_join_all(stop_tasks).await?;
// create container with the same mounts as each container in the group // create container with the same mounts as each container in the group
// run the new container // run the new container
// restart the containers // restart the containers
let start_tasks = containers.into_iter().map(async |container| { try_join_all(containers.into_iter().map(|container| start_container(&docker, container))).await?;
eprintln!("Starting container: {:#?}", container.id);
let start_opts = bollard::query_parameters::StartContainerOptionsBuilder::new().build();
docker.start_container(&container.id, Some(start_opts)).await?;
Ok::<(), crate::Error>(())
});
futures::future::try_join_all(start_tasks).await?;
} }
Ok(()) Ok(())
} }
async fn stop_container(docker: &Docker, container: &crate::docker::Container) -> crate::Result<()> {
info!("Stoping container: {:#?}", container.id);
let stop_opts = bollard::query_parameters::StopContainerOptionsBuilder::new().build();
docker.stop_container(&container.id, Some(stop_opts)).await?;
Ok::<(), crate::Error>(())
}
async fn start_container(docker: &Docker, container: &crate::docker::Container) -> crate::Result<()> {
info!("Starting container: {:#?}", container.id);
let start_opts = bollard::query_parameters::StartContainerOptionsBuilder::new().build();
docker.start_container(&container.id, Some(start_opts)).await?;
Ok::<(), crate::Error>(())
}