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:
commit
861edb6261
3 changed files with 118 additions and 33 deletions
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue