11use crate :: boxplot;
2+ use crate :: speedtest:: Metadata ;
23use crate :: speedtest:: TestType ;
34use crate :: OutputFormat ;
45use indexmap:: IndexSet ;
@@ -50,6 +51,7 @@ pub(crate) fn log_measurements(
5051 payload_sizes : Vec < usize > ,
5152 verbose : bool ,
5253 output_format : OutputFormat ,
54+ metadata : Option < & Metadata > ,
5355) {
5456 if output_format == OutputFormat :: StdOut {
5557 println ! ( "\n Summary Statistics" ) ;
@@ -79,32 +81,12 @@ pub(crate) fn log_measurements(
7981 wtr. flush ( ) . unwrap ( ) ;
8082 }
8183 OutputFormat :: Json => {
82- let mut output = serde_json:: Map :: new ( ) ;
83- output. insert (
84- "speed_measurements" . to_string ( ) ,
85- serde_json:: to_value ( & stat_measurements) . unwrap ( ) ,
86- ) ;
87- if let Some ( latency) = latency_measurement {
88- output. insert (
89- "latency_measurement" . to_string ( ) ,
90- serde_json:: to_value ( latency) . unwrap ( ) ,
91- ) ;
92- }
84+ let output = compose_output_json ( & stat_measurements, latency_measurement, metadata) ;
9385 serde_json:: to_writer ( io:: stdout ( ) , & output) . unwrap ( ) ;
9486 println ! ( ) ;
9587 }
9688 OutputFormat :: JsonPretty => {
97- let mut output = serde_json:: Map :: new ( ) ;
98- output. insert (
99- "speed_measurements" . to_string ( ) ,
100- serde_json:: to_value ( & stat_measurements) . unwrap ( ) ,
101- ) ;
102- if let Some ( latency) = latency_measurement {
103- output. insert (
104- "latency_measurement" . to_string ( ) ,
105- serde_json:: to_value ( latency) . unwrap ( ) ,
106- ) ;
107- }
89+ let output = compose_output_json ( & stat_measurements, latency_measurement, metadata) ;
10890 serde_json:: to_writer_pretty ( io:: stdout ( ) , & output) . unwrap ( ) ;
10991 println ! ( ) ;
11092 }
@@ -113,6 +95,31 @@ pub(crate) fn log_measurements(
11395 }
11496}
11597
98+ fn compose_output_json (
99+ stat_measurements : & [ StatMeasurement ] ,
100+ latency_measurement : Option < & LatencyMeasurement > ,
101+ metadata : Option < & Metadata > ,
102+ ) -> serde_json:: Map < String , serde_json:: Value > {
103+ let mut output = serde_json:: Map :: new ( ) ;
104+ output. insert (
105+ "speed_measurements" . to_string ( ) ,
106+ serde_json:: to_value ( stat_measurements) . unwrap ( ) ,
107+ ) ;
108+ if let Some ( latency) = latency_measurement {
109+ output. insert (
110+ "latency_measurement" . to_string ( ) ,
111+ serde_json:: to_value ( latency) . unwrap ( ) ,
112+ ) ;
113+ }
114+ if let Some ( metadata) = metadata {
115+ output. insert (
116+ "metadata" . to_string ( ) ,
117+ serde_json:: to_value ( metadata) . unwrap ( ) ,
118+ ) ;
119+ }
120+ output
121+ }
122+
116123fn log_measurements_by_test_type (
117124 measurements : & [ Measurement ] ,
118125 payload_sizes : Vec < usize > ,
@@ -317,4 +324,60 @@ mod tests {
317324 fn test_median_single_value ( ) {
318325 assert_eq ! ( median( & [ 5.0 ] ) , 5.0 ) ;
319326 }
327+
328+ #[ test]
329+ fn test_compose_output_json_includes_metadata ( ) {
330+ let stat_measurements = vec ! [ StatMeasurement {
331+ test_type: TestType :: Download ,
332+ payload_size: 100_000 ,
333+ min: 1.0 ,
334+ q1: 1.5 ,
335+ median: 2.0 ,
336+ q3: 2.5 ,
337+ max: 3.0 ,
338+ avg: 2.0 ,
339+ } ] ;
340+ let latency = LatencyMeasurement {
341+ avg_latency_ms : 10.0 ,
342+ min_latency_ms : 9.0 ,
343+ max_latency_ms : 11.0 ,
344+ latency_measurements : vec ! [ 9.0 , 10.0 , 11.0 ] ,
345+ } ;
346+ let metadata = Metadata {
347+ city : "City" . to_string ( ) ,
348+ country : "Country" . to_string ( ) ,
349+ ip : "127.0.0.1" . to_string ( ) ,
350+ asn : "ASN" . to_string ( ) ,
351+ colo : "ABC" . to_string ( ) ,
352+ } ;
353+
354+ let output =
355+ super :: compose_output_json ( & stat_measurements, Some ( & latency) , Some ( & metadata) ) ;
356+
357+ let metadata_value = output. get ( "metadata" ) . expect ( "metadata missing" ) ;
358+ let metadata_obj = metadata_value. as_object ( ) . expect ( "metadata not an object" ) ;
359+ assert_eq ! (
360+ metadata_obj. get( "city" ) . and_then( |v| v. as_str( ) ) ,
361+ Some ( "City" )
362+ ) ;
363+ assert_eq ! (
364+ metadata_obj. get( "country" ) . and_then( |v| v. as_str( ) ) ,
365+ Some ( "Country" )
366+ ) ;
367+ assert_eq ! (
368+ metadata_obj. get( "ip" ) . and_then( |v| v. as_str( ) ) ,
369+ Some ( "127.0.0.1" )
370+ ) ;
371+ assert_eq ! (
372+ metadata_obj. get( "asn" ) . and_then( |v| v. as_str( ) ) ,
373+ Some ( "ASN" )
374+ ) ;
375+ assert_eq ! (
376+ metadata_obj. get( "colo" ) . and_then( |v| v. as_str( ) ) ,
377+ Some ( "ABC" )
378+ ) ;
379+
380+ assert ! ( output. get( "latency_measurement" ) . is_some( ) ) ;
381+ assert ! ( output. get( "speed_measurements" ) . is_some( ) ) ;
382+ }
320383}
0 commit comments