ConfigFactory.java revision b814481ad1f8d0e429d799b1571a6272e1a7f6c5
1/* 2 * Copyright (C) 2017 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 */ 16package com.android.statsd.loadtest; 17 18import android.content.Context; 19import android.content.res.Resources; 20import android.util.Log; 21 22import com.android.internal.os.StatsdConfigProto.Bucket; 23import com.android.internal.os.StatsdConfigProto.Predicate; 24import com.android.internal.os.StatsdConfigProto.CountMetric; 25import com.android.internal.os.StatsdConfigProto.DurationMetric; 26import com.android.internal.os.StatsdConfigProto.MetricConditionLink; 27import com.android.internal.os.StatsdConfigProto.EventMetric; 28import com.android.internal.os.StatsdConfigProto.GaugeMetric; 29import com.android.internal.os.StatsdConfigProto.ValueMetric; 30import com.android.internal.os.StatsdConfigProto.FieldValueMatcher; 31import com.android.internal.os.StatsdConfigProto.AtomMatcher; 32import com.android.internal.os.StatsdConfigProto.SimplePredicate; 33import com.android.internal.os.StatsdConfigProto.StatsdConfig; 34import com.android.internal.os.StatsdConfigProto.TimeUnit; 35 36import java.io.InputStream; 37import java.io.IOException; 38import java.util.ArrayList; 39import java.util.List; 40 41/** 42 * Creates StatsdConfig protos for loadtesting. 43 */ 44public class ConfigFactory { 45 public static final long CONFIG_ID = 123456789; 46 47 private static final String TAG = "loadtest.ConfigFactory"; 48 49 private final StatsdConfig mTemplate; 50 51 public ConfigFactory(Context context) { 52 // Read the config template from the resoures. 53 Resources res = context.getResources(); 54 byte[] template = null; 55 StatsdConfig templateProto = null; 56 try { 57 InputStream inputStream = res.openRawResource(R.raw.loadtest_config); 58 template = new byte[inputStream.available()]; 59 inputStream.read(template); 60 templateProto = StatsdConfig.parseFrom(template); 61 } catch (IOException e) { 62 Log.e(TAG, "Unable to read or parse loadtest config template. Using an empty config."); 63 } 64 mTemplate = templateProto == null ? StatsdConfig.newBuilder().build() : templateProto; 65 66 Log.d(TAG, "Loadtest template config: " + mTemplate); 67 } 68 69 /** 70 * Generates a config. 71 * 72 * All configs are based on the same template. 73 * That template is designed to make the most use of the set of atoms that {@code SequencePusher} 74 * pushes, and to exercise as many of the metrics features as possible. 75 * Furthermore, by passing a replication factor to this method, one can artificially inflate 76 * the number of metrics in the config. One can also adjust the bucket size for aggregate 77 * metrics. 78 * 79 * @param replication The number of times each metric is replicated in the config. 80 * If the config template has n metrics, the generated config will have n * replication 81 * ones 82 * @param bucketMillis The bucket size, in milliseconds, for aggregate metrics 83 * @param placebo If true, only return an empty config 84 * @return The serialized config 85 */ 86 public byte[] getConfig(int replication, TimeUnit bucket, boolean placebo, boolean includeCount, 87 boolean includeDuration, boolean includeEvent, boolean includeValue, 88 boolean includeGauge) { 89 StatsdConfig.Builder config = StatsdConfig.newBuilder() 90 .setId(CONFIG_ID); 91 if (placebo) { 92 replication = 0; // Config will be empty, aside from a name. 93 } 94 int numMetrics = 0; 95 for (int i = 0; i < replication; i++) { 96 // metrics 97 if (includeEvent) { 98 for (EventMetric metric : mTemplate.getEventMetricList()) { 99 addEventMetric(metric, i, config); 100 numMetrics++; 101 } 102 } 103 if (includeCount) { 104 for (CountMetric metric : mTemplate.getCountMetricList()) { 105 addCountMetric(metric, i, bucket, config); 106 numMetrics++; 107 } 108 } 109 if (includeDuration) { 110 for (DurationMetric metric : mTemplate.getDurationMetricList()) { 111 addDurationMetric(metric, i, bucket, config); 112 numMetrics++; 113 } 114 } 115 if (includeGauge) { 116 for (GaugeMetric metric : mTemplate.getGaugeMetricList()) { 117 addGaugeMetric(metric, i, bucket, config); 118 numMetrics++; 119 } 120 } 121 if (includeValue) { 122 for (ValueMetric metric : mTemplate.getValueMetricList()) { 123 addValueMetric(metric, i, bucket, config); 124 numMetrics++; 125 } 126 } 127 // predicates 128 for (Predicate predicate : mTemplate.getPredicateList()) { 129 addPredicate(predicate, i, config); 130 } 131 // matchers 132 for (AtomMatcher matcher : mTemplate.getAtomMatcherList()) { 133 addMatcher(matcher, i, config); 134 } 135 } 136 137 Log.d(TAG, "Loadtest config is : " + config.build()); 138 Log.d(TAG, "Generated config has " + numMetrics + " metrics"); 139 140 return config.build().toByteArray(); 141 } 142 143 /** 144 * Creates {@link MetricConditionLink}s that are identical to the one passed to this method, 145 * except that the names are appended with the provided suffix. 146 */ 147 private List<MetricConditionLink> getLinks( 148 List<MetricConditionLink> links, int suffix) { 149 List<MetricConditionLink> newLinks = new ArrayList(); 150 for (MetricConditionLink link : links) { 151 newLinks.add(link.toBuilder() 152 .setCondition(link.getCondition() + suffix) 153 .build()); 154 } 155 return newLinks; 156 } 157 158 /** 159 * Creates an {@link EventMetric} based on the template. Makes sure that all names are appended 160 * with the provided suffix. Then adds that metric to the config. 161 */ 162 private void addEventMetric(EventMetric template, int suffix, StatsdConfig.Builder config) { 163 EventMetric.Builder metric = template.toBuilder() 164 .setId(template.getId() + suffix) 165 .setWhat(template.getWhat() + suffix); 166 if (template.hasCondition()) { 167 metric.setCondition(template.getCondition() + suffix); 168 } 169 if (template.getLinksCount() > 0) { 170 List<MetricConditionLink> links = getLinks(template.getLinksList(), suffix); 171 metric.clearLinks(); 172 metric.addAllLinks(links); 173 } 174 config.addEventMetric(metric); 175 } 176 177 /** 178 * Creates a {@link CountMetric} based on the template. Makes sure that all names are appended 179 * with the provided suffix, and overrides the bucket size. Then adds that metric to the config. 180 */ 181 private void addCountMetric(CountMetric template, int suffix, TimeUnit bucket, 182 StatsdConfig.Builder config) { 183 CountMetric.Builder metric = template.toBuilder() 184 .setId(template.getId() + suffix) 185 .setWhat(template.getWhat() + suffix); 186 if (template.hasCondition()) { 187 metric.setCondition(template.getCondition() + suffix); 188 } 189 if (template.getLinksCount() > 0) { 190 List<MetricConditionLink> links = getLinks(template.getLinksList(), suffix); 191 metric.clearLinks(); 192 metric.addAllLinks(links); 193 } 194 metric.setBucket(bucket); 195 config.addCountMetric(metric); 196 } 197 198 /** 199 * Creates a {@link DurationMetric} based on the template. Makes sure that all names are appended 200 * with the provided suffix, and overrides the bucket size. Then adds that metric to the config. 201 */ 202 private void addDurationMetric(DurationMetric template, int suffix, TimeUnit bucket, 203 StatsdConfig.Builder config) { 204 DurationMetric.Builder metric = template.toBuilder() 205 .setId(template.getId() + suffix) 206 .setWhat(template.getWhat() + suffix); 207 if (template.hasCondition()) { 208 metric.setCondition(template.getCondition() + suffix); 209 } 210 if (template.getLinksCount() > 0) { 211 List<MetricConditionLink> links = getLinks(template.getLinksList(), suffix); 212 metric.clearLinks(); 213 metric.addAllLinks(links); 214 } 215 metric.setBucket(bucket); 216 config.addDurationMetric(metric); 217 } 218 219 /** 220 * Creates a {@link GaugeMetric} based on the template. Makes sure that all names are appended 221 * with the provided suffix, and overrides the bucket size. Then adds that metric to the config. 222 */ 223 private void addGaugeMetric(GaugeMetric template, int suffix, TimeUnit bucket, 224 StatsdConfig.Builder config) { 225 GaugeMetric.Builder metric = template.toBuilder() 226 .setId(template.getId() + suffix) 227 .setWhat(template.getWhat() + suffix); 228 if (template.hasCondition()) { 229 metric.setCondition(template.getCondition() + suffix); 230 } 231 if (template.getLinksCount() > 0) { 232 List<MetricConditionLink> links = getLinks(template.getLinksList(), suffix); 233 metric.clearLinks(); 234 metric.addAllLinks(links); 235 } 236 metric.setBucket(bucket); 237 config.addGaugeMetric(metric); 238 } 239 240 /** 241 * Creates a {@link ValueMetric} based on the template. Makes sure that all names are appended 242 * with the provided suffix, and overrides the bucket size. Then adds that metric to the config. 243 */ 244 private void addValueMetric(ValueMetric template, int suffix, TimeUnit bucket, 245 StatsdConfig.Builder config) { 246 ValueMetric.Builder metric = template.toBuilder() 247 .setId(template.getId() + suffix) 248 .setWhat(template.getWhat() + suffix); 249 if (template.hasCondition()) { 250 metric.setCondition(template.getCondition() + suffix); 251 } 252 if (template.getLinksCount() > 0) { 253 List<MetricConditionLink> links = getLinks(template.getLinksList(), suffix); 254 metric.clearLinks(); 255 metric.addAllLinks(links); 256 } 257 metric.setBucket(bucket); 258 config.addValueMetric(metric); 259 } 260 261 /** 262 * Creates a {@link Predicate} based on the template. Makes sure that all names 263 * are appended with the provided suffix. Then adds that predicate to the config. 264 */ 265 private void addPredicate(Predicate template, int suffix, StatsdConfig.Builder config) { 266 Predicate.Builder predicate = template.toBuilder() 267 .setId(template.getId() + suffix); 268 if (template.hasCombination()) { 269 Predicate.Combination.Builder cb = template.getCombination().toBuilder() 270 .clearPredicate(); 271 for (long child : template.getCombination().getPredicateList()) { 272 cb.addPredicate(child + suffix); 273 } 274 predicate.setCombination(cb.build()); 275 } 276 if (template.hasSimplePredicate()) { 277 SimplePredicate.Builder sc = template.getSimplePredicate().toBuilder() 278 .setStart(template.getSimplePredicate().getStart() + suffix) 279 .setStop(template.getSimplePredicate().getStop() + suffix); 280 if (template.getSimplePredicate().hasStopAll()) { 281 sc.setStopAll(template.getSimplePredicate().getStopAll() + suffix); 282 } 283 predicate.setSimplePredicate(sc.build()); 284 } 285 config.addPredicate(predicate); 286 } 287 288 /** 289 * Creates a {@link AtomMatcher} based on the template. Makes sure that all names 290 * are appended with the provided suffix. Then adds that matcher to the config. 291 */ 292 private void addMatcher(AtomMatcher template, int suffix, StatsdConfig.Builder config) { 293 AtomMatcher.Builder matcher = template.toBuilder() 294 .setId(template.getId() + suffix); 295 if (template.hasCombination()) { 296 AtomMatcher.Combination.Builder cb = template.getCombination().toBuilder() 297 .clearMatcher(); 298 for (long child : template.getCombination().getMatcherList()) { 299 cb.addMatcher(child + suffix); 300 } 301 matcher.setCombination(cb); 302 } 303 config.addAtomMatcher(matcher); 304 } 305} 306