| 
 | 1 | +// Copyright The OpenTelemetry Authors  | 
 | 2 | +// SPDX-License-Identifier: Apache-2.0  | 
 | 3 | + | 
 | 4 | +using OpenTelemetry.Internal;  | 
 | 5 | + | 
 | 6 | +namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.Serializer;  | 
 | 7 | + | 
 | 8 | +internal sealed class ProtobufOtlpTagWriter : TagWriter<ProtobufOtlpTagWriter.OtlpTagWriterState, ProtobufOtlpTagWriter.OtlpTagWriterArrayState>  | 
 | 9 | +{  | 
 | 10 | +    private ProtobufOtlpTagWriter()  | 
 | 11 | +        : base(new OtlpArrayTagWriter())  | 
 | 12 | +    {  | 
 | 13 | +    }  | 
 | 14 | + | 
 | 15 | +    public static ProtobufOtlpTagWriter Instance { get; } = new();  | 
 | 16 | + | 
 | 17 | +    protected override void WriteIntegralTag(ref OtlpTagWriterState state, string key, long value)  | 
 | 18 | +    {  | 
 | 19 | +        // Write KeyValue tag  | 
 | 20 | +        state.WritePosition = ProtobufSerializer.WriteStringWithTag(state.Buffer, state.WritePosition, ProtobufOtlpFieldNumberConstants.KeyValue_Key, key);  | 
 | 21 | + | 
 | 22 | +        // Write KeyValue.Value tag, length and value.  | 
 | 23 | +        var size = ProtobufSerializer.ComputeVarInt64Size((ulong)value) + 1; // ComputeVarint64Size(ulong) + TagSize  | 
 | 24 | +        state.WritePosition = ProtobufSerializer.WriteTagAndLength(state.Buffer, state.WritePosition, size, ProtobufOtlpFieldNumberConstants.KeyValue_Value, ProtobufWireType.LEN);  | 
 | 25 | +        state.WritePosition = ProtobufSerializer.WriteInt64WithTag(state.Buffer, state.WritePosition, ProtobufOtlpFieldNumberConstants.AnyValue_Int_Value, (ulong)value);  | 
 | 26 | +    }  | 
 | 27 | + | 
 | 28 | +    protected override void WriteFloatingPointTag(ref OtlpTagWriterState state, string key, double value)  | 
 | 29 | +    {  | 
 | 30 | +        // Write KeyValue tag  | 
 | 31 | +        state.WritePosition = ProtobufSerializer.WriteStringWithTag(state.Buffer, state.WritePosition, ProtobufOtlpFieldNumberConstants.KeyValue_Key, key);  | 
 | 32 | + | 
 | 33 | +        // Write KeyValue.Value tag, length and value.  | 
 | 34 | +        state.WritePosition = ProtobufSerializer.WriteTagAndLength(state.Buffer, state.WritePosition, 9, ProtobufOtlpFieldNumberConstants.KeyValue_Value, ProtobufWireType.LEN); // 8 + TagSize  | 
 | 35 | +        state.WritePosition = ProtobufSerializer.WriteDoubleWithTag(state.Buffer, state.WritePosition, ProtobufOtlpFieldNumberConstants.AnyValue_Double_Value, value);  | 
 | 36 | +    }  | 
 | 37 | + | 
 | 38 | +    protected override void WriteBooleanTag(ref OtlpTagWriterState state, string key, bool value)  | 
 | 39 | +    {  | 
 | 40 | +        // Write KeyValue tag  | 
 | 41 | +        state.WritePosition = ProtobufSerializer.WriteStringWithTag(state.Buffer, state.WritePosition, ProtobufOtlpFieldNumberConstants.KeyValue_Key, key);  | 
 | 42 | + | 
 | 43 | +        // Write KeyValue.Value tag, length and value.  | 
 | 44 | +        state.WritePosition = ProtobufSerializer.WriteTagAndLength(state.Buffer, state.WritePosition, 2, ProtobufOtlpFieldNumberConstants.KeyValue_Value, ProtobufWireType.LEN); // 1 + TagSize  | 
 | 45 | +        state.WritePosition = ProtobufSerializer.WriteBoolWithTag(state.Buffer, state.WritePosition, ProtobufOtlpFieldNumberConstants.AnyValue_Bool_Value, value);  | 
 | 46 | +    }  | 
 | 47 | + | 
 | 48 | +    protected override void WriteStringTag(ref OtlpTagWriterState state, string key, ReadOnlySpan<char> value)  | 
 | 49 | +    {  | 
 | 50 | +        // Write KeyValue tag  | 
 | 51 | +        state.WritePosition = ProtobufSerializer.WriteStringWithTag(state.Buffer, state.WritePosition, ProtobufOtlpFieldNumberConstants.KeyValue_Key, key);  | 
 | 52 | + | 
 | 53 | +        // Write KeyValue.Value tag, length and value.  | 
 | 54 | +        var numberOfUtf8CharsInString = ProtobufSerializer.GetNumberOfUtf8CharsInString(value);  | 
 | 55 | +        var serializedLengthSize = ProtobufSerializer.ComputeVarInt64Size((ulong)numberOfUtf8CharsInString);  | 
 | 56 | + | 
 | 57 | +        // length = numberOfUtf8CharsInString + tagSize + length field size.  | 
 | 58 | +        state.WritePosition = ProtobufSerializer.WriteTagAndLength(state.Buffer, state.WritePosition, numberOfUtf8CharsInString + 1 + serializedLengthSize, ProtobufOtlpFieldNumberConstants.KeyValue_Value, ProtobufWireType.LEN);  | 
 | 59 | +        state.WritePosition = ProtobufSerializer.WriteStringWithTag(state.Buffer, state.WritePosition, ProtobufOtlpFieldNumberConstants.AnyValue_String_Value, numberOfUtf8CharsInString, value);  | 
 | 60 | +    }  | 
 | 61 | + | 
 | 62 | +    protected override void WriteArrayTag(ref OtlpTagWriterState state, string key, ref OtlpTagWriterArrayState value)  | 
 | 63 | +    {  | 
 | 64 | +        // TODO: Expand OtlpTagWriterArrayState.Buffer on IndexOutOfRangeException.  | 
 | 65 | +        // Write KeyValue tag  | 
 | 66 | +        state.WritePosition = ProtobufSerializer.WriteStringWithTag(state.Buffer, state.WritePosition, ProtobufOtlpFieldNumberConstants.KeyValue_Key, key);  | 
 | 67 | + | 
 | 68 | +        // Write KeyValue.Value tag and length  | 
 | 69 | +        var serializedLengthSize = ProtobufSerializer.ComputeVarInt64Size((ulong)value.WritePosition);  | 
 | 70 | +        state.WritePosition = ProtobufSerializer.WriteTagAndLength(state.Buffer, state.WritePosition, value.WritePosition + 1 + serializedLengthSize, ProtobufOtlpFieldNumberConstants.KeyValue_Value, ProtobufWireType.LEN); // Array content length + Array tag size + length field size  | 
 | 71 | + | 
 | 72 | +        // Write Array tag and length  | 
 | 73 | +        state.WritePosition = ProtobufSerializer.WriteTagAndLength(state.Buffer, state.WritePosition, value.WritePosition, ProtobufOtlpFieldNumberConstants.AnyValue_Array_Value, ProtobufWireType.LEN);  | 
 | 74 | +        Buffer.BlockCopy(value.Buffer, 0, state.Buffer, state.WritePosition, value.WritePosition);  | 
 | 75 | +        state.WritePosition += value.WritePosition;  | 
 | 76 | +    }  | 
 | 77 | + | 
 | 78 | +    protected override void OnUnsupportedTagDropped(  | 
 | 79 | +        string tagKey,  | 
 | 80 | +        string tagValueTypeFullName) => OpenTelemetryProtocolExporterEventSource.Log.UnsupportedAttributeType(  | 
 | 81 | +            tagValueTypeFullName,  | 
 | 82 | +            tagKey);  | 
 | 83 | + | 
 | 84 | +    internal struct OtlpTagWriterState  | 
 | 85 | +    {  | 
 | 86 | +        public byte[] Buffer;  | 
 | 87 | +        public int WritePosition;  | 
 | 88 | +    }  | 
 | 89 | + | 
 | 90 | +    internal struct OtlpTagWriterArrayState  | 
 | 91 | +    {  | 
 | 92 | +        public byte[] Buffer;  | 
 | 93 | +        public int WritePosition;  | 
 | 94 | +    }  | 
 | 95 | + | 
 | 96 | +    private sealed class OtlpArrayTagWriter : ArrayTagWriter<OtlpTagWriterArrayState>  | 
 | 97 | +    {  | 
 | 98 | +        [ThreadStatic]  | 
 | 99 | +        private static byte[]? threadBuffer;  | 
 | 100 | + | 
 | 101 | +        public override OtlpTagWriterArrayState BeginWriteArray()  | 
 | 102 | +        {  | 
 | 103 | +            threadBuffer ??= new byte[2048];  | 
 | 104 | + | 
 | 105 | +            return new OtlpTagWriterArrayState  | 
 | 106 | +            {  | 
 | 107 | +                Buffer = threadBuffer,  | 
 | 108 | +                WritePosition = 0,  | 
 | 109 | +            };  | 
 | 110 | +        }  | 
 | 111 | + | 
 | 112 | +        public override void WriteNullValue(ref OtlpTagWriterArrayState state)  | 
 | 113 | +        {  | 
 | 114 | +        }  | 
 | 115 | + | 
 | 116 | +        public override void WriteIntegralValue(ref OtlpTagWriterArrayState state, long value)  | 
 | 117 | +        {  | 
 | 118 | +            var size = ProtobufSerializer.ComputeVarInt64Size((ulong)value) + 1;  | 
 | 119 | +            state.WritePosition = ProtobufSerializer.WriteTagAndLength(state.Buffer, state.WritePosition, size, ProtobufOtlpFieldNumberConstants.ArrayValue_Value, ProtobufWireType.LEN);  | 
 | 120 | +            state.WritePosition = ProtobufSerializer.WriteInt64WithTag(state.Buffer, state.WritePosition, ProtobufOtlpFieldNumberConstants.AnyValue_Int_Value, (ulong)value);  | 
 | 121 | +        }  | 
 | 122 | + | 
 | 123 | +        public override void WriteFloatingPointValue(ref OtlpTagWriterArrayState state, double value)  | 
 | 124 | +        {  | 
 | 125 | +            state.WritePosition = ProtobufSerializer.WriteTagAndLength(state.Buffer, state.WritePosition, 9, ProtobufOtlpFieldNumberConstants.ArrayValue_Value, ProtobufWireType.LEN);  | 
 | 126 | +            state.WritePosition = ProtobufSerializer.WriteDoubleWithTag(state.Buffer, state.WritePosition, ProtobufOtlpFieldNumberConstants.AnyValue_Double_Value, value);  | 
 | 127 | +        }  | 
 | 128 | + | 
 | 129 | +        public override void WriteBooleanValue(ref OtlpTagWriterArrayState state, bool value)  | 
 | 130 | +        {  | 
 | 131 | +            state.WritePosition = ProtobufSerializer.WriteTagAndLength(state.Buffer, state.WritePosition, 2, ProtobufOtlpFieldNumberConstants.ArrayValue_Value, ProtobufWireType.LEN);  | 
 | 132 | +            state.WritePosition = ProtobufSerializer.WriteBoolWithTag(state.Buffer, state.WritePosition, ProtobufOtlpFieldNumberConstants.AnyValue_Bool_Value, value);  | 
 | 133 | +        }  | 
 | 134 | + | 
 | 135 | +        public override void WriteStringValue(ref OtlpTagWriterArrayState state, ReadOnlySpan<char> value)  | 
 | 136 | +        {  | 
 | 137 | +            // Write KeyValue.Value tag, length and value.  | 
 | 138 | +            var numberOfUtf8CharsInString = ProtobufSerializer.GetNumberOfUtf8CharsInString(value);  | 
 | 139 | +            var serializedLengthSize = ProtobufSerializer.ComputeVarInt64Size((ulong)numberOfUtf8CharsInString);  | 
 | 140 | + | 
 | 141 | +            // length = numberOfUtf8CharsInString + tagSize + length field size.  | 
 | 142 | +            state.WritePosition = ProtobufSerializer.WriteTagAndLength(state.Buffer, state.WritePosition, numberOfUtf8CharsInString + 1 + serializedLengthSize, ProtobufOtlpFieldNumberConstants.ArrayValue_Value, ProtobufWireType.LEN);  | 
 | 143 | +            state.WritePosition = ProtobufSerializer.WriteStringWithTag(state.Buffer, state.WritePosition, ProtobufOtlpFieldNumberConstants.AnyValue_String_Value, numberOfUtf8CharsInString, value);  | 
 | 144 | +        }  | 
 | 145 | + | 
 | 146 | +        public override void EndWriteArray(ref OtlpTagWriterArrayState state)  | 
 | 147 | +        {  | 
 | 148 | +        }  | 
 | 149 | +    }  | 
 | 150 | +}  | 
0 commit comments