vrl/stdlib/
parse_aws_alb_log.rs

1use crate::compiler::prelude::*;
2use nom::{
3    IResult, Parser,
4    branch::alt,
5    bytes::complete::{tag, take_while1},
6    character::complete::char,
7    combinator::map_res,
8    sequence::{delimited, preceded},
9};
10use std::collections::BTreeMap;
11use std::sync::LazyLock;
12
13static DEFAULT_STRICT_MODE: LazyLock<Value> = LazyLock::new(|| Value::Boolean(true));
14
15static PARAMETERS: LazyLock<Vec<Parameter>> = LazyLock::new(|| {
16    vec![
17        Parameter::required(
18            "value",
19            kind::BYTES,
20            "Access log of the Application Load Balancer.",
21        ),
22        Parameter::optional("strict_mode", kind::BOOLEAN, "When set to `false`, the parser ignores any newly added or trailing fields in AWS ALB logs instead of failing. Defaults to `true` to preserve strict parsing behavior.")
23            .default(&DEFAULT_STRICT_MODE),
24    ]
25});
26
27fn parse_aws_alb_log(bytes: Value, strict_mode: Value) -> Resolved {
28    let bytes = bytes.try_bytes()?;
29    let strict_mode = strict_mode.try_boolean()?;
30    parse_log(&String::from_utf8_lossy(&bytes), strict_mode)
31}
32
33#[derive(Clone, Copy, Debug)]
34pub struct ParseAwsAlbLog;
35
36impl Function for ParseAwsAlbLog {
37    fn identifier(&self) -> &'static str {
38        "parse_aws_alb_log"
39    }
40
41    fn usage(&self) -> &'static str {
42        "Parses `value` in the [Elastic Load Balancer Access format](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html#access-log-entry-examples)."
43    }
44
45    fn category(&self) -> &'static str {
46        Category::Parse.as_ref()
47    }
48
49    fn internal_failure_reasons(&self) -> &'static [&'static str] {
50        &["`value` is not a properly formatted AWS ALB log."]
51    }
52
53    fn return_kind(&self) -> u16 {
54        kind::OBJECT
55    }
56
57    fn examples(&self) -> &'static [Example] {
58        &[
59            example! {
60                title: "Parse AWS ALB log",
61                source: indoc! {r#"
62                    parse_aws_alb_log!(
63                        "http 2018-11-30T22:23:00.186641Z app/my-loadbalancer/50dc6c495c0c9188 192.168.131.39:2817 - 0.000 0.001 0.000 200 200 34 366 \"GET http://www.example.com:80/ HTTP/1.1\" \"curl/7.46.0\" - - arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067 \"Root=1-58337364-23a8c76965a2ef7629b185e3\" \"-\" \"-\" 0 2018-11-30T22:22:48.364000Z \"forward\" \"-\" \"-\" \"-\" \"-\" \"-\" \"-\""
64                    )
65                "#},
66                result: Ok(indoc! {r#"
67                    {
68                      "actions_executed": "forward",
69                      "chosen_cert_arn": null,
70                      "classification": null,
71                      "classification_reason": null,
72                      "client_host": "192.168.131.39:2817",
73                      "domain_name": null,
74                      "elb": "app/my-loadbalancer/50dc6c495c0c9188",
75                      "elb_status_code": "200",
76                      "error_reason": null,
77                      "matched_rule_priority": "0",
78                      "received_bytes": 34,
79                      "redirect_url": null,
80                      "request_creation_time": "2018-11-30T22:22:48.364000Z",
81                      "request_method": "GET",
82                      "request_processing_time": 0.0,
83                      "request_protocol": "HTTP/1.1",
84                      "request_url": "http://www.example.com:80/",
85                      "response_processing_time": 0.0,
86                      "sent_bytes": 366,
87                      "ssl_cipher": null,
88                      "ssl_protocol": null,
89                      "target_group_arn": "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067",
90                      "target_host": null,
91                      "target_port_list": [],
92                      "target_processing_time": 0.001,
93                      "target_status_code": "200",
94                      "target_status_code_list": [],
95                      "timestamp": "2018-11-30T22:23:00.186641Z",
96                      "trace_id": "Root=1-58337364-23a8c76965a2ef7629b185e3",
97                      "traceability_id": null,
98                      "type": "http",
99                      "user_agent": "curl/7.46.0"
100                    }
101                "#}),
102            },
103            example! {
104                title: "Parse AWS ALB log with trailing fields (non-strict mode)",
105                source: indoc! {r#"
106                    parse_aws_alb_log!(
107                        "http 2018-11-30T22:23:00.186641Z app/my-loadbalancer/50dc6c495c0c9188 192.168.131.39:2817 - 0.000 0.001 0.000 200 200 34 366 \"GET http://www.example.com:80/ HTTP/1.1\" \"curl/7.46.0\" - - arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067 \"Root=1-58337364-23a8c76965a2ef7629b185e3\" \"-\" \"-\" 0 2018-11-30T22:22:48.364000Z \"forward\" \"-\" \"-\" \"-\" \"-\" \"-\" \"-\" TID_12345 \"-\" \"-\" \"-\"",
108                        strict_mode: false
109                    )
110                "#},
111                result: Ok(indoc! {r#"
112                    {
113                      "actions_executed": "forward",
114                      "chosen_cert_arn": null,
115                      "classification": null,
116                      "classification_reason": null,
117                      "client_host": "192.168.131.39:2817",
118                      "domain_name": null,
119                      "elb": "app/my-loadbalancer/50dc6c495c0c9188",
120                      "elb_status_code": "200",
121                      "error_reason": null,
122                      "matched_rule_priority": "0",
123                      "received_bytes": 34,
124                      "redirect_url": null,
125                      "request_creation_time": "2018-11-30T22:22:48.364000Z",
126                      "request_method": "GET",
127                      "request_processing_time": 0.0,
128                      "request_protocol": "HTTP/1.1",
129                      "request_url": "http://www.example.com:80/",
130                      "response_processing_time": 0.0,
131                      "sent_bytes": 366,
132                      "ssl_cipher": null,
133                      "ssl_protocol": null,
134                      "target_group_arn": "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067",
135                      "target_host": null,
136                      "target_port_list": [],
137                      "target_processing_time": 0.001,
138                      "target_status_code": "200",
139                      "target_status_code_list": [],
140                      "timestamp": "2018-11-30T22:23:00.186641Z",
141                      "trace_id": "Root=1-58337364-23a8c76965a2ef7629b185e3",
142                      "traceability_id": "TID_12345",
143                      "type": "http",
144                      "user_agent": "curl/7.46.0"
145                    }
146                "#}),
147            },
148        ]
149    }
150
151    fn compile(
152        &self,
153        _state: &state::TypeState,
154        _ctx: &mut FunctionCompileContext,
155        arguments: ArgumentList,
156    ) -> Compiled {
157        let value = arguments.required("value");
158        let strict_mode = arguments.optional("strict_mode");
159
160        Ok(ParseAwsAlbLogFn::new(value, strict_mode).as_expr())
161    }
162
163    fn parameters(&self) -> &'static [Parameter] {
164        PARAMETERS.as_slice()
165    }
166}
167
168#[derive(Debug, Clone)]
169struct ParseAwsAlbLogFn {
170    value: Box<dyn Expression>,
171    strict_mode: Option<Box<dyn Expression>>,
172}
173
174impl ParseAwsAlbLogFn {
175    fn new(value: Box<dyn Expression>, strict_mode: Option<Box<dyn Expression>>) -> Self {
176        Self { value, strict_mode }
177    }
178}
179
180impl FunctionExpression for ParseAwsAlbLogFn {
181    fn resolve(&self, ctx: &mut Context) -> Resolved {
182        let bytes = self.value.resolve(ctx)?;
183        let strict_mode = self
184            .strict_mode
185            .map_resolve_with_default(ctx, || DEFAULT_STRICT_MODE.clone())?;
186        parse_aws_alb_log(bytes, strict_mode)
187    }
188
189    fn type_def(&self, _: &state::TypeState) -> TypeDef {
190        TypeDef::object(inner_kind()).fallible(/* log parsing error */)
191    }
192}
193
194fn inner_kind() -> BTreeMap<Field, Kind> {
195    BTreeMap::from([
196        (
197            Field::from("actions_executed"),
198            Kind::bytes() | Kind::null(),
199        ),
200        (Field::from("chosen_cert_arn"), Kind::bytes() | Kind::null()),
201        (
202            Field::from("classification_reason"),
203            Kind::bytes() | Kind::null(),
204        ),
205        (Field::from("classification"), Kind::bytes() | Kind::null()),
206        (Field::from("client_host"), Kind::bytes()),
207        (Field::from("domain_name"), Kind::bytes() | Kind::null()),
208        (Field::from("elb_status_code"), Kind::bytes()),
209        (Field::from("elb"), Kind::bytes()),
210        (Field::from("error_reason"), Kind::bytes() | Kind::null()),
211        (
212            Field::from("matched_rule_priority"),
213            Kind::bytes() | Kind::null(),
214        ),
215        (Field::from("received_bytes"), Kind::integer()),
216        (Field::from("redirect_url"), Kind::bytes() | Kind::null()),
217        (Field::from("request_creation_time"), Kind::bytes()),
218        (Field::from("request_method"), Kind::bytes()),
219        (Field::from("request_processing_time"), Kind::float()),
220        (Field::from("request_protocol"), Kind::bytes()),
221        (Field::from("request_url"), Kind::bytes()),
222        (Field::from("response_processing_time"), Kind::float()),
223        (Field::from("sent_bytes"), Kind::integer()),
224        (Field::from("ssl_cipher"), Kind::bytes() | Kind::null()),
225        (Field::from("ssl_protocol"), Kind::bytes() | Kind::null()),
226        (Field::from("target_group_arn"), Kind::bytes()),
227        (Field::from("target_host"), Kind::bytes() | Kind::null()),
228        (
229            Field::from("target_port_list"),
230            Kind::bytes() | Kind::null(),
231        ),
232        (Field::from("target_processing_time"), Kind::float()),
233        (
234            Field::from("target_status_code_list"),
235            Kind::bytes() | Kind::null(),
236        ),
237        (
238            Field::from("target_status_code"),
239            Kind::bytes() | Kind::null(),
240        ),
241        (Field::from("timestamp"), Kind::bytes()),
242        (Field::from("trace_id"), Kind::bytes()),
243        (Field::from("type"), Kind::bytes()),
244        (Field::from("user_agent"), Kind::bytes()),
245        (Field::from("traceability_id"), Kind::bytes() | Kind::null()),
246    ])
247}
248
249#[allow(clippy::too_many_lines)]
250fn parse_log(mut input: &str, strict_mode: bool) -> ExpressionResult<Value> {
251    let mut log = BTreeMap::<KeyString, Value>::new();
252
253    macro_rules! get_value {
254        ($name:expr_2021, $parser:expr_2021, $err:ty) => {{
255            let result: IResult<_, _, $err> = $parser.parse(input);
256            match result {
257                Ok((rest, value)) => {
258                    input = rest;
259                    value
260                }
261                Err(error) => {
262                    return Err(format!("failed to get field `{}`: {}", $name, error).into());
263                }
264            }
265        }};
266        ($name:expr_2021, $parser:expr_2021) => {
267            get_value!($name, $parser, (&str, nom::error::ErrorKind))
268        };
269    }
270    macro_rules! field_raw {
271        ($name:expr_2021, $parser:expr_2021, $err:ty) => {
272            log.insert(
273                $name.into(),
274                match get_value!($name, $parser, $err).into() {
275                    Value::Bytes(bytes) if bytes == "-" => Value::Null,
276                    value => value,
277                },
278            )
279        };
280        ($name:expr_2021, $parser:expr_2021) => {
281            field_raw!($name, $parser, (&str, nom::error::ErrorKind))
282        };
283    }
284    macro_rules! field {
285        ($name:expr_2021, $($pattern:pat_param)|+) => {
286            field_raw!($name, preceded(char(' '), take_while1(|c| matches!(c, $($pattern)|+))))
287        };
288    }
289    macro_rules! field_parse {
290        ($name:expr_2021, $($pattern:pat_param)|+, $type:ty) => {
291            field_raw!($name, map_res(preceded(char(' '), take_while1(|c| matches!(c, $($pattern)|+))), |s: &str| s.parse::<$type>()))
292        };
293    }
294    macro_rules! field_tid {
295        ($name:expr_2021) => {
296            log.insert(
297                $name.into(),
298                match get_value!($name, take_tid_or_nothing) {
299                    Some(value) => Value::Bytes(value.to_owned().into()),
300                    None => Value::Null,
301                },
302            )
303        };
304    }
305
306    field_raw!("type", take_while1(|c| matches!(c, 'a'..='z' | '0'..='9')));
307    field!("timestamp", '0'..='9' | '.' | '-' | ':' | 'T' | 'Z');
308    field_raw!("elb", take_anything);
309    field!("client_host", '0'..='9' | 'a'..='f' | '.' | ':' | '-');
310    field!("target_host", '0'..='9' | 'a'..='f' | '.' | ':' | '-');
311    field_parse!(
312        "request_processing_time",
313        '0'..='9' | '.' | '-',
314        NotNan<f64>
315    );
316    field_parse!("target_processing_time", '0'..='9' | '.' | '-', NotNan<f64>);
317    field_parse!(
318        "response_processing_time",
319        '0'..='9' | '.' | '-',
320        NotNan<f64>
321    );
322    field!("elb_status_code", '0'..='9' | '-');
323    field!("target_status_code", '0'..='9' | '-');
324    field_parse!("received_bytes", '0'..='9' | '-', i64);
325    field_parse!("sent_bytes", '0'..='9' | '-', i64);
326    let request = get_value!("request", take_quoted1);
327    let mut iter = request.splitn(2, ' ');
328    log.insert(
329        "request_method".to_owned().into(),
330        match iter.next().unwrap().into() {
331            Value::Bytes(bytes) if bytes == "-" => Value::Null,
332            value => value,
333        },
334    ); // split always have at least 1 item
335    match iter.next() {
336        Some(value) => {
337            let mut iter = value.rsplitn(2, ' ');
338            log.insert(
339                "request_protocol".to_owned().into(),
340                match iter.next().unwrap().into() {
341                    Value::Bytes(bytes) if bytes == "-" => Value::Null,
342                    value => value,
343                },
344            ); // same as previous one
345            match iter.next() {
346                Some(value) => log.insert("request_url".into(), value.into()),
347                None => return Err("failed to get field `request_url`".into()),
348            }
349        }
350        None => return Err("failed to get field `request_url`".into()),
351    };
352
353    field_raw!("user_agent", take_quoted1);
354    field_raw!("ssl_cipher", take_anything);
355    field_raw!("ssl_protocol", take_anything);
356    field_raw!("target_group_arn", take_anything);
357    field_raw!("trace_id", take_quoted1);
358    field_raw!("domain_name", take_quoted1);
359    field_raw!("chosen_cert_arn", take_quoted1);
360    field!("matched_rule_priority", '0'..='9' | '-');
361    field!(
362        "request_creation_time",
363        '0'..='9' | '.' | '-' | ':' | 'T' | 'Z'
364    );
365    field_raw!("actions_executed", take_quoted1);
366    field_raw!("redirect_url", take_quoted1);
367    field_raw!("error_reason", take_quoted1);
368    field_raw!(
369        "target_port_list",
370        take_maybe_quoted_list(|c| matches!(c, '0'..='9' | 'a'..='f' | '.' | ':' | '-')),
371        ()
372    );
373    field_raw!(
374        "target_status_code_list",
375        take_maybe_quoted_list(|c| c.is_ascii_digit()),
376        ()
377    );
378    field_raw!("classification", take_quoted1);
379    field_raw!("classification_reason", take_quoted1);
380    field_tid!("traceability_id");
381
382    if input.is_empty() {
383        Ok(log.into())
384    } else if strict_mode {
385        Err(format!(r#"Log should be fully consumed: "{input}""#).into())
386    } else {
387        // Ignore any trailing, unknown fields when not in strict mode
388        Ok(log.into())
389    }
390}
391
392type SResult<'a, O> = IResult<&'a str, O, (&'a str, nom::error::ErrorKind)>;
393
394fn take_anything(input: &str) -> SResult<'_, &str> {
395    preceded(char(' '), take_while1(|c| c != ' ')).parse(input)
396}
397
398fn take_quoted1(input: &str) -> SResult<'_, String> {
399    delimited(tag(" \""), until_quote, char('"')).parse(input)
400}
401
402fn take_tid_or_nothing(input: &str) -> SResult<'_, Option<&str>> {
403    if input.starts_with(" TID_") {
404        let (rest, value) = take_anything(input)?;
405        Ok((rest, Some(value)))
406    } else {
407        Ok((input, None))
408    }
409}
410
411fn until_quote(input: &str) -> SResult<'_, String> {
412    let mut ret = String::new();
413    let mut skip_delimiter = false;
414    for (i, ch) in input.char_indices() {
415        if ch == '\\' && !skip_delimiter {
416            skip_delimiter = true;
417        } else if ch == '"' && !skip_delimiter {
418            return Ok((&input[i..], ret));
419        } else {
420            ret.push(ch);
421            skip_delimiter = false;
422        }
423    }
424    Err(nom::Err::Incomplete(nom::Needed::Unknown))
425}
426
427fn take_maybe_quoted_list<'a>(
428    cond: impl Fn(char) -> bool + Clone,
429) -> impl Parser<&'a str, Error = (), Output = Vec<&'a str>> {
430    alt((
431        map_res(tag(r#" "-""#), |_| {
432            Ok::<_, std::convert::Infallible>(vec![])
433        }),
434        map_res(
435            delimited(tag(" \""), take_while1(cond.clone()), char('"')),
436            |v: &str| Ok::<_, std::convert::Infallible>(vec![v]),
437        ),
438        map_res(preceded(char(' '), take_while1(cond)), |v: &str| {
439            Ok::<_, std::convert::Infallible>(vec![v])
440        }),
441    ))
442}
443
444#[cfg(test)]
445mod tests {
446    use super::*;
447    use crate::value;
448
449    test_function![
450        parse_aws_alb_log => ParseAwsAlbLog;
451
452        one {
453            args: func_args![value: r#"http 2018-07-02T22:23:00.186641Z app/my-loadbalancer/50dc6c495c0c9188 192.168.131.39:2817 10.0.0.1:80 0.000 0.001 0.000 200 200 34 366 "GET http://www.example.com:80/ HTTP/1.1" "curl/7.46.0" - - arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067 "Root=1-58337262-36d228ad5d99923122bbe354" "-" "-" 0 2018-07-02T22:22:48.364000Z "forward" "-" "-" 10.0.0.1:80 200 "-" "-" TID_dc57cebed65b444ebc8177bb698fe166"#],
454            want: Ok(value!({actions_executed: "forward",
455                             chosen_cert_arn: null,
456                             classification: null,
457                             classification_reason: null,
458                             client_host: "192.168.131.39:2817",
459                             domain_name: null,
460                             elb: "app/my-loadbalancer/50dc6c495c0c9188",
461                             elb_status_code: "200",
462                             error_reason: null,
463                             matched_rule_priority: "0",
464                             received_bytes: 34,
465                             redirect_url: null,
466                             request_creation_time: "2018-07-02T22:22:48.364000Z",
467                             request_method: "GET",
468                             request_processing_time: 0.0,
469                             request_protocol: "HTTP/1.1",
470                             request_url: "http://www.example.com:80/",
471                             response_processing_time: 0.0,
472                             sent_bytes: 366,
473                             ssl_cipher: null,
474                             ssl_protocol: null,
475                             target_group_arn: "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067",
476                             target_host: "10.0.0.1:80",
477                             target_port_list: ["10.0.0.1:80"],
478                             target_processing_time: 0.001,
479                             target_status_code: "200",
480                             target_status_code_list: ["200"],
481                             timestamp: "2018-07-02T22:23:00.186641Z",
482                             trace_id: "Root=1-58337262-36d228ad5d99923122bbe354",
483                             type: "http",
484                             user_agent: "curl/7.46.0",
485                             traceability_id: "TID_dc57cebed65b444ebc8177bb698fe166"
486
487
488            })),
489            tdef: TypeDef::object(inner_kind()).fallible(),
490        }
491
492        two {
493            args: func_args![value: r#"https 2018-07-02T22:23:00.186641Z app/my-loadbalancer/50dc6c495c0c9188 192.168.131.39:2817 10.0.0.1:80 0.086 0.048 0.037 200 200 0 57 "GET https://www.example.com:443/ HTTP/1.1" "curl/7.46.0" ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067 "Root=1-58337281-1d84f3d73c47ec4e58577259" "www.example.com" "arn:aws:acm:us-east-2:123456789012:certificate/12345678-1234-1234-1234-123456789012" 1 2018-07-02T22:22:48.364000Z "authenticate,forward" "-" "-" 10.0.0.1:80 200 "-" "-" TID_dc57cebed65b444ebc8177bb698fe166"#],
494            want: Ok(value! ({actions_executed: "authenticate,forward",
495                              chosen_cert_arn: "arn:aws:acm:us-east-2:123456789012:certificate/12345678-1234-1234-1234-123456789012",
496                              classification: null,
497                              classification_reason: null,
498                              client_host: "192.168.131.39:2817",
499                              domain_name: "www.example.com",
500                              elb: "app/my-loadbalancer/50dc6c495c0c9188",
501                              elb_status_code: "200",
502                              error_reason: null,
503                              matched_rule_priority: "1",
504                              received_bytes: 0,
505                              redirect_url: null,
506                              request_creation_time: "2018-07-02T22:22:48.364000Z",
507                              request_method: "GET",
508                              request_processing_time: 0.086,
509                              request_protocol: "HTTP/1.1",
510                              request_url: "https://www.example.com:443/",
511                              response_processing_time: 0.037,
512                              sent_bytes: 57,
513                              ssl_cipher: "ECDHE-RSA-AES128-GCM-SHA256",
514                              ssl_protocol: "TLSv1.2",
515                              target_group_arn: "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067",
516                              target_host: "10.0.0.1:80",
517                              target_port_list: ["10.0.0.1:80"],
518                              target_processing_time: 0.048,
519                              target_status_code: "200",
520                              target_status_code_list: ["200"],
521                              timestamp: "2018-07-02T22:23:00.186641Z",
522                              trace_id: "Root=1-58337281-1d84f3d73c47ec4e58577259",
523                              type: "https",
524                              user_agent: "curl/7.46.0",
525                              traceability_id: "TID_dc57cebed65b444ebc8177bb698fe166"})),
526            tdef: TypeDef::object(inner_kind()).fallible(),
527        }
528
529        three {
530            args: func_args![value: r#"h2 2018-07-02T22:23:00.186641Z app/my-loadbalancer/50dc6c495c0c9188 10.0.1.252:48160 10.0.0.66:9000 0.000 0.002 0.000 200 200 5 257 "GET https://10.0.2.105:773/ HTTP/2.0" "curl/7.46.0" ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067 "Root=1-58337327-72bd00b0343d75b906739c42" "-" "-" 1 2018-07-02T22:22:48.364000Z "redirect" "https://example.com:80/" "-" 10.0.0.66:9000 200 "-" "-" TID_dc57cebed65b444ebc8177bb698fe166"#],
531            want: Ok(value! ({actions_executed: "redirect",
532                              chosen_cert_arn: null,
533                              classification: null,
534                              classification_reason: null,
535                              client_host: "10.0.1.252:48160",
536                              domain_name: null,
537                              elb: "app/my-loadbalancer/50dc6c495c0c9188",
538                              elb_status_code: "200",
539                              error_reason: null,
540                              matched_rule_priority: "1",
541                              received_bytes: 5,
542                              redirect_url: "https://example.com:80/",
543                              request_creation_time: "2018-07-02T22:22:48.364000Z",
544                              request_method: "GET",
545                              request_processing_time: 0.0,
546                              request_protocol: "HTTP/2.0",
547                              request_url: "https://10.0.2.105:773/",
548                              response_processing_time: 0.0,
549                              sent_bytes: 257,
550                              ssl_cipher: "ECDHE-RSA-AES128-GCM-SHA256",
551                              ssl_protocol: "TLSv1.2",
552                              target_group_arn: "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067",
553                              target_host: "10.0.0.66:9000",
554                              target_port_list: ["10.0.0.66:9000"],
555                              target_processing_time: 0.002,
556                              target_status_code: "200",
557                              target_status_code_list: ["200"],
558                              timestamp: "2018-07-02T22:23:00.186641Z",
559                              trace_id: "Root=1-58337327-72bd00b0343d75b906739c42",
560                              type: "h2",
561                              user_agent: "curl/7.46.0",
562                              traceability_id: "TID_dc57cebed65b444ebc8177bb698fe166"})),
563            tdef: TypeDef::object(inner_kind()).fallible(),
564        }
565
566        four {
567            args: func_args![value: r#"ws 2018-07-02T22:23:00.186641Z app/my-loadbalancer/50dc6c495c0c9188 10.0.0.140:40914 10.0.1.192:8010 0.001 0.003 0.000 101 101 218 587 "GET http://10.0.0.30:80/ HTTP/1.1" "-" - - arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067 "Root=1-58337364-23a8c76965a2ef7629b185e3" "-" "-" 1 2018-07-02T22:22:48.364000Z "forward" "-" "-" 10.0.1.192:8010 101 "-" "-" TID_dc57cebed65b444ebc8177bb698fe166"#],
568            want: Ok(value!({actions_executed: "forward",
569                             chosen_cert_arn: null,
570                             classification: null,
571                             classification_reason: null,
572                             client_host: "10.0.0.140:40914",
573                             domain_name: null,
574                             elb: "app/my-loadbalancer/50dc6c495c0c9188",
575                             elb_status_code: "101",
576                             error_reason: null,
577                             matched_rule_priority: "1",
578                             received_bytes: 218,
579                             redirect_url: null,
580                             request_creation_time: "2018-07-02T22:22:48.364000Z",
581                             request_method: "GET",
582                             request_processing_time: 0.001,
583                             request_protocol: "HTTP/1.1",
584                             request_url: "http://10.0.0.30:80/",
585                             response_processing_time: 0.0,
586                             sent_bytes: 587,
587                             ssl_cipher: null,
588                             ssl_protocol: null,
589                             target_group_arn: "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067",
590                             target_host: "10.0.1.192:8010",
591                             target_port_list: ["10.0.1.192:8010"],
592                             target_processing_time: 0.003,
593                             target_status_code: "101",
594                             target_status_code_list: ["101"],
595                             timestamp: "2018-07-02T22:23:00.186641Z",
596                             trace_id: "Root=1-58337364-23a8c76965a2ef7629b185e3",
597                             type: "ws",
598                             user_agent: null,
599                             traceability_id: "TID_dc57cebed65b444ebc8177bb698fe166"})),
600            tdef: TypeDef::object(inner_kind()).fallible(),
601        }
602
603        five {
604            args: func_args![value: r#"wss 2018-07-02T22:23:00.186641Z app/my-loadbalancer/50dc6c495c0c9188 10.0.0.140:44244 10.0.0.171:8010 0.000 0.001 0.000 101 101 218 786 "GET https://10.0.0.30:443/ HTTP/1.1" "-" ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 arn:aws:elasticloadbalancing:us-west-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067 "Root=1-58337364-23a8c76965a2ef7629b185e3" "-" "-" 1 2018-07-02T22:22:48.364000Z "forward" "-" "-" 10.0.0.171:8010 101 "-" "-" TID_dc57cebed65b444ebc8177bb698fe166"#],
605            want: Ok(value! ({actions_executed: "forward",
606                              chosen_cert_arn: null,
607                              classification: null,
608                              classification_reason: null,
609                              client_host: "10.0.0.140:44244",
610                              domain_name: null,
611                              elb: "app/my-loadbalancer/50dc6c495c0c9188",
612                              elb_status_code: "101",
613                              error_reason: null,
614                              matched_rule_priority: "1",
615                              received_bytes: 218,
616                              redirect_url: null,
617                              request_creation_time: "2018-07-02T22:22:48.364000Z",
618                              request_method: "GET",
619                              request_processing_time: 0.0,
620                              request_protocol: "HTTP/1.1",
621                              request_url: "https://10.0.0.30:443/",
622                              response_processing_time: 0.0,
623                              sent_bytes: 786,
624                              ssl_cipher: "ECDHE-RSA-AES128-GCM-SHA256",
625                              ssl_protocol: "TLSv1.2",
626                              target_group_arn: "arn:aws:elasticloadbalancing:us-west-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067",
627                              target_host: "10.0.0.171:8010",
628                              target_port_list: ["10.0.0.171:8010"],
629                              target_processing_time: 0.001,
630                              target_status_code: "101",
631                              target_status_code_list: ["101"],
632                              timestamp: "2018-07-02T22:23:00.186641Z",
633                              trace_id: "Root=1-58337364-23a8c76965a2ef7629b185e3",
634                              type: "wss",
635                              user_agent: null,
636                              traceability_id: "TID_dc57cebed65b444ebc8177bb698fe166"})),
637            tdef: TypeDef::object(inner_kind()).fallible(),
638        }
639
640        six {
641            args: func_args![value: r#"http 2018-11-30T22:23:00.186641Z app/my-loadbalancer/50dc6c495c0c9188 192.168.131.39:2817 - 0.000 0.001 0.000 200 200 34 366 "GET http://www.example.com:80/ HTTP/1.1" "curl/7.46.0" - - arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067 "Root=1-58337364-23a8c76965a2ef7629b185e3" "-" "-" 0 2018-11-30T22:22:48.364000Z "forward" "-" "-" "-" "-" "-" "-" TID_dc57cebed65b444ebc8177bb698fe166"#],
642            want: Ok(value! ({actions_executed: "forward",
643                              chosen_cert_arn: null,
644                              classification: null,
645                              classification_reason: null,
646                              client_host: "192.168.131.39:2817",
647                              domain_name: null,
648                              elb: "app/my-loadbalancer/50dc6c495c0c9188",
649                              elb_status_code: "200",
650                              error_reason: null,
651                              matched_rule_priority: "0",
652                              received_bytes: 34,
653                              redirect_url: null,
654                              request_creation_time: "2018-11-30T22:22:48.364000Z",
655                              request_method: "GET",
656                              request_processing_time: 0.0,
657                              request_protocol: "HTTP/1.1",
658                              request_url: "http://www.example.com:80/",
659                              response_processing_time: 0.0,
660                              sent_bytes: 366,
661                              ssl_cipher: null,
662                              ssl_protocol: null,
663                              target_group_arn: "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067",
664                              target_host: null,
665                              target_port_list: [],
666                              target_processing_time: 0.001,
667                              target_status_code: "200",
668                              target_status_code_list: [],
669                              timestamp: "2018-11-30T22:23:00.186641Z",
670                              trace_id: "Root=1-58337364-23a8c76965a2ef7629b185e3",
671                              type: "http",
672                              user_agent: "curl/7.46.0",
673                              traceability_id: "TID_dc57cebed65b444ebc8177bb698fe166"})),
674            tdef: TypeDef::object(inner_kind()).fallible(),
675        }
676
677        seven {
678            args: func_args![value: r#"http 2018-11-30T22:23:00.186641Z app/my-loadbalancer/50dc6c495c0c9188 192.168.131.39:2817 - 0.000 0.001 0.000 502 - 34 366 "GET http://www.example.com:80/ HTTP/1.1" "curl/7.46.0" - - arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067 "Root=1-58337364-23a8c76965a2ef7629b185e3" "-" "-" 0 2018-11-30T22:22:48.364000Z "forward" "-" "LambdaInvalidResponse" "-" "-" "-" "-" TID_dc57cebed65b444ebc8177bb698fe166"#],
679            want: Ok(value!({actions_executed: "forward",
680                             chosen_cert_arn: null,
681                             classification: null,
682                             classification_reason: null,
683                             client_host: "192.168.131.39:2817",
684                             domain_name: null,
685                             elb: "app/my-loadbalancer/50dc6c495c0c9188",
686                             elb_status_code: "502",
687                             error_reason: "LambdaInvalidResponse",
688                             matched_rule_priority: "0",
689                             received_bytes: 34,
690                             redirect_url: null,
691                             request_creation_time: "2018-11-30T22:22:48.364000Z",
692                             request_method: "GET",
693                             request_processing_time: 0.0,
694                             request_protocol: "HTTP/1.1",
695                             request_url: "http://www.example.com:80/",
696                             response_processing_time: 0.0,
697                             sent_bytes: 366,
698                             ssl_cipher: null,
699                             ssl_protocol: null,
700                             target_group_arn: "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067",
701                             target_host: null,
702                             target_port_list: [],
703                             target_processing_time: 0.001,
704                             target_status_code: null,
705                             target_status_code_list: [],
706                             timestamp: "2018-11-30T22:23:00.186641Z",
707                             trace_id: "Root=1-58337364-23a8c76965a2ef7629b185e3",
708                             type: "http",
709                             user_agent: "curl/7.46.0",
710                             traceability_id: "TID_dc57cebed65b444ebc8177bb698fe166"})),
711            tdef: TypeDef::object(inner_kind()).fallible(),
712        }
713
714        eight {
715            args: func_args![value: r#"https 2021-03-16T20:20:00.135052Z app/awseb-AWSEB-1MVD8OW91UMOH/a32a5528b8fdaa6b 10.209.14.140:50599 10.119.5.47:80 0.001 0.052 0.000 200 200 589 2084 "POST https://test.domain.com:443/api/deposits/transactions:search?detailsLevel=FULL&offset=0&limit=50 HTTP/1.1" "User 1.0" ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 arn:aws:elasticloadbalancing:us-east-1:755269215481:targetgroup/awseb-AWSEB-91MZX0WA1A0F/5a03cc723870f039 "Root=1-605112f0-31f367be4fd3da651daa4157" "some.domain.com" "arn:aws:acm:us-east-1:765229915481:certificate/d8450a8a-b4f6-4714-8535-17c625c36899" 0 2021-03-16T20:20:00.081000Z "waf,forward" "-" "-" "10.229.5.47:80" "200" "-" "-" TID_dc57cebed65b444ebc8177bb698fe166"#],
716            want: Ok(value!({type: "https",
717                             timestamp: "2021-03-16T20:20:00.135052Z",
718                             elb: "app/awseb-AWSEB-1MVD8OW91UMOH/a32a5528b8fdaa6b",
719                             client_host: "10.209.14.140:50599",
720                             target_host: "10.119.5.47:80",
721                             request_processing_time: 0.001,
722                             target_processing_time: 0.052,
723                             response_processing_time: 0.0,
724                             elb_status_code: "200",
725                             target_status_code: "200",
726                             received_bytes: 589,
727                             sent_bytes: 2084,
728                             request_method: "POST",
729                             request_url: "https://test.domain.com:443/api/deposits/transactions:search?detailsLevel=FULL&offset=0&limit=50",
730                             request_protocol: "HTTP/1.1",
731                             user_agent: "User 1.0",
732                             ssl_cipher: "ECDHE-RSA-AES128-GCM-SHA256",
733                             ssl_protocol: "TLSv1.2",
734                             target_group_arn: "arn:aws:elasticloadbalancing:us-east-1:755269215481:targetgroup/awseb-AWSEB-91MZX0WA1A0F/5a03cc723870f039",
735                             trace_id: "Root=1-605112f0-31f367be4fd3da651daa4157",
736                             domain_name: "some.domain.com",
737                             chosen_cert_arn: "arn:aws:acm:us-east-1:765229915481:certificate/d8450a8a-b4f6-4714-8535-17c625c36899",
738                             matched_rule_priority: "0",
739                             request_creation_time: "2021-03-16T20:20:00.081000Z",
740                             actions_executed: "waf,forward",
741                             redirect_url: null,
742                             error_reason: null,
743                             target_port_list: ["10.229.5.47:80"],
744                             target_status_code_list: ["200"],
745                             classification: null,
746                             classification_reason: null,
747                             traceability_id: "TID_dc57cebed65b444ebc8177bb698fe166"})),
748            tdef: TypeDef::object(inner_kind()).fallible(),
749        }
750
751        nine {
752            args: func_args![value: r#"http 2021-03-17T18:54:14.216357Z app/awseb-AWSEB-1KGU6EBAG3FAD/7f0dc2b05788640f 113.241.19.90:15070 - -1 -1 -1 400 - 0 272 "- http://awseb-awseb-1kgu6fbag3fad-640112591.us-east-1.elb.amazonaws.com:80- -" "-" - - - "-" "-" "-" - 2021-03-17T18:54:13.967000Z "-" "-" "-" "-" "-" "-" "-" TID_dc57cebed65b444ebc8177bb698fe166"#],
753            want: Ok(value!({type: "http",
754                             timestamp: "2021-03-17T18:54:14.216357Z",
755                             elb: "app/awseb-AWSEB-1KGU6EBAG3FAD/7f0dc2b05788640f",
756                             client_host: "113.241.19.90:15070",
757                             target_host: null,
758                             request_processing_time: (-1.0),
759                             target_processing_time: (-1.0),
760                             response_processing_time: (-1.0),
761                             elb_status_code: "400",
762                             target_status_code: null,
763                             received_bytes: 0,
764                             sent_bytes: 272,
765                             request_method: null,
766                             request_url: "http://awseb-awseb-1kgu6fbag3fad-640112591.us-east-1.elb.amazonaws.com:80-",
767                             request_protocol: null,
768                             user_agent: null,
769                             ssl_cipher: null,
770                             ssl_protocol: null,
771                             target_group_arn: null,
772                             trace_id: null,
773                             domain_name: null,
774                             chosen_cert_arn: null,
775                             matched_rule_priority: null,
776                             request_creation_time: "2021-03-17T18:54:13.967000Z",
777                             actions_executed: null,
778                             redirect_url: null,
779                             error_reason: null,
780                             target_port_list: [],
781                             target_status_code_list: [],
782                             classification: null,
783                             classification_reason: null,
784                             traceability_id: "TID_dc57cebed65b444ebc8177bb698fe166"})),
785            tdef: TypeDef::object(inner_kind()).fallible(),
786        }
787
788        ten {
789            args: func_args![value: r#"http 2021-03-18T04:00:26.920977Z app/awseb-AWSEB-1KGU6EBAG3FAD/7f0dc2b05788640f 31.211.20.175:57720 - -1 -1 -1 400 - 191 272 "POST http://awseb-awseb-1kgu6fbag3fad-640112591.us-east-1.elb.amazonaws.com:80/cgi-bin/login.cgi HTTP/1.1" "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0" - - - "-" "-" "-" - 2021-03-18T04:00:26.599000Z "-" "-" "-" "-" "-" "-" "-" TID_dc57cebed65b444ebc8177bb698fe166"#],
790            want: Ok(value!({type: "http",
791                             timestamp: "2021-03-18T04:00:26.920977Z",
792                             elb: "app/awseb-AWSEB-1KGU6EBAG3FAD/7f0dc2b05788640f",
793                             client_host: "31.211.20.175:57720",
794                             target_host: null,
795                             request_processing_time: (-1.0),
796                             target_processing_time: (-1.0),
797                             response_processing_time: (-1.0),
798                             elb_status_code: "400",
799                             target_status_code: null,
800                             received_bytes: 191,
801                             sent_bytes: 272,
802                             request_method: "POST",
803                             request_url: "http://awseb-awseb-1kgu6fbag3fad-640112591.us-east-1.elb.amazonaws.com:80/cgi-bin/login.cgi",
804                             request_protocol: "HTTP/1.1",
805                             user_agent: "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0",
806                             ssl_cipher: null,
807                             ssl_protocol: null,
808                             target_group_arn: null,
809                             trace_id: null,
810                             domain_name: null,
811                             chosen_cert_arn: null,
812                             matched_rule_priority: null,
813                             request_creation_time: "2021-03-18T04:00:26.599000Z",
814                             actions_executed: null,
815                             redirect_url: null,
816                             error_reason: null,
817                             target_port_list: [],
818                             target_status_code_list: [],
819                             classification: null,
820                             classification_reason: null,
821                             traceability_id: "TID_dc57cebed65b444ebc8177bb698fe166"})),
822            tdef: TypeDef::object(inner_kind()).fallible(),
823        }
824
825        eleven {
826            args: func_args![value: r#"https 2021-03-16T20:20:00.135052Z app/awseb-AWSEB-1MVD8OW91UMOH/a32a5528b8fdaa6b 2601:6bbc:c529:9dad:6bbc:c529:9dad:6bbc:50599 fd6d:6bbc:c529:6::face:ed83:f46:80 0.001 0.052 0.000 200 200 589 2084 "POST https://test.domain.com:443/api/deposits/transactions:search?detailsLevel=FULL&offset=0&limit=50 HTTP/1.1" "User 1.0" ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 arn:aws:elasticloadbalancing:us-east-1:755269215481:targetgroup/awseb-AWSEB-91MZX0WA1A0F/5a03cc723870f039 "Root=1-605112f0-31f367be4fd3da651daa4157" "some.domain.com" "arn:aws:acm:us-east-1:765229915481:certificate/d8450a8a-b4f6-4714-8535-17c625c36899" 0 2021-03-16T20:20:00.081000Z "waf,forward" "-" "-" "fd6d:6bbc:c529:27ff:b::dead:ed84:80" "200" "-" "-" TID_dc57cebed65b444ebc8177bb698fe166"#],
827            want: Ok(value!({type: "https",
828                             timestamp: "2021-03-16T20:20:00.135052Z",
829                             elb: "app/awseb-AWSEB-1MVD8OW91UMOH/a32a5528b8fdaa6b",
830                             client_host: "2601:6bbc:c529:9dad:6bbc:c529:9dad:6bbc:50599",
831                             target_host: "fd6d:6bbc:c529:6::face:ed83:f46:80",
832                             request_processing_time: 0.001,
833                             target_processing_time: 0.052,
834                             response_processing_time: 0.0,
835                             elb_status_code: "200",
836                             target_status_code: "200",
837                             received_bytes: 589,
838                             sent_bytes: 2084,
839                             request_method: "POST",
840                             request_url: "https://test.domain.com:443/api/deposits/transactions:search?detailsLevel=FULL&offset=0&limit=50",
841                             request_protocol: "HTTP/1.1",
842                             user_agent: "User 1.0",
843                             ssl_cipher: "ECDHE-RSA-AES128-GCM-SHA256",
844                             ssl_protocol: "TLSv1.2",
845                             target_group_arn: "arn:aws:elasticloadbalancing:us-east-1:755269215481:targetgroup/awseb-AWSEB-91MZX0WA1A0F/5a03cc723870f039",
846                             trace_id: "Root=1-605112f0-31f367be4fd3da651daa4157",
847                             domain_name: "some.domain.com",
848                             chosen_cert_arn: "arn:aws:acm:us-east-1:765229915481:certificate/d8450a8a-b4f6-4714-8535-17c625c36899",
849                             matched_rule_priority: "0",
850                             request_creation_time: "2021-03-16T20:20:00.081000Z",
851                             actions_executed: "waf,forward",
852                             redirect_url: null,
853                             error_reason: null,
854                             target_port_list: ["fd6d:6bbc:c529:27ff:b::dead:ed84:80"],
855                             target_status_code_list: ["200"],
856                             classification: null,
857                             classification_reason: null,
858                             traceability_id: "TID_dc57cebed65b444ebc8177bb698fe166"})),
859            tdef: TypeDef::object(inner_kind()).fallible(),
860        }
861        twelve {
862            args: func_args![value: r#"https 2021-03-16T20:20:00.135052Z app/awseb-AWSEB-1MVD8OW91UMOH/a32a5528b8fdaa6b 2601:6bbc:c529:9dad:6bbc:c529:9dad:6bbc:50599 fd6d:6bbc:c529:6::face:ed83:f46:80 0.001 0.052 0.000 200 200 589 2084 "POST https://test.domain.com:443/api/deposits/transactions:search?detailsLevel=FULL&offset=0&limit=50 HTTP/1.1" "User 1.0" ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 arn:aws:elasticloadbalancing:us-east-1:755269215481:targetgroup/awseb-AWSEB-91MZX0WA1A0F/5a03cc723870f039 "Root=1-605112f0-31f367be4fd3da651daa4157" "some.domain.com" "arn:aws:acm:us-east-1:765229915481:certificate/d8450a8a-b4f6-4714-8535-17c625c36899" 0 2021-03-16T20:20:00.081000Z "waf,forward" "-" "-" "fd6d:6bbc:c529:27ff:b::dead:ed84:80" "200" "-" "-""#],
863            want: Ok(value!({type: "https",
864                             timestamp: "2021-03-16T20:20:00.135052Z",
865                             elb: "app/awseb-AWSEB-1MVD8OW91UMOH/a32a5528b8fdaa6b",
866                             client_host: "2601:6bbc:c529:9dad:6bbc:c529:9dad:6bbc:50599",
867                             target_host: "fd6d:6bbc:c529:6::face:ed83:f46:80",
868                             request_processing_time: 0.001,
869                             target_processing_time: 0.052,
870                             response_processing_time: 0.0,
871                             elb_status_code: "200",
872                             target_status_code: "200",
873                             received_bytes: 589,
874                             sent_bytes: 2084,
875                             request_method: "POST",
876                             request_url: "https://test.domain.com:443/api/deposits/transactions:search?detailsLevel=FULL&offset=0&limit=50",
877                             request_protocol: "HTTP/1.1",
878                             user_agent: "User 1.0",
879                             ssl_cipher: "ECDHE-RSA-AES128-GCM-SHA256",
880                             ssl_protocol: "TLSv1.2",
881                             target_group_arn: "arn:aws:elasticloadbalancing:us-east-1:755269215481:targetgroup/awseb-AWSEB-91MZX0WA1A0F/5a03cc723870f039",
882                             trace_id: "Root=1-605112f0-31f367be4fd3da651daa4157",
883                             domain_name: "some.domain.com",
884                             chosen_cert_arn: "arn:aws:acm:us-east-1:765229915481:certificate/d8450a8a-b4f6-4714-8535-17c625c36899",
885                             matched_rule_priority: "0",
886                             request_creation_time: "2021-03-16T20:20:00.081000Z",
887                             actions_executed: "waf,forward",
888                             redirect_url: null,
889                             error_reason: null,
890                             target_port_list: ["fd6d:6bbc:c529:27ff:b::dead:ed84:80"],
891                             target_status_code_list: ["200"],
892                             classification: null,
893                             classification_reason: null,
894                             traceability_id: null})),
895                tdef: TypeDef::object(inner_kind()).fallible(),
896            }
897            thirteen {
898                args: func_args![value: r#"http 2018-07-02T22:23:00.186641Z app/my-loadbalancer/50dc6c495c0c9188 192.168.131.39:2817 10.0.0.1:80 0.000 0.001 0.000 200 200 34 366 "GET http://www.example.com:80/ HTTP/1.1" "curl/7.46.0" - - arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067 "Root=1-58337262-36d228ad5d99923122bbe354" "-" "-" 0 2018-07-02T22:22:48.364000Z "forward" "-" "-" 10.0.0.1:80 200 "-" "-" TID_dc57cebed65b444ebc8177bb698fe166 "-" "-" "-""#, strict_mode: false],
899                want: Ok(value!({actions_executed: "forward",
900                                 chosen_cert_arn: null,
901                                 classification: null,
902                                 classification_reason: null,
903                                 client_host: "192.168.131.39:2817",
904                                 domain_name: null,
905                                 elb: "app/my-loadbalancer/50dc6c495c0c9188",
906                                 elb_status_code: "200",
907                                 error_reason: null,
908                                 matched_rule_priority: "0",
909                                 received_bytes: 34,
910                                 redirect_url: null,
911                                 request_creation_time: "2018-07-02T22:22:48.364000Z",
912                                 request_method: "GET",
913                                 request_processing_time: 0.0,
914                                 request_protocol: "HTTP/1.1",
915                                 request_url: "http://www.example.com:80/",
916                                 response_processing_time: 0.0,
917                                 sent_bytes: 366,
918                                 ssl_cipher: null,
919                                 ssl_protocol: null,
920                                 target_group_arn: "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067",
921                                 target_host: "10.0.0.1:80",
922                                 target_port_list: ["10.0.0.1:80"],
923                                 target_processing_time: 0.001,
924                                 target_status_code: "200",
925                                 target_status_code_list: ["200"],
926                                 timestamp: "2018-07-02T22:23:00.186641Z",
927                                 trace_id: "Root=1-58337262-36d228ad5d99923122bbe354",
928                                 type: "http",
929                                 user_agent: "curl/7.46.0",
930                                 traceability_id: "TID_dc57cebed65b444ebc8177bb698fe166"
931                })),
932                tdef: TypeDef::object(inner_kind()).fallible(),
933            }
934    ];
935}