First stab at service logging
This commit is contained in:
parent
ea7e13b0c0
commit
5e3a497c32
|
@ -143,6 +143,37 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.spawn(tracing::Span::current(), enclose!((root_ds) move |t| {
|
||||||
|
let n_unknown: AnyValue = AnyValue::symbol("-");
|
||||||
|
let n_pid: AnyValue = AnyValue::symbol("pid");
|
||||||
|
let n_line: AnyValue = AnyValue::symbol("line");
|
||||||
|
let n_service: AnyValue = AnyValue::symbol("service");
|
||||||
|
let n_stream: AnyValue = AnyValue::symbol("stream");
|
||||||
|
let e = syndicate::during::entity(())
|
||||||
|
.on_message(move |(), _t, captures: AnyValue| {
|
||||||
|
if let Some(mut d) = captures.value_owned().into_sequence().and_then(
|
||||||
|
|s| s.into_iter().next().and_then(|d| d.value_owned().into_dictionary()))
|
||||||
|
{
|
||||||
|
let pid = d.remove(&n_pid).unwrap_or_else(|| n_unknown.clone());
|
||||||
|
let line = d.remove(&n_line).unwrap_or_else(|| n_unknown.clone());
|
||||||
|
let service = d.remove(&n_service).unwrap_or_else(|| n_unknown.clone());
|
||||||
|
let stream = d.remove(&n_stream).unwrap_or_else(|| n_unknown.clone());
|
||||||
|
if d.is_empty() {
|
||||||
|
tracing::info!(?stream, ?service, ?pid, message = ?line);
|
||||||
|
} else {
|
||||||
|
tracing::info!(?stream, ?service, ?pid, data = ?d, message = ?line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.create_cap(t);
|
||||||
|
root_ds.assert(t, language(), &syndicate::schemas::dataspace::Observe {
|
||||||
|
pattern: syndicate_macros::pattern!(<log $>),
|
||||||
|
observer: e,
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
}));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}).await??;
|
}).await??;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,11 @@ use std::sync::Arc;
|
||||||
use syndicate::actor::*;
|
use syndicate::actor::*;
|
||||||
use syndicate::enclose;
|
use syndicate::enclose;
|
||||||
use syndicate::supervise::{Supervisor, SupervisorConfiguration};
|
use syndicate::supervise::{Supervisor, SupervisorConfiguration};
|
||||||
|
use syndicate::value::NestedValue;
|
||||||
|
|
||||||
|
use tokio::io::AsyncRead;
|
||||||
|
use tokio::io::AsyncBufReadExt;
|
||||||
|
use tokio::io::BufReader;
|
||||||
use tokio::process;
|
use tokio::process;
|
||||||
|
|
||||||
use crate::counter;
|
use crate::counter;
|
||||||
|
@ -97,8 +101,8 @@ impl FullProcess {
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.stdin(std::process::Stdio::null());
|
cmd.stdin(std::process::Stdio::null());
|
||||||
cmd.stdout(std::process::Stdio::inherit());
|
cmd.stdout(std::process::Stdio::piped());
|
||||||
cmd.stderr(std::process::Stdio::inherit());
|
cmd.stderr(std::process::Stdio::piped());
|
||||||
cmd.kill_on_drop(true);
|
cmd.kill_on_drop(true);
|
||||||
|
|
||||||
Some(cmd)
|
Some(cmd)
|
||||||
|
@ -131,6 +135,8 @@ impl CommandLine {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DaemonInstance {
|
struct DaemonInstance {
|
||||||
|
log_ds: Arc<Cap>,
|
||||||
|
service: AnyValue,
|
||||||
name: tracing::Span,
|
name: tracing::Span,
|
||||||
cmd: process::Command,
|
cmd: process::Command,
|
||||||
announce_presumed_readiness: bool,
|
announce_presumed_readiness: bool,
|
||||||
|
@ -180,6 +186,50 @@ impl DaemonInstance {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn log<R: 'static + Send + AsyncRead + Unpin>(
|
||||||
|
&self,
|
||||||
|
t: &mut Activation,
|
||||||
|
facet: FacetRef,
|
||||||
|
pid: Option<u32>,
|
||||||
|
r: R,
|
||||||
|
kind: &str
|
||||||
|
) {
|
||||||
|
let log_ds = self.log_ds.clone();
|
||||||
|
let service = self.service.clone();
|
||||||
|
let kind = AnyValue::symbol(kind);
|
||||||
|
let pid = match pid {
|
||||||
|
Some(n) => AnyValue::new(n),
|
||||||
|
None => AnyValue::symbol("unknown"),
|
||||||
|
};
|
||||||
|
t.spawn(syndicate::name!(parent: self.name.clone(), "log"), move |t| {
|
||||||
|
t.linked_task(tracing::Span::current(), async move {
|
||||||
|
let mut r = BufReader::new(r);
|
||||||
|
loop {
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
if r.read_until(b'\n', &mut buf).await? == 0 {
|
||||||
|
return Ok(LinkedTaskTermination::Normal);
|
||||||
|
}
|
||||||
|
let buf = match std::str::from_utf8(&buf) {
|
||||||
|
Ok(s) => AnyValue::new(s),
|
||||||
|
Err(_) => AnyValue::bytestring(buf),
|
||||||
|
};
|
||||||
|
facet.activate(Account::new(tracing::Span::current()),
|
||||||
|
enclose!((pid, service, kind) |t| {
|
||||||
|
log_ds.message(t, &(), &syndicate_macros::template!(
|
||||||
|
"<log {
|
||||||
|
pid: =pid,
|
||||||
|
service: =service,
|
||||||
|
stream: =kind,
|
||||||
|
line: =buf,
|
||||||
|
}>"));
|
||||||
|
Ok(())
|
||||||
|
}))?;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn start(mut self, t: &mut Activation) -> ActorResult {
|
fn start(mut self, t: &mut Activation) -> ActorResult {
|
||||||
t.facet(|t| {
|
t.facet(|t| {
|
||||||
tracing::trace!(cmd = ?self.cmd, "starting");
|
tracing::trace!(cmd = ?self.cmd, "starting");
|
||||||
|
@ -190,14 +240,21 @@ impl DaemonInstance {
|
||||||
return self.handle_exit(t, Some(format!("{}", e)));
|
return self.handle_exit(t, Some(format!("{}", e)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
tracing::info!(pid = ?child.id(), cmd = ?self.cmd, "started");
|
let pid = child.id();
|
||||||
|
tracing::info!(?pid, cmd = ?self.cmd, "started");
|
||||||
|
|
||||||
|
let facet = t.facet.clone();
|
||||||
|
|
||||||
|
if let Some(r) = child.stdout.take() { self.log(t, facet.clone(), pid, r, "stdout"); }
|
||||||
|
if let Some(r) = child.stderr.take() { self.log(t, facet.clone(), pid, r, "stderr"); }
|
||||||
|
|
||||||
if self.announce_presumed_readiness {
|
if self.announce_presumed_readiness {
|
||||||
counter::adjust(t, &self.unready_configs, -1);
|
counter::adjust(t, &self.unready_configs, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let facet = t.facet.clone();
|
t.linked_task(
|
||||||
t.linked_task(syndicate::name!(parent: self.name.clone(), "wait"), async move {
|
syndicate::name!(parent: self.name.clone(), "wait"),
|
||||||
|
enclose!((facet) async move {
|
||||||
tracing::trace!("waiting for process exit");
|
tracing::trace!("waiting for process exit");
|
||||||
let status = child.wait().await?;
|
let status = child.wait().await?;
|
||||||
tracing::info!(?status);
|
tracing::info!(?status);
|
||||||
|
@ -206,7 +263,7 @@ impl DaemonInstance {
|
||||||
self.handle_exit(t, m)
|
self.handle_exit(t, m)
|
||||||
})?;
|
})?;
|
||||||
Ok(LinkedTaskTermination::Normal)
|
Ok(LinkedTaskTermination::Normal)
|
||||||
});
|
}));
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -216,7 +273,7 @@ impl DaemonInstance {
|
||||||
fn run(
|
fn run(
|
||||||
t: &mut Activation,
|
t: &mut Activation,
|
||||||
config_ds: Arc<Cap>,
|
config_ds: Arc<Cap>,
|
||||||
_root_ds: Arc<Cap>,
|
root_ds: Arc<Cap>,
|
||||||
service: DaemonService,
|
service: DaemonService,
|
||||||
) -> ActorResult {
|
) -> ActorResult {
|
||||||
let spec = language().unparse(&service);
|
let spec = language().unparse(&service);
|
||||||
|
@ -247,7 +304,7 @@ fn run(
|
||||||
}))?;
|
}))?;
|
||||||
|
|
||||||
enclose!((unready_configs, completed_processes) during!(t, config_ds, language(), <daemon #(service.id) $config>, {
|
enclose!((unready_configs, completed_processes) during!(t, config_ds, language(), <daemon #(service.id) $config>, {
|
||||||
enclose!((unready_configs, completed_processes) |t: &mut Activation| {
|
enclose!((spec, root_ds, unready_configs, completed_processes) |t: &mut Activation| {
|
||||||
tracing::debug!(?config, "new config");
|
tracing::debug!(?config, "new config");
|
||||||
counter::adjust(t, &unready_configs, 1);
|
counter::adjust(t, &unready_configs, 1);
|
||||||
counter::adjust(t, &total_configs, 1);
|
counter::adjust(t, &total_configs, 1);
|
||||||
|
@ -278,6 +335,8 @@ fn run(
|
||||||
};
|
};
|
||||||
|
|
||||||
let daemon_instance = DaemonInstance {
|
let daemon_instance = DaemonInstance {
|
||||||
|
log_ds: root_ds,
|
||||||
|
service: spec,
|
||||||
name: tracing::Span::current(),
|
name: tracing::Span::current(),
|
||||||
cmd,
|
cmd,
|
||||||
announce_presumed_readiness,
|
announce_presumed_readiness,
|
||||||
|
|
Loading…
Reference in New Issue