package output import ( "bufio" "fmt" "os" "time" "github.com/apex/log" "github.com/mitchellh/go-wordwrap" "github.com/ooni/probe-cli/v3/internal/database" ) // MeasurementJSON prints the JSON of a measurement func MeasurementJSON(j map[string]interface{}) { log.WithFields(log.Fields{ "type": "measurement_json", "measurement_json": j, }).Info("Measurement JSON") } // Progress logs a progress type event func Progress(key string, perc float64, eta float64, msg string) { log.WithFields(log.Fields{ "type": "progress", "key": key, "percentage": perc, "eta": eta, }).Info(msg) } // MeasurementSummaryData contains summary information on the measurement type MeasurementSummaryData struct { TotalRuntime float64 TotalCount int64 AnomalyCount int64 DataUsageUp float64 DataUsageDown float64 ASN uint NetworkName string NetworkCountryCode string StartTime time.Time } // MeasurementSummary emits the measurement summary func MeasurementSummary(msmt MeasurementSummaryData) { log.WithFields(log.Fields{ "type": "measurement_summary", "total_runtime": msmt.TotalRuntime, "total_count": msmt.TotalCount, "anomaly_count": msmt.AnomalyCount, "data_usage_down": msmt.DataUsageDown, "data_usage_up": msmt.DataUsageUp, "asn": msmt.ASN, "network_country_code": msmt.NetworkCountryCode, "network_name": msmt.NetworkName, "start_time": msmt.StartTime, }).Info("measurement summary") } // MeasurementItem logs a progress type event func MeasurementItem(msmt database.MeasurementURLNetwork, isFirst bool, isLast bool) { log.WithFields(log.Fields{ "type": "measurement_item", "is_first": isFirst, "is_last": isLast, "id": msmt.Measurement.ID, "test_name": msmt.TestName, "test_group_name": msmt.Result.TestGroupName, "start_time": msmt.Measurement.StartTime, "test_keys": msmt.TestKeys, "network_country_code": msmt.Network.CountryCode, "network_name": msmt.Network.NetworkName, "asn": msmt.Network.ASN, "runtime": msmt.Measurement.Runtime, "url": msmt.URL.URL.String, "url_category_code": msmt.URL.CategoryCode.String, "url_country_code": msmt.URL.CountryCode.String, "is_anomaly": msmt.IsAnomaly.Bool, "is_uploaded": msmt.Measurement.IsUploaded, "is_upload_failed": msmt.IsUploadFailed, "upload_failure_msg": msmt.UploadFailureMsg.String, "is_failed": msmt.IsFailed, "failure_msg": msmt.FailureMsg.String, "is_done": msmt.Measurement.IsDone, "report_file_path": msmt.ReportFilePath.String, "measurement_file_path": msmt.MeasurementFilePath.String, }).Info("measurement") } // ResultItemData is the metadata about a result type ResultItemData struct { ID int64 Name string StartTime time.Time TestKeys string MeasurementCount uint64 MeasurementAnomalyCount uint64 Runtime float64 Country string NetworkName string ASN uint Done bool IsUploaded bool DataUsageDown float64 DataUsageUp float64 Index int TotalCount int } // ResultItem logs a progress type event func ResultItem(result ResultItemData) { log.WithFields(log.Fields{ "type": "result_item", "id": result.ID, "name": result.Name, "start_time": result.StartTime, "test_keys": result.TestKeys, "measurement_count": result.MeasurementCount, "measurement_anomaly_count": result.MeasurementAnomalyCount, "network_country_code": result.Country, "network_name": result.NetworkName, "asn": result.ASN, "runtime": result.Runtime, "is_done": result.Done, "is_uploaded": result.IsUploaded, "data_usage_down": result.DataUsageDown, "data_usage_up": result.DataUsageUp, "index": result.Index, "total_count": result.TotalCount, }).Info("result item") } // ResultSummaryData contains the summary data of a result type ResultSummaryData struct { TotalTests int64 TotalDataUsageUp float64 TotalDataUsageDown float64 TotalNetworks int64 } // ResultSummary emits the result summary func ResultSummary(result ResultSummaryData) { log.WithFields(log.Fields{ "type": "result_summary", "total_tests": result.TotalTests, "total_data_usage_up": result.TotalDataUsageUp, "total_data_usage_down": result.TotalDataUsageDown, "total_networks": result.TotalNetworks, }).Info("result summary") } // SectionTitle is the title of a section func SectionTitle(text string) { log.WithFields(log.Fields{ "type": "section_title", "title": text, }).Info(text) } // Paragraph makes a word-wrapped paragraph out of text func Paragraph(text string) { const width = 80 fmt.Println(wordwrap.WrapString(text, width)) } // Bullet is like paragraph but with a bullet point in front func Bullet(text string) { const width = 80 fmt.Printf("• %s\n", wordwrap.WrapString(text, width)) } // PressAnyKeyToContinue blocks until the user presses any key func PressAnyKeyToContinue(text string) error { fmt.Print(text) _, err := bufio.NewReader(os.Stdin).ReadBytes('\n') return err }