• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <cstdio>
18 #include <cstdlib>
19 
20 #include "constants.h"
21 #include "metrics/metrics_library.h"
22 
23 enum Mode {
24     kModeDumpHistograms,
25     kModeSendSample,
26     kModeSendEnumSample,
27     kModeSendSparseSample,
28     kModeSendCrosEvent,
29     kModeHasConsent,
30     kModeIsGuestMode,
31 };
32 
ShowUsage()33 void ShowUsage() {
34   fprintf(stderr,
35           "Usage:  metrics_client [-t] name sample min max nbuckets\n"
36           "        metrics_client -e   name sample max\n"
37           "        metrics_client -s   name sample\n"
38           "        metrics_client -v   event\n"
39           "        metrics_client [-cdg]\n"
40           "\n"
41           "  default: send metric with integer values \n"
42           "           |min| > 0, |min| <= sample < |max|\n"
43           "  -c: return exit status 0 if user consents to stats, 1 otherwise,\n"
44           "      in guest mode always return 1\n"
45           "  -d: dump the histograms recorded by metricsd to stdout\n"
46           "  -e: send linear/enumeration histogram data\n"
47           "  -g: return exit status 0 if machine in guest mode, 1 otherwise\n"
48           "  -s: send a sparse histogram sample\n"
49           "  -t: convert sample from double seconds to int milliseconds\n"
50           "  -v: send a Platform.CrOSEvent enum histogram sample\n");
51   exit(1);
52 }
53 
ParseInt(const char * arg)54 static int ParseInt(const char *arg) {
55   char *endptr;
56   int value = strtol(arg, &endptr, 0);
57   if (*endptr != '\0') {
58     fprintf(stderr, "metrics client: bad integer \"%s\"\n", arg);
59     ShowUsage();
60   }
61   return value;
62 }
63 
ParseDouble(const char * arg)64 static double ParseDouble(const char *arg) {
65   char *endptr;
66   double value = strtod(arg, &endptr);
67   if (*endptr != '\0') {
68     fprintf(stderr, "metrics client: bad double \"%s\"\n", arg);
69     ShowUsage();
70   }
71   return value;
72 }
73 
DumpHistograms()74 static int DumpHistograms() {
75   MetricsLibrary metrics_lib;
76   metrics_lib.Init();
77 
78   std::string dump;
79   if (!metrics_lib.GetHistogramsDump(&dump)) {
80     printf("Failed to dump the histograms.");
81     return 1;
82   }
83 
84   printf("%s\n", dump.c_str());
85   return 0;
86 }
87 
SendStats(char * argv[],int name_index,enum Mode mode,bool secs_to_msecs)88 static int SendStats(char* argv[],
89                      int name_index,
90                      enum Mode mode,
91                      bool secs_to_msecs) {
92   const char* name = argv[name_index];
93   int sample;
94   if (secs_to_msecs) {
95     sample = static_cast<int>(ParseDouble(argv[name_index + 1]) * 1000.0);
96   } else {
97     sample = ParseInt(argv[name_index + 1]);
98   }
99 
100   MetricsLibrary metrics_lib;
101   metrics_lib.Init();
102   if (mode == kModeSendSparseSample) {
103     metrics_lib.SendSparseToUMA(name, sample);
104   } else if (mode == kModeSendEnumSample) {
105     int max = ParseInt(argv[name_index + 2]);
106     metrics_lib.SendEnumToUMA(name, sample, max);
107   } else {
108     int min = ParseInt(argv[name_index + 2]);
109     int max = ParseInt(argv[name_index + 3]);
110     int nbuckets = ParseInt(argv[name_index + 4]);
111     metrics_lib.SendToUMA(name, sample, min, max, nbuckets);
112   }
113   return 0;
114 }
115 
SendCrosEvent(char * argv[],int action_index)116 static int SendCrosEvent(char* argv[], int action_index) {
117   const char* event = argv[action_index];
118   bool result;
119   MetricsLibrary metrics_lib;
120   metrics_lib.Init();
121   result = metrics_lib.SendCrosEventToUMA(event);
122   if (!result) {
123     fprintf(stderr, "metrics_client: could not send event %s\n", event);
124     return 1;
125   }
126   return 0;
127 }
128 
HasConsent()129 static int HasConsent() {
130   MetricsLibrary metrics_lib;
131   metrics_lib.Init();
132   return metrics_lib.AreMetricsEnabled() ? 0 : 1;
133 }
134 
IsGuestMode()135 static int IsGuestMode() {
136   MetricsLibrary metrics_lib;
137   metrics_lib.Init();
138   return metrics_lib.IsGuestMode() ? 0 : 1;
139 }
140 
main(int argc,char ** argv)141 int main(int argc, char** argv) {
142   enum Mode mode = kModeSendSample;
143   bool secs_to_msecs = false;
144 
145   // Parse arguments
146   int flag;
147   while ((flag = getopt(argc, argv, "abcdegstv")) != -1) {
148     switch (flag) {
149       case 'c':
150         mode = kModeHasConsent;
151         break;
152       case 'd':
153         mode = kModeDumpHistograms;
154         break;
155       case 'e':
156         mode = kModeSendEnumSample;
157         break;
158       case 'g':
159         mode = kModeIsGuestMode;
160         break;
161       case 's':
162         mode = kModeSendSparseSample;
163         break;
164       case 't':
165         secs_to_msecs = true;
166         break;
167       case 'v':
168         mode = kModeSendCrosEvent;
169         break;
170       default:
171         ShowUsage();
172         break;
173     }
174   }
175   int arg_index = optind;
176 
177   int expected_args = 0;
178   if (mode == kModeSendSample)
179     expected_args = 5;
180   else if (mode == kModeSendEnumSample)
181     expected_args = 3;
182   else if (mode == kModeSendSparseSample)
183     expected_args = 2;
184   else if (mode == kModeSendCrosEvent)
185     expected_args = 1;
186 
187   if ((arg_index + expected_args) != argc) {
188     ShowUsage();
189   }
190 
191   switch (mode) {
192     case kModeDumpHistograms:
193       return DumpHistograms();
194     case kModeSendSample:
195     case kModeSendEnumSample:
196     case kModeSendSparseSample:
197       if ((mode != kModeSendSample) && secs_to_msecs) {
198         ShowUsage();
199       }
200       return SendStats(argv,
201                        arg_index,
202                        mode,
203                        secs_to_msecs);
204     case kModeSendCrosEvent:
205       return SendCrosEvent(argv, arg_index);
206     case kModeHasConsent:
207       return HasConsent();
208     case kModeIsGuestMode:
209       return IsGuestMode();
210     default:
211       ShowUsage();
212       return 0;
213   }
214 }
215