@@ -5,6 +5,8 @@ use tokio::sync::Mutex;
5
5
use tower:: Service ;
6
6
use tracing:: { error, trace} ;
7
7
8
+ use crate :: { Error , ExtensionError } ;
9
+
8
10
/// Payload received from the Lambda Logs API
9
11
/// See: https://docs.aws.amazon.com/lambda/latest/dg/runtimes-logs-api.html#runtimes-logs-api-msg
10
12
#[ derive( Clone , Debug , Deserialize , PartialEq ) ]
@@ -110,7 +112,7 @@ pub struct LogPlatformReportMetrics {
110
112
111
113
/// Log buffering configuration.
112
114
/// Allows Lambda to buffer logs before deliverying them to a subscriber.
113
- #[ derive( Debug , Serialize ) ]
115
+ #[ derive( Debug , Serialize , Copy , Clone ) ]
114
116
#[ serde( rename_all = "camelCase" ) ]
115
117
pub struct LogBuffering {
116
118
/// The maximum time (in milliseconds) to buffer a batch.
@@ -124,6 +126,40 @@ pub struct LogBuffering {
124
126
pub max_items : usize ,
125
127
}
126
128
129
+ static LOG_BUFFERING_MIN_TIMEOUT_MS : usize = 25 ;
130
+ static LOG_BUFFERING_MAX_TIMEOUT_MS : usize = 30_000 ;
131
+ static LOG_BUFFERING_MIN_BYTES : usize = 262_144 ;
132
+ static LOG_BUFFERING_MAX_BYTES : usize = 1_048_576 ;
133
+ static LOG_BUFFERING_MIN_ITEMS : usize = 1_000 ;
134
+ static LOG_BUFFERING_MAX_ITEMS : usize = 10_000 ;
135
+
136
+ impl LogBuffering {
137
+ fn validate ( & self ) -> Result < ( ) , Error > {
138
+ if self . timeout_ms < LOG_BUFFERING_MIN_TIMEOUT_MS || self . timeout_ms > LOG_BUFFERING_MAX_TIMEOUT_MS {
139
+ let error = format ! (
140
+ "LogBuffering validation error: Invalid timeout_ms: {}. Allowed values: Minumun: {}. Maximum: {}" ,
141
+ self . timeout_ms, LOG_BUFFERING_MIN_TIMEOUT_MS , LOG_BUFFERING_MAX_TIMEOUT_MS
142
+ ) ;
143
+ return Err ( ExtensionError :: boxed ( error) ) ;
144
+ }
145
+ if self . max_bytes < LOG_BUFFERING_MIN_BYTES || self . max_bytes > LOG_BUFFERING_MAX_BYTES {
146
+ let error = format ! (
147
+ "LogBuffering validation error: Invalid max_bytes: {}. Allowed values: Minumun: {}. Maximum: {}" ,
148
+ self . max_bytes, LOG_BUFFERING_MIN_BYTES , LOG_BUFFERING_MAX_BYTES
149
+ ) ;
150
+ return Err ( ExtensionError :: boxed ( error) ) ;
151
+ }
152
+ if self . max_items < LOG_BUFFERING_MIN_ITEMS || self . max_items > LOG_BUFFERING_MAX_ITEMS {
153
+ let error = format ! (
154
+ "LogBuffering validation error: Invalid max_items: {}. Allowed values: Minumun: {}. Maximum: {}" ,
155
+ self . max_items, LOG_BUFFERING_MIN_ITEMS , LOG_BUFFERING_MAX_ITEMS
156
+ ) ;
157
+ return Err ( ExtensionError :: boxed ( error) ) ;
158
+ }
159
+ Ok ( ( ) )
160
+ }
161
+ }
162
+
127
163
impl Default for LogBuffering {
128
164
fn default ( ) -> Self {
129
165
LogBuffering {
@@ -134,6 +170,18 @@ impl Default for LogBuffering {
134
170
}
135
171
}
136
172
173
+ /// Validate the `LogBuffering` configuration (if present)
174
+ ///
175
+ /// # Errors
176
+ ///
177
+ /// This function will return an error if `LogBuffering` is present and configured incorrectly
178
+ pub ( crate ) fn validate_buffering_configuration ( log_buffering : Option < LogBuffering > ) -> Result < ( ) , Error > {
179
+ match log_buffering {
180
+ Some ( log_buffering) => log_buffering. validate ( ) ,
181
+ None => Ok ( ( ) ) ,
182
+ }
183
+ }
184
+
137
185
/// Wrapper function that sends logs to the subscriber Service
138
186
///
139
187
/// This takes an `hyper::Request` and transforms it into `Vec<LambdaLog>` for the
@@ -303,4 +351,67 @@ mod tests {
303
351
} ,
304
352
) ,
305
353
}
354
+
355
+ macro_rules! log_buffering_configuration_tests {
356
+ ( $( $name: ident: $value: expr, ) * ) => {
357
+ $(
358
+ #[ test]
359
+ fn $name( ) {
360
+ let ( input, expected) = $value;
361
+ let result = validate_buffering_configuration( input) ;
362
+
363
+ if let Some ( expected) = expected {
364
+ assert!( result. is_err( ) ) ;
365
+ assert_eq!( result. unwrap_err( ) . to_string( ) , expected. to_string( ) ) ;
366
+ } else {
367
+ assert!( result. is_ok( ) ) ;
368
+ }
369
+
370
+ }
371
+ ) *
372
+ }
373
+ }
374
+
375
+ log_buffering_configuration_tests ! {
376
+ log_buffer_configuration_none_success: (
377
+ None ,
378
+ None :: <ExtensionError >
379
+ ) ,
380
+ log_buffer_configuration_default_success: (
381
+ Some ( LogBuffering :: default ( ) ) ,
382
+ None :: <ExtensionError >
383
+ ) ,
384
+ log_buffer_configuration_min_success: (
385
+ Some ( LogBuffering { timeout_ms: LOG_BUFFERING_MIN_TIMEOUT_MS , max_bytes: LOG_BUFFERING_MIN_BYTES , max_items: LOG_BUFFERING_MIN_ITEMS } ) ,
386
+ None :: <ExtensionError >
387
+ ) ,
388
+ log_buffer_configuration_max_success: (
389
+ Some ( LogBuffering { timeout_ms: LOG_BUFFERING_MAX_TIMEOUT_MS , max_bytes: LOG_BUFFERING_MAX_BYTES , max_items: LOG_BUFFERING_MAX_ITEMS } ) ,
390
+ None :: <ExtensionError >
391
+ ) ,
392
+ min_timeout_ms_error: (
393
+ Some ( LogBuffering { timeout_ms: LOG_BUFFERING_MIN_TIMEOUT_MS -1 , max_bytes: LOG_BUFFERING_MAX_BYTES , max_items: LOG_BUFFERING_MAX_ITEMS } ) ,
394
+ Some ( ExtensionError :: boxed( "LogBuffering validation error: Invalid timeout_ms: 24. Allowed values: Minumun: 25. Maximum: 30000" ) )
395
+ ) ,
396
+ max_timeout_ms_error: (
397
+ Some ( LogBuffering { timeout_ms: LOG_BUFFERING_MAX_TIMEOUT_MS +1 , max_bytes: LOG_BUFFERING_MAX_BYTES , max_items: LOG_BUFFERING_MAX_ITEMS } ) ,
398
+ Some ( ExtensionError :: boxed( "LogBuffering validation error: Invalid timeout_ms: 30001. Allowed values: Minumun: 25. Maximum: 30000" ) )
399
+ ) ,
400
+ min_max_bytes_error: (
401
+ Some ( LogBuffering { timeout_ms: LOG_BUFFERING_MAX_TIMEOUT_MS , max_bytes: LOG_BUFFERING_MIN_BYTES -1 , max_items: LOG_BUFFERING_MAX_ITEMS } ) ,
402
+ Some ( ExtensionError :: boxed( "LogBuffering validation error: Invalid max_bytes: 262143. Allowed values: Minumun: 262144. Maximum: 1048576" ) )
403
+ ) ,
404
+ max_max_bytes_error: (
405
+ Some ( LogBuffering { timeout_ms: LOG_BUFFERING_MAX_TIMEOUT_MS , max_bytes: LOG_BUFFERING_MAX_BYTES +1 , max_items: LOG_BUFFERING_MAX_ITEMS } ) ,
406
+ Some ( ExtensionError :: boxed( "LogBuffering validation error: Invalid max_bytes: 1048577. Allowed values: Minumun: 262144. Maximum: 1048576" ) )
407
+ ) ,
408
+ min_max_items_error: (
409
+ Some ( LogBuffering { timeout_ms: LOG_BUFFERING_MAX_TIMEOUT_MS , max_bytes: LOG_BUFFERING_MAX_BYTES , max_items: LOG_BUFFERING_MIN_ITEMS -1 } ) ,
410
+ Some ( ExtensionError :: boxed( "LogBuffering validation error: Invalid max_items: 999. Allowed values: Minumun: 1000. Maximum: 10000" ) )
411
+ ) ,
412
+ max_max_items_error: (
413
+ Some ( LogBuffering { timeout_ms: LOG_BUFFERING_MAX_TIMEOUT_MS , max_bytes: LOG_BUFFERING_MAX_BYTES , max_items: LOG_BUFFERING_MAX_ITEMS +1 } ) ,
414
+ Some ( ExtensionError :: boxed( "LogBuffering validation error: Invalid max_items: 10001. Allowed values: Minumun: 1000. Maximum: 10000" ) )
415
+ ) ,
416
+ }
306
417
}
0 commit comments