|
|
@@ -59,6 +59,24 @@ pub async fn serve(
|
|
|
Ok(())
|
|
|
}
|
|
|
|
|
|
+/// Builds the `docker logs` shell command used to fetch the last `tail`
|
|
|
+/// lines of the container for `recipe_name` on a specific `rank`.
|
|
|
+pub(crate) fn logs_tail_cmd(recipe_name: &str, rank: u32, tail: usize) -> String {
|
|
|
+ format!(
|
|
|
+ "docker ps -q --filter \"label=sm121.recipe={}\" --filter \"label=sm121.rank={}\" | xargs -r docker logs --timestamps --tail={} 2>&1",
|
|
|
+ recipe_name, rank, tail
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+/// Builds the `docker logs -f` shell command used to follow the head
|
|
|
+/// container of `recipe_name` in real time.
|
|
|
+pub(crate) fn logs_follow_cmd(recipe_name: &str) -> String {
|
|
|
+ format!(
|
|
|
+ "docker ps -q --filter \"label=sm121.recipe={}\" --filter \"label=sm121.rank=0\" | xargs -r docker logs -f --timestamps",
|
|
|
+ recipe_name
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
/// Shows Docker logs for a recipe across all nodes (or follows head node).
|
|
|
pub async fn show_logs(
|
|
|
config: &Config,
|
|
|
@@ -70,13 +88,9 @@ pub async fn show_logs(
|
|
|
if follow {
|
|
|
let head_node = cluster.nodes.first().context("No nodes in cluster")?;
|
|
|
info!("📜 Following logs for '{}' (head node)...", head_node.name);
|
|
|
- let cmd = format!(
|
|
|
- "docker ps -q --filter \"label=sm121.recipe={}\" --filter \"label=sm121.rank=0\" | xargs -r docker logs -f",
|
|
|
- recipe_name
|
|
|
- );
|
|
|
+ let cmd = logs_follow_cmd(recipe_name);
|
|
|
run_ssh_follow(config, head_node, cmd, dry_run).await?;
|
|
|
} else {
|
|
|
- let flag = "--tail=100";
|
|
|
info!(
|
|
|
"📜 Логи кластера '{}' ({} узлов):",
|
|
|
cluster.name,
|
|
|
@@ -84,10 +98,7 @@ pub async fn show_logs(
|
|
|
);
|
|
|
let mut handles = Vec::new();
|
|
|
for node in &cluster.nodes {
|
|
|
- let cmd = format!(
|
|
|
- "docker ps -q --filter \"label=sm121.recipe={}\" --filter \"label=sm121.rank={}\" | xargs -r docker logs {} 2>&1",
|
|
|
- recipe_name, node.rank, flag
|
|
|
- );
|
|
|
+ let cmd = logs_tail_cmd(recipe_name, node.rank, 100);
|
|
|
let config = config.clone();
|
|
|
let node = node.clone();
|
|
|
let dry = dry_run;
|