logd: liblog: logcat: Add Statistics
- logd add statistical collection and formatting
- liblog add android_logger_get_statistics call
- logcat add -S flag
- logcat add -b all
(cherry picked from commit 51a29c8dc445e4fb89860561933e54a231e6ffb4)
Change-Id: I521753b1969ecd4590c956aeeb1557d101059d67
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 3c33938..812e2e0 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -225,10 +225,11 @@
" -t <count> print only the most recent <count> lines (implies -d)\n"
" -T <count> print only the most recent <count> lines (does not imply -d)\n"
" -g get the size of the log's ring buffer and exit\n"
- " -b <buffer> Request alternate ring buffer, 'main', 'system', 'radio'\n"
- " or 'events'. Multiple -b parameters are allowed and the\n"
+ " -b <buffer> Request alternate ring buffer, 'main', 'system', 'radio',\n"
+ " 'events' or 'all'. Multiple -b parameters are allowed and\n"
" results are interleaved. The default is -b main -b system.\n"
- " -B output the log in binary");
+ " -B output the log in binary.\n"
+ " -S output statistics");
fprintf(stderr,"\nfilterspecs are a series of \n"
@@ -278,6 +279,7 @@
int hasSetLogFormat = 0;
int clearLog = 0;
int getLogSize = 0;
+ int printStatistics = 0;
int mode = O_RDONLY;
const char *forceFilters = NULL;
log_device_t* devices = NULL;
@@ -303,7 +305,7 @@
for (;;) {
int ret;
- ret = getopt(argc, argv, "cdt:T:gsQf:r::n:v:b:B");
+ ret = getopt(argc, argv, "cdt:T:gsQf:r::n:v:b:BS");
if (ret < 0) {
break;
@@ -336,6 +338,39 @@
break;
case 'b': {
+ if (strcmp(optarg, "all") == 0) {
+ while (devices) {
+ dev = devices;
+ devices = dev->next;
+ delete dev;
+ }
+
+ dev = devices = new log_device_t("main", false, 'm');
+ android::g_devCount = 1;
+ if (android_name_to_log_id("system") == LOG_ID_SYSTEM) {
+ dev->next = new log_device_t("system", false, 's');
+ if (dev->next) {
+ dev = dev->next;
+ android::g_devCount++;
+ }
+ }
+ if (android_name_to_log_id("radio") == LOG_ID_RADIO) {
+ dev->next = new log_device_t("radio", false, 'r');
+ if (dev->next) {
+ dev = dev->next;
+ android::g_devCount++;
+ }
+ }
+ if (android_name_to_log_id("events") == LOG_ID_EVENTS) {
+ dev->next = new log_device_t("events", true, 'e');
+ if (dev->next) {
+ android::g_devCount++;
+ needBinary = true;
+ }
+ }
+ break;
+ }
+
bool binary = strcmp(optarg, "events") == 0;
if (binary) {
needBinary = true;
@@ -470,6 +505,10 @@
}
break;
+ case 'S':
+ printStatistics = 1;
+ break;
+
default:
fprintf(stderr,"Unrecognized Option\n");
android::show_help(argv[0]);
@@ -587,6 +626,56 @@
dev = dev->next;
}
+ if (printStatistics) {
+ size_t len = 8192;
+ char *buf;
+
+ for(int retry = 32;
+ (retry >= 0) && ((buf = new char [len]));
+ delete [] buf, --retry) {
+ android_logger_get_statistics(logger_list, buf, len);
+
+ buf[len-1] = '\0';
+ size_t ret = atol(buf) + 1;
+ if (ret < 4) {
+ delete [] buf;
+ buf = NULL;
+ break;
+ }
+ bool check = ret <= len;
+ len = ret;
+ if (check) {
+ break;
+ }
+ }
+
+ if (!buf) {
+ perror("statistics read");
+ exit(EXIT_FAILURE);
+ }
+
+ // remove trailing FF
+ char *cp = buf + len - 1;
+ *cp = '\0';
+ bool truncated = *--cp != '\f';
+ if (!truncated) {
+ *cp = '\0';
+ }
+
+ // squash out the byte count
+ cp = buf;
+ if (!truncated) {
+ while (isdigit(*cp) || (*cp == '\n')) {
+ ++cp;
+ }
+ }
+
+ printf("%s", cp);
+ delete [] buf;
+ exit(0);
+ }
+
+
if (getLogSize) {
exit(0);
}