Skip to main content

vantage_aws/models/
log_stream.rs

1use serde::{Deserialize, Serialize};
2use vantage_table::table::Table;
3
4use crate::{AwsAccount, eq};
5
6use super::log_event::{LogEvent, log_events_table};
7
8/// One CloudWatch Logs stream from `DescribeLogStreams`. Field names
9/// match the wire shape.
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct LogStream {
12    #[serde(rename = "logStreamName")]
13    pub log_stream_name: String,
14    #[serde(default)]
15    pub arn: String,
16    #[serde(rename = "creationTime", default)]
17    pub creation_time: i64,
18    #[serde(rename = "firstEventTimestamp", default)]
19    pub first_event_timestamp: i64,
20    #[serde(rename = "lastEventTimestamp", default)]
21    pub last_event_timestamp: i64,
22    #[serde(rename = "lastIngestionTime", default)]
23    pub last_ingestion_time: i64,
24    #[serde(rename = "storedBytes", default)]
25    pub stored_bytes: i64,
26    #[serde(rename = "uploadSequenceToken", default)]
27    pub upload_sequence_token: String,
28}
29
30/// `DescribeLogStreams` table. AWS requires `logGroupName` before it
31/// will list anything, so add `eq("logGroupName", "...")` first.
32///
33/// ```no_run
34/// # use vantage_aws::{AwsAccount, eq};
35/// # use vantage_aws::models::log_streams_table;
36/// # async fn run() -> vantage_core::Result<()> {
37/// # let aws = AwsAccount::from_default()?;
38/// let mut streams = log_streams_table(aws);
39/// streams.add_condition(eq("logGroupName", "/aws/lambda/foo"));
40/// # Ok(()) }
41/// ```
42pub fn log_streams_table(aws: AwsAccount) -> Table<AwsAccount, LogStream> {
43    Table::new("logStreams:logs/Logs_20140328.DescribeLogStreams", aws)
44        .with_id_column("logStreamName")
45        .with_column_of::<String>("arn")
46        .with_column_of::<i64>("creationTime")
47        .with_column_of::<i64>("firstEventTimestamp")
48        .with_column_of::<i64>("lastEventTimestamp")
49        .with_column_of::<i64>("lastIngestionTime")
50        .with_column_of::<i64>("storedBytes")
51        .with_column_of::<String>("uploadSequenceToken")
52}
53
54impl LogStream {
55    /// The owning log group's name, parsed out of [`Self::arn`].
56    /// Stream ARNs have the shape
57    /// `arn:aws:logs:<region>:<account>:log-group:<group>:log-stream:<stream>`.
58    pub fn log_group_name(&self) -> Option<&str> {
59        let after = self.arn.split(":log-group:").nth(1)?;
60        after.split(":log-stream:").next()
61    }
62
63    /// Events table pre-filtered to *this* stream. The log group is
64    /// pulled from this stream's ARN; if the ARN is empty, pass it
65    /// in via [`Self::ref_events_in`] instead.
66    pub fn ref_events(&self, aws: AwsAccount) -> Option<Table<AwsAccount, LogEvent>> {
67        let group = self.log_group_name()?;
68        Some(self.ref_events_in(aws, group))
69    }
70
71    /// Events table pre-filtered to *this* stream within the given
72    /// log group. Use when the stream ARN isn't populated (e.g.
73    /// streams synthesised by hand).
74    pub fn ref_events_in(
75        &self,
76        aws: AwsAccount,
77        log_group_name: &str,
78    ) -> Table<AwsAccount, LogEvent> {
79        let mut t = log_events_table(aws);
80        t.add_condition(eq("logGroupName", log_group_name));
81        t.add_condition(eq("logStreamNamePrefix", self.log_stream_name.clone()));
82        t
83    }
84}