Skip to content

Commit

Permalink
Simplify API for JSON writing.
Browse files Browse the repository at this point in the history
  • Loading branch information
raphw committed Sep 28, 2023
1 parent fa6181b commit da91e15
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public class DslJsonDataWriter implements DataWriter {

private final Reporter reporter;

private final StringBuilder replaceBuilder = new StringBuilder();

public DslJsonDataWriter(JsonWriter jw, Reporter reporter) {
this.jw = jw;
this.reporter = reporter;
Expand Down Expand Up @@ -62,6 +64,8 @@ public void write(StructureType type) {
case NEW_LINE:
jw.writeByte((byte) '\n');
break;
default:
throw new IllegalArgumentException();
}
}

Expand All @@ -70,6 +74,16 @@ public void writeFieldName(String name) {
DslJsonSerializer.writeFieldName(name, jw);
}

@Override
public void writeFieldName(String name, boolean sanitized) {
if (sanitized) {
DslJsonSerializer.writeStringValue(DslJsonSerializer.sanitizePropertyName(name, replaceBuilder), replaceBuilder, jw);
jw.writeByte(JsonWriter.SEMI);
} else {
writeFieldName(name);
}
}

@Override
public void serialize(boolean value) {
BoolConverter.serialize(value, jw);
Expand All @@ -91,13 +105,17 @@ public void writeString(CharSequence value) {
}

@Override
public void writeStringValue(CharSequence value, StringBuilder replaceBuilder) {
DslJsonSerializer.writeStringValue(value, replaceBuilder, jw);
public void writeString(CharSequence value, boolean trimmed) {
if (trimmed) {
DslJsonSerializer.writeStringValue(value, replaceBuilder, jw);
} else {
writeString(value);
}
}

@Override
public CharSequence sanitizePropertyName(String key, StringBuilder replaceBuilder) {
return DslJsonSerializer.sanitizePropertyName(key, replaceBuilder);
public String sanitizePropertyName(String key) {
return DslJsonSerializer.sanitizePropertyName(key, replaceBuilder).toString();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
*/
package co.elastic.apm.agent.micrometer;

import co.elastic.apm.agent.report.serialize.DslJsonDataWriter;
import co.elastic.apm.agent.sdk.internal.util.PrivilegedActionUtils;
import co.elastic.apm.agent.sdk.logging.Logger;
import co.elastic.apm.agent.sdk.logging.LoggerFactory;
Expand Down Expand Up @@ -61,7 +60,6 @@ public class MicrometerMeterRegistrySerializer {
private static final int BUFFER_SIZE_LIMIT = 2048;

private static final Logger logger = LoggerFactory.getLogger(MicrometerMeterRegistrySerializer.class);
private final StringBuilder replaceBuilder = new StringBuilder();
private final MetricsConfiguration config;
private final ReportingTracer tracer;
private final WeakSet<Meter> internallyDisabledMeters = WeakConcurrent.buildSet();
Expand Down Expand Up @@ -91,15 +89,15 @@ public List<DataWriter> serialize(final Map<Meter.Id, Meter> metersById, final l
}
for (Map.Entry<List<Tag>, List<Meter>> entry : metersGroupedByTags.entrySet()) {
DataWriter writer = tracer.newWriter(maxSerializedSize);
if (serializeMetricSet(entry.getKey(), entry.getValue(), epochMicros, replaceBuilder, writer)) {
if (serializeMetricSet(entry.getKey(), entry.getValue(), epochMicros, writer)) {
serializedMeters.add(writer);
maxSerializedSize = Math.max(Math.min(writer.size(), BUFFER_SIZE_LIMIT), maxSerializedSize);
}
}
return serializedMeters;
}

boolean serializeMetricSet(List<Tag> tags, List<Meter> meters, long epochMicros, StringBuilder replaceBuilder, DataWriter writer) {
boolean serializeMetricSet(List<Tag> tags, List<Meter> meters, long epochMicros, DataWriter writer) {
boolean hasSamples = false;
boolean dedotMetricName = config.isDedotCustomMetrics();
writer.write(OBJECT_START);
Expand All @@ -110,7 +108,7 @@ boolean serializeMetricSet(List<Tag> tags, List<Meter> meters, long epochMicros,
writer.writeFieldName("timestamp");
writer.serialize(epochMicros);
writer.write(COMMA);
serializeTags(tags, replaceBuilder, writer);
serializeTags(tags, writer);
writer.writeFieldName("samples");
writer.write(OBJECT_START);

Expand All @@ -126,25 +124,25 @@ boolean serializeMetricSet(List<Tag> tags, List<Meter> meters, long epochMicros,
PrivilegedActionUtils.setContextClassLoader(Thread.currentThread(), PrivilegedActionUtils.getClassLoader(meter.getClass()));
if (meter instanceof Timer) {
Timer timer = (Timer) meter;
hasSamples = serializeTimer(writer, timer.takeSnapshot(), timer.getId(), timer.count(), timer.totalTime(TimeUnit.MICROSECONDS), hasSamples, replaceBuilder, dedotMetricName);
hasSamples = serializeTimer(writer, timer.takeSnapshot(), timer.getId(), timer.count(), timer.totalTime(TimeUnit.MICROSECONDS), hasSamples, dedotMetricName);
} else if (meter instanceof FunctionTimer) {
FunctionTimer timer = (FunctionTimer) meter;
hasSamples = serializeTimer(writer, null, timer.getId(), (long) timer.count(), timer.totalTime(TimeUnit.MICROSECONDS), hasSamples, replaceBuilder, dedotMetricName);
hasSamples = serializeTimer(writer, null, timer.getId(), (long) timer.count(), timer.totalTime(TimeUnit.MICROSECONDS), hasSamples, dedotMetricName);
} else if (meter instanceof LongTaskTimer) {
LongTaskTimer timer = (LongTaskTimer) meter;
hasSamples = serializeTimer(writer, timer.takeSnapshot(), timer.getId(), timer.activeTasks(), timer.duration(TimeUnit.MICROSECONDS), hasSamples, replaceBuilder, dedotMetricName);
hasSamples = serializeTimer(writer, timer.takeSnapshot(), timer.getId(), timer.activeTasks(), timer.duration(TimeUnit.MICROSECONDS), hasSamples, dedotMetricName);
} else if (meter instanceof DistributionSummary) {
DistributionSummary summary = (DistributionSummary) meter;
hasSamples = serializeDistributionSummary(writer, summary.takeSnapshot(), summary.getId(), summary.count(), summary.totalAmount(), hasSamples, replaceBuilder, dedotMetricName);
hasSamples = serializeDistributionSummary(writer, summary.takeSnapshot(), summary.getId(), summary.count(), summary.totalAmount(), hasSamples, dedotMetricName);
} else if (meter instanceof Gauge) {
Gauge gauge = (Gauge) meter;
hasSamples = serializeValue(gauge.getId(), gauge.value(), hasSamples, writer, replaceBuilder, dedotMetricName);
hasSamples = serializeValue(gauge.getId(), gauge.value(), hasSamples, writer, dedotMetricName);
} else if (meter instanceof Counter) {
Counter counter = (Counter) meter;
hasSamples = serializeValue(counter.getId(), counter.count(), hasSamples, writer, replaceBuilder, dedotMetricName);
hasSamples = serializeValue(counter.getId(), counter.count(), hasSamples, writer, dedotMetricName);
} else if (meter instanceof FunctionCounter) {
FunctionCounter counter = (FunctionCounter) meter;
hasSamples = serializeValue(counter.getId(), counter.count(), hasSamples, writer, replaceBuilder, dedotMetricName);
hasSamples = serializeValue(counter.getId(), counter.count(), hasSamples, writer, dedotMetricName);
}
} catch (Throwable throwable) {
String meterName = meter.getId().getName();
Expand All @@ -167,7 +165,7 @@ boolean serializeMetricSet(List<Tag> tags, List<Meter> meters, long epochMicros,
return hasSamples;
}

private static void serializeTags(List<Tag> tags, StringBuilder replaceBuilder, DataWriter writer) {
private static void serializeTags(List<Tag> tags, DataWriter writer) {
if (tags.isEmpty()) {
return;
}
Expand All @@ -178,9 +176,8 @@ private static void serializeTags(List<Tag> tags, StringBuilder replaceBuilder,
if (i > 0) {
writer.write(COMMA);
}
writer.writeStringValue(writer.sanitizePropertyName(tag.getKey(), replaceBuilder), replaceBuilder);
writer.write(SEMI);
writer.writeStringValue(tag.getValue(), replaceBuilder);
writer.writeFieldName(tag.getKey(), true);
writer.writeString(tag.getValue(), true);
}
writer.write(OBJECT_END);
writer.write(COMMA);
Expand All @@ -195,19 +192,18 @@ private static void serializeTags(List<Tag> tags, StringBuilder replaceBuilder,
* @param count count
* @param totalTime total time
* @param hasValue whether a value has already been written
* @param replaceBuilder
* @param dedotMetricName
* @return true if a value has been written before, including this one; false otherwise
*/
private static boolean serializeTimer(DataWriter writer, HistogramSnapshot histogramSnapshot, Meter.Id id, long count, double totalTime, boolean hasValue, StringBuilder replaceBuilder, boolean dedotMetricName) {
private static boolean serializeTimer(DataWriter writer, HistogramSnapshot histogramSnapshot, Meter.Id id, long count, double totalTime, boolean hasValue, boolean dedotMetricName) {
if (isValidValue(totalTime)) {
if (hasValue) writer.write(COMMA);
serializeValue(id, ".count", count, writer, replaceBuilder, dedotMetricName);
serializeValue(id, ".count", count, writer, dedotMetricName);
writer.write(COMMA);
serializeValue(id, ".sum.us", totalTime, writer, replaceBuilder, dedotMetricName);
serializeValue(id, ".sum.us", totalTime, writer, dedotMetricName);
if (histogramSnapshot != null && histogramSnapshot.histogramCounts().length > 0) {
writer.write(COMMA);
serializeHistogram(id, histogramSnapshot, writer, replaceBuilder, dedotMetricName);
serializeHistogram(id, histogramSnapshot, writer, dedotMetricName);
}
return true;
}
Expand All @@ -223,32 +219,31 @@ private static boolean serializeTimer(DataWriter writer, HistogramSnapshot histo
* @param count count
* @param totalAmount total amount of recorded events
* @param hasValue whether a value has already been written
* @param replaceBuilder
* @param dedotMetricName
* @return true if a value has been written before, including this one; false otherwise
*/
private static boolean serializeDistributionSummary(DataWriter writer, HistogramSnapshot histogramSnapshot, Meter.Id id, long count, double totalAmount, boolean hasValue, StringBuilder replaceBuilder, boolean dedotMetricName) {
private static boolean serializeDistributionSummary(DataWriter writer, HistogramSnapshot histogramSnapshot, Meter.Id id, long count, double totalAmount, boolean hasValue, boolean dedotMetricName) {
if (isValidValue(totalAmount)) {
if (hasValue) writer.write(COMMA);
serializeValue(id, ".count", count, writer, replaceBuilder, dedotMetricName);
serializeValue(id, ".count", count, writer, dedotMetricName);
writer.write(COMMA);
serializeValue(id, ".sum", totalAmount, writer, replaceBuilder, dedotMetricName);
serializeValue(id, ".sum", totalAmount, writer, dedotMetricName);
if (histogramSnapshot != null && histogramSnapshot.histogramCounts().length > 0) {
writer.write(COMMA);
serializeHistogram(id, histogramSnapshot, writer, replaceBuilder, dedotMetricName);
serializeHistogram(id, histogramSnapshot, writer, dedotMetricName);
}
return true;
}
return hasValue;
}

private static void serializeHistogram(Meter.Id id, HistogramSnapshot histogramSnapshot, DataWriter writer, StringBuilder replaceBuilder, boolean dedotMetricName) {
private static void serializeHistogram(Meter.Id id, HistogramSnapshot histogramSnapshot, DataWriter writer, boolean dedotMetricName) {
if (histogramSnapshot == null) {
return;
}
String suffix = ".histogram";
CountAtBucket[] bucket = histogramSnapshot.histogramCounts();
serializeObjectStart(id.getName(), "values", suffix, writer, replaceBuilder, dedotMetricName);
serializeObjectStart(id.getName(), "values", suffix, writer, dedotMetricName);
writer.write(ARRAY_START);
if (bucket.length > 0) {
writer.serialize(bucket[0].bucket());
Expand Down Expand Up @@ -284,8 +279,8 @@ private static void serializeHistogram(Meter.Id id, HistogramSnapshot histogramS
writer.write(OBJECT_END);
}

private static void serializeValue(Meter.Id id, String suffix, long value, DataWriter writer, StringBuilder replaceBuilder, boolean dedotMetricName) {
serializeValueStart(id.getName(), suffix, writer, replaceBuilder, dedotMetricName);
private static void serializeValue(Meter.Id id, String suffix, long value, DataWriter writer, boolean dedotMetricName) {
serializeValueStart(id.getName(), suffix, writer, dedotMetricName);
writer.serialize(value);
writer.write(OBJECT_END);
}
Expand All @@ -297,45 +292,36 @@ private static void serializeValue(Meter.Id id, String suffix, long value, DataW
* @param value meter value
* @param hasValue whether a value has already been written
* @param writer writer
* @param replaceBuilder
* @param dedotMetricName
* @return true if a value has been written before, including this one; false otherwise
*/
private static boolean serializeValue(Meter.Id id, double value, boolean hasValue, DataWriter writer, StringBuilder replaceBuilder, boolean dedotMetricName) {
private static boolean serializeValue(Meter.Id id, double value, boolean hasValue, DataWriter writer, boolean dedotMetricName) {
if (isValidValue(value)) {
if (hasValue) writer.write(COMMA);
serializeValue(id, "", value, writer, replaceBuilder, dedotMetricName);
serializeValue(id, "", value, writer, dedotMetricName);
return true;
}
return hasValue;
}

private static void serializeValue(Meter.Id id, String suffix, double value, DataWriter writer, StringBuilder replaceBuilder, boolean dedotMetricName) {
serializeValueStart(id.getName(), suffix, writer, replaceBuilder, dedotMetricName);
private static void serializeValue(Meter.Id id, String suffix, double value, DataWriter writer, boolean dedotMetricName) {
serializeValueStart(id.getName(), suffix, writer, dedotMetricName);
writer.serialize(value);
writer.write(OBJECT_END);
}

private static void serializeValueStart(String key, String suffix, DataWriter writer, StringBuilder replaceBuilder, boolean dedotMetricName) {
serializeObjectStart(key, "value", suffix, writer, replaceBuilder, dedotMetricName);
private static void serializeValueStart(String key, String suffix, DataWriter writer, boolean dedotMetricName) {
serializeObjectStart(key, "value", suffix, writer, dedotMetricName);
}

private static void serializeObjectStart(String key, String objectName, String suffix, DataWriter writer, StringBuilder replaceBuilder, boolean dedotMetricName) {
replaceBuilder.setLength(0);
if (dedotMetricName) {
writer.sanitizePropertyName(key, replaceBuilder);
private static void serializeObjectStart(String key, String objectName, String suffix, DataWriter writer, boolean dedotMetricName) {
String name;
if (suffix == null) {
name = key;
} else {
replaceBuilder.append(key);
name = key + suffix;
}
if (suffix != null) {
if (replaceBuilder.length() == 0) {
replaceBuilder.append(key);
}
replaceBuilder.append(suffix);
}
writer.writeString(replaceBuilder);

writer.write(SEMI);
writer.writeFieldName(name, dedotMetricName);
writer.write(OBJECT_START);
writer.writeFieldName(objectName);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,10 @@ class MetricSetSerializer {

private static final int INITIAL_BUFFER_SIZE = 2048;

private final StringBuilder replaceBuilder;
private final DataWriter writer;
private boolean anySamplesWritten;

public MetricSetSerializer(ReportingTracer tracer, Attributes attributes, CharSequence instrumentationScopeName, long epochMicros, StringBuilder replaceBuilder) {
this.replaceBuilder = replaceBuilder;
public MetricSetSerializer(ReportingTracer tracer, Attributes attributes, CharSequence instrumentationScopeName, long epochMicros) {
anySamplesWritten = false;
writer = tracer.newWriter(INITIAL_BUFFER_SIZE);
writer.write(OBJECT_START);
Expand Down Expand Up @@ -203,8 +201,7 @@ private boolean serializeAttribute(AttributeKey<?> key, @Nullable Object value,
if (prependComma) {
writer.write(COMMA);
}
writer.writeStringValue(writer.sanitizePropertyName(key.getKey(), replaceBuilder), replaceBuilder);
writer.write(SEMI);
writer.writeFieldName(key.getKey(), true);

AttributeType type = key.getType();
switch (type) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ public class OtelMetricSerializer {
private static final Logger logger = LoggerFactory.getLogger(OtelMetricSerializer.class);
private final ReporterConfiguration reporterConfig;
private final ReportingTracer tracer;
private final StringBuilder serializationTempBuilder;

private final Set<String> metricsWithBadAggregations = Collections.newSetFromMap(new ConcurrentHashMap<>());

private final Map<InstrumentationScopeAndTimestamp, Map<Attributes, MetricSetSerializer>> metricSets;
Expand All @@ -57,7 +55,6 @@ public OtelMetricSerializer(ReporterConfiguration reporterConfig, ReportingTrace
this.reporterConfig = reporterConfig;
this.tracer = tracer;
metricSets = new HashMap<>();
serializationTempBuilder = new StringBuilder();
}

public void addValues(MetricData metric) {
Expand Down Expand Up @@ -152,7 +149,7 @@ private MetricSetSerializer getOrCreateMetricSet(CharSequence instrScopeName, lo

MetricSetSerializer ms = timestampMetricSets.get(attributes);
if (ms == null) {
ms = new MetricSetSerializer(tracer, attributes, key.instrumentationScopeName, key.timestamp, serializationTempBuilder);
ms = new MetricSetSerializer(tracer, attributes, key.instrumentationScopeName, key.timestamp);
timestampMetricSets.put(attributes, ms);
}
return ms;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public interface DataWriter {

void writeFieldName(String name);

void writeFieldName(String name, boolean sanitized);

void write(StructureType type);

void serialize(boolean value);
Expand All @@ -32,11 +34,11 @@ public interface DataWriter {

void writeString(CharSequence value);

void writeStringValue(CharSequence value, StringBuilder replaceBuilder);
void writeString(CharSequence value, boolean trimmed);

int size();

CharSequence sanitizePropertyName(String key, StringBuilder replaceBuilder);
String sanitizePropertyName(String key);

void report();

Expand Down

0 comments on commit da91e15

Please sign in to comment.