@@ -5,6 +5,7 @@ pub mod lambda_private {
55 use tokio:: time:: Duration as TokioDuration ;
66 use aws_sdk_lambda:: Client as LambdaClient ;
77 use aws_sdk_lambda:: config:: Builder as LambdaConfigBuilder ;
8+ use aws_sdk_lambda:: error:: ProvideErrorMetadata ;
89 use aws_sdk_lambda:: types:: InvocationType ;
910 use aws_credential_types:: Credentials ;
1011 use aws_types:: region:: Region ;
@@ -439,8 +440,15 @@ pub mod lambda_private {
439440 invoke_future
440441 )
441442 . await
442- . map_err ( |_| format ! ( "Lambda invocation timed out after {}s" , timeout_secs) ) ?
443- . map_err ( |e| format ! ( "Lambda invocation failed: {:?}" , e) ) ?;
443+ . map_err ( |_| format ! ( "Invocation timed out after {}s" , timeout_secs) ) ?
444+ . map_err ( |e| {
445+ // Extract concise error message from AWS SDK error
446+ if let Some ( code) = e. code ( ) {
447+ code. to_string ( )
448+ } else {
449+ format ! ( "Invocation failed: {}" , e)
450+ }
451+ } ) ?;
444452
445453 Ok ( InvokeResponse {
446454 status_code : result. status_code ( ) ,
@@ -490,6 +498,37 @@ pub mod lambda_private {
490498 }
491499 }
492500
501+ /// Probe result details for visualization
502+ struct ProbeResult {
503+ invoked : bool , // Successfully invoked Lambda
504+ received : bool , // Received valid response payload
505+ status_ok : bool , // HTTP status was 2xx
506+ }
507+
508+ impl ProbeResult {
509+ /// Format probe result as 8-character bitmap matching Varnish format:
510+ /// Position 0: '4' if invoked successfully, '-' if failed
511+ /// Position 1: '-' (no IPv6)
512+ /// Position 2: '-' (no Unix sockets)
513+ /// Position 3: 'x' if invoke failed, '-' if successful
514+ /// Position 4: 'X' if invoked successfully, '-' if failed
515+ /// Position 5: 'r' if payload problem, '-' if ok
516+ /// Position 6: 'R' if payload valid, '-' if not
517+ /// Position 7: 'H' if happy (2xx status), '-' if not
518+ fn to_string ( & self ) -> String {
519+ let mut s = String :: with_capacity ( 8 ) ;
520+ s. push ( if self . invoked { '4' } else { '-' } ) ;
521+ s. push ( '-' ) ; // No IPv6
522+ s. push ( '-' ) ; // No Unix sockets
523+ s. push ( if self . invoked { '-' } else { 'x' } ) ;
524+ s. push ( if self . invoked { 'X' } else { '-' } ) ;
525+ s. push ( if !self . invoked || self . received { '-' } else { 'r' } ) ;
526+ s. push ( if self . received { 'R' } else { '-' } ) ;
527+ s. push ( if self . status_ok { 'H' } else { '-' } ) ;
528+ s
529+ }
530+ }
531+
493532 fn spawn_probe ( bgt : & ' static BgThread , probe_state : * mut ProbeState , name : String , client : LambdaClient ) {
494533 let probe_state = unsafe { probe_state. as_mut ( ) . unwrap ( ) } ;
495534 let spec = probe_state. spec . clone ( ) ;
@@ -508,6 +547,11 @@ pub mod lambda_private {
508547 loop {
509548 let msg;
510549 let mut time = 0_f64 ;
550+ let mut probe_result = ProbeResult {
551+ invoked : false ,
552+ received : false ,
553+ status_ok : false ,
554+ } ;
511555
512556 let start = Instant :: now ( ) ;
513557 let result = invoke_lambda (
@@ -519,26 +563,35 @@ pub mod lambda_private {
519563
520564 let new_bit = match result {
521565 Err ( e) => {
522- msg = format ! ( "Error: {e}" ) ;
566+ msg = e;
567+ // invoked=false, received=false, status_ok=false (all defaults)
523568 false
524569 }
525- Ok ( resp) if resp. function_error . is_none ( ) && resp. status_code == 200 => {
526- msg = format ! ( "Success: status {}" , resp. status_code) ;
527- if avg_rate < 4.0 {
528- avg_rate += 1.0 ;
529- }
530- time = start. elapsed ( ) . as_secs_f64 ( ) ;
531- let mut avg = avg. lock ( ) . unwrap ( ) ;
532- * avg += ( time - * avg) / avg_rate;
533- true
534- }
535570 Ok ( resp) => {
536- msg = format ! (
537- "Error: status {}, function_error: {:?}" ,
538- resp. status_code,
539- resp. function_error
540- ) ;
541- false
571+ probe_result. invoked = true ;
572+ time = start. elapsed ( ) . as_secs_f64 ( ) ;
573+
574+ if resp. payload . is_some ( ) {
575+ probe_result. received = true ;
576+ }
577+
578+ let status_ok = resp. function_error . is_none ( ) && resp. status_code == 200 ;
579+ if status_ok {
580+ probe_result. status_ok = true ;
581+ msg = "HTTP/1.1 200 OK" . to_string ( ) ;
582+ if avg_rate < 4.0 {
583+ avg_rate += 1.0 ;
584+ }
585+ let mut avg = avg. lock ( ) . unwrap ( ) ;
586+ * avg += ( time - * avg) / avg_rate;
587+ } else if let Some ( func_err) = resp. function_error {
588+ msg = format ! ( "Function error: {}" , func_err) ;
589+ } else if !probe_result. received {
590+ msg = "No response payload" . to_string ( ) ;
591+ } else {
592+ msg = format ! ( "HTTP/1.1 {} Error" , resp. status_code) ;
593+ }
594+ status_ok
542595 }
543596 } ;
544597
@@ -547,11 +600,11 @@ pub mod lambda_private {
547600 log (
548601 LogTag :: BackendHealth ,
549602 format ! (
550- "{} {} {} {} {} {} {} {} {} {}" ,
603+ "{} {} {} {} {} {} {} {:.6 } {:.6 } {}" ,
551604 name,
552605 if health_update. health_unchanged { "Still" } else { "Went" } ,
553606 if health_update. is_healthy { "healthy" } else { "sick" } ,
554- name ,
607+ probe_result . to_string ( ) ,
555608 good_probes( health_update. bitmap, spec. window) ,
556609 spec. threshold,
557610 spec. window,
0 commit comments