blob: 93ca7f90330acec12fe0bf5c3611f09d07bbcb32 [file] [log] [blame]
// Copyright 2011 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <getopt.h>
#include <unistd.h>
#include <cstdio>
#include <cstdlib>
#include "metrics/metrics_client_util.h"
#include "metrics/metrics_library.h"
#include "metrics/structured/metrics_client_structured_events.h"
#include "metrics/structured/recorder.h"
#include "metrics/structured/recorder_singleton.h"
namespace {
enum Mode {
kModeSendSample,
kModeSendEnumSample,
kModeSendSparseSample,
kModeSendUserAction,
kModeSendCrosEvent,
kModeHasConsent,
kModeIsGuestMode,
kModeShowConsentId,
kModeCreateConsent,
kModeDeleteConsent,
kModeReplayFile,
};
int ParseInt(const char* arg) {
char* endptr;
int value = strtol(arg, &endptr, 0);
if (*endptr != '\0') {
fprintf(stderr, "metrics client: bad integer \"%s\"\n", arg);
metrics_client::ShowUsage(stderr);
exit(1);
}
return value;
}
double ParseDouble(const char* arg) {
char* endptr;
double value = strtod(arg, &endptr);
if (*endptr != '\0') {
fprintf(stderr, "metrics client: bad double \"%s\"\n", arg);
metrics_client::ShowUsage(stderr);
exit(1);
}
return value;
}
int SendStats(char* argv[],
int name_index,
enum Mode mode,
bool secs_to_msecs,
const char* output_file,
int num_samples) {
const char* name = argv[name_index];
int sample;
if (secs_to_msecs) {
sample = static_cast<int>(ParseDouble(argv[name_index + 1]) * 1000.0);
} else {
sample = ParseInt(argv[name_index + 1]);
}
MetricsLibrary metrics_lib;
if (output_file) {
metrics_lib.SetOutputFile(output_file);
}
if (mode == kModeSendSparseSample) {
metrics_lib.SendRepeatedSparseToUMA(name, sample, num_samples);
} else if (mode == kModeSendEnumSample) {
int exclusive_max = ParseInt(argv[name_index + 2]);
metrics_lib.SendRepeatedEnumToUMA(name, sample, exclusive_max, num_samples);
} else {
int min = ParseInt(argv[name_index + 2]);
int max = ParseInt(argv[name_index + 3]);
int nbuckets = ParseInt(argv[name_index + 4]);
metrics_lib.SendRepeatedToUMA(name, sample, min, max, nbuckets,
num_samples);
}
return 0;
}
int SendUserAction(char* argv[], int action_index, int num_samples) {
const char* action = argv[action_index];
MetricsLibrary metrics_lib;
metrics_lib.SendRepeatedUserActionToUMA(action, num_samples);
return 0;
}
int SendCrosEvent(char* argv[], int action_index, int num_samples) {
const char* event = argv[action_index];
bool result;
MetricsLibrary metrics_lib;
result = metrics_lib.SendRepeatedCrosEventToUMA(event, num_samples);
if (!result) {
fprintf(stderr, "metrics_client: could not send event %s\n", event);
return 1;
}
return 0;
}
int CreateConsent() {
MetricsLibrary metrics_lib;
return metrics_lib.EnableMetrics() ? 0 : 1;
}
int DeleteConsent() {
MetricsLibrary metrics_lib;
return metrics_lib.DisableMetrics() ? 0 : 1;
}
int HasConsent() {
MetricsLibrary metrics_lib;
return metrics_lib.AreMetricsEnabled() ? 0 : 1;
}
int IsGuestMode() {
MetricsLibrary metrics_lib;
return metrics_lib.IsGuestMode() ? 0 : 1;
}
int ShowConsentId() {
MetricsLibrary metrics_lib;
std::string id;
if (metrics_lib.ConsentId(&id) == false) {
fprintf(stderr, "error: consent not given\n");
return 1;
}
printf("%s\n", id.c_str());
return 0;
}
int ReplayFile(const char* input_file, const char* output_file) {
MetricsLibrary metrics_lib;
if (output_file) {
metrics_lib.SetOutputFile(output_file);
}
return metrics_lib.Replay(input_file) ? 0 : 1;
}
int SendStructuredMetricWrapper(int argc, char* argv[], int current_arg) {
int result =
metrics_client::SendStructuredMetric(argc, argv, current_arg, stderr);
metrics::structured::RecorderSingleton::GetInstance()->GetRecorder()->Flush();
return result;
}
} // namespace
int main(int argc, char** argv) {
enum Mode mode = kModeSendSample;
bool secs_to_msecs = false;
const char* output_file = nullptr;
const char* input_file = nullptr;
const char* num_samples_cstr = nullptr;
constexpr int kStructuredVal = 0x5740;
struct option longoptions[2];
longoptions[0].name = "structured";
longoptions[0].has_arg = false;
longoptions[0].flag = nullptr;
longoptions[0].val = kStructuredVal;
longoptions[1].name = nullptr;
longoptions[1].has_arg = false;
longoptions[1].flag = nullptr;
longoptions[1].val = 0;
// Parse arguments
int flag;
while ((flag = getopt_long(argc, argv, "CDR:W:cegin:stuv", longoptions,
nullptr)) != -1) {
switch (flag) {
case 'C':
mode = kModeCreateConsent;
break;
case 'D':
mode = kModeDeleteConsent;
break;
case 'R':
mode = kModeReplayFile;
input_file = optarg;
break;
case 'W':
output_file = optarg;
break;
case 'c':
mode = kModeHasConsent;
break;
case 'e':
mode = kModeSendEnumSample;
break;
case 'g':
mode = kModeIsGuestMode;
break;
case 'i':
// This flag is slated for removal.
// See comment in ShowUsage().
mode = kModeShowConsentId;
break;
case 'n':
num_samples_cstr = optarg;
break;
case 's':
mode = kModeSendSparseSample;
break;
case 't':
secs_to_msecs = true;
break;
case 'u':
mode = kModeSendUserAction;
break;
case 'v':
mode = kModeSendCrosEvent;
break;
case kStructuredVal:
return SendStructuredMetricWrapper(argc, argv, optind);
default:
metrics_client::ShowUsage(stderr);
return 1;
}
}
int arg_index = optind;
int num_samples = 1;
if (num_samples_cstr) {
num_samples = ParseInt(num_samples_cstr);
if (num_samples <= 0) {
fprintf(stderr, "metrics client: bad num_samples \"%s\"\n",
num_samples_cstr);
metrics_client::ShowUsage(stderr);
return 1;
}
}
int expected_args = 0;
if (mode == kModeSendSample) {
expected_args = 5;
} else if (mode == kModeSendEnumSample) {
expected_args = 3;
} else if (mode == kModeSendSparseSample) {
expected_args = 2;
} else if (mode == kModeSendUserAction) {
expected_args = 1;
} else if (mode == kModeSendCrosEvent) {
expected_args = 1;
}
if ((arg_index + expected_args) != argc) {
metrics_client::ShowUsage(stderr);
return 1;
}
switch (mode) {
case kModeSendSample:
case kModeSendEnumSample:
case kModeSendSparseSample:
if ((mode != kModeSendSample) && secs_to_msecs) {
metrics_client::ShowUsage(stderr);
return 1;
}
return SendStats(argv, arg_index, mode, secs_to_msecs, output_file,
num_samples);
case kModeSendUserAction:
return SendUserAction(argv, arg_index, num_samples);
case kModeSendCrosEvent:
return SendCrosEvent(argv, arg_index, num_samples);
case kModeCreateConsent:
return CreateConsent();
case kModeDeleteConsent:
return DeleteConsent();
case kModeHasConsent:
return HasConsent();
case kModeIsGuestMode:
return IsGuestMode();
case kModeShowConsentId:
return ShowConsentId();
case kModeReplayFile:
return ReplayFile(input_file, output_file);
default:
metrics_client::ShowUsage(stderr);
return 1;
}
}