diff --git a/README.md b/README.md index a00ee3a..daffc78 100644 --- a/README.md +++ b/README.md @@ -153,6 +153,16 @@ To use the loki driver, you'll need to set up: - `--loki-url` (or the env var `VERCEL_LOG_DRAIN_LOKI_URL`) - (optional, if you have basic auth) `--loki-basic-auth-user` and `--loki-basic-auth-pass` (or the corresponding env vars `VERCEL_LOG_DRAIN_LOKI_USER` and `VERCEL_LOG_DRAIN_LOKI_PASS`) +### Standard Out + +You can enable the `stdout` driver by simply adding `--enable-stdout` which will print the each `Message` payload as json to stdout. Application logging will be printed to `stderr`. + +> [!IMPORTANT] +> If you have a previous deployment and enable the `stdout` driver it may effect your logging setup. +> The default (without stdout driver) application logs from the `vercel-log-drain` go to stdout. +> With this driver enabled app will now go to `stderr` and the Vercel messages are printed to `stdout`. + + ## Configuration | CLI Flag | Environment Variable | Default Value | Description | diff --git a/src/drivers/mod.rs b/src/drivers/mod.rs index 655b7dd..7e17624 100644 --- a/src/drivers/mod.rs +++ b/src/drivers/mod.rs @@ -1,8 +1,12 @@ +mod stdout; + #[cfg(feature = "cloudwatch")] mod cloudwatch; #[cfg(feature = "loki")] mod loki; +pub use stdout::StdOutDriver; + #[cfg(feature = "cloudwatch")] pub use cloudwatch::CloudWatchDriver; #[cfg(feature = "loki")] diff --git a/src/drivers/stdout.rs b/src/drivers/stdout.rs new file mode 100644 index 0000000..cfc07d7 --- /dev/null +++ b/src/drivers/stdout.rs @@ -0,0 +1,25 @@ +use crate::types::{LogDriver, Message}; +use anyhow::Result; +use async_trait::async_trait; +use tracing::debug; + +pub struct StdOutDriver; + +impl StdOutDriver { + pub fn new() -> Self { + Self {} + } +} +#[async_trait] +impl LogDriver for StdOutDriver { + async fn init(&mut self) -> Result<()> { + debug!("init stdout driver"); + Ok(()) + } + + async fn send_log(&mut self, message: &Message) -> Result<()> { + let log_line = serde_json::to_string(message)?; + println!("{}", log_line); + Ok(()) + } +} diff --git a/src/main.rs b/src/main.rs index b960a7d..0e2e443 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ use crate::types::LogDriver; use axum::routing::get; use axum_prometheus::PrometheusMetricLayerBuilder; use clap::Parser; +use std::io; use tokio::signal::{unix, unix::SignalKind}; use tokio::sync::mpsc; use tracing::{debug, info, Level}; @@ -38,6 +39,9 @@ struct Args { #[arg(long, env = "VERCEL_LOG_DRAIN_METRICS_PREFIX", default_value = "drain")] metrics_prefix: String, + #[arg(long, env = "VERCEL_LOG_DRAIN_ENABLE_STDOUT")] + enable_stdout: bool, + #[cfg(feature = "cloudwatch")] #[arg(long, env = "VERCEL_LOG_DRAIN_ENABLE_CLOUDWATCH")] enable_cloudwatch: bool, @@ -59,15 +63,27 @@ struct Args { #[tokio::main] async fn main() -> anyhow::Result<()> { let args = Args::parse(); - tracing_subscriber::fmt() - .json() - .with_max_level(args.log) - .init(); + if args.enable_stdout { + tracing_subscriber::fmt() + .json() + .with_max_level(args.log) + .with_writer(io::stderr) + .init(); + } else { + tracing_subscriber::fmt() + .json() + .with_max_level(args.log) + .init(); + } let (tx, rx) = mpsc::unbounded_channel::(); let mut drivers: Vec> = Vec::new(); + if args.enable_stdout { + drivers.push(Box::new(StdOutDriver::new())); + } + #[cfg(feature = "cloudwatch")] if args.enable_cloudwatch { let config = aws_config::load_defaults(aws_config::BehaviorVersion::v2024_03_28()).await;