1 /*
2  * Copyright (C) 2018 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 package com.android.tradefed.util.proto;
17 
18 import com.android.tradefed.log.LogUtil.CLog;
19 import com.android.tradefed.metrics.proto.MetricMeasurement.DataType;
20 import com.android.tradefed.metrics.proto.MetricMeasurement.Directionality;
21 import com.android.tradefed.metrics.proto.MetricMeasurement.Measurements;
22 import com.android.tradefed.metrics.proto.MetricMeasurement.Measurements.MeasurementCase;
23 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
24 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric.Builder;
25 
26 import java.util.HashMap;
27 import java.util.LinkedHashMap;
28 import java.util.Map;
29 
30 /** Utility class to help with the Map<String, String> to Map<String, Metric> transition. */
31 public class TfMetricProtoUtil {
32 
33     /**
34      * Conversion of Map<String, Metric> to Map<String, String>. All the single value string
35      * representation are used, list representation are not converted and will be lost.
36      */
compatibleConvert(Map<String, Metric> map)37     public static Map<String, String> compatibleConvert(Map<String, Metric> map) {
38         Map<String, String> oldFormat = new LinkedHashMap<>();
39         for (String key : map.keySet()) {
40             Measurements measures = map.get(key).getMeasurements();
41             MeasurementCase set = measures.getMeasurementCase();
42             String value = "";
43             switch (set) {
44                 case SINGLE_DOUBLE:
45                     value = Double.toString(measures.getSingleDouble());
46                     break;
47                 case SINGLE_INT:
48                     value = Long.toString(measures.getSingleInt());
49                     break;
50                 case SINGLE_STRING:
51                     value = measures.getSingleString();
52                     break;
53                 case MEASUREMENT_NOT_SET:
54                     CLog.d("No measurements was set for key '%s'", key);
55                     continue;
56                 default:
57                     CLog.d(
58                             "Could not convert complex '%s' type to String. Use the new metric "
59                                     + "interface.",
60                             set);
61                     continue;
62             }
63             oldFormat.put(key, value);
64         }
65         return oldFormat;
66     }
67 
68     /**
69      * Conversion from Map<String, String> to HashMap<String, Metric>. In order to go to the new
70      * interface. Information might only be partially populated because of the old format
71      * limitations.
72      */
upgradeConvert(Map<String, String> metrics)73     public static HashMap<String, Metric> upgradeConvert(Map<String, String> metrics) {
74         return upgradeConvert(metrics, false);
75     }
76 
77     /**
78      * Conversion from Map<String, String> to HashMap<String, Metric>. In order to go to the new
79      * interface. Information might only be partially populated because of the old format
80      * limitations.
81      *
82      * @param smartNumbers convert numbers to int metrics
83      */
upgradeConvert( Map<String, String> metrics, boolean smartNumbers)84     public static HashMap<String, Metric> upgradeConvert(
85             Map<String, String> metrics, boolean smartNumbers) {
86         HashMap<String, Metric> newFormat = new LinkedHashMap<>();
87         for (String key : metrics.keySet()) {
88             Metric metric = null;
89             String stringMetric = metrics.get(key);
90             if (smartNumbers) {
91                 Long numMetric = isLong(stringMetric);
92                 if (numMetric != null) {
93                     metric = createSingleValue(numMetric.longValue(), null);
94                 }
95             }
96             // Default to String metric
97             if (metric == null) {
98                 metric = stringToMetric(stringMetric);
99             }
100             newFormat.put(key, metric);
101         }
102         return newFormat;
103     }
104 
isLong(String strNum)105     private static Long isLong(String strNum) {
106         if (strNum == null) {
107             return null;
108         }
109         try {
110             return Long.parseLong(strNum);
111         } catch (NumberFormatException nfe) {
112             return null;
113         }
114     }
115 
116     /**
117      * Convert a simple String metric (old format) to a {@link Metric} (new format).
118      *
119      * @param metric The string containing a metric.
120      * @return The created {@link Metric}
121      */
stringToMetric(String metric)122     public static Metric stringToMetric(String metric) {
123         Measurements measures = Measurements.newBuilder().setSingleString(metric).build();
124         Metric m =
125                 Metric.newBuilder()
126                         .setMeasurements(measures)
127                         .setDirection(Directionality.DIRECTIONALITY_UNSPECIFIED)
128                         .setType(DataType.RAW)
129                         .build();
130         return m;
131     }
132 
133     /**
134      * Create a {@link Metric} for a single long/int value, and optionally provide a unit.
135      *
136      * @param value The value that will be stored.
137      * @param unit the unit of the value, or null if no unit.
138      * @return a {@link Metric} populated with the informations.
139      */
createSingleValue(long value, String unit)140     public static Metric createSingleValue(long value, String unit) {
141         Measurements measure = Measurements.newBuilder().setSingleInt(value).build();
142         Builder metricBuilder = Metric.newBuilder().setType(DataType.RAW).setMeasurements(measure);
143         if (unit != null) {
144             metricBuilder.setUnit(unit);
145         }
146         return metricBuilder.build();
147     }
148 }
149