com.netflix.spectator.stateless.JsonUtils Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2014-2019 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.netflix.spectator.stateless;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.netflix.spectator.api.Id;
import com.netflix.spectator.api.Measurement;
import com.netflix.spectator.api.Tag;
import com.netflix.spectator.api.Utils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Helper for encoding measurements into a JSON array that can be read by the aggregator
* service. For more information see:
*
* https://github.com/Netflix-Skunkworks/iep-apps/tree/master/atlas-aggregator
*/
final class JsonUtils {
private static final JsonFactory FACTORY = new JsonFactory();
private static final int ADD = 0;
private static final int MAX = 10;
private JsonUtils() {
}
/** Encode the measurements to a JSON payload that can be sent to the aggregator. */
static byte[] encode(
Map commonTags,
List measurements) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
JsonGenerator gen = FACTORY.createGenerator(baos);
gen.writeStartArray();
Map strings = buildStringTable(gen, commonTags, measurements);
for (Measurement m : measurements) {
appendMeasurement(gen, strings, commonTags, m.id(), m.value());
}
gen.writeEndArray();
gen.close();
return baos.toByteArray();
}
private static Map buildStringTable(
JsonGenerator gen,
Map commonTags,
List measurements) throws IOException {
Map strings = new HashMap<>();
strings.put("name", 0);
commonTags.forEach((k, v) -> {
strings.put(k, 0);
strings.put(v, 0);
});
for (Measurement m : measurements) {
Id id = m.id();
strings.put(id.name(), 0);
for (Tag t : id.tags()) {
strings.put(t.key(), 0);
strings.put(t.value(), 0);
}
}
String[] sorted = strings.keySet().toArray(new String[0]);
Arrays.sort(sorted);
gen.writeNumber(sorted.length);
for (int i = 0; i < sorted.length; ++i) {
gen.writeString(sorted[i]);
strings.put(sorted[i], i);
}
return strings;
}
private static void appendMeasurement(
JsonGenerator gen,
Map strings,
Map commonTags,
Id id,
double value) throws IOException {
int op = operation(id);
if (shouldSend(op, value)) {
// Number of tag entries, commonTags + name + tags
int n = commonTags.size() + 1 + Utils.size(id.tags());
gen.writeNumber(n);
// Write out the key/value pairs for the tags
for (Map.Entry entry : commonTags.entrySet()) {
gen.writeNumber(strings.get(entry.getKey()));
gen.writeNumber(strings.get(entry.getValue()));
}
for (Tag t : id.tags()) {
gen.writeNumber(strings.get(t.key()));
gen.writeNumber(strings.get(t.value()));
}
gen.writeNumber(strings.get("name"));
gen.writeNumber(strings.get(id.name()));
// Write out the operation and delta value
gen.writeNumber(op);
gen.writeNumber(value);
}
}
private static int operation(Id id) {
for (Tag t : id.tags()) {
if ("statistic".equals(t.key())) {
return operation(t.value());
}
}
return MAX;
}
private static int operation(String stat) {
int op;
switch (stat) {
case "count":
case "totalAmount":
case "totalTime":
case "totalOfSquares":
case "percentile":
op = ADD; break;
default:
op = MAX; break;
}
return op;
}
private static boolean shouldSend(int op, double value) {
return !Double.isNaN(value) && (value > 0.0 || op == MAX);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy