timber_rust/service/aws/
cout.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 Dante Doménech Martinez dante19031999@gmail.com
3
4#![cfg(feature = "awscout")]
5#![cfg_attr(docsrs, doc(cfg(feature = "awscout")))]
6
7use crate::Message;
8use crate::service::write::MessageFormatter;
9use crate::service::{CoutWrite, ServiceError};
10use serde_json::json;
11use std::io::Write;
12
13/// A [`MessageFormatter`] that serializes log messages into a single-line JSON format.
14///
15/// This formatter is specifically designed for AWS CloudWatch Logs when running in
16/// environments like AWS Lambda, ECS, or Fargate, where `stdout` is automatically
17/// captured and ingested as structured logs.
18///
19/// ### Output Format
20/// ```json
21/// {"level":"INFO","msg":"Your log message here"}
22/// ```
23#[derive(Default)]
24pub struct CloudWatchCoutMessageFormatter {}
25
26impl CloudWatchCoutMessageFormatter {
27    /// Creates a new instance of [`CloudWatchCoutMessageFormatter`].
28    pub fn new() -> Self {
29        Self::default()
30    }
31}
32
33impl MessageFormatter for CloudWatchCoutMessageFormatter {
34    /// Formats the [`Message`] as a JSON string and writes it to an IO stream.
35    ///
36    /// # Errors
37    /// Returns [`ServiceError::Io`] if writing to the stream fails.
38    fn format_io(
39        &mut self,
40        message: &Message,
41        write: &mut (dyn Write + Send + Sync),
42    ) -> Result<(), ServiceError> {
43        let json_payload = json!({
44            "level": message.level().to_string(),
45            "msg": message.content().to_string(),
46        })
47        .to_string();
48
49        // CloudWatch usually expects a newline per log entry
50        writeln!(write, "{}", json_payload)?;
51        Ok(())
52    }
53
54    /// Formats the [`Message`] as a JSON string and writes it to a core fmt formatter.
55    fn format_fmt(
56        &mut self,
57        message: &Message,
58        write: &mut (dyn std::fmt::Write + Send + Sync),
59    ) -> Result<(), ServiceError> {
60        let json_payload = json!({
61            "level": message.level().to_string(),
62            "msg": message.content().to_string(),
63        })
64        .to_string();
65
66        writeln!(write, "{}", json_payload)?;
67        Ok(())
68    }
69}
70
71/// A specialized [`CoutWrite`] service that outputs JSON logs for AWS CloudWatch.
72///
73/// This service is specifically designed for AWS CloudWatch Logs when running in
74/// environments like AWS Lambda, ECS, or Fargate, where `stdout` is automatically
75/// captured and ingested as structured logs.
76pub type CloudWatchCout = CoutWrite<CloudWatchCoutMessageFormatter>;