2765d0abcc
Instead of passing different filenames around, only rely on the metrics directory and infer the filepath from it. This makes testing easier. BUG: 23939404 TEST: unit tests. Change-Id: I79086acc3a546464114fa8ec4656ec04e1c43e35
261 lines
7.2 KiB
C++
261 lines
7.2 KiB
C++
/*
|
|
* Copyright (C) 2015 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
|
|
#include <base/memory/scoped_vector.h>
|
|
|
|
#include "constants.h"
|
|
#include "metrics/metrics_library.h"
|
|
#include "serialization/metric_sample.h"
|
|
#include "serialization/serialization_utils.h"
|
|
|
|
enum Mode {
|
|
kModeDumpLogs,
|
|
kModeSendSample,
|
|
kModeSendEnumSample,
|
|
kModeSendSparseSample,
|
|
kModeSendUserAction,
|
|
kModeSendCrosEvent,
|
|
kModeHasConsent,
|
|
kModeIsGuestMode,
|
|
};
|
|
|
|
void ShowUsage() {
|
|
fprintf(stderr,
|
|
"Usage: metrics_client [-t] name sample min max nbuckets\n"
|
|
" metrics_client -e name sample max\n"
|
|
" metrics_client -s name sample\n"
|
|
" metrics_client -v event\n"
|
|
" metrics_client -u action\n"
|
|
" metrics_client [-cdg]\n"
|
|
"\n"
|
|
" default: send metric with integer values \n"
|
|
" |min| > 0, |min| <= sample < |max|\n"
|
|
" -c: return exit status 0 if user consents to stats, 1 otherwise,\n"
|
|
" in guest mode always return 1\n"
|
|
" -d: dump cached logs to the console\n"
|
|
" -e: send linear/enumeration histogram data\n"
|
|
" -g: return exit status 0 if machine in guest mode, 1 otherwise\n"
|
|
" -s: send a sparse histogram sample\n"
|
|
" -t: convert sample from double seconds to int milliseconds\n"
|
|
" -u: send a user action to Chrome\n"
|
|
" -v: send a Platform.CrOSEvent enum histogram sample\n");
|
|
exit(1);
|
|
}
|
|
|
|
static 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);
|
|
ShowUsage();
|
|
}
|
|
return value;
|
|
}
|
|
|
|
static double ParseDouble(const char *arg) {
|
|
char *endptr;
|
|
double value = strtod(arg, &endptr);
|
|
if (*endptr != '\0') {
|
|
fprintf(stderr, "metrics client: bad double \"%s\"\n", arg);
|
|
ShowUsage();
|
|
}
|
|
return value;
|
|
}
|
|
|
|
static int SendStats(char* argv[],
|
|
int name_index,
|
|
enum Mode mode,
|
|
bool secs_to_msecs) {
|
|
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;
|
|
metrics_lib.Init();
|
|
if (mode == kModeSendSparseSample) {
|
|
metrics_lib.SendSparseToUMA(name, sample);
|
|
} else if (mode == kModeSendEnumSample) {
|
|
int max = ParseInt(argv[name_index + 2]);
|
|
metrics_lib.SendEnumToUMA(name, sample, max);
|
|
} else {
|
|
int min = ParseInt(argv[name_index + 2]);
|
|
int max = ParseInt(argv[name_index + 3]);
|
|
int nbuckets = ParseInt(argv[name_index + 4]);
|
|
metrics_lib.SendToUMA(name, sample, min, max, nbuckets);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int SendUserAction(char* argv[], int action_index) {
|
|
const char* action = argv[action_index];
|
|
MetricsLibrary metrics_lib;
|
|
metrics_lib.Init();
|
|
metrics_lib.SendUserActionToUMA(action);
|
|
return 0;
|
|
}
|
|
|
|
static int SendCrosEvent(char* argv[], int action_index) {
|
|
const char* event = argv[action_index];
|
|
bool result;
|
|
MetricsLibrary metrics_lib;
|
|
metrics_lib.Init();
|
|
result = metrics_lib.SendCrosEventToUMA(event);
|
|
if (!result) {
|
|
fprintf(stderr, "metrics_client: could not send event %s\n", event);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int HasConsent() {
|
|
MetricsLibrary metrics_lib;
|
|
metrics_lib.Init();
|
|
return metrics_lib.AreMetricsEnabled() ? 0 : 1;
|
|
}
|
|
|
|
static int IsGuestMode() {
|
|
MetricsLibrary metrics_lib;
|
|
metrics_lib.Init();
|
|
return metrics_lib.IsGuestMode() ? 0 : 1;
|
|
}
|
|
|
|
static int DumpLogs() {
|
|
base::FilePath events_file = base::FilePath(
|
|
metrics::kMetricsDirectory).Append(metrics::kMetricsEventsFileName);
|
|
printf("Metrics from %s\n\n", events_file.value().data());
|
|
|
|
ScopedVector<metrics::MetricSample> metrics;
|
|
metrics::SerializationUtils::ReadMetricsFromFile(events_file.value(),
|
|
&metrics);
|
|
|
|
for (ScopedVector<metrics::MetricSample>::const_iterator i = metrics.begin();
|
|
i != metrics.end(); ++i) {
|
|
const metrics::MetricSample* sample = *i;
|
|
printf("name: %s\t", sample->name().c_str());
|
|
printf("type: ");
|
|
|
|
switch (sample->type()) {
|
|
case metrics::MetricSample::CRASH:
|
|
printf("CRASH");
|
|
break;
|
|
case metrics::MetricSample::HISTOGRAM:
|
|
printf("HISTOGRAM");
|
|
break;
|
|
case metrics::MetricSample::LINEAR_HISTOGRAM:
|
|
printf("LINEAR_HISTOGRAM");
|
|
break;
|
|
case metrics::MetricSample::SPARSE_HISTOGRAM:
|
|
printf("SPARSE_HISTOGRAM");
|
|
break;
|
|
case metrics::MetricSample::USER_ACTION:
|
|
printf("USER_ACTION");
|
|
break;
|
|
}
|
|
|
|
printf("\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
enum Mode mode = kModeSendSample;
|
|
bool secs_to_msecs = false;
|
|
|
|
// Parse arguments
|
|
int flag;
|
|
while ((flag = getopt(argc, argv, "abcdegstuv")) != -1) {
|
|
switch (flag) {
|
|
case 'c':
|
|
mode = kModeHasConsent;
|
|
break;
|
|
case 'd':
|
|
mode = kModeDumpLogs;
|
|
break;
|
|
case 'e':
|
|
mode = kModeSendEnumSample;
|
|
break;
|
|
case 'g':
|
|
mode = kModeIsGuestMode;
|
|
break;
|
|
case 's':
|
|
mode = kModeSendSparseSample;
|
|
break;
|
|
case 't':
|
|
secs_to_msecs = true;
|
|
break;
|
|
case 'u':
|
|
mode = kModeSendUserAction;
|
|
break;
|
|
case 'v':
|
|
mode = kModeSendCrosEvent;
|
|
break;
|
|
default:
|
|
ShowUsage();
|
|
break;
|
|
}
|
|
}
|
|
int arg_index = optind;
|
|
|
|
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) {
|
|
ShowUsage();
|
|
}
|
|
|
|
switch (mode) {
|
|
case kModeSendSample:
|
|
case kModeSendEnumSample:
|
|
case kModeSendSparseSample:
|
|
if ((mode != kModeSendSample) && secs_to_msecs) {
|
|
ShowUsage();
|
|
}
|
|
return SendStats(argv,
|
|
arg_index,
|
|
mode,
|
|
secs_to_msecs);
|
|
case kModeSendUserAction:
|
|
return SendUserAction(argv, arg_index);
|
|
case kModeSendCrosEvent:
|
|
return SendCrosEvent(argv, arg_index);
|
|
case kModeHasConsent:
|
|
return HasConsent();
|
|
case kModeIsGuestMode:
|
|
return IsGuestMode();
|
|
case kModeDumpLogs:
|
|
return DumpLogs();
|
|
default:
|
|
ShowUsage();
|
|
return 0;
|
|
}
|
|
}
|