am b02b6f41: Merge "metrics: Add an option to metrics_client to dump the logs cache."

* commit 'b02b6f410d5c92c7b016ed26895b5e21c16418a9':
  metrics: Add an option to metrics_client to dump the logs cache.
This commit is contained in:
James Hawkins 2015-09-11 22:14:03 +00:00 committed by Android Git Automerger
commit 861edb6261
3 changed files with 118 additions and 33 deletions

View file

@ -17,9 +17,15 @@
#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,
@ -36,12 +42,13 @@ void ShowUsage() {
" metrics_client -s name sample\n"
" metrics_client -v event\n"
" metrics_client -u action\n"
" metrics_client [-cg]\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"
@ -132,17 +139,57 @@ static int IsGuestMode() {
return metrics_lib.IsGuestMode() ? 0 : 1;
}
static int DumpLogs() {
printf("Metrics from %s\n\n", metrics::kMetricsEventsFilePath);
ScopedVector<metrics::MetricSample> metrics;
metrics::SerializationUtils::ReadMetricsFromFile(
metrics::kMetricsEventsFilePath, &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, "abcegstuv")) != -1) {
while ((flag = getopt(argc, argv, "abcdegstuv")) != -1) {
switch (flag) {
case 'c':
mode = kModeHasConsent;
break;
case 'd':
mode = kModeDumpLogs;
break;
case 'e':
mode = kModeSendEnumSample;
break;
@ -203,6 +250,8 @@ int main(int argc, char** argv) {
return HasConsent();
case kModeIsGuestMode:
return IsGuestMode();
case kModeDumpLogs:
return DumpLogs();
default:
ShowUsage();
return 0;

View file

@ -96,6 +96,50 @@ bool ReadMessage(int fd, std::string* message) {
return true;
}
// Opens the metrics log file at |filename| in the given |mode|.
//
// Returns the file descriptor wrapped in a valid ScopedFD on success.
base::ScopedFD OpenMetricsFile(const std::string& filename, mode_t mode) {
struct stat stat_buf;
int result;
result = stat(filename.c_str(), &stat_buf);
if (result < 0) {
if (errno != ENOENT)
DPLOG(ERROR) << filename << ": bad metrics file stat";
// Nothing to collect---try later.
return base::ScopedFD();
}
if (stat_buf.st_size == 0) {
// Also nothing to collect.
return base::ScopedFD();
}
base::ScopedFD fd(open(filename.c_str(), mode));
if (fd.get() < 0) {
DPLOG(ERROR) << filename << ": cannot open";
return base::ScopedFD();
}
return fd.Pass();
}
// Parses the contents of the metrics log file descriptor |fd| into |metrics|.
void ReadAllMetricsFromFd(int fd, ScopedVector<MetricSample>* metrics) {
for (;;) {
std::string message;
if (!ReadMessage(fd, &message))
break;
scoped_ptr<MetricSample> sample = SerializationUtils::ParseSample(message);
if (sample)
metrics->push_back(sample.release());
}
}
} // namespace
scoped_ptr<MetricSample> SerializationUtils::ParseSample(
@ -131,30 +175,27 @@ scoped_ptr<MetricSample> SerializationUtils::ParseSample(
return scoped_ptr<MetricSample>();
}
void SerializationUtils::ReadMetricsFromFile(
const std::string& filename,
ScopedVector<MetricSample>* metrics) {
base::ScopedFD fd(OpenMetricsFile(filename, O_RDONLY));
if (!fd.is_valid()) {
return;
}
// This processes all messages in the log.
ReadAllMetricsFromFd(fd.get(), metrics);
}
void SerializationUtils::ReadAndTruncateMetricsFromFile(
const std::string& filename,
ScopedVector<MetricSample>* metrics) {
struct stat stat_buf;
int result;
base::ScopedFD fd(OpenMetricsFile(filename, O_RDWR));
if (!fd.is_valid()) {
return;
}
result = stat(filename.c_str(), &stat_buf);
if (result < 0) {
if (errno != ENOENT)
DPLOG(ERROR) << filename << ": bad metrics file stat";
// Nothing to collect---try later.
return;
}
if (stat_buf.st_size == 0) {
// Also nothing to collect.
return;
}
base::ScopedFD fd(open(filename.c_str(), O_RDWR));
if (fd.get() < 0) {
DPLOG(ERROR) << filename << ": cannot open";
return;
}
result = flock(fd.get(), LOCK_EX);
int result = flock(fd.get(), LOCK_EX);
if (result < 0) {
DPLOG(ERROR) << filename << ": cannot lock";
return;
@ -162,16 +203,7 @@ void SerializationUtils::ReadAndTruncateMetricsFromFile(
// This processes all messages in the log. When all messages are
// read and processed, or an error occurs, truncate the file to zero size.
for (;;) {
std::string message;
if (!ReadMessage(fd.get(), &message))
break;
scoped_ptr<MetricSample> sample = ParseSample(message);
if (sample)
metrics->push_back(sample.release());
}
ReadAllMetricsFromFd(fd.get(), metrics);
result = ftruncate(fd.get(), 0);
if (result < 0)

View file

@ -35,7 +35,11 @@ namespace SerializationUtils {
// deserialization was successful) or a NULL scoped_ptr.
scoped_ptr<MetricSample> ParseSample(const std::string& sample);
// Reads all samples from a file and truncate the file when done.
// Reads all samples from a file. The file contents remain unchanged.
void ReadMetricsFromFile(const std::string& filename,
ScopedVector<MetricSample>* metrics);
// Reads all samples from a file and truncates the file when done.
void ReadAndTruncateMetricsFromFile(const std::string& filename,
ScopedVector<MetricSample>* metrics);