All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.opentelemetry.exporter.internal.marshal.Serializer Maven / Gradle / Ivy

/*
 * Copyright The OpenTelemetry Authors
 * SPDX-License-Identifier: Apache-2.0
 */

package io.opentelemetry.exporter.internal.marshal;

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.sdk.internal.DynamicPrimitiveLongList;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import javax.annotation.Nullable;

/**
 * Serializer to use when converting from an SDK data object into a protobuf output format. Unlike
 * {@link CodedOutputStream}, which strictly encodes data into the protobuf binary format, this
 *
 * 
    *
  • Handles proto3 semantics of not outputting the value when it matches the default of a field *
  • Can be implemented to serialize into protobuf JSON format (not binary) *
* *

This class is internal and is hence not for public use. Its APIs are unstable and can change * at any time. */ public abstract class Serializer implements AutoCloseable { private static final MarshalerContext.Key ATTRIBUTES_WRITER_KEY = MarshalerContext.key(); Serializer() {} /** Serializes a trace ID field. */ public void serializeTraceId(ProtoFieldInfo field, @Nullable String traceId) throws IOException { if (traceId == null) { return; } writeTraceId(field, traceId); } public void serializeTraceId( ProtoFieldInfo field, @Nullable String traceId, MarshalerContext context) throws IOException { if (traceId == null) { return; } writeTraceId(field, traceId, context); } protected abstract void writeTraceId(ProtoFieldInfo field, String traceId) throws IOException; protected void writeTraceId(ProtoFieldInfo field, String traceId, MarshalerContext context) throws IOException { writeTraceId(field, traceId); } /** Serializes a span ID field. */ public void serializeSpanId(ProtoFieldInfo field, @Nullable String spanId) throws IOException { if (spanId == null) { return; } writeSpanId(field, spanId); } public void serializeSpanId( ProtoFieldInfo field, @Nullable String spanId, MarshalerContext context) throws IOException { if (spanId == null) { return; } writeSpanId(field, spanId, context); } protected abstract void writeSpanId(ProtoFieldInfo field, String spanId) throws IOException; protected void writeSpanId(ProtoFieldInfo field, String spanId, MarshalerContext context) throws IOException { writeSpanId(field, spanId); } /** Serializes a protobuf {@code bool} field. */ public void serializeBool(ProtoFieldInfo field, boolean value) throws IOException { if (!value) { return; } writeBool(field, value); } /** Writes a protobuf {@code bool} field, even if it matches the default value. */ public abstract void writeBool(ProtoFieldInfo field, boolean value) throws IOException; /** Serializes a protobuf {@code enum} field. */ public void serializeEnum(ProtoFieldInfo field, ProtoEnumInfo enumValue) throws IOException { if (enumValue.getEnumNumber() == 0) { return; } writeEnum(field, enumValue); } protected abstract void writeEnum(ProtoFieldInfo field, ProtoEnumInfo enumValue) throws IOException; /** Serializes a protobuf {@code uint32} field. */ public void serializeUInt32(ProtoFieldInfo field, int value) throws IOException { if (value == 0) { return; } writeUint32(field, value); } protected abstract void writeUint32(ProtoFieldInfo field, int value) throws IOException; /** Serializes a protobuf {@code sint32} field. */ public void serializeSInt32(ProtoFieldInfo field, int value) throws IOException { if (value == 0) { return; } writeSInt32(field, value); } protected abstract void writeSInt32(ProtoFieldInfo info, int value) throws IOException; /** Serializes a protobuf {@code uint32} field. */ public void serializeInt32(ProtoFieldInfo field, int value) throws IOException { if (value == 0) { return; } writeint32(field, value); } protected abstract void writeint32(ProtoFieldInfo field, int value) throws IOException; /** Serializes a protobuf {@code int64} field. */ public void serializeInt64(ProtoFieldInfo field, long value) throws IOException { if (value == 0) { return; } writeInt64(field, value); } /** Serializes a protobuf {@code uint64} field. */ public void serializeUInt64(ProtoFieldInfo field, long value) throws IOException { if (value == 0) { return; } writeUInt64(field, value); } /** Writes a protobuf {@code int64} field, even if it matches the default value. */ public abstract void writeInt64(ProtoFieldInfo field, long value) throws IOException; /** Writes a protobuf {@code uint64} field, even if it matches the default value. */ public abstract void writeUInt64(ProtoFieldInfo field, long value) throws IOException; /** Serializes a protobuf {@code fixed64} field. */ public void serializeFixed64(ProtoFieldInfo field, long value) throws IOException { if (value == 0) { return; } writeFixed64(field, value); } /** Serializes a protobuf {@code fixed64} field. */ public void serializeFixed64Optional(ProtoFieldInfo field, long value) throws IOException { writeFixed64(field, value); } protected abstract void writeFixed64(ProtoFieldInfo field, long value) throws IOException; protected abstract void writeFixed64Value(long value) throws IOException; protected abstract void writeUInt64Value(long value) throws IOException; /** * Serializes a byte as a protobuf {@code fixed32} field. Ensures that there is no sign * propagation if the high bit in the byte is set. */ public void serializeByteAsFixed32(ProtoFieldInfo field, byte value) throws IOException { serializeFixed32(field, ((int) value) & 0xff); } /** Serializes a protobuf {@code fixed32} field. */ public void serializeFixed32(ProtoFieldInfo field, int value) throws IOException { if (value == 0) { return; } writeFixed32(field, value); } protected abstract void writeFixed32(ProtoFieldInfo field, int value) throws IOException; /** Serializes a proto buf {@code double} field. */ public void serializeDouble(ProtoFieldInfo field, double value) throws IOException { if (value == 0D) { return; } writeDouble(field, value); } /** Serializes a proto buf {@code double} field. */ public void serializeDoubleOptional(ProtoFieldInfo field, double value) throws IOException { writeDouble(field, value); } /** Writes a protobuf {@code double} field, even if it matches the default value. */ public abstract void writeDouble(ProtoFieldInfo field, double value) throws IOException; protected abstract void writeDoubleValue(double value) throws IOException; /** * Serializes a protobuf {@code string} field. {@code utf8Bytes} is the UTF8 encoded bytes of the * string to serialize. */ public void serializeString(ProtoFieldInfo field, byte[] utf8Bytes) throws IOException { if (utf8Bytes.length == 0) { return; } writeString(field, utf8Bytes); } /** * Serializes a protobuf {@code string} field. {@code string} is the value to be serialized and * {@code utf8Length} is the length of the string after it is encoded in UTF8. This method reads * elements from context, use together with {@link * StatelessMarshalerUtil#sizeStringWithContext(ProtoFieldInfo, String, MarshalerContext)}. */ public void serializeStringWithContext( ProtoFieldInfo field, @Nullable String string, MarshalerContext context) throws IOException { if (string == null || string.isEmpty()) { return; } if (context.marshalStringNoAllocation()) { writeString(field, string, context.getSize(), context); } else { byte[] valueUtf8 = context.getData(byte[].class); writeString(field, valueUtf8); } } /** Writes a protobuf {@code string} field, even if it matches the default value. */ public abstract void writeString(ProtoFieldInfo field, byte[] utf8Bytes) throws IOException; public abstract void writeString( ProtoFieldInfo field, String string, int utf8Length, MarshalerContext context) throws IOException; /** Serializes a protobuf {@code bytes} field. */ public void serializeBytes(ProtoFieldInfo field, byte[] value) throws IOException { if (value.length == 0) { return; } writeBytes(field, value); } /** * Serializes a protobuf {@code bytes} field. Writes all content of the ByteBuffer regardless of * the current position and limit. Does not alter the position or limit of the provided * ByteBuffer. */ public void serializeByteBuffer(ProtoFieldInfo field, ByteBuffer value) throws IOException { if (value.capacity() == 0) { return; } writeByteBuffer(field, value); } public abstract void writeBytes(ProtoFieldInfo field, byte[] value) throws IOException; public abstract void writeByteBuffer(ProtoFieldInfo field, ByteBuffer value) throws IOException; protected abstract void writeStartMessage(ProtoFieldInfo field, int protoMessageSize) throws IOException; protected abstract void writeEndMessage() throws IOException; /** Serializes a protobuf embedded {@code message}. */ public void serializeMessage(ProtoFieldInfo field, Marshaler message) throws IOException { writeStartMessage(field, message.getBinarySerializedSize()); message.writeTo(this); writeEndMessage(); } /** * Serializes a protobuf embedded {@code message}. This method adds elements to context, use * together with {@link StatelessMarshalerUtil#sizeMessageWithContext(ProtoFieldInfo, Object, * StatelessMarshaler, MarshalerContext)}. */ public void serializeMessageWithContext( ProtoFieldInfo field, T message, StatelessMarshaler marshaler, MarshalerContext context) throws IOException { writeStartMessage(field, context.getSize()); marshaler.writeTo(this, message, context); writeEndMessage(); } /** * Serializes a protobuf embedded {@code message}. This method adds elements to context, use * together with {@link StatelessMarshalerUtil#sizeMessageWithContext(ProtoFieldInfo, Object, * Object, StatelessMarshaler2, MarshalerContext)}. */ public void serializeMessageWithContext( ProtoFieldInfo field, K key, V value, StatelessMarshaler2 marshaler, MarshalerContext context) throws IOException { writeStartMessage(field, context.getSize()); marshaler.writeTo(this, key, value, context); writeEndMessage(); } @SuppressWarnings("SameParameterValue") protected abstract void writeStartRepeatedPrimitive( ProtoFieldInfo field, int protoSizePerElement, int numElements) throws IOException; protected abstract void writeEndRepeatedPrimitive() throws IOException; protected abstract void writeStartRepeatedVarint(ProtoFieldInfo field, int payloadSize) throws IOException; protected abstract void writeEndRepeatedVarint() throws IOException; /** Serializes a {@code repeated fixed64} field. */ public void serializeRepeatedFixed64(ProtoFieldInfo field, List values) throws IOException { if (values.isEmpty()) { return; } writeStartRepeatedPrimitive(field, WireFormat.FIXED64_SIZE, values.size()); for (int i = 0; i < values.size(); i++) { Long value = values.get(i); writeFixed64Value(value); } writeEndRepeatedPrimitive(); } /** Serializes a {@code repeated fixed64} field. */ public void serializeRepeatedFixed64(ProtoFieldInfo field, long[] values) throws IOException { if (values.length == 0) { return; } writeStartRepeatedPrimitive(field, WireFormat.FIXED64_SIZE, values.length); for (long value : values) { writeFixed64Value(value); } writeEndRepeatedPrimitive(); } /** Serializes a {@code repeated uint64} field. */ public void serializeRepeatedUInt64(ProtoFieldInfo field, long[] values) throws IOException { if (values.length == 0) { return; } int payloadSize = 0; for (long v : values) { payloadSize += CodedOutputStream.computeUInt64SizeNoTag(v); } writeStartRepeatedVarint(field, payloadSize); for (long value : values) { writeUInt64Value(value); } writeEndRepeatedVarint(); } /** Serializes a {@code repeated uint64} field. */ public void serializeRepeatedUInt64(ProtoFieldInfo field, List values) throws IOException { if (values.isEmpty()) { return; } int payloadSize = 0; for (long v : values) { payloadSize += CodedOutputStream.computeUInt64SizeNoTag(v); } writeStartRepeatedVarint(field, payloadSize); for (long value : values) { writeUInt64Value(value); } writeEndRepeatedVarint(); } /** * Serializes a {@code repeated uint64} field. * *

NOTE: This is the same as {@link #serializeRepeatedUInt64(ProtoFieldInfo, long[])} but * instead of taking a primitive array it takes a {@link DynamicPrimitiveLongList} as input. */ public void serializeRepeatedUInt64(ProtoFieldInfo field, DynamicPrimitiveLongList values) throws IOException { if (values.isEmpty()) { return; } int payloadSize = 0; for (int i = 0; i < values.size(); i++) { long v = values.getLong(i); payloadSize += CodedOutputStream.computeUInt64SizeNoTag(v); } writeStartRepeatedVarint(field, payloadSize); for (int i = 0; i < values.size(); i++) { long value = values.getLong(i); writeUInt64Value(value); } writeEndRepeatedVarint(); } /** Serializes a {@code repeated int64} field. */ public void serializeRepeatedInt64(ProtoFieldInfo field, List values) throws IOException { if (values.isEmpty()) { return; } int payloadSize = 0; for (long v : values) { payloadSize += CodedOutputStream.computeInt64SizeNoTag(v); } writeStartRepeatedVarint(field, payloadSize); for (long value : values) { writeUInt64Value(value); } writeEndRepeatedVarint(); } /** Serializes a {@code repeated double} field. */ public void serializeRepeatedDouble(ProtoFieldInfo field, List values) throws IOException { if (values.isEmpty()) { return; } writeStartRepeatedPrimitive(field, WireFormat.FIXED64_SIZE, values.size()); for (int i = 0; i < values.size(); i++) { Double value = values.get(i); writeDoubleValue(value); } writeEndRepeatedPrimitive(); } /** Serializes {@code repeated message} field. */ @SuppressWarnings("AvoidObjectArrays") public abstract void serializeRepeatedMessage(ProtoFieldInfo field, Marshaler[] repeatedMessage) throws IOException; /** Serializes {@code repeated message} field. */ public abstract void serializeRepeatedMessage( ProtoFieldInfo field, List repeatedMessage) throws IOException; /** * Serializes {@code repeated message} field. This method reads elements from context, use * together with {@link StatelessMarshalerUtil#sizeRepeatedMessageWithContext(ProtoFieldInfo, * List, StatelessMarshaler, MarshalerContext)}. */ public abstract void serializeRepeatedMessageWithContext( ProtoFieldInfo field, List messages, StatelessMarshaler marshaler, MarshalerContext context) throws IOException; /** * Serializes {@code repeated message} field. This method reads elements from context, use * together with {@link StatelessMarshalerUtil#sizeRepeatedMessageWithContext(ProtoFieldInfo, * Collection, StatelessMarshaler, MarshalerContext, MarshalerContext.Key)}. */ @SuppressWarnings("unchecked") public void serializeRepeatedMessageWithContext( ProtoFieldInfo field, Collection messages, StatelessMarshaler marshaler, MarshalerContext context, MarshalerContext.Key key) throws IOException { if (messages instanceof List) { serializeRepeatedMessageWithContext(field, (List) messages, marshaler, context); return; } writeStartRepeated(field); if (!messages.isEmpty()) { RepeatedElementWriter writer = context.getInstance(key, RepeatedElementWriter::new); writer.initialize(field, this, marshaler, context); messages.forEach(writer); } writeEndRepeated(); } /** * Serializes {@code repeated message} field. This method reads elements from context, use * together with {@link StatelessMarshalerUtil#sizeRepeatedMessageWithContext(ProtoFieldInfo, Map, * StatelessMarshaler2, MarshalerContext, MarshalerContext.Key)}. */ public void serializeRepeatedMessageWithContext( ProtoFieldInfo field, Map messages, StatelessMarshaler2 marshaler, MarshalerContext context, MarshalerContext.Key key) throws IOException { writeStartRepeated(field); if (!messages.isEmpty()) { RepeatedElementPairWriter writer = context.getInstance(key, RepeatedElementPairWriter::new); writer.initialize(field, this, marshaler, context); messages.forEach(writer); } writeEndRepeated(); } /** * Serializes {@code repeated message} field. This method reads elements from context, use * together with {@link StatelessMarshalerUtil#sizeRepeatedMessageWithContext(ProtoFieldInfo, * Attributes, StatelessMarshaler2, MarshalerContext)}. */ public void serializeRepeatedMessageWithContext( ProtoFieldInfo field, Attributes attributes, StatelessMarshaler2, Object> marshaler, MarshalerContext context) throws IOException { writeStartRepeated(field); if (!attributes.isEmpty()) { RepeatedElementPairWriter, Object> writer = context.getInstance(ATTRIBUTES_WRITER_KEY, RepeatedElementPairWriter::new); writer.initialize(field, this, marshaler, context); attributes.forEach(writer); } writeEndRepeated(); } private static class RepeatedElementWriter implements Consumer { @SuppressWarnings("NullAway") private ProtoFieldInfo field; @SuppressWarnings("NullAway") private Serializer output; @SuppressWarnings("NullAway") private StatelessMarshaler marshaler; @SuppressWarnings("NullAway") private MarshalerContext context; void initialize( ProtoFieldInfo field, Serializer output, StatelessMarshaler marshaler, MarshalerContext context) { this.field = field; this.output = output; this.marshaler = marshaler; this.context = context; } @Override public void accept(T element) { try { output.writeStartRepeatedElement(field, context.getSize()); marshaler.writeTo(output, element, context); output.writeEndRepeatedElement(); } catch (IOException e) { throw new IllegalStateException(e); } } } private static class RepeatedElementPairWriter implements BiConsumer { @SuppressWarnings("NullAway") private ProtoFieldInfo field; @SuppressWarnings("NullAway") private Serializer output; @SuppressWarnings("NullAway") private StatelessMarshaler2 marshaler; @SuppressWarnings("NullAway") private MarshalerContext context; void initialize( ProtoFieldInfo field, Serializer output, StatelessMarshaler2 marshaler, MarshalerContext context) { this.field = field; this.output = output; this.marshaler = marshaler; this.context = context; } @Override public void accept(K key, V value) { try { output.writeStartRepeatedElement(field, context.getSize()); marshaler.writeTo(output, key, value, context); output.writeEndRepeatedElement(); } catch (IOException e) { throw new IllegalStateException(e); } } } /** Writes start of repeated messages. */ protected abstract void writeStartRepeated(ProtoFieldInfo field) throws IOException; /** Writes end of repeated messages. */ protected abstract void writeEndRepeated() throws IOException; /** Writes start of a repeated message element. */ protected abstract void writeStartRepeatedElement(ProtoFieldInfo field, int protoMessageSize) throws IOException; /** Writes end of a repeated message element. */ protected abstract void writeEndRepeatedElement() throws IOException; /** Writes the value for a message field that has been pre-serialized. */ public abstract void writeSerializedMessage(byte[] protoSerialized, String jsonSerialized) throws IOException; @Override public abstract void close() throws IOException; }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy