use std::io;
use async_trait::async_trait;
use pingora::{
server::{ListenFds, ShutdownWatch},
services::Service,
};
use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};
use tracing_subscriber::fmt::MakeWriter;
#[derive(Debug, Clone)]
pub struct StdoutLogger(UnboundedSender<Vec<u8>>);
impl io::Write for StdoutLogger {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let buf_copy = buf.to_owned();
if let Ok(()) = self.0.send(buf_copy) {
return Ok(buf.len());
}
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
#[derive(Debug)]
pub struct ProxyLogger {
stdout: StdoutLogger,
}
impl ProxyLogger {
pub fn new(sender: UnboundedSender<Vec<u8>>) -> Self {
ProxyLogger {
stdout: StdoutLogger(sender.clone()),
}
}
}
impl<'a> MakeWriter<'a> for ProxyLogger {
type Writer = StdoutLogger;
fn make_writer(&'a self) -> Self::Writer {
self.stdout.clone()
}
}
pub struct ProxyLoggerReceiver(pub UnboundedReceiver<Vec<u8>>);
#[async_trait]
impl Service for ProxyLoggerReceiver {
async fn start_service(&mut self, _fds: Option<ListenFds>, _shutdown: ShutdownWatch) {
loop {
if let Some(buf) = self.0.recv().await {
let buf = std::str::from_utf8(&buf).unwrap();
print!("{}", buf);
}
}
}
fn name(&self) -> &str {
"ProxyLogger"
}
fn threads(&self) -> Option<usize> {
Some(1)
}
}