Skip to content

Package: Metrics

Metrics

nameinstructionbranchcomplexitylinemethod
addMetric(KuraPayloadProto.KuraPayload.Builder, String, Object)
M: 125 C: 0
0%
M: 16 C: 0
0%
M: 9 C: 0
0%
M: 28 C: 0
0%
M: 1 C: 0
0%
buildBody(KuraPayloadProto.KuraPayload.Builder, ByteBuffer)
M: 12 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
buildMetrics(KuraPayloadProto.KuraPayload.Builder, Map)
M: 23 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
buildPayload(KuraPayloadProto.KuraPayload.Builder, Payload)
M: 19 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 6 C: 0
0%
M: 1 C: 0
0%
buildPosition(KuraPayloadProto.KuraPayload.Builder, Position)
M: 85 C: 0
0%
M: 18 C: 0
0%
M: 10 C: 0
0%
M: 22 C: 0
0%
M: 1 C: 0
0%
extractMetrics(KuraPayloadProto.KuraPayload)
M: 8 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
extractMetrics(List)
M: 84 C: 0
0%
M: 12 C: 0
0%
M: 10 C: 0
0%
M: 21 C: 0
0%
M: 1 C: 0
0%
getAsString(Map, String)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getAsString(Map, String, String)
M: 16 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 6 C: 0
0%
M: 1 C: 0
0%
readFrom(Object, Map)
M: 190 C: 0
0%
M: 16 C: 0
0%
M: 9 C: 0
0%
M: 36 C: 0
0%
M: 1 C: 0
0%
toKuraPayload(Payload)
M: 12 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2017, 2022 Red Hat Inc and others
3: *
4: * This program and the accompanying materials are made
5: * available under the terms of the Eclipse Public License 2.0
6: * which is available at https://www.eclipse.org/legal/epl-2.0/
7: *
8: * SPDX-License-Identifier: EPL-2.0
9: *
10: * Contributors:
11: * Red Hat Inc - initial API and implementation
12: *******************************************************************************/
13: package org.eclipse.kapua.kura.simulator.payload;
14:
15: import com.google.protobuf.ByteString;
16: import org.apache.commons.lang3.reflect.FieldUtils;
17: import org.apache.commons.lang3.reflect.MethodUtils;
18: import org.eclipse.kapua.kura.simulator.generator.Payload;
19: import org.eclipse.kapua.kura.simulator.generator.Position;
20: import org.eclipse.kapua.kura.simulator.proto.KuraPayloadProto.KuraPayload;
21: import org.eclipse.kapua.kura.simulator.proto.KuraPayloadProto.KuraPayload.KuraMetric;
22: import org.eclipse.kapua.kura.simulator.proto.KuraPayloadProto.KuraPayload.KuraMetric.ValueType;
23: import org.eclipse.kapua.kura.simulator.proto.KuraPayloadProto.KuraPayload.KuraPosition;
24:
25: import java.lang.reflect.Field;
26: import java.lang.reflect.InvocationTargetException;
27: import java.lang.reflect.Method;
28: import java.nio.ByteBuffer;
29: import java.util.List;
30: import java.util.Map;
31: import java.util.Objects;
32: import java.util.TreeMap;
33:
34: public final class Metrics {
35:
36: private Metrics() {
37: }
38:
39: public static final String KEY_REQUESTER_CLIENT_ID = "requester.client.id";
40: public static final String KEY_REQUEST_ID = "request.id";
41: public static final String KEY_RESPONSE_CODE = "response.code";
42: public static final String KEY_RESPONSE_EXCEPTION_MESSAGE = "response.exception.message";
43: public static final String KEY_RESPONSE_EXCEPTION_STACKTRACE = "response.exception.stack";
44:
45: /**
46: * Convert plain key value map into a Kura metric structure <br>
47: * Only the supported Kura values types must be used (String, boolean, int,
48: * long, float, double, byte[])
49: *
50: * @param builder
51: * the builder to append the metrics to
52: * @param metrics
53: * the metrics map
54: * @throws IllegalArgumentException
55: * in case of an unsupported value type
56: */
57: public static void buildMetrics(final KuraPayload.Builder builder, final Map<String, ?> metrics) {
58: Objects.requireNonNull(metrics);
59:
60:• for (final Map.Entry<String, ?> metric : metrics.entrySet()) {
61: addMetric(builder, metric.getKey(), metric.getValue());
62: }
63: }
64:
65: public static KuraPayload toKuraPayload(final Payload payload) {
66:• if (payload == null) {
67: return null;
68: }
69:
70: final KuraPayload.Builder result = KuraPayload.newBuilder();
71: buildPayload(result, payload);
72: return result.build();
73: }
74:
75: public static void buildPayload(final KuraPayload.Builder builder, final Payload payload) {
76: Objects.requireNonNull(builder);
77: Objects.requireNonNull(payload);
78:
79: buildBody(builder, payload.getBody());
80: buildPosition(builder, payload.getPosition());
81: buildMetrics(builder, payload.getMetrics());
82: }
83:
84: public static void buildPosition(final KuraPayload.Builder builder, final Position position) {
85:• if (position == null) {
86: return;
87: }
88:
89: Objects.requireNonNull(builder);
90:
91: final KuraPosition.Builder result = KuraPosition.newBuilder();
92:
93:• if (position.getAltitude() != null) {
94: result.setAltitude(position.getAltitude());
95: }
96:
97:• if (position.getHeading() != null) {
98: result.setHeading(position.getHeading());
99: }
100:
101:• if (position.getLatitude() != null) {
102: result.setLatitude(position.getLatitude());
103: }
104:
105:• if (position.getLongitude() != null) {
106: result.setLongitude(position.getLongitude());
107: }
108:
109:• if (position.getPrecision() != null) {
110: result.setPrecision(position.getPrecision());
111: }
112:
113:• if (position.getSatellites() != null) {
114: result.setSatellites(position.getSatellites());
115: }
116:
117:• if (position.getSpeed() != null) {
118: result.setSpeed(position.getSpeed());
119: }
120:
121:• if (position.getTimestamp() != null) {
122: result.setTimestamp(position.getTimestamp().toEpochMilli());
123: }
124:
125: builder.setPosition(result);
126: }
127:
128: public static void buildBody(final KuraPayload.Builder builder, final ByteBuffer body) {
129:• if (body == null) {
130: return;
131: }
132:
133: Objects.requireNonNull(builder);
134:
135: builder.setBody(ByteString.copyFrom(body));
136: }
137:
138: public static void addMetric(final KuraPayload.Builder builder, final String key, final Object value) {
139: final KuraMetric.Builder b = KuraMetric.newBuilder();
140: b.setName(key);
141:
142:• if (value == null) {
143: return;
144:• } else if (value instanceof Boolean) {
145: b.setType(ValueType.BOOL);
146: b.setBoolValue((boolean) value);
147:• } else if (value instanceof Integer) {
148: b.setType(ValueType.INT32);
149: b.setIntValue((int) value);
150:• } else if (value instanceof String) {
151: b.setType(ValueType.STRING);
152: b.setStringValue((String) value);
153:• } else if (value instanceof Long) {
154: b.setType(ValueType.INT64);
155: b.setLongValue((Long) value);
156:• } else if (value instanceof Double) {
157: b.setType(ValueType.DOUBLE);
158: b.setDoubleValue((Double) value);
159:• } else if (value instanceof Float) {
160: b.setType(ValueType.FLOAT);
161: b.setFloatValue((Float) value);
162:• } else if (value instanceof byte[]) {
163: b.setType(ValueType.BYTES);
164: b.setBytesValue(ByteString.copyFrom((byte[]) value));
165: } else {
166: throw new IllegalArgumentException(String.format("Illegal metric data type: %s", value.getClass()));
167: }
168:
169: builder.addMetric(b);
170: }
171:
172: public static Map<String, Object> extractMetrics(final KuraPayload payload) {
173:• if (payload == null) {
174: return null;
175: }
176: return extractMetrics(payload.getMetricList());
177: }
178:
179: public static Map<String, Object> extractMetrics(final List<KuraMetric> metricList) {
180:• if (metricList == null) {
181: return null;
182: }
183:
184: /*
185: * We are using a TreeMap in order to have a stable order of properties
186: */
187: final Map<String, Object> result = new TreeMap<>();
188:
189:• for (final KuraMetric metric : metricList) {
190: final String name = metric.getName();
191:• switch (metric.getType()) {
192: case BOOL:
193: result.put(name, metric.getBoolValue());
194: break;
195: case BYTES:
196: result.put(name, metric.getBytesValue().toByteArray());
197: break;
198: case DOUBLE:
199: result.put(name, metric.getDoubleValue());
200: break;
201: case FLOAT:
202: result.put(name, metric.getFloatValue());
203: break;
204: case INT32:
205: result.put(name, metric.getIntValue());
206: break;
207: case INT64:
208: result.put(name, metric.getLongValue());
209: break;
210: case STRING:
211: result.put(name, metric.getStringValue());
212: break;
213: }
214: }
215:
216: return result;
217: }
218:
219: public static String getAsString(final Map<String, Object> metrics, final String key) {
220: return getAsString(metrics, key, null);
221: }
222:
223: public static String getAsString(final Map<String, Object> metrics, final String key, final String defaultValue) {
224: final Object value = metrics.get(key);
225:• if (value == null) {
226: return defaultValue;
227: }
228:• if (value instanceof String) {
229: return (String) value;
230: }
231: return defaultValue;
232: }
233:
234: public static <T> T readFrom(final T object, final Map<String, Object> metrics) {
235: Objects.requireNonNull(object);
236:
237:• for (final Field field : FieldUtils.getFieldsListWithAnnotation(object.getClass(), Metric.class)) {
238: final Metric m = field.getAnnotation(Metric.class);
239: final boolean optional = field.isAnnotationPresent(Optional.class);
240:
241: final Object value = metrics.get(m.value());
242:• if (value == null && !optional) {
243: throw new IllegalArgumentException(
244: String.format("Field '%s' is missing metric '%s'", field.getName(), m.value()));
245: }
246:
247:• if (value == null) {
248: // not set but optional
249: continue;
250: }
251:
252: try {
253: FieldUtils.writeField(field, object, value, true);
254: } catch (final IllegalArgumentException e) {
255: // provide a better message
256: throw new IllegalArgumentException(String.format("Failed to assign '%s' (%s) to field '%s'", value,
257: value.getClass().getName(), field.getName()), e);
258: } catch (final IllegalAccessException e) {
259: throw new RuntimeException(e);
260: }
261: }
262:
263:• for (final Method method : MethodUtils.getMethodsListWithAnnotation(object.getClass(), Metric.class)) {
264: final Metric m = method.getAnnotation(Metric.class);
265: final boolean optional = method.isAnnotationPresent(Optional.class);
266:
267: final Object value = metrics.get(m.value());
268:• if (value == null && !optional) {
269: throw new IllegalArgumentException(
270: String.format("Method '%s' is missing metric '%s'", method.getName(), m.value()));
271: }
272:
273:• if (value == null) {
274: // not set but optional
275: continue;
276: }
277:
278: try {
279: method.invoke(object, value);
280: } catch (final IllegalArgumentException e) {
281: // provide a better message
282: throw new IllegalArgumentException(String.format("Failed to call '%s' (%s) with method '%s'", value,
283: value.getClass().getName(), method.getName()), e);
284: } catch (IllegalAccessException | InvocationTargetException e) {
285: throw new RuntimeException(e);
286: }
287: }
288:
289: return object;
290: }
291: }