1+ mod cpu_usage;
2+ mod datadog;
13mod metrics;
4+ mod utils;
25
36use std:: collections:: BTreeMap ;
47use std:: path:: { Path , PathBuf } ;
@@ -8,6 +11,10 @@ use anyhow::Context;
811use clap:: Parser ;
912use serde_yaml:: Value ;
1013
14+ use crate :: cpu_usage:: load_cpu_usage;
15+ use crate :: datadog:: upload_datadog_metric;
16+ use crate :: utils:: load_env_var;
17+
1118use crate :: metrics:: postprocess_metrics;
1219
1320const CI_DIRECTORY : & str = concat ! ( env!( "CARGO_MANIFEST_DIR" ) , "/.." ) ;
@@ -75,7 +82,7 @@ impl JobDatabase {
7582}
7683
7784fn load_job_db ( path : & Path ) -> anyhow:: Result < JobDatabase > {
78- let db = read_to_string ( path) ?;
85+ let db = utils :: read_to_string ( path) ?;
7986 let mut db: Value = serde_yaml:: from_str ( & db) ?;
8087
8188 // We need to expand merge keys (<<), because serde_yaml can't deal with them
@@ -148,10 +155,6 @@ impl GitHubContext {
148155 }
149156}
150157
151- fn load_env_var ( name : & str ) -> anyhow:: Result < String > {
152- std:: env:: var ( name) . with_context ( || format ! ( "Cannot find variable {name}" ) )
153- }
154-
155158fn load_github_ctx ( ) -> anyhow:: Result < GitHubContext > {
156159 let event_name = load_env_var ( "GITHUB_EVENT_NAME" ) ?;
157160 let commit_message =
@@ -325,6 +328,18 @@ fn run_workflow_locally(db: JobDatabase, job_type: JobType, name: String) -> any
325328 if !result. success ( ) { Err ( anyhow:: anyhow!( "Job failed" ) ) } else { Ok ( ( ) ) }
326329}
327330
331+ fn upload_ci_metrics ( cpu_usage_csv : & Path ) -> anyhow:: Result < ( ) > {
332+ let usage = load_cpu_usage ( cpu_usage_csv) . context ( "Cannot load CPU usage from input CSV" ) ?;
333+ eprintln ! ( "CPU usage\n {usage:?}" ) ;
334+
335+ let avg = if !usage. is_empty ( ) { usage. iter ( ) . sum :: < f64 > ( ) / usage. len ( ) as f64 } else { 0.0 } ;
336+ eprintln ! ( "CPU usage average: {avg}" ) ;
337+
338+ upload_datadog_metric ( "avg-cpu-usage" , avg) . context ( "Cannot upload Datadog metric" ) ?;
339+
340+ Ok ( ( ) )
341+ }
342+
328343#[ derive( clap:: Parser ) ]
329344enum Args {
330345 /// Calculate a list of jobs that should be executed on CI.
@@ -350,6 +365,11 @@ enum Args {
350365 /// Usually, this will be GITHUB_STEP_SUMMARY on CI.
351366 summary_path : PathBuf ,
352367 } ,
368+ /// Upload CI metrics to Datadog.
369+ UploadBuildMetrics {
370+ /// Path to a CSV containing the CI job CPU usage.
371+ cpu_usage_csv : PathBuf ,
372+ } ,
353373}
354374
355375#[ derive( clap:: ValueEnum , Clone ) ]
@@ -370,7 +390,7 @@ fn main() -> anyhow::Result<()> {
370390 let jobs_path = jobs_file. as_deref ( ) . unwrap_or ( default_jobs_file) ;
371391 let gh_ctx = load_github_ctx ( )
372392 . context ( "Cannot load environment variables from GitHub Actions" ) ?;
373- let channel = read_to_string ( Path :: new ( CI_DIRECTORY ) . join ( "channel" ) )
393+ let channel = utils :: read_to_string ( Path :: new ( CI_DIRECTORY ) . join ( "channel" ) )
374394 . context ( "Cannot read channel file" ) ?
375395 . trim ( )
376396 . to_string ( ) ;
@@ -379,7 +399,10 @@ fn main() -> anyhow::Result<()> {
379399 . context ( "Failed to calculate job matrix" ) ?;
380400 }
381401 Args :: RunJobLocally { job_type, name } => {
382- run_workflow_locally ( load_db ( default_jobs_file) ?, job_type, name) ?
402+ run_workflow_locally ( load_db ( default_jobs_file) ?, job_type, name) ?;
403+ }
404+ Args :: UploadBuildMetrics { cpu_usage_csv } => {
405+ upload_ci_metrics ( & cpu_usage_csv) ?;
383406 }
384407 Args :: PostprocessMetrics { metrics_path, summary_path } => {
385408 postprocess_metrics ( & metrics_path, & summary_path) ?;
@@ -388,8 +411,3 @@ fn main() -> anyhow::Result<()> {
388411
389412 Ok ( ( ) )
390413}
391-
392- fn read_to_string < P : AsRef < Path > > ( path : P ) -> anyhow:: Result < String > {
393- let error = format ! ( "Cannot read file {:?}" , path. as_ref( ) ) ;
394- std:: fs:: read_to_string ( path) . context ( error)
395- }
0 commit comments