Remove Jaeger Exporter - part 3: remove implementation and tests (#4796)
This commit is contained in:
parent
2f6e1e5a48
commit
73df32b967
|
|
@ -60,10 +60,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testdata", "testdata", "{77
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{E359BB2B-9AEC-497D-B321-7DF2450C3B8E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Jaeger", "src\OpenTelemetry.Exporter.Jaeger\OpenTelemetry.Exporter.Jaeger.csproj", "{8D47E3CF-9AE3-42FE-9084-FEB72D9AD769}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Jaeger.Tests", "test\OpenTelemetry.Exporter.Jaeger.Tests\OpenTelemetry.Exporter.Jaeger.Tests.csproj", "{21E69213-72D5-453F-BD00-75EF36AC4965}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Shims.OpenTracing", "src\OpenTelemetry.Shims.OpenTracing\OpenTelemetry.Shims.OpenTracing.csproj", "{AAC408FE-40EF-4479-97D9-697F2C1A0B28}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Shims.OpenTracing.Tests", "test\OpenTelemetry.Shims.OpenTracing.Tests\OpenTelemetry.Shims.OpenTracing.Tests.csproj", "{49A7853F-5B6F-4B65-A781-7D29A1C92164}"
|
||||
|
|
@ -342,14 +338,6 @@ Global
|
|||
{2A47F6A8-63E5-4237-8046-94CAF321E797}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2A47F6A8-63E5-4237-8046-94CAF321E797}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2A47F6A8-63E5-4237-8046-94CAF321E797}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8D47E3CF-9AE3-42FE-9084-FEB72D9AD769}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8D47E3CF-9AE3-42FE-9084-FEB72D9AD769}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8D47E3CF-9AE3-42FE-9084-FEB72D9AD769}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8D47E3CF-9AE3-42FE-9084-FEB72D9AD769}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{21E69213-72D5-453F-BD00-75EF36AC4965}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{21E69213-72D5-453F-BD00-75EF36AC4965}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{21E69213-72D5-453F-BD00-75EF36AC4965}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{21E69213-72D5-453F-BD00-75EF36AC4965}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AAC408FE-40EF-4479-97D9-697F2C1A0B28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AAC408FE-40EF-4479-97D9-697F2C1A0B28}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AAC408FE-40EF-4479-97D9-697F2C1A0B28}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
OpenTelemetry.Exporter.JaegerExporter
|
||||
OpenTelemetry.Exporter.JaegerExporter.JaegerExporter(OpenTelemetry.Exporter.JaegerExporterOptions options) -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.AgentHost.get -> string
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.AgentHost.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.AgentPort.get -> int
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.AgentPort.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.BatchExportProcessorOptions.get -> OpenTelemetry.BatchExportProcessorOptions<System.Diagnostics.Activity>
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.BatchExportProcessorOptions.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.Endpoint.get -> System.Uri
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.Endpoint.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.ExportProcessorType.get -> OpenTelemetry.ExportProcessorType
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.ExportProcessorType.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.HttpClientFactory.get -> System.Func<System.Net.Http.HttpClient>
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.HttpClientFactory.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.JaegerExporterOptions() -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.MaxPayloadSizeInBytes.get -> int?
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.MaxPayloadSizeInBytes.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.Protocol.get -> OpenTelemetry.Exporter.JaegerExportProtocol
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.Protocol.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExportProtocol
|
||||
OpenTelemetry.Exporter.JaegerExportProtocol.HttpBinaryThrift = 1 -> OpenTelemetry.Exporter.JaegerExportProtocol
|
||||
OpenTelemetry.Exporter.JaegerExportProtocol.UdpCompactThrift = 0 -> OpenTelemetry.Exporter.JaegerExportProtocol
|
||||
OpenTelemetry.Trace.JaegerExporterHelperExtensions
|
||||
override OpenTelemetry.Exporter.JaegerExporter.Dispose(bool disposing) -> void
|
||||
override OpenTelemetry.Exporter.JaegerExporter.Export(in OpenTelemetry.Batch<System.Diagnostics.Activity> activityBatch) -> OpenTelemetry.ExportResult
|
||||
static OpenTelemetry.Trace.JaegerExporterHelperExtensions.AddJaegerExporter(this OpenTelemetry.Trace.TracerProviderBuilder builder) -> OpenTelemetry.Trace.TracerProviderBuilder
|
||||
static OpenTelemetry.Trace.JaegerExporterHelperExtensions.AddJaegerExporter(this OpenTelemetry.Trace.TracerProviderBuilder builder, string name, System.Action<OpenTelemetry.Exporter.JaegerExporterOptions> configure) -> OpenTelemetry.Trace.TracerProviderBuilder
|
||||
static OpenTelemetry.Trace.JaegerExporterHelperExtensions.AddJaegerExporter(this OpenTelemetry.Trace.TracerProviderBuilder builder, System.Action<OpenTelemetry.Exporter.JaegerExporterOptions> configure) -> OpenTelemetry.Trace.TracerProviderBuilder
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
OpenTelemetry.Exporter.JaegerExporter
|
||||
OpenTelemetry.Exporter.JaegerExporter.JaegerExporter(OpenTelemetry.Exporter.JaegerExporterOptions options) -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.AgentHost.get -> string
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.AgentHost.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.AgentPort.get -> int
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.AgentPort.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.BatchExportProcessorOptions.get -> OpenTelemetry.BatchExportProcessorOptions<System.Diagnostics.Activity>
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.BatchExportProcessorOptions.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.Endpoint.get -> System.Uri
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.Endpoint.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.ExportProcessorType.get -> OpenTelemetry.ExportProcessorType
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.ExportProcessorType.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.HttpClientFactory.get -> System.Func<System.Net.Http.HttpClient>
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.HttpClientFactory.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.JaegerExporterOptions() -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.MaxPayloadSizeInBytes.get -> int?
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.MaxPayloadSizeInBytes.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.Protocol.get -> OpenTelemetry.Exporter.JaegerExportProtocol
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.Protocol.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExportProtocol
|
||||
OpenTelemetry.Exporter.JaegerExportProtocol.HttpBinaryThrift = 1 -> OpenTelemetry.Exporter.JaegerExportProtocol
|
||||
OpenTelemetry.Exporter.JaegerExportProtocol.UdpCompactThrift = 0 -> OpenTelemetry.Exporter.JaegerExportProtocol
|
||||
OpenTelemetry.Trace.JaegerExporterHelperExtensions
|
||||
override OpenTelemetry.Exporter.JaegerExporter.Dispose(bool disposing) -> void
|
||||
override OpenTelemetry.Exporter.JaegerExporter.Export(in OpenTelemetry.Batch<System.Diagnostics.Activity> activityBatch) -> OpenTelemetry.ExportResult
|
||||
static OpenTelemetry.Trace.JaegerExporterHelperExtensions.AddJaegerExporter(this OpenTelemetry.Trace.TracerProviderBuilder builder) -> OpenTelemetry.Trace.TracerProviderBuilder
|
||||
static OpenTelemetry.Trace.JaegerExporterHelperExtensions.AddJaegerExporter(this OpenTelemetry.Trace.TracerProviderBuilder builder, string name, System.Action<OpenTelemetry.Exporter.JaegerExporterOptions> configure) -> OpenTelemetry.Trace.TracerProviderBuilder
|
||||
static OpenTelemetry.Trace.JaegerExporterHelperExtensions.AddJaegerExporter(this OpenTelemetry.Trace.TracerProviderBuilder builder, System.Action<OpenTelemetry.Exporter.JaegerExporterOptions> configure) -> OpenTelemetry.Trace.TracerProviderBuilder
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
OpenTelemetry.Exporter.JaegerExporter
|
||||
OpenTelemetry.Exporter.JaegerExporter.JaegerExporter(OpenTelemetry.Exporter.JaegerExporterOptions options) -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.AgentHost.get -> string
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.AgentHost.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.AgentPort.get -> int
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.AgentPort.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.BatchExportProcessorOptions.get -> OpenTelemetry.BatchExportProcessorOptions<System.Diagnostics.Activity>
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.BatchExportProcessorOptions.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.Endpoint.get -> System.Uri
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.Endpoint.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.ExportProcessorType.get -> OpenTelemetry.ExportProcessorType
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.ExportProcessorType.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.HttpClientFactory.get -> System.Func<System.Net.Http.HttpClient>
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.HttpClientFactory.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.JaegerExporterOptions() -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.MaxPayloadSizeInBytes.get -> int?
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.MaxPayloadSizeInBytes.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.Protocol.get -> OpenTelemetry.Exporter.JaegerExportProtocol
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.Protocol.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExportProtocol
|
||||
OpenTelemetry.Exporter.JaegerExportProtocol.HttpBinaryThrift = 1 -> OpenTelemetry.Exporter.JaegerExportProtocol
|
||||
OpenTelemetry.Exporter.JaegerExportProtocol.UdpCompactThrift = 0 -> OpenTelemetry.Exporter.JaegerExportProtocol
|
||||
OpenTelemetry.Trace.JaegerExporterHelperExtensions
|
||||
override OpenTelemetry.Exporter.JaegerExporter.Dispose(bool disposing) -> void
|
||||
override OpenTelemetry.Exporter.JaegerExporter.Export(in OpenTelemetry.Batch<System.Diagnostics.Activity> activityBatch) -> OpenTelemetry.ExportResult
|
||||
static OpenTelemetry.Trace.JaegerExporterHelperExtensions.AddJaegerExporter(this OpenTelemetry.Trace.TracerProviderBuilder builder) -> OpenTelemetry.Trace.TracerProviderBuilder
|
||||
static OpenTelemetry.Trace.JaegerExporterHelperExtensions.AddJaegerExporter(this OpenTelemetry.Trace.TracerProviderBuilder builder, string name, System.Action<OpenTelemetry.Exporter.JaegerExporterOptions> configure) -> OpenTelemetry.Trace.TracerProviderBuilder
|
||||
static OpenTelemetry.Trace.JaegerExporterHelperExtensions.AddJaegerExporter(this OpenTelemetry.Trace.TracerProviderBuilder builder, System.Action<OpenTelemetry.Exporter.JaegerExporterOptions> configure) -> OpenTelemetry.Trace.TracerProviderBuilder
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
OpenTelemetry.Exporter.JaegerExporter
|
||||
OpenTelemetry.Exporter.JaegerExporter.JaegerExporter(OpenTelemetry.Exporter.JaegerExporterOptions options) -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.AgentHost.get -> string
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.AgentHost.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.AgentPort.get -> int
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.AgentPort.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.BatchExportProcessorOptions.get -> OpenTelemetry.BatchExportProcessorOptions<System.Diagnostics.Activity>
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.BatchExportProcessorOptions.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.Endpoint.get -> System.Uri
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.Endpoint.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.ExportProcessorType.get -> OpenTelemetry.ExportProcessorType
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.ExportProcessorType.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.HttpClientFactory.get -> System.Func<System.Net.Http.HttpClient>
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.HttpClientFactory.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.JaegerExporterOptions() -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.MaxPayloadSizeInBytes.get -> int?
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.MaxPayloadSizeInBytes.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.Protocol.get -> OpenTelemetry.Exporter.JaegerExportProtocol
|
||||
OpenTelemetry.Exporter.JaegerExporterOptions.Protocol.set -> void
|
||||
OpenTelemetry.Exporter.JaegerExportProtocol
|
||||
OpenTelemetry.Exporter.JaegerExportProtocol.HttpBinaryThrift = 1 -> OpenTelemetry.Exporter.JaegerExportProtocol
|
||||
OpenTelemetry.Exporter.JaegerExportProtocol.UdpCompactThrift = 0 -> OpenTelemetry.Exporter.JaegerExportProtocol
|
||||
OpenTelemetry.Trace.JaegerExporterHelperExtensions
|
||||
override OpenTelemetry.Exporter.JaegerExporter.Dispose(bool disposing) -> void
|
||||
override OpenTelemetry.Exporter.JaegerExporter.Export(in OpenTelemetry.Batch<System.Diagnostics.Activity> activityBatch) -> OpenTelemetry.ExportResult
|
||||
static OpenTelemetry.Trace.JaegerExporterHelperExtensions.AddJaegerExporter(this OpenTelemetry.Trace.TracerProviderBuilder builder) -> OpenTelemetry.Trace.TracerProviderBuilder
|
||||
static OpenTelemetry.Trace.JaegerExporterHelperExtensions.AddJaegerExporter(this OpenTelemetry.Trace.TracerProviderBuilder builder, string name, System.Action<OpenTelemetry.Exporter.JaegerExporterOptions> configure) -> OpenTelemetry.Trace.TracerProviderBuilder
|
||||
static OpenTelemetry.Trace.JaegerExporterHelperExtensions.AddJaegerExporter(this OpenTelemetry.Trace.TracerProviderBuilder builder, System.Action<OpenTelemetry.Exporter.JaegerExporterOptions> configure) -> OpenTelemetry.Trace.TracerProviderBuilder
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
// <auto-generated/> (Turns off StyleCop analysis in this file.)
|
||||
|
||||
// Licensed to the Apache Software Foundation(ASF) under one
|
||||
// or more contributor license agreements.See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership.The ASF licenses this file
|
||||
// to you 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.
|
||||
|
||||
namespace Thrift.Protocol.Entities
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct TField
|
||||
{
|
||||
public TField(string name, TType type, short id)
|
||||
{
|
||||
Name = name;
|
||||
Type = type;
|
||||
ID = id;
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public TType Type { get; set; }
|
||||
|
||||
// ReSharper disable once InconsistentNaming - do not rename - it used for generation
|
||||
public short ID { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
// <auto-generated/> (Turns off StyleCop analysis in this file.)
|
||||
|
||||
// Licensed to the Apache Software Foundation(ASF) under one
|
||||
// or more contributor license agreements.See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership.The ASF licenses this file
|
||||
// to you 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.
|
||||
|
||||
namespace Thrift.Protocol.Entities
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct TList
|
||||
{
|
||||
public TList(TType elementType, int count)
|
||||
{
|
||||
ElementType = elementType;
|
||||
Count = count;
|
||||
}
|
||||
|
||||
public TType ElementType { get; set; }
|
||||
|
||||
public int Count { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
// <auto-generated/> (Turns off StyleCop analysis in this file.)
|
||||
|
||||
// Licensed to the Apache Software Foundation(ASF) under one
|
||||
// or more contributor license agreements.See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership.The ASF licenses this file
|
||||
// to you 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.
|
||||
|
||||
namespace Thrift.Protocol.Entities
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct TMap
|
||||
{
|
||||
public TMap(TType keyType, TType valueType, int count)
|
||||
{
|
||||
KeyType = keyType;
|
||||
ValueType = valueType;
|
||||
Count = count;
|
||||
}
|
||||
|
||||
public TType KeyType { get; set; }
|
||||
|
||||
public TType ValueType { get; set; }
|
||||
|
||||
public int Count { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
// <auto-generated/> (Turns off StyleCop analysis in this file.)
|
||||
|
||||
// Licensed to the Apache Software Foundation(ASF) under one
|
||||
// or more contributor license agreements.See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership.The ASF licenses this file
|
||||
// to you 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.
|
||||
|
||||
namespace Thrift.Protocol.Entities
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct TMessage
|
||||
{
|
||||
public TMessage(string name, TMessageType type, int seqid)
|
||||
{
|
||||
Name = name;
|
||||
Type = type;
|
||||
SeqID = seqid;
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public TMessageType Type { get; set; }
|
||||
|
||||
// ReSharper disable once InconsistentNaming - do not rename - it used for generation
|
||||
public int SeqID { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
// <auto-generated/> (Turns off StyleCop analysis in this file.)
|
||||
|
||||
// Licensed to the Apache Software Foundation(ASF) under one
|
||||
// or more contributor license agreements.See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership.The ASF licenses this file
|
||||
// to you 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.
|
||||
|
||||
namespace Thrift.Protocol.Entities
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal enum TMessageType
|
||||
{
|
||||
Call = 1,
|
||||
Reply = 2,
|
||||
Exception = 3,
|
||||
Oneway = 4
|
||||
}
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
// <auto-generated/> (Turns off StyleCop analysis in this file.)
|
||||
|
||||
// Licensed to the Apache Software Foundation(ASF) under one
|
||||
// or more contributor license agreements.See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership.The ASF licenses this file
|
||||
// to you 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.
|
||||
|
||||
namespace Thrift.Protocol.Entities
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct TSet
|
||||
{
|
||||
public TSet(TType elementType, int count)
|
||||
{
|
||||
ElementType = elementType;
|
||||
Count = count;
|
||||
}
|
||||
|
||||
public TSet(TList list)
|
||||
: this(list.ElementType, list.Count)
|
||||
{
|
||||
}
|
||||
|
||||
public TType ElementType { get; set; }
|
||||
|
||||
public int Count { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
// <auto-generated/> (Turns off StyleCop analysis in this file.)
|
||||
|
||||
// Licensed to the Apache Software Foundation(ASF) under one
|
||||
// or more contributor license agreements.See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership.The ASF licenses this file
|
||||
// to you 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.
|
||||
|
||||
namespace Thrift.Protocol.Entities
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct TStruct
|
||||
{
|
||||
public TStruct(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
// <auto-generated/> (Turns off StyleCop analysis in this file.)
|
||||
|
||||
// Licensed to the Apache Software Foundation(ASF) under one
|
||||
// or more contributor license agreements.See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership.The ASF licenses this file
|
||||
// to you 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.
|
||||
|
||||
namespace Thrift.Protocol.Entities
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal enum TType : byte
|
||||
{
|
||||
Stop = 0,
|
||||
Void = 1,
|
||||
Bool = 2,
|
||||
Byte = 3,
|
||||
Double = 4,
|
||||
I16 = 6,
|
||||
I32 = 8,
|
||||
I64 = 10,
|
||||
String = 11,
|
||||
Struct = 12,
|
||||
Map = 13,
|
||||
Set = 14,
|
||||
List = 15
|
||||
}
|
||||
}
|
||||
|
|
@ -1,231 +0,0 @@
|
|||
// <auto-generated/> (Turns off StyleCop analysis in this file.)
|
||||
|
||||
// Licensed to the Apache Software Foundation(ASF) under one
|
||||
// or more contributor license agreements.See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership.The ASF licenses this file
|
||||
// to you 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.
|
||||
|
||||
using System;
|
||||
using Thrift.Protocol.Entities;
|
||||
|
||||
namespace Thrift.Protocol
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal sealed class TBinaryProtocol : TProtocol
|
||||
{
|
||||
private const uint VersionMask = 0xffff0000;
|
||||
private const uint Version1 = 0x80010000;
|
||||
|
||||
private readonly bool StrictRead;
|
||||
private readonly bool StrictWrite;
|
||||
|
||||
// minimize memory allocations by means of an preallocated bytes buffer
|
||||
// The value of 128 is arbitrarily chosen, the required minimum size must be sizeof(long)
|
||||
private readonly byte[] PreAllocatedBuffer = new byte[128];
|
||||
|
||||
private static readonly TStruct AnonymousStruct = new TStruct(string.Empty);
|
||||
private static readonly TField StopField = new TField() { Type = TType.Stop };
|
||||
|
||||
public TBinaryProtocol(int initialCapacity = 8192)
|
||||
: this(false, true, initialCapacity)
|
||||
{
|
||||
}
|
||||
|
||||
public TBinaryProtocol(bool strictRead, bool strictWrite, int initialCapacity = 8192)
|
||||
: base(initialCapacity)
|
||||
{
|
||||
StrictRead = strictRead;
|
||||
StrictWrite = strictWrite;
|
||||
}
|
||||
|
||||
public override void WriteMessageBegin(TMessage message)
|
||||
{
|
||||
if (StrictWrite)
|
||||
{
|
||||
var version = Version1 | (uint)message.Type;
|
||||
WriteI32((int)version);
|
||||
WriteString(message.Name);
|
||||
WriteI32(message.SeqID);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteString(message.Name);
|
||||
WriteByte((sbyte)message.Type);
|
||||
WriteI32(message.SeqID);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteMessageBegin(TMessage message, out int seqIdPosition)
|
||||
{
|
||||
if (StrictWrite)
|
||||
{
|
||||
var version = Version1 | (uint)message.Type;
|
||||
WriteI32((int)version);
|
||||
WriteString(message.Name);
|
||||
seqIdPosition = (int)Transport.Position;
|
||||
WriteI32(message.SeqID);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteString(message.Name);
|
||||
WriteByte((sbyte)message.Type);
|
||||
seqIdPosition = (int)Transport.Position;
|
||||
WriteI32(message.SeqID);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteMessageEnd()
|
||||
{
|
||||
}
|
||||
|
||||
public override void WriteStructBegin(TStruct @struct)
|
||||
{
|
||||
}
|
||||
|
||||
public override void WriteStructEnd()
|
||||
{
|
||||
}
|
||||
|
||||
public override void WriteFieldBegin(TField field)
|
||||
{
|
||||
WriteByte((sbyte)field.Type);
|
||||
WriteI16(field.ID);
|
||||
}
|
||||
|
||||
public override void WriteFieldEnd()
|
||||
{
|
||||
}
|
||||
|
||||
public override void WriteFieldStop()
|
||||
{
|
||||
WriteByte((sbyte)TType.Stop);
|
||||
}
|
||||
|
||||
public override void WriteListBegin(TList list)
|
||||
{
|
||||
WriteByte((sbyte)list.ElementType);
|
||||
WriteI32(list.Count);
|
||||
}
|
||||
|
||||
public override void WriteListBegin(TList list, out int countPosition)
|
||||
{
|
||||
WriteByte((sbyte)list.ElementType);
|
||||
countPosition = (int)Transport.Position;
|
||||
WriteI32(list.Count);
|
||||
}
|
||||
|
||||
public override void WriteListEnd()
|
||||
{
|
||||
}
|
||||
|
||||
public override void WriteBool(bool b)
|
||||
{
|
||||
WriteByte(b ? (sbyte)1 : (sbyte)0);
|
||||
}
|
||||
|
||||
public override void WriteByte(sbyte b)
|
||||
{
|
||||
PreAllocatedBuffer[0] = (byte)b;
|
||||
|
||||
Transport.Write(PreAllocatedBuffer, 0, 1);
|
||||
}
|
||||
|
||||
public override void WriteI16(short i16)
|
||||
{
|
||||
PreAllocatedBuffer[0] = (byte)(0xff & (i16 >> 8));
|
||||
PreAllocatedBuffer[1] = (byte)(0xff & i16);
|
||||
|
||||
Transport.Write(PreAllocatedBuffer, 0, 2);
|
||||
}
|
||||
|
||||
public override int WriteUI32(uint ui32, Span<byte> buffer)
|
||||
{
|
||||
if (buffer.Length < 4)
|
||||
return 0;
|
||||
|
||||
buffer[0] = (byte)(0xff & (ui32 >> 24));
|
||||
buffer[1] = (byte)(0xff & (ui32 >> 16));
|
||||
buffer[2] = (byte)(0xff & (ui32 >> 8));
|
||||
buffer[3] = (byte)(0xff & ui32);
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
public override void WriteI32(int i32)
|
||||
{
|
||||
PreAllocatedBuffer[0] = (byte)(0xff & (i32 >> 24));
|
||||
PreAllocatedBuffer[1] = (byte)(0xff & (i32 >> 16));
|
||||
PreAllocatedBuffer[2] = (byte)(0xff & (i32 >> 8));
|
||||
PreAllocatedBuffer[3] = (byte)(0xff & i32);
|
||||
|
||||
Transport.Write(PreAllocatedBuffer, 0, 4);
|
||||
}
|
||||
|
||||
public override void WriteI64(long i64)
|
||||
{
|
||||
PreAllocatedBuffer[0] = (byte)(0xff & (i64 >> 56));
|
||||
PreAllocatedBuffer[1] = (byte)(0xff & (i64 >> 48));
|
||||
PreAllocatedBuffer[2] = (byte)(0xff & (i64 >> 40));
|
||||
PreAllocatedBuffer[3] = (byte)(0xff & (i64 >> 32));
|
||||
PreAllocatedBuffer[4] = (byte)(0xff & (i64 >> 24));
|
||||
PreAllocatedBuffer[5] = (byte)(0xff & (i64 >> 16));
|
||||
PreAllocatedBuffer[6] = (byte)(0xff & (i64 >> 8));
|
||||
PreAllocatedBuffer[7] = (byte)(0xff & i64);
|
||||
|
||||
Transport.Write(PreAllocatedBuffer, 0, 8);
|
||||
}
|
||||
|
||||
public override void WriteDouble(double d)
|
||||
{
|
||||
WriteI64(BitConverter.DoubleToInt64Bits(d));
|
||||
}
|
||||
|
||||
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
|
||||
public override void WriteBinary(ReadOnlySpan<byte> bytes)
|
||||
{
|
||||
WriteI32(bytes.Length);
|
||||
Transport.Write(bytes);
|
||||
}
|
||||
#endif
|
||||
|
||||
public override void WriteBinary(byte[] bytes, int offset, int count)
|
||||
{
|
||||
WriteI32(count);
|
||||
Transport.Write(bytes, offset, count);
|
||||
}
|
||||
|
||||
public sealed class Factory : TProtocolFactory
|
||||
{
|
||||
private readonly bool StrictRead;
|
||||
private readonly bool StrictWrite;
|
||||
|
||||
public Factory()
|
||||
: this(false, true)
|
||||
{
|
||||
}
|
||||
|
||||
public Factory(bool strictRead, bool strictWrite)
|
||||
{
|
||||
StrictRead = strictRead;
|
||||
StrictWrite = strictWrite;
|
||||
}
|
||||
|
||||
public override TProtocol GetProtocol(int initialCapacity = 8192)
|
||||
{
|
||||
return new TBinaryProtocol(StrictRead, StrictWrite, initialCapacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,434 +0,0 @@
|
|||
// <auto-generated/> (Turns off StyleCop analysis in this file.)
|
||||
|
||||
// Licensed to the Apache Software Foundation(ASF) under one
|
||||
// or more contributor license agreements.See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership.The ASF licenses this file
|
||||
// to you 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.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Thrift.Protocol.Entities;
|
||||
|
||||
namespace Thrift.Protocol
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal sealed class TCompactProtocol : TProtocol
|
||||
{
|
||||
private const byte ProtocolId = 0x82;
|
||||
private const byte Version = 1;
|
||||
private const byte VersionMask = 0x1f; // 0001 1111
|
||||
private const byte TypeMask = 0xE0; // 1110 0000
|
||||
private const byte TypeBits = 0x07; // 0000 0111
|
||||
private const int TypeShiftAmount = 5;
|
||||
private static readonly TStruct AnonymousStruct = new TStruct(string.Empty);
|
||||
private static readonly TField StopField = new TField(string.Empty, TType.Stop, 0);
|
||||
|
||||
private const byte NoTypeOverride = 0xFF;
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
private static readonly byte[] TTypeToCompactType = new byte[16];
|
||||
private static readonly TType[] CompactTypeToTType = new TType[13];
|
||||
|
||||
/// <summary>
|
||||
/// Used to keep track of the last field for the current and previous structs, so we can do the delta stuff.
|
||||
/// </summary>
|
||||
private readonly Stack<short> _lastField = new Stack<short>(15);
|
||||
|
||||
/// <summary>
|
||||
/// If we encounter a boolean field begin, save the TField here so it can have the value incorporated.
|
||||
/// </summary>
|
||||
private TField? _booleanField;
|
||||
|
||||
private short _lastFieldId;
|
||||
|
||||
// minimize memory allocations by means of an preallocated bytes buffer
|
||||
// The value of 128 is arbitrarily chosen, the required minimum size must be sizeof(long)
|
||||
private readonly byte[] PreAllocatedBuffer = new byte[128];
|
||||
|
||||
private struct VarInt
|
||||
{
|
||||
public byte[] bytes;
|
||||
public int count;
|
||||
}
|
||||
|
||||
// minimize memory allocations by means of an preallocated VarInt buffer
|
||||
private VarInt PreAllocatedVarInt = new VarInt()
|
||||
{
|
||||
bytes = new byte[10], // see Int64ToVarInt()
|
||||
count = 0
|
||||
};
|
||||
|
||||
private readonly byte[] EmptyUInt32Buffer = new byte[5];
|
||||
|
||||
public TCompactProtocol(int initialCapacity = 8192)
|
||||
: base(initialCapacity)
|
||||
{
|
||||
TTypeToCompactType[(int)TType.Stop] = Types.Stop;
|
||||
TTypeToCompactType[(int)TType.Bool] = Types.BooleanTrue;
|
||||
TTypeToCompactType[(int)TType.Byte] = Types.Byte;
|
||||
TTypeToCompactType[(int)TType.I16] = Types.I16;
|
||||
TTypeToCompactType[(int)TType.I32] = Types.I32;
|
||||
TTypeToCompactType[(int)TType.I64] = Types.I64;
|
||||
TTypeToCompactType[(int)TType.Double] = Types.Double;
|
||||
TTypeToCompactType[(int)TType.String] = Types.Binary;
|
||||
TTypeToCompactType[(int)TType.List] = Types.List;
|
||||
TTypeToCompactType[(int)TType.Set] = Types.Set;
|
||||
TTypeToCompactType[(int)TType.Map] = Types.Map;
|
||||
TTypeToCompactType[(int)TType.Struct] = Types.Struct;
|
||||
|
||||
CompactTypeToTType[Types.Stop] = TType.Stop;
|
||||
CompactTypeToTType[Types.BooleanTrue] = TType.Bool;
|
||||
CompactTypeToTType[Types.BooleanFalse] = TType.Bool;
|
||||
CompactTypeToTType[Types.Byte] = TType.Byte;
|
||||
CompactTypeToTType[Types.I16] = TType.I16;
|
||||
CompactTypeToTType[Types.I32] = TType.I32;
|
||||
CompactTypeToTType[Types.I64] = TType.I64;
|
||||
CompactTypeToTType[Types.Double] = TType.Double;
|
||||
CompactTypeToTType[Types.Binary] = TType.String;
|
||||
CompactTypeToTType[Types.List] = TType.List;
|
||||
CompactTypeToTType[Types.Set] = TType.Set;
|
||||
CompactTypeToTType[Types.Map] = TType.Map;
|
||||
CompactTypeToTType[Types.Struct] = TType.Struct;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_lastField.Clear();
|
||||
_lastFieldId = 0;
|
||||
|
||||
base.Reset();
|
||||
}
|
||||
|
||||
public override void WriteMessageBegin(TMessage message)
|
||||
{
|
||||
PreAllocatedBuffer[0] = ProtocolId;
|
||||
PreAllocatedBuffer[1] = (byte)((Version & VersionMask) | (((uint)message.Type << TypeShiftAmount) & TypeMask));
|
||||
Transport.Write(PreAllocatedBuffer, 0, 2);
|
||||
|
||||
Int32ToVarInt((uint)message.SeqID, ref PreAllocatedVarInt);
|
||||
Transport.Write(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count);
|
||||
|
||||
WriteString(message.Name);
|
||||
}
|
||||
|
||||
public override void WriteMessageBegin(TMessage message, out int seqIdPosition)
|
||||
{
|
||||
PreAllocatedBuffer[0] = ProtocolId;
|
||||
PreAllocatedBuffer[1] = (byte)((Version & VersionMask) | (((uint)message.Type << TypeShiftAmount) & TypeMask));
|
||||
Transport.Write(PreAllocatedBuffer, 0, 2);
|
||||
|
||||
seqIdPosition = (int)Transport.Position;
|
||||
// Write empty bytes to reserve the space for the seqId to be written later on.
|
||||
Transport.Write(EmptyUInt32Buffer, 0, 5);
|
||||
|
||||
WriteString(message.Name);
|
||||
}
|
||||
|
||||
public override void WriteMessageEnd()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write a struct begin. This doesn't actually put anything on the wire. We
|
||||
/// use it as an opportunity to put special placeholder markers on the field
|
||||
/// stack so we can get the field id deltas correct.
|
||||
/// </summary>
|
||||
public override void WriteStructBegin(TStruct @struct)
|
||||
{
|
||||
_lastField.Push(_lastFieldId);
|
||||
_lastFieldId = 0;
|
||||
}
|
||||
|
||||
public override void WriteStructEnd()
|
||||
{
|
||||
_lastFieldId = _lastField.Pop();
|
||||
}
|
||||
|
||||
private void WriteFieldBeginInternal(TField field, byte fieldType)
|
||||
{
|
||||
// if there's a exType override passed in, use that. Otherwise ask GetCompactType().
|
||||
if (fieldType == NoTypeOverride)
|
||||
fieldType = GetCompactType(field.Type);
|
||||
|
||||
// check if we can use delta encoding for the field id
|
||||
if (field.ID > _lastFieldId)
|
||||
{
|
||||
var delta = field.ID - _lastFieldId;
|
||||
if (delta <= 15)
|
||||
{
|
||||
// Write them together
|
||||
PreAllocatedBuffer[0] = (byte)((delta << 4) | fieldType);
|
||||
Transport.Write(PreAllocatedBuffer, 0, 1);
|
||||
_lastFieldId = field.ID;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Write them separate
|
||||
PreAllocatedBuffer[0] = fieldType;
|
||||
Transport.Write(PreAllocatedBuffer, 0, 1);
|
||||
WriteI16(field.ID);
|
||||
_lastFieldId = field.ID;
|
||||
}
|
||||
|
||||
public override void WriteFieldBegin(TField field)
|
||||
{
|
||||
if (field.Type == TType.Bool)
|
||||
{
|
||||
_booleanField = field;
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteFieldBeginInternal(field, NoTypeOverride);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteFieldEnd()
|
||||
{
|
||||
}
|
||||
|
||||
public override void WriteFieldStop()
|
||||
{
|
||||
PreAllocatedBuffer[0] = Types.Stop;
|
||||
Transport.Write(PreAllocatedBuffer, 0, 1);
|
||||
}
|
||||
|
||||
public override void WriteListBegin(TList list)
|
||||
{
|
||||
if (list.Count <= 14)
|
||||
{
|
||||
PreAllocatedBuffer[0] = (byte)((list.Count << 4) | GetCompactType(list.ElementType));
|
||||
Transport.Write(PreAllocatedBuffer, 0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
PreAllocatedBuffer[0] = (byte)(0xf0 | GetCompactType(list.ElementType));
|
||||
Transport.Write(PreAllocatedBuffer, 0, 1);
|
||||
|
||||
Int32ToVarInt((uint)list.Count, ref PreAllocatedVarInt);
|
||||
Transport.Write(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteListBegin(TList list, out int countPosition)
|
||||
{
|
||||
/*
|
||||
Note: Compact sizing disabled because size might not be known initially.
|
||||
if (list.Count <= 14)
|
||||
{
|
||||
PreAllocatedBuffer[0] = (byte)((list.Count << 4) | GetCompactType(list.ElementType));
|
||||
Transport.Write(PreAllocatedBuffer, 0, 1);
|
||||
}
|
||||
else*/
|
||||
{
|
||||
PreAllocatedBuffer[0] = (byte)(0xf0 | GetCompactType(list.ElementType));
|
||||
Transport.Write(PreAllocatedBuffer, 0, 1);
|
||||
|
||||
countPosition = (int)Transport.Position;
|
||||
// Write empty bytes to reserve the space for the count to be written later on.
|
||||
Transport.Write(EmptyUInt32Buffer, 0, 5);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteListEnd()
|
||||
{
|
||||
}
|
||||
|
||||
public override void WriteBool(bool b)
|
||||
{
|
||||
/*
|
||||
Write a boolean value. Potentially, this could be a boolean field, in
|
||||
which case the field header info isn't written yet. If so, decide what the
|
||||
right exType header is for the value and then Write the field header.
|
||||
Otherwise, Write a single byte.
|
||||
*/
|
||||
|
||||
if (_booleanField != null)
|
||||
{
|
||||
// we haven't written the field header yet
|
||||
var type = b ? Types.BooleanTrue : Types.BooleanFalse;
|
||||
WriteFieldBeginInternal(_booleanField.Value, type);
|
||||
_booleanField = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we're not part of a field, so just write the value.
|
||||
PreAllocatedBuffer[0] = b ? Types.BooleanTrue : Types.BooleanFalse;
|
||||
Transport.Write(PreAllocatedBuffer, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteByte(sbyte b)
|
||||
{
|
||||
PreAllocatedBuffer[0] = (byte)b;
|
||||
Transport.Write(PreAllocatedBuffer, 0, 1);
|
||||
}
|
||||
|
||||
public override void WriteI16(short i16)
|
||||
{
|
||||
Int32ToVarInt(IntToZigzag(i16), ref PreAllocatedVarInt);
|
||||
Transport.Write(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count);
|
||||
}
|
||||
|
||||
private static void Int32ToVarInt(uint n, ref VarInt varint)
|
||||
{
|
||||
// Write an i32 as a varint. Results in 1 - 5 bytes on the wire.
|
||||
varint.count = 0;
|
||||
Debug.Assert(varint.bytes.Length >= 5);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if ((n & ~0x7F) == 0)
|
||||
{
|
||||
varint.bytes[varint.count++] = (byte)n;
|
||||
break;
|
||||
}
|
||||
|
||||
varint.bytes[varint.count++] = (byte)((n & 0x7F) | 0x80);
|
||||
n >>= 7;
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteI32(int i32)
|
||||
{
|
||||
Int32ToVarInt(IntToZigzag(i32), ref PreAllocatedVarInt);
|
||||
Transport.Write(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count);
|
||||
}
|
||||
|
||||
public override int WriteUI32(uint ui32, Span<byte> buffer)
|
||||
{
|
||||
if (buffer.Length < 5)
|
||||
return 0;
|
||||
|
||||
buffer[0] = (byte)(0x80 | (ui32 & 0x7F));
|
||||
ui32 >>= 7;
|
||||
buffer[1] = (byte)(0x80 | (ui32 & 0x7F));
|
||||
ui32 >>= 7;
|
||||
buffer[2] = (byte)(0x80 | (ui32 & 0x7F));
|
||||
ui32 >>= 7;
|
||||
buffer[3] = (byte)(0x80 | (ui32 & 0x7F));
|
||||
ui32 >>= 7;
|
||||
buffer[4] = (byte)ui32;
|
||||
|
||||
return 5;
|
||||
}
|
||||
|
||||
static private void Int64ToVarInt(ulong n, ref VarInt varint)
|
||||
{
|
||||
// Write an i64 as a varint. Results in 1-10 bytes on the wire.
|
||||
varint.count = 0;
|
||||
Debug.Assert(varint.bytes.Length >= 10);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if ((n & ~(ulong)0x7FL) == 0)
|
||||
{
|
||||
varint.bytes[varint.count++] = (byte)n;
|
||||
break;
|
||||
}
|
||||
varint.bytes[varint.count++] = (byte)((n & 0x7F) | 0x80);
|
||||
n >>= 7;
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteI64(long i64)
|
||||
{
|
||||
Int64ToVarInt(LongToZigzag(i64), ref PreAllocatedVarInt);
|
||||
Transport.Write(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count);
|
||||
}
|
||||
|
||||
public override void WriteDouble(double d)
|
||||
{
|
||||
FixedLongToBytes(BitConverter.DoubleToInt64Bits(d), PreAllocatedBuffer, 0);
|
||||
Transport.Write(PreAllocatedBuffer, 0, 8);
|
||||
}
|
||||
|
||||
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
|
||||
public override void WriteBinary(ReadOnlySpan<byte> bytes)
|
||||
{
|
||||
Int32ToVarInt((uint)bytes.Length, ref PreAllocatedVarInt);
|
||||
Transport.Write(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count);
|
||||
Transport.Write(bytes);
|
||||
}
|
||||
#endif
|
||||
|
||||
public override void WriteBinary(byte[] bytes, int offset, int count)
|
||||
{
|
||||
Int32ToVarInt((uint)count, ref PreAllocatedVarInt);
|
||||
Transport.Write(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count);
|
||||
Transport.Write(bytes, offset, count);
|
||||
}
|
||||
|
||||
private static byte GetCompactType(TType ttype)
|
||||
{
|
||||
// Given a TType value, find the appropriate TCompactProtocol.Types constant.
|
||||
return TTypeToCompactType[(int)ttype];
|
||||
}
|
||||
|
||||
private static ulong LongToZigzag(long n)
|
||||
{
|
||||
// Convert l into a zigzag long. This allows negative numbers to be represented compactly as a varint
|
||||
return (ulong)(n << 1) ^ (ulong)(n >> 63);
|
||||
}
|
||||
|
||||
private static uint IntToZigzag(int n)
|
||||
{
|
||||
// Convert n into a zigzag int. This allows negative numbers to be represented compactly as a varint
|
||||
return (uint)(n << 1) ^ (uint)(n >> 31);
|
||||
}
|
||||
|
||||
private static void FixedLongToBytes(long n, byte[] buf, int off)
|
||||
{
|
||||
// Convert a long into little-endian bytes in buf starting at off and going until off+7.
|
||||
buf[off + 0] = (byte)(n & 0xff);
|
||||
buf[off + 1] = (byte)((n >> 8) & 0xff);
|
||||
buf[off + 2] = (byte)((n >> 16) & 0xff);
|
||||
buf[off + 3] = (byte)((n >> 24) & 0xff);
|
||||
buf[off + 4] = (byte)((n >> 32) & 0xff);
|
||||
buf[off + 5] = (byte)((n >> 40) & 0xff);
|
||||
buf[off + 6] = (byte)((n >> 48) & 0xff);
|
||||
buf[off + 7] = (byte)((n >> 56) & 0xff);
|
||||
}
|
||||
|
||||
public sealed class Factory : TProtocolFactory
|
||||
{
|
||||
public override TProtocol GetProtocol(int initialCapacity = 8192)
|
||||
{
|
||||
return new TCompactProtocol(initialCapacity);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// All of the on-wire exType codes.
|
||||
/// </summary>
|
||||
private static class Types
|
||||
{
|
||||
public const byte Stop = 0x00;
|
||||
public const byte BooleanTrue = 0x01;
|
||||
public const byte BooleanFalse = 0x02;
|
||||
public const byte Byte = 0x03;
|
||||
public const byte I16 = 0x04;
|
||||
public const byte I32 = 0x05;
|
||||
public const byte I64 = 0x06;
|
||||
public const byte Double = 0x07;
|
||||
public const byte Binary = 0x08;
|
||||
public const byte List = 0x09;
|
||||
public const byte Set = 0x0A;
|
||||
public const byte Map = 0x0B;
|
||||
public const byte Struct = 0x0C;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,189 +0,0 @@
|
|||
// <auto-generated/> (Turns off StyleCop analysis in this file.)
|
||||
|
||||
// Licensed to the Apache Software Foundation(ASF) under one
|
||||
// or more contributor license agreements.See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership.The ASF licenses this file
|
||||
// to you 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.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Thrift.Protocol.Entities;
|
||||
|
||||
namespace Thrift.Protocol
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal abstract class TProtocol : IDisposable
|
||||
{
|
||||
public const int DefaultRecursionDepth = 64;
|
||||
|
||||
private bool _isDisposed;
|
||||
|
||||
protected TProtocol(int initialCapacity = 8192)
|
||||
{
|
||||
Transport = new MemoryStream(initialCapacity);
|
||||
RecursionLimit = DefaultRecursionDepth;
|
||||
RecursionDepth = 0;
|
||||
}
|
||||
|
||||
protected MemoryStream Transport { get; }
|
||||
|
||||
protected int RecursionDepth { get; set; }
|
||||
|
||||
protected int RecursionLimit { get; set; }
|
||||
|
||||
public ArraySegment<byte> WrittenData
|
||||
{
|
||||
get => new ArraySegment<byte>(Transport.GetBuffer(), 0, (int)Transport.Length);
|
||||
}
|
||||
|
||||
public int Position
|
||||
{
|
||||
get => (int)Transport.Position;
|
||||
set => Transport.Position = value;
|
||||
}
|
||||
|
||||
public int Length => (int)Transport.Length;
|
||||
|
||||
public void Clear(int offset = 0)
|
||||
{
|
||||
if (offset > Transport.Length)
|
||||
throw new ArgumentOutOfRangeException(nameof(offset));
|
||||
|
||||
Transport.Position = offset;
|
||||
Transport.SetLength(offset);
|
||||
}
|
||||
|
||||
public virtual void Reset()
|
||||
{
|
||||
RecursionDepth = 0;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public void IncrementRecursionDepth()
|
||||
{
|
||||
if (RecursionDepth >= RecursionLimit)
|
||||
{
|
||||
throw new TProtocolException(TProtocolException.DEPTH_LIMIT, $"Depth of recursion exceeded the limit: {RecursionLimit}");
|
||||
}
|
||||
|
||||
++RecursionDepth;
|
||||
}
|
||||
|
||||
public void DecrementRecursionDepth()
|
||||
{
|
||||
--RecursionDepth;
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_isDisposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
Transport.Dispose();
|
||||
}
|
||||
}
|
||||
_isDisposed = true;
|
||||
}
|
||||
|
||||
public abstract void WriteMessageBegin(TMessage message);
|
||||
|
||||
public abstract void WriteMessageBegin(TMessage message, out int seqIdPosition);
|
||||
|
||||
public abstract void WriteMessageEnd();
|
||||
|
||||
public abstract void WriteStructBegin(TStruct @struct);
|
||||
|
||||
public abstract void WriteStructEnd();
|
||||
|
||||
public abstract void WriteFieldBegin(TField field);
|
||||
|
||||
public abstract void WriteFieldEnd();
|
||||
|
||||
public abstract void WriteFieldStop();
|
||||
|
||||
public abstract void WriteListBegin(TList list);
|
||||
|
||||
public abstract void WriteListBegin(TList list, out int countPosition);
|
||||
|
||||
public abstract void WriteListEnd();
|
||||
|
||||
public abstract void WriteBool(bool b);
|
||||
|
||||
public abstract void WriteByte(sbyte b);
|
||||
|
||||
public abstract void WriteI16(short i16);
|
||||
|
||||
public abstract void WriteI32(int i32);
|
||||
|
||||
public abstract int WriteUI32(uint ui32, Span<byte> buffer);
|
||||
|
||||
public abstract void WriteI64(long i64);
|
||||
|
||||
public abstract void WriteDouble(double d);
|
||||
|
||||
public virtual void WriteString(string s)
|
||||
{
|
||||
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
|
||||
if (s.Length <= 128)
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[256];
|
||||
int numberOfBytes = Encoding.UTF8.GetBytes(s, buffer);
|
||||
WriteBinary(buffer.Slice(0, numberOfBytes));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
var buf = ArrayPool<byte>.Shared.Rent(Encoding.UTF8.GetByteCount(s));
|
||||
try
|
||||
{
|
||||
var numberOfBytes = Encoding.UTF8.GetBytes(s, 0, s.Length, buf, 0);
|
||||
|
||||
WriteBinary(buf, 0, numberOfBytes);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(buf);
|
||||
}
|
||||
}
|
||||
|
||||
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
|
||||
public abstract void WriteBinary(ReadOnlySpan<byte> bytes);
|
||||
#endif
|
||||
|
||||
public abstract void WriteBinary(byte[] bytes, int offset, int count);
|
||||
|
||||
public void WriteRaw(byte[] bytes)
|
||||
{
|
||||
this.Transport.Write(bytes, 0, bytes.Length);
|
||||
}
|
||||
|
||||
public void WriteRaw(byte[] bytes, int offset, int count)
|
||||
{
|
||||
this.Transport.Write(bytes, offset, count);
|
||||
}
|
||||
|
||||
public void WriteRaw(ArraySegment<byte> bytes)
|
||||
{
|
||||
this.Transport.Write(bytes.Array, bytes.Offset, bytes.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
// <auto-generated/> (Turns off StyleCop analysis in this file.)
|
||||
|
||||
// Licensed to the Apache Software Foundation(ASF) under one
|
||||
// or more contributor license agreements.See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership.The ASF licenses this file
|
||||
// to you 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.
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
using System;
|
||||
|
||||
namespace Thrift.Protocol
|
||||
{
|
||||
internal class TProtocolException : TException
|
||||
{
|
||||
// do not rename public constants - they used in generated files
|
||||
public const int UNKNOWN = 0;
|
||||
public const int INVALID_DATA = 1;
|
||||
public const int NEGATIVE_SIZE = 2;
|
||||
public const int SIZE_LIMIT = 3;
|
||||
public const int BAD_VERSION = 4;
|
||||
public const int NOT_IMPLEMENTED = 5;
|
||||
public const int DEPTH_LIMIT = 6;
|
||||
|
||||
protected int Type = UNKNOWN;
|
||||
|
||||
public TProtocolException()
|
||||
{
|
||||
}
|
||||
|
||||
public TProtocolException(int type, Exception inner = null)
|
||||
: base(string.Empty, inner)
|
||||
{
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public TProtocolException(int type, string message, Exception inner = null)
|
||||
: base(message, inner)
|
||||
{
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public TProtocolException(string message, Exception inner = null)
|
||||
: base(message, inner)
|
||||
{
|
||||
}
|
||||
|
||||
public int GetExceptionType()
|
||||
{
|
||||
return Type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
// <auto-generated/> (Turns off StyleCop analysis in this file.)
|
||||
|
||||
// Licensed to the Apache Software Foundation(ASF) under one
|
||||
// or more contributor license agreements.See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership.The ASF licenses this file
|
||||
// to you 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.
|
||||
|
||||
namespace Thrift.Protocol
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal abstract class TProtocolFactory
|
||||
{
|
||||
public abstract TProtocol GetProtocol(int initialCapacity = 8192);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
// <auto-generated/> (Turns off StyleCop analysis in this file.)
|
||||
|
||||
// Licensed to the Apache Software Foundation(ASF) under one
|
||||
// or more contributor license agreements.See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership.The ASF licenses this file
|
||||
// to you 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.
|
||||
|
||||
namespace Thrift.Protocol
|
||||
{
|
||||
internal interface TUnionBase
|
||||
{
|
||||
void Write(TProtocol tProtocol);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
# OpenTelemetry - Jaeger Exporter - Apache Thrift
|
||||
|
||||
This folder contains a stripped-down and customized fork of the [ApacheThrift
|
||||
0.13.0.1](https://www.nuget.org/packages/ApacheThrift/0.13.0.1) library from the
|
||||
[apache/thrift](https://github.com/apache/thrift/tree/0.13.0) repo. Only the
|
||||
client bits we need to transmit spans to Jaeger using the compact Thrift
|
||||
protocol over UDP and binary Thrift over HTTP are included. Further
|
||||
customizations have been made to improve the performance of our specific use
|
||||
cases.
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
// <auto-generated/> (Turns off StyleCop analysis in this file.)
|
||||
|
||||
// Licensed to the Apache Software Foundation(ASF) under one
|
||||
// or more contributor license agreements.See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership.The ASF licenses this file
|
||||
// to you 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.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Thrift
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal class TException : Exception
|
||||
{
|
||||
public TException()
|
||||
{
|
||||
}
|
||||
|
||||
public TException(string message, Exception inner)
|
||||
: base(message, inner)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
// <copyright file="AssemblyInfo.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
#if SIGNED
|
||||
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Jaeger.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")]
|
||||
[assembly: InternalsVisibleTo("Benchmarks, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")]
|
||||
|
||||
// Used by Moq.
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
|
||||
#else
|
||||
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Jaeger.Tests")]
|
||||
[assembly: InternalsVisibleTo("Benchmarks")]
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] // Used by Moq.
|
||||
#endif
|
||||
|
|
@ -1,378 +0,0 @@
|
|||
# Changelog
|
||||
|
||||
## Unreleased
|
||||
|
||||
## 1.6.0-rc.1
|
||||
|
||||
Released 2023-Aug-21
|
||||
|
||||
## 1.6.0-alpha.1
|
||||
|
||||
Released 2023-Jul-12
|
||||
|
||||
## 1.5.1
|
||||
|
||||
Released 2023-Jun-26
|
||||
|
||||
## 1.5.0
|
||||
|
||||
Released 2023-Jun-05
|
||||
|
||||
## 1.5.0-rc.1
|
||||
|
||||
Released 2023-May-25
|
||||
|
||||
* Added direct reference to `System.Text.Encodings.Web` with minimum version of
|
||||
`4.7.2` in response to [CVE-2021-26701](https://github.com/dotnet/runtime/issues/49377).
|
||||
|
||||
## 1.5.0-alpha.2
|
||||
|
||||
Released 2023-Mar-31
|
||||
|
||||
* Enabled performance optimizations for .NET 6.0+ runtimes.
|
||||
([#4349](https://github.com/open-telemetry/opentelemetry-dotnet/pull/4349))
|
||||
|
||||
## 1.5.0-alpha.1
|
||||
|
||||
Released 2023-Mar-07
|
||||
|
||||
## 1.4.0
|
||||
|
||||
Released 2023-Feb-24
|
||||
|
||||
* Updated OTel SDK dependency to 1.4.0
|
||||
|
||||
## 1.4.0-rc.4
|
||||
|
||||
Released 2023-Feb-10
|
||||
|
||||
## 1.4.0-rc.3
|
||||
|
||||
Released 2023-Feb-01
|
||||
|
||||
## 1.4.0-rc.2
|
||||
|
||||
Released 2023-Jan-09
|
||||
|
||||
## 1.4.0-rc.1
|
||||
|
||||
Released 2022-Dec-12
|
||||
|
||||
## 1.4.0-beta.3
|
||||
|
||||
Released 2022-Nov-07
|
||||
|
||||
* Bumped the minimum required version of `System.Text.Json` to 4.7.2 in response
|
||||
to [CVE-2021-26701](https://github.com/dotnet/runtime/issues/49377).
|
||||
([#3789](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3789))
|
||||
|
||||
## 1.4.0-beta.2
|
||||
|
||||
Released 2022-Oct-17
|
||||
|
||||
* Added support for loading environment variables from `IConfiguration` when
|
||||
using the `AddJaegerExporter` extension
|
||||
([#3720](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3720))
|
||||
|
||||
## 1.4.0-beta.1
|
||||
|
||||
Released 2022-Sep-29
|
||||
|
||||
* Added overloads which accept a name to the `TracerProviderBuilder`
|
||||
`AddJaegerExporter` extension to allow for more fine-grained options
|
||||
management
|
||||
([#3656](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3656))
|
||||
|
||||
## 1.4.0-alpha.2
|
||||
|
||||
Released 2022-Aug-18
|
||||
|
||||
## 1.4.0-alpha.1
|
||||
|
||||
Released 2022-Aug-02
|
||||
|
||||
## 1.3.0
|
||||
|
||||
Released 2022-Jun-03
|
||||
|
||||
## 1.3.0-rc.2
|
||||
|
||||
Released 2022-June-1
|
||||
|
||||
* Improve the conversion and formatting of attribute values.
|
||||
The list of data types that must be supported per the
|
||||
[OpenTelemetry specification](https://github.com/open-telemetry/opentelemetry-specification/tree/main/specification/common#attribute)
|
||||
is more narrow than what the .NET OpenTelemetry SDK supports. Numeric
|
||||
[built-in value types](https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/built-in-types)
|
||||
are supported by converting to a `long` or `double` as appropriate except for
|
||||
numeric types that could cause overflow (`ulong`) or rounding (`decimal`)
|
||||
which are converted to strings. Non-numeric built-in types - `string`,
|
||||
`char`, `bool` are supported. All other types are converted to a `string`.
|
||||
Array values are also supported.
|
||||
([#3281](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3281))
|
||||
* Fix conversion of array-valued resource attributes. They were previously
|
||||
converted to a string like "System.String[]".
|
||||
([#3281](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3281))
|
||||
* Fix exporting of array-valued attributes on an `Activity`. Previously, each
|
||||
item in the array would result in a new tag on an exported `Activity`. Now,
|
||||
array-valued attributes are serialzed to a JSON-array representation.
|
||||
([#3281](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3281))
|
||||
|
||||
## 1.3.0-beta.2
|
||||
|
||||
Released 2022-May-16
|
||||
|
||||
* Removes net5.0 target and replaced with net6.0
|
||||
as .NET 5.0 is going out of support.
|
||||
The package keeps netstandard2.1 target, so it
|
||||
can still be used with .NET5.0 apps.
|
||||
([#3147](https://github.com/open-telemetry/opentelemetry-dotnet/issues/3147))
|
||||
|
||||
## 1.3.0-beta.1
|
||||
|
||||
Released 2022-Apr-15
|
||||
|
||||
* Removes .NET Framework 4.6.1. The minimum .NET Framework
|
||||
version supported is .NET 4.6.2. ([#3190](https://github.com/open-telemetry/opentelemetry-dotnet/issues/3190))
|
||||
|
||||
## 1.2.0
|
||||
|
||||
Released 2022-Apr-15
|
||||
|
||||
## 1.2.0-rc5
|
||||
|
||||
Released 2022-Apr-12
|
||||
|
||||
## 1.2.0-rc4
|
||||
|
||||
Released 2022-Mar-30
|
||||
|
||||
* Added support for Activity Status and StatusDescription which were
|
||||
added to Activity from `System.Diagnostics.DiagnosticSource` version 6.0.
|
||||
Prior to version 6.0, setting the status of an Activity was provided by the
|
||||
.NET OpenTelemetry API via the `Activity.SetStatus` extension method in the
|
||||
`OpenTelemetry.Trace` namespace. Internally, this extension method added the
|
||||
status as tags on the Activity: `otel.status_code` and `otel.status_description`.
|
||||
Therefore, to maintain backward compatibility, the exporter falls back to using
|
||||
these tags to infer status.
|
||||
([#3073](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3073))
|
||||
|
||||
## 1.2.0-rc3
|
||||
|
||||
Released 2022-Mar-04
|
||||
|
||||
* Change supported values for `OTEL_EXPORTER_JAEGER_PROTOCOL`
|
||||
Supported values: `udp/thrift.compact` and `http/thrift.binary` defined
|
||||
in the [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/9a0a3300c6269c2837a1d7c9c5232ec816f63222/specification/sdk-environment-variables.md?plain=1#L129).
|
||||
([#2914](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2914))
|
||||
* Change handling of `OTEL_EXPORTER_JAEGER_ENDPOINT` to require the path to
|
||||
post. Previous versions of this library would append `/api/traces` to the
|
||||
value specified in this variable, but now the application author must do so.
|
||||
This change must also be made if you manually configure the
|
||||
`JaegerExporterOptions` class - the `Endpoint` must now include the path.
|
||||
For most environments, this will be `/api/traces`. The effective default
|
||||
is still `http://localhost:14268/api/traces`. This was done to match
|
||||
the clarified [specification](https://github.com/open-telemetry/opentelemetry-specification/pull/2333))
|
||||
([#2847](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2847))
|
||||
|
||||
## 1.2.0-rc2
|
||||
|
||||
Released 2022-Feb-02
|
||||
|
||||
* Improved span duration's precision from millisecond to microsecond
|
||||
([#2814](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2814))
|
||||
|
||||
## 1.2.0-rc1
|
||||
|
||||
Released 2021-Nov-29
|
||||
|
||||
## 1.2.0-beta2
|
||||
|
||||
Released 2021-Nov-19
|
||||
|
||||
* Changed `JaegerExporterOptions` constructor to throw
|
||||
`FormatException` if it fails to parse any of the supported environment
|
||||
variables.
|
||||
|
||||
* Added support for sending spans directly to a Jaeger Collector over HTTP
|
||||
([#2574](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2574))
|
||||
|
||||
## 1.2.0-beta1
|
||||
|
||||
Released 2021-Oct-08
|
||||
|
||||
## 1.2.0-alpha4
|
||||
|
||||
Released 2021-Sep-23
|
||||
|
||||
## 1.2.0-alpha3
|
||||
|
||||
Released 2021-Sep-13
|
||||
|
||||
* `JaegerExporterOptions.BatchExportProcessorOptions` is initialized with
|
||||
`BatchExportActivityProcessorOptions` which supports field value overriding
|
||||
using `OTEL_BSP_SCHEDULE_DELAY`, `OTEL_BSP_EXPORT_TIMEOUT`,
|
||||
`OTEL_BSP_MAX_QUEUE_SIZE`, `OTEL_BSP_MAX_EXPORT_BATCH_SIZE`
|
||||
environmental variables as defined in the
|
||||
[specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.5.0/specification/sdk-environment-variables.md#batch-span-processor).
|
||||
([#2219](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2219))
|
||||
|
||||
## 1.2.0-alpha2
|
||||
|
||||
Released 2021-Aug-24
|
||||
|
||||
## 1.2.0-alpha1
|
||||
|
||||
Released 2021-Jul-23
|
||||
|
||||
* Removes .NET Framework 4.6 support. The minimum .NET Framework
|
||||
version supported is .NET 4.6.1. ([#2138](https://github.com/open-telemetry/opentelemetry-dotnet/issues/2138))
|
||||
|
||||
* The `JaegerExporterOptions` defaults can be overridden using
|
||||
`OTEL_EXPORTER_JAEGER_AGENT_HOST` and `OTEL_EXPORTER_JAEGER_AGENT_PORT`
|
||||
environmental variables as defined in the
|
||||
[specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/sdk-environment-variables.md#jaeger-exporter).
|
||||
([#2123](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2123))
|
||||
|
||||
## 1.1.0
|
||||
|
||||
Released 2021-Jul-12
|
||||
|
||||
## 1.1.0-rc1
|
||||
|
||||
Released 2021-Jun-25
|
||||
|
||||
## 1.1.0-beta4
|
||||
|
||||
Released 2021-Jun-09
|
||||
|
||||
## 1.1.0-beta3
|
||||
|
||||
Released 2021-May-11
|
||||
|
||||
## 1.1.0-beta2
|
||||
|
||||
Released 2021-Apr-23
|
||||
|
||||
* When using OpenTelemetry.Extensions.Hosting you can now bind
|
||||
`JaegerExporterOptions` to `IConfiguration` using the `Configure` extension
|
||||
(ex:
|
||||
`services.Configure<JaegerExporterOptions>(this.Configuration.GetSection("Jaeger"));`).
|
||||
([#1889](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1889))
|
||||
* Fixed data corruption when creating Jaeger Batch messages
|
||||
([#1372](https://github.com/open-telemetry/opentelemetry-dotnet/issues/1372))
|
||||
|
||||
## 1.1.0-beta1
|
||||
|
||||
Released 2021-Mar-19
|
||||
|
||||
## 1.0.1
|
||||
|
||||
Released 2021-Feb-10
|
||||
|
||||
## 1.0.0-rc4
|
||||
|
||||
Released 2021-Feb-09
|
||||
|
||||
## 1.0.0-rc3
|
||||
|
||||
Released 2021-Feb-04
|
||||
|
||||
* Moved `JaegerExporter` and `JaegerExporterOptions` classes to
|
||||
`OpenTelemetry.Exporter` namespace.
|
||||
([#1770](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1770))
|
||||
* Default ServiceName, if not found in Resource is obtained from SDK
|
||||
using GetDefaultResource().
|
||||
[#1768](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1768)
|
||||
* Removed ProcessTags from JaegerExporterOptions. The alternate option is
|
||||
to use Resource attributes.
|
||||
|
||||
## 1.0.0-rc2
|
||||
|
||||
Released 2021-Jan-29
|
||||
|
||||
* Changed `JaegerExporter` class and constructor from internal to public.
|
||||
([#1612](https://github.com/open-telemetry/opentelemetry-dotnet/issues/1612))
|
||||
|
||||
* In `JaegerExporterOptions`: Exporter options now include a switch for Batch vs
|
||||
Simple exporter, and settings for batch exporting properties.
|
||||
|
||||
* Jaeger will now set the `error` tag when `otel.status_code` is set to `ERROR`.
|
||||
([#1579](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1579)
|
||||
[#1620](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1620))
|
||||
|
||||
* Jaeger will no longer send the `otel.status_code` tag if the value is `UNSET`.
|
||||
([#1609](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1609)
|
||||
[#1620](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1620))
|
||||
|
||||
* Span Event.Name will now be populated as the `event` field on Jaeger Logs
|
||||
instead of `message`.
|
||||
([#1609](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1609))
|
||||
|
||||
* `JaegerExporter` batch format has changed to be compliant with the spec. This
|
||||
may impact the way spans are displayed in Jaeger UI.
|
||||
([#1732](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1732))
|
||||
|
||||
## 1.0.0-rc1.1
|
||||
|
||||
Released 2020-Nov-17
|
||||
|
||||
* Jaeger tags used for InstrumentationLibrary changed from library.name,
|
||||
library.version to otel.library.name, otel.library.version respectively.
|
||||
([#1513](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1513))
|
||||
* The `JaegerExporter` class has been made internal.
|
||||
([#1540](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1540))
|
||||
* Removed `ServiceName` from options available on the `AddJaegerExporter`
|
||||
extension. It is not required by the
|
||||
[specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk_exporters/jaeger.md).
|
||||
([#1572](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1572))
|
||||
|
||||
## 0.8.0-beta.1
|
||||
|
||||
Released 2020-Nov-5
|
||||
|
||||
* Moving Jaeger Process from public to internal.
|
||||
([#1421](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1421))
|
||||
|
||||
## 0.7.0-beta.1
|
||||
|
||||
Released 2020-Oct-16
|
||||
|
||||
* Renamed `MaxPacketSize` -> `MaxPayloadSizeInBytes` on `JaegerExporterOptions`.
|
||||
Lowered the default value from 65,000 to 4096.
|
||||
([#1247](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1274))
|
||||
|
||||
## 0.6.0-beta.1
|
||||
|
||||
Released 2020-Sep-15
|
||||
|
||||
* Removed `MaxFlushInterval` from `JaegerExporterOptions`. Batching is now
|
||||
handled by `BatchExportActivityProcessor` exclusively.
|
||||
([#1254](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1254))
|
||||
|
||||
## 0.5.0-beta.2
|
||||
|
||||
Released 2020-08-28
|
||||
|
||||
* Changed `JaegerExporter` to use `BatchExportActivityProcessor` by default.
|
||||
([#1125](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1125))
|
||||
* Span links will now be sent as `FOLLOWS_FROM` reference type. Previously they
|
||||
were sent as `CHILD_OF`.
|
||||
([#970](https://github.com/open-telemetry/opentelemetry-dotnet/pull/970))
|
||||
* Fixed issue when span has both the `net.peer.name` and `net.peer.port`
|
||||
attributes but did not include `net.peer.port` in the `peer.service` field.
|
||||
([#1195](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1195))
|
||||
|
||||
* Renamed extension method from `UseJaegerExporter` to `AddJaegerExporter`.
|
||||
|
||||
## 0.4.0-beta.2
|
||||
|
||||
Released 2020-07-24
|
||||
|
||||
* First beta release
|
||||
|
||||
## 0.3.0-beta
|
||||
|
||||
Released 2020-07-23
|
||||
|
||||
* Initial release
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
// <copyright file="Batch.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using Thrift.Protocol;
|
||||
using Thrift.Protocol.Entities;
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Implementation;
|
||||
|
||||
internal sealed class Batch
|
||||
{
|
||||
public Batch(Process process, TProtocol protocol)
|
||||
{
|
||||
this.BatchBeginMessage = GenerateBeginMessage(process, protocol, out int spanCountPosition);
|
||||
this.SpanCountPosition = spanCountPosition;
|
||||
this.BatchEndMessage = GenerateEndMessage(protocol);
|
||||
}
|
||||
|
||||
public byte[] BatchBeginMessage { get; }
|
||||
|
||||
public int SpanCountPosition { get; set; }
|
||||
|
||||
public byte[] BatchEndMessage { get; }
|
||||
|
||||
public int MinimumMessageSize => this.BatchBeginMessage.Length
|
||||
+ this.BatchEndMessage.Length;
|
||||
|
||||
private static byte[] GenerateBeginMessage(Process process, TProtocol oprot, out int spanCountPosition)
|
||||
{
|
||||
var struc = new TStruct("Batch");
|
||||
|
||||
oprot.WriteStructBegin(struc);
|
||||
|
||||
var field = new TField
|
||||
{
|
||||
Name = "process",
|
||||
Type = TType.Struct,
|
||||
ID = 1,
|
||||
};
|
||||
|
||||
oprot.WriteFieldBegin(field);
|
||||
process.Write(oprot);
|
||||
oprot.WriteFieldEnd();
|
||||
|
||||
field.Name = "spans";
|
||||
field.Type = TType.List;
|
||||
field.ID = 2;
|
||||
|
||||
oprot.WriteFieldBegin(field);
|
||||
|
||||
oprot.WriteListBegin(new TList(TType.Struct, 0), out spanCountPosition);
|
||||
|
||||
byte[] beginMessage = oprot.WrittenData.ToArray();
|
||||
oprot.Clear();
|
||||
return beginMessage;
|
||||
}
|
||||
|
||||
private static byte[] GenerateEndMessage(TProtocol oprot)
|
||||
{
|
||||
oprot.WriteListEnd();
|
||||
|
||||
oprot.WriteFieldEnd();
|
||||
oprot.WriteFieldStop();
|
||||
oprot.WriteStructEnd();
|
||||
|
||||
byte[] endMessage = oprot.WrittenData.ToArray();
|
||||
oprot.Clear();
|
||||
return endMessage;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
// <copyright file="EmitBatchArgs.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using Thrift.Protocol;
|
||||
using Thrift.Protocol.Entities;
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Implementation;
|
||||
|
||||
internal sealed class EmitBatchArgs
|
||||
{
|
||||
public EmitBatchArgs(TProtocol protocol)
|
||||
{
|
||||
this.EmitBatchArgsBeginMessage = GenerateBeginMessage(protocol, out int seqIdPosition);
|
||||
this.SeqIdPosition = seqIdPosition;
|
||||
this.EmitBatchArgsEndMessage = GenerateEndMessage(protocol);
|
||||
}
|
||||
|
||||
public byte[] EmitBatchArgsBeginMessage { get; }
|
||||
|
||||
public int SeqIdPosition { get; }
|
||||
|
||||
public byte[] EmitBatchArgsEndMessage { get; }
|
||||
|
||||
public int MinimumMessageSize => this.EmitBatchArgsBeginMessage.Length
|
||||
+ this.EmitBatchArgsEndMessage.Length;
|
||||
|
||||
private static byte[] GenerateBeginMessage(TProtocol oprot, out int seqIdPosition)
|
||||
{
|
||||
oprot.WriteMessageBegin(new TMessage("emitBatch", TMessageType.Oneway, 0), out seqIdPosition);
|
||||
|
||||
var struc = new TStruct("emitBatch_args");
|
||||
oprot.WriteStructBegin(struc);
|
||||
|
||||
var field = new TField
|
||||
{
|
||||
Name = "batch",
|
||||
Type = TType.Struct,
|
||||
ID = 1,
|
||||
};
|
||||
|
||||
oprot.WriteFieldBegin(field);
|
||||
|
||||
byte[] beginMessage = oprot.WrittenData.ToArray();
|
||||
oprot.Clear();
|
||||
return beginMessage;
|
||||
}
|
||||
|
||||
private static byte[] GenerateEndMessage(TProtocol oprot)
|
||||
{
|
||||
oprot.WriteFieldEnd();
|
||||
oprot.WriteFieldStop();
|
||||
oprot.WriteStructEnd();
|
||||
|
||||
oprot.WriteMessageEnd();
|
||||
|
||||
byte[] endMessage = oprot.WrittenData.ToArray();
|
||||
oprot.Clear();
|
||||
return endMessage;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
// <copyright file="IJaegerClient.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Implementation;
|
||||
|
||||
internal interface IJaegerClient : IDisposable
|
||||
{
|
||||
bool Connected { get; }
|
||||
|
||||
void Connect();
|
||||
|
||||
void Close();
|
||||
|
||||
int Send(byte[] buffer, int offset, int count);
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
// <copyright file="Int128.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Implementation;
|
||||
|
||||
internal readonly struct Int128
|
||||
{
|
||||
public static Int128 Empty;
|
||||
|
||||
private const int SpanIdBytes = 8;
|
||||
private const int TraceIdBytes = 16;
|
||||
|
||||
public Int128(ActivitySpanId spanId)
|
||||
{
|
||||
Span<byte> bytes = stackalloc byte[SpanIdBytes];
|
||||
spanId.CopyTo(bytes);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
bytes.Reverse();
|
||||
}
|
||||
|
||||
var longs = MemoryMarshal.Cast<byte, long>(bytes);
|
||||
this.High = 0;
|
||||
this.Low = longs[0];
|
||||
}
|
||||
|
||||
public Int128(ActivityTraceId traceId)
|
||||
{
|
||||
Span<byte> bytes = stackalloc byte[TraceIdBytes];
|
||||
traceId.CopyTo(bytes);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
bytes.Reverse();
|
||||
}
|
||||
|
||||
var longs = MemoryMarshal.Cast<byte, long>(bytes);
|
||||
this.High = BitConverter.IsLittleEndian ? longs[1] : longs[0];
|
||||
this.Low = BitConverter.IsLittleEndian ? longs[0] : longs[1];
|
||||
}
|
||||
|
||||
public long High { get; }
|
||||
|
||||
public long Low { get; }
|
||||
}
|
||||
|
|
@ -1,377 +0,0 @@
|
|||
// <copyright file="JaegerActivityExtensions.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using OpenTelemetry.Internal;
|
||||
using OpenTelemetry.Trace;
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Implementation;
|
||||
|
||||
internal static class JaegerActivityExtensions
|
||||
{
|
||||
internal const string JaegerErrorFlagTagName = "error";
|
||||
|
||||
private const int DaysPerYear = 365;
|
||||
|
||||
// Number of days in 4 years
|
||||
private const int DaysPer4Years = (DaysPerYear * 4) + 1; // 1461
|
||||
|
||||
// Number of days in 100 years
|
||||
private const int DaysPer100Years = (DaysPer4Years * 25) - 1; // 36524
|
||||
|
||||
// Number of days in 400 years
|
||||
private const int DaysPer400Years = (DaysPer100Years * 4) + 1; // 146097
|
||||
|
||||
// Number of days from 1/1/0001 to 12/31/1969
|
||||
private const int DaysTo1970 = (DaysPer400Years * 4) + (DaysPer100Years * 3) + (DaysPer4Years * 17) + DaysPerYear; // 719,162
|
||||
|
||||
private const long UnixEpochTicks = DaysTo1970 * TimeSpan.TicksPerDay;
|
||||
private const long TicksPerMicrosecond = TimeSpan.TicksPerMillisecond / 1000;
|
||||
private const long UnixEpochMicroseconds = UnixEpochTicks / TicksPerMicrosecond; // 62,135,596,800,000,000
|
||||
|
||||
public static JaegerSpan ToJaegerSpan(this Activity activity)
|
||||
{
|
||||
var jaegerTags = new TagEnumerationState
|
||||
{
|
||||
Tags = PooledList<JaegerTag>.Create(),
|
||||
};
|
||||
|
||||
jaegerTags.EnumerateTags(activity);
|
||||
|
||||
if (activity.Status != ActivityStatusCode.Unset)
|
||||
{
|
||||
if (activity.Status == ActivityStatusCode.Ok)
|
||||
{
|
||||
PooledList<JaegerTag>.Add(
|
||||
ref jaegerTags.Tags,
|
||||
new JaegerTag(SpanAttributeConstants.StatusCodeKey, JaegerTagType.STRING, vStr: "OK"));
|
||||
}
|
||||
else
|
||||
{
|
||||
PooledList<JaegerTag>.Add(
|
||||
ref jaegerTags.Tags,
|
||||
new JaegerTag(SpanAttributeConstants.StatusCodeKey, JaegerTagType.STRING, vStr: "ERROR"));
|
||||
|
||||
PooledList<JaegerTag>.Add(
|
||||
ref jaegerTags.Tags,
|
||||
new JaegerTag(JaegerErrorFlagTagName, JaegerTagType.BOOL, vBool: true));
|
||||
|
||||
PooledList<JaegerTag>.Add(
|
||||
ref jaegerTags.Tags,
|
||||
new JaegerTag(SpanAttributeConstants.StatusDescriptionKey, JaegerTagType.STRING, vStr: activity.StatusDescription ?? string.Empty));
|
||||
}
|
||||
}
|
||||
else if (jaegerTags.StatusCode.HasValue && jaegerTags.StatusCode != StatusCode.Unset)
|
||||
{
|
||||
PooledList<JaegerTag>.Add(
|
||||
ref jaegerTags.Tags,
|
||||
new JaegerTag(
|
||||
SpanAttributeConstants.StatusCodeKey,
|
||||
JaegerTagType.STRING,
|
||||
vStr: StatusHelper.GetTagValueForStatusCode(jaegerTags.StatusCode.Value)));
|
||||
|
||||
if (jaegerTags.StatusCode == StatusCode.Error)
|
||||
{
|
||||
PooledList<JaegerTag>.Add(
|
||||
ref jaegerTags.Tags,
|
||||
new JaegerTag(JaegerErrorFlagTagName, JaegerTagType.BOOL, vBool: true));
|
||||
|
||||
PooledList<JaegerTag>.Add(
|
||||
ref jaegerTags.Tags,
|
||||
new JaegerTag(SpanAttributeConstants.StatusDescriptionKey, JaegerTagType.STRING, vStr: jaegerTags.StatusDescription ?? string.Empty));
|
||||
}
|
||||
}
|
||||
|
||||
string peerServiceName = null;
|
||||
if (activity.Kind == ActivityKind.Client || activity.Kind == ActivityKind.Producer)
|
||||
{
|
||||
PeerServiceResolver.Resolve(ref jaegerTags, out peerServiceName, out bool addAsTag);
|
||||
|
||||
if (peerServiceName != null && addAsTag)
|
||||
{
|
||||
PooledList<JaegerTag>.Add(ref jaegerTags.Tags, new JaegerTag(SemanticConventions.AttributePeerService, JaegerTagType.STRING, vStr: peerServiceName));
|
||||
}
|
||||
}
|
||||
|
||||
// The Span.Kind must translate into a tag.
|
||||
// See https://opentracing.io/specification/conventions/
|
||||
if (activity.Kind != ActivityKind.Internal)
|
||||
{
|
||||
string spanKind = null;
|
||||
|
||||
if (activity.Kind == ActivityKind.Server)
|
||||
{
|
||||
spanKind = "server";
|
||||
}
|
||||
else if (activity.Kind == ActivityKind.Client)
|
||||
{
|
||||
spanKind = "client";
|
||||
}
|
||||
else if (activity.Kind == ActivityKind.Consumer)
|
||||
{
|
||||
spanKind = "consumer";
|
||||
}
|
||||
else if (activity.Kind == ActivityKind.Producer)
|
||||
{
|
||||
spanKind = "producer";
|
||||
}
|
||||
|
||||
if (spanKind != null)
|
||||
{
|
||||
PooledList<JaegerTag>.Add(ref jaegerTags.Tags, new JaegerTag("span.kind", JaegerTagType.STRING, vStr: spanKind));
|
||||
}
|
||||
}
|
||||
|
||||
var activitySource = activity.Source;
|
||||
if (!string.IsNullOrEmpty(activitySource.Name))
|
||||
{
|
||||
PooledList<JaegerTag>.Add(ref jaegerTags.Tags, new JaegerTag("otel.library.name", JaegerTagType.STRING, vStr: activitySource.Name));
|
||||
if (!string.IsNullOrEmpty(activitySource.Version))
|
||||
{
|
||||
PooledList<JaegerTag>.Add(ref jaegerTags.Tags, new JaegerTag("otel.library.version", JaegerTagType.STRING, vStr: activitySource.Version));
|
||||
}
|
||||
}
|
||||
|
||||
var traceId = Int128.Empty;
|
||||
var spanId = Int128.Empty;
|
||||
var parentSpanId = Int128.Empty;
|
||||
|
||||
if (activity.IdFormat == ActivityIdFormat.W3C)
|
||||
{
|
||||
// TODO: The check above should be enforced by the usage of the exporter. Perhaps enforce at higher-level.
|
||||
traceId = new Int128(activity.TraceId);
|
||||
spanId = new Int128(activity.SpanId);
|
||||
if (activity.ParentSpanId != default)
|
||||
{
|
||||
parentSpanId = new Int128(activity.ParentSpanId);
|
||||
}
|
||||
}
|
||||
|
||||
return new JaegerSpan(
|
||||
peerServiceName: peerServiceName,
|
||||
traceIdLow: traceId.Low,
|
||||
traceIdHigh: traceId.High,
|
||||
spanId: spanId.Low,
|
||||
parentSpanId: parentSpanId.Low,
|
||||
operationName: activity.DisplayName,
|
||||
flags: (activity.Context.TraceFlags & ActivityTraceFlags.Recorded) > 0 ? 0x1 : 0,
|
||||
startTime: ToEpochMicroseconds(activity.StartTimeUtc),
|
||||
duration: activity.Duration.Ticks / TicksPerMicrosecond,
|
||||
references: activity.ToJaegerSpanRefs(),
|
||||
tags: jaegerTags.Tags,
|
||||
logs: activity.ToJaegerLogs());
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static PooledList<JaegerSpanRef> ToJaegerSpanRefs(this Activity activity)
|
||||
{
|
||||
LinkEnumerationState references = default;
|
||||
|
||||
references.EnumerateLinks(activity);
|
||||
|
||||
return references.SpanRefs;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static PooledList<JaegerLog> ToJaegerLogs(this Activity activity)
|
||||
{
|
||||
EventEnumerationState logs = default;
|
||||
|
||||
logs.EnumerateEvents(activity);
|
||||
|
||||
return logs.Logs;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static JaegerLog ToJaegerLog(this in ActivityEvent timedEvent)
|
||||
{
|
||||
var jaegerTags = new EventTagsEnumerationState
|
||||
{
|
||||
Tags = PooledList<JaegerTag>.Create(),
|
||||
};
|
||||
|
||||
jaegerTags.EnumerateTags(in timedEvent);
|
||||
|
||||
if (!jaegerTags.HasEvent)
|
||||
{
|
||||
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk_exporters/jaeger.md#events
|
||||
PooledList<JaegerTag>.Add(ref jaegerTags.Tags, new JaegerTag("event", JaegerTagType.STRING, vStr: timedEvent.Name));
|
||||
}
|
||||
|
||||
// TODO: Use the same function as JaegerConversionExtensions or check that the perf here is acceptable.
|
||||
return new JaegerLog(timedEvent.Timestamp.ToEpochMicroseconds(), jaegerTags.Tags);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static JaegerSpanRef ToJaegerSpanRef(this in ActivityLink link)
|
||||
{
|
||||
var traceId = new Int128(link.Context.TraceId);
|
||||
var spanId = new Int128(link.Context.SpanId);
|
||||
|
||||
// Assume FOLLOWS_FROM for links, mirrored from Java: https://github.com/open-telemetry/opentelemetry-java/pull/481#discussion_r312577862
|
||||
var refType = JaegerSpanRefType.FOLLOWS_FROM;
|
||||
|
||||
return new JaegerSpanRef(refType, traceId.Low, traceId.High, spanId.Low);
|
||||
}
|
||||
|
||||
public static long ToEpochMicroseconds(this DateTime utcDateTime)
|
||||
{
|
||||
// Truncate sub-microsecond precision before offsetting by the Unix Epoch to avoid
|
||||
// the last digit being off by one for dates that result in negative Unix times
|
||||
long microseconds = utcDateTime.Ticks / TicksPerMicrosecond;
|
||||
return microseconds - UnixEpochMicroseconds;
|
||||
}
|
||||
|
||||
public static long ToEpochMicroseconds(this DateTimeOffset timestamp)
|
||||
{
|
||||
// Truncate sub-microsecond precision before offsetting by the Unix Epoch to avoid
|
||||
// the last digit being off by one for dates that result in negative Unix times
|
||||
long microseconds = timestamp.UtcDateTime.Ticks / TicksPerMicrosecond;
|
||||
return microseconds - UnixEpochMicroseconds;
|
||||
}
|
||||
|
||||
private struct TagEnumerationState : PeerServiceResolver.IPeerServiceState
|
||||
{
|
||||
public PooledList<JaegerTag> Tags;
|
||||
|
||||
public string PeerService { get; set; }
|
||||
|
||||
public int? PeerServicePriority { get; set; }
|
||||
|
||||
public string HostName { get; set; }
|
||||
|
||||
public string IpAddress { get; set; }
|
||||
|
||||
public long Port { get; set; }
|
||||
|
||||
public StatusCode? StatusCode { get; set; }
|
||||
|
||||
public string StatusDescription { get; set; }
|
||||
|
||||
public void EnumerateTags(Activity activity)
|
||||
{
|
||||
foreach (ref readonly var tag in activity.EnumerateTagObjects())
|
||||
{
|
||||
if (tag.Value != null)
|
||||
{
|
||||
var key = tag.Key;
|
||||
|
||||
if (!JaegerTagTransformer.Instance.TryTransformTag(tag, out var jaegerTag))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (jaegerTag.VStr != null)
|
||||
{
|
||||
PeerServiceResolver.InspectTag(ref this, key, jaegerTag.VStr);
|
||||
|
||||
if (key == SpanAttributeConstants.StatusCodeKey)
|
||||
{
|
||||
StatusCode? statusCode = StatusHelper.GetStatusCodeForTagValue(jaegerTag.VStr);
|
||||
this.StatusCode = statusCode;
|
||||
continue;
|
||||
}
|
||||
else if (key == SpanAttributeConstants.StatusDescriptionKey)
|
||||
{
|
||||
this.StatusDescription = jaegerTag.VStr;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (jaegerTag.VLong.HasValue)
|
||||
{
|
||||
PeerServiceResolver.InspectTag(ref this, key, jaegerTag.VLong.Value);
|
||||
}
|
||||
|
||||
PooledList<JaegerTag>.Add(ref this.Tags, jaegerTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct LinkEnumerationState
|
||||
{
|
||||
public bool Created;
|
||||
|
||||
public PooledList<JaegerSpanRef> SpanRefs;
|
||||
|
||||
public void EnumerateLinks(Activity activity)
|
||||
{
|
||||
var enumerator = activity.EnumerateLinks();
|
||||
|
||||
if (enumerator.MoveNext())
|
||||
{
|
||||
this.SpanRefs = PooledList<JaegerSpanRef>.Create();
|
||||
this.Created = true;
|
||||
|
||||
do
|
||||
{
|
||||
ref readonly var link = ref enumerator.Current;
|
||||
PooledList<JaegerSpanRef>.Add(ref this.SpanRefs, link.ToJaegerSpanRef());
|
||||
}
|
||||
while (enumerator.MoveNext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct EventEnumerationState
|
||||
{
|
||||
public bool Created;
|
||||
|
||||
public PooledList<JaegerLog> Logs;
|
||||
|
||||
public void EnumerateEvents(Activity activity)
|
||||
{
|
||||
var enumerator = activity.EnumerateEvents();
|
||||
|
||||
if (enumerator.MoveNext())
|
||||
{
|
||||
this.Logs = PooledList<JaegerLog>.Create();
|
||||
this.Created = true;
|
||||
|
||||
do
|
||||
{
|
||||
ref readonly var @event = ref enumerator.Current;
|
||||
PooledList<JaegerLog>.Add(ref this.Logs, @event.ToJaegerLog());
|
||||
}
|
||||
while (enumerator.MoveNext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct EventTagsEnumerationState
|
||||
{
|
||||
public PooledList<JaegerTag> Tags;
|
||||
|
||||
public bool HasEvent;
|
||||
|
||||
public void EnumerateTags(in ActivityEvent @event)
|
||||
{
|
||||
foreach (ref readonly var tag in @event.EnumerateTagObjects())
|
||||
{
|
||||
if (JaegerTagTransformer.Instance.TryTransformTag(tag, out var result))
|
||||
{
|
||||
PooledList<JaegerTag>.Add(ref this.Tags, result);
|
||||
|
||||
if (tag.Key == "event")
|
||||
{
|
||||
this.HasEvent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
// <copyright file="JaegerExporterEventSource.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using System.Diagnostics.Tracing;
|
||||
using OpenTelemetry.Internal;
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Implementation;
|
||||
|
||||
/// <summary>
|
||||
/// EventSource events emitted from the project.
|
||||
/// </summary>
|
||||
[EventSource(Name = "OpenTelemetry-Exporter-Jaeger")]
|
||||
internal sealed class JaegerExporterEventSource : EventSource
|
||||
{
|
||||
public static JaegerExporterEventSource Log = new();
|
||||
|
||||
[NonEvent]
|
||||
public void FailedExport(Exception ex)
|
||||
{
|
||||
if (this.IsEnabled(EventLevel.Error, EventKeywords.All))
|
||||
{
|
||||
this.FailedExport(ex.ToInvariantString());
|
||||
}
|
||||
}
|
||||
|
||||
[Event(1, Message = "Failed to send spans: '{0}'", Level = EventLevel.Error)]
|
||||
public void FailedExport(string exception)
|
||||
{
|
||||
this.WriteEvent(1, exception);
|
||||
}
|
||||
|
||||
[Event(2, Message = "Unsupported attribute type '{0}' for '{1}'. Attribute will not be exported.", Level = EventLevel.Warning)]
|
||||
public void UnsupportedAttributeType(string type, string key)
|
||||
{
|
||||
this.WriteEvent(2, type.ToString(), key);
|
||||
}
|
||||
|
||||
[Event(3, Message = "{0} environment variable has an invalid value: '{1}'", Level = EventLevel.Warning)]
|
||||
public void InvalidEnvironmentVariable(string key, string value)
|
||||
{
|
||||
this.WriteEvent(3, key, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
// <copyright file="JaegerExporterException.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Implementation;
|
||||
|
||||
#pragma warning disable CA1032 // Implement standard exception constructors
|
||||
#pragma warning disable CA1064 // Exceptions should be public
|
||||
internal sealed class JaegerExporterException : Exception
|
||||
#pragma warning restore CA1064 // Exceptions should be public
|
||||
#pragma warning restore CA1032 // Implement standard exception constructors
|
||||
{
|
||||
public JaegerExporterException(string message, Exception originalException)
|
||||
: base(message, originalException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
// <copyright file="JaegerHttpClient.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using System.Diagnostics;
|
||||
#if NETFRAMEWORK
|
||||
using System.Net.Http;
|
||||
#endif
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Implementation;
|
||||
|
||||
internal sealed class JaegerHttpClient : IJaegerClient
|
||||
{
|
||||
private static readonly MediaTypeHeaderValue ContentTypeHeader = new("application/vnd.apache.thrift.binary");
|
||||
|
||||
private readonly Uri endpoint;
|
||||
private readonly HttpClient httpClient;
|
||||
private bool disposed;
|
||||
|
||||
public JaegerHttpClient(Uri endpoint, HttpClient httpClient)
|
||||
{
|
||||
Debug.Assert(endpoint != null, "endpoint is null");
|
||||
Debug.Assert(httpClient != null, "httpClient is null");
|
||||
|
||||
this.endpoint = endpoint;
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
public bool Connected => true;
|
||||
|
||||
public void Close()
|
||||
{
|
||||
}
|
||||
|
||||
public void Connect()
|
||||
{
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (this.disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.httpClient.Dispose();
|
||||
|
||||
this.disposed = true;
|
||||
}
|
||||
|
||||
public int Send(byte[] buffer, int offset, int count)
|
||||
{
|
||||
// Prevent Jaeger's HTTP operations from being instrumented.
|
||||
using var scope = SuppressInstrumentationScope.Begin();
|
||||
|
||||
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, this.endpoint);
|
||||
|
||||
request.Content = new ByteArrayContent(buffer, offset, count)
|
||||
{
|
||||
Headers = { ContentType = ContentTypeHeader },
|
||||
};
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
using HttpResponseMessage response = this.httpClient.Send(request);
|
||||
#else
|
||||
using HttpResponseMessage response = this.httpClient.SendAsync(request).GetAwaiter().GetResult();
|
||||
#endif
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
// <copyright file="JaegerLog.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using System.Text;
|
||||
using OpenTelemetry.Internal;
|
||||
using Thrift.Protocol;
|
||||
using Thrift.Protocol.Entities;
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Implementation;
|
||||
|
||||
internal readonly struct JaegerLog : TUnionBase
|
||||
{
|
||||
public JaegerLog(long timestamp, in PooledList<JaegerTag> fields)
|
||||
{
|
||||
this.Timestamp = timestamp;
|
||||
this.Fields = fields;
|
||||
}
|
||||
|
||||
public long Timestamp { get; }
|
||||
|
||||
public PooledList<JaegerTag> Fields { get; }
|
||||
|
||||
public void Write(TProtocol oprot)
|
||||
{
|
||||
oprot.IncrementRecursionDepth();
|
||||
try
|
||||
{
|
||||
var struc = new TStruct("Log");
|
||||
oprot.WriteStructBegin(struc);
|
||||
|
||||
var field = new TField
|
||||
{
|
||||
Name = "timestamp",
|
||||
Type = TType.I64,
|
||||
ID = 1,
|
||||
};
|
||||
|
||||
oprot.WriteFieldBegin(field);
|
||||
oprot.WriteI64(this.Timestamp);
|
||||
oprot.WriteFieldEnd();
|
||||
|
||||
field.Name = "fields";
|
||||
field.Type = TType.List;
|
||||
field.ID = 2;
|
||||
|
||||
oprot.WriteFieldBegin(field);
|
||||
{
|
||||
oprot.WriteListBegin(new TList(TType.Struct, this.Fields.Count));
|
||||
|
||||
for (int i = 0; i < this.Fields.Count; i++)
|
||||
{
|
||||
this.Fields[i].Write(oprot);
|
||||
}
|
||||
|
||||
oprot.WriteListEnd();
|
||||
}
|
||||
|
||||
oprot.WriteFieldEnd();
|
||||
oprot.WriteFieldStop();
|
||||
oprot.WriteStructEnd();
|
||||
}
|
||||
finally
|
||||
{
|
||||
oprot.DecrementRecursionDepth();
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder("Log(");
|
||||
sb.Append(", Timestamp: ");
|
||||
sb.Append(this.Timestamp);
|
||||
sb.Append(", Fields: ");
|
||||
sb.Append(this.Fields);
|
||||
sb.Append(')');
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,278 +0,0 @@
|
|||
// <copyright file="JaegerSpan.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using System.Text;
|
||||
using OpenTelemetry.Internal;
|
||||
using Thrift.Protocol;
|
||||
using Thrift.Protocol.Entities;
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Implementation;
|
||||
|
||||
internal readonly struct JaegerSpan : TUnionBase
|
||||
{
|
||||
public JaegerSpan(
|
||||
string peerServiceName,
|
||||
long traceIdLow,
|
||||
long traceIdHigh,
|
||||
long spanId,
|
||||
long parentSpanId,
|
||||
string operationName,
|
||||
int flags,
|
||||
long startTime,
|
||||
long duration,
|
||||
in PooledList<JaegerSpanRef> references,
|
||||
in PooledList<JaegerTag> tags,
|
||||
in PooledList<JaegerLog> logs)
|
||||
{
|
||||
this.PeerServiceName = peerServiceName;
|
||||
this.TraceIdLow = traceIdLow;
|
||||
this.TraceIdHigh = traceIdHigh;
|
||||
this.SpanId = spanId;
|
||||
this.ParentSpanId = parentSpanId;
|
||||
this.OperationName = operationName;
|
||||
this.Flags = flags;
|
||||
this.StartTime = startTime;
|
||||
this.Duration = duration;
|
||||
this.References = references;
|
||||
this.Tags = tags;
|
||||
this.Logs = logs;
|
||||
}
|
||||
|
||||
public string PeerServiceName { get; }
|
||||
|
||||
public long TraceIdLow { get; }
|
||||
|
||||
public long TraceIdHigh { get; }
|
||||
|
||||
public long SpanId { get; }
|
||||
|
||||
public long ParentSpanId { get; }
|
||||
|
||||
public string OperationName { get; }
|
||||
|
||||
public PooledList<JaegerSpanRef> References { get; }
|
||||
|
||||
public int Flags { get; }
|
||||
|
||||
public long StartTime { get; }
|
||||
|
||||
public long Duration { get; }
|
||||
|
||||
public PooledList<JaegerTag> Tags { get; }
|
||||
|
||||
public PooledList<JaegerLog> Logs { get; }
|
||||
|
||||
public void Write(TProtocol oprot)
|
||||
{
|
||||
oprot.IncrementRecursionDepth();
|
||||
try
|
||||
{
|
||||
var struc = new TStruct("Span");
|
||||
oprot.WriteStructBegin(struc);
|
||||
|
||||
var field = new TField
|
||||
{
|
||||
Name = "traceIdLow",
|
||||
Type = TType.I64,
|
||||
ID = 1,
|
||||
};
|
||||
|
||||
oprot.WriteFieldBegin(field);
|
||||
oprot.WriteI64(this.TraceIdLow);
|
||||
oprot.WriteFieldEnd();
|
||||
|
||||
field.Name = "traceIdHigh";
|
||||
field.Type = TType.I64;
|
||||
field.ID = 2;
|
||||
|
||||
oprot.WriteFieldBegin(field);
|
||||
oprot.WriteI64(this.TraceIdHigh);
|
||||
oprot.WriteFieldEnd();
|
||||
|
||||
field.Name = "spanId";
|
||||
field.Type = TType.I64;
|
||||
field.ID = 3;
|
||||
|
||||
oprot.WriteFieldBegin(field);
|
||||
oprot.WriteI64(this.SpanId);
|
||||
oprot.WriteFieldEnd();
|
||||
|
||||
field.Name = "parentSpanId";
|
||||
field.Type = TType.I64;
|
||||
field.ID = 4;
|
||||
|
||||
oprot.WriteFieldBegin(field);
|
||||
oprot.WriteI64(this.ParentSpanId);
|
||||
oprot.WriteFieldEnd();
|
||||
|
||||
field.Name = "operationName";
|
||||
field.Type = TType.String;
|
||||
field.ID = 5;
|
||||
|
||||
oprot.WriteFieldBegin(field);
|
||||
oprot.WriteString(this.OperationName);
|
||||
oprot.WriteFieldEnd();
|
||||
|
||||
if (!this.References.IsEmpty)
|
||||
{
|
||||
field.Name = "references";
|
||||
field.Type = TType.List;
|
||||
field.ID = 6;
|
||||
oprot.WriteFieldBegin(field);
|
||||
{
|
||||
oprot.WriteListBegin(new TList(TType.Struct, this.References.Count));
|
||||
|
||||
for (int i = 0; i < this.References.Count; i++)
|
||||
{
|
||||
this.References[i].Write(oprot);
|
||||
}
|
||||
|
||||
oprot.WriteListEnd();
|
||||
}
|
||||
|
||||
oprot.WriteFieldEnd();
|
||||
}
|
||||
|
||||
field.Name = "flags";
|
||||
field.Type = TType.I32;
|
||||
field.ID = 7;
|
||||
|
||||
oprot.WriteFieldBegin(field);
|
||||
oprot.WriteI32(this.Flags);
|
||||
oprot.WriteFieldEnd();
|
||||
|
||||
field.Name = "startTime";
|
||||
field.Type = TType.I64;
|
||||
field.ID = 8;
|
||||
|
||||
oprot.WriteFieldBegin(field);
|
||||
oprot.WriteI64(this.StartTime);
|
||||
oprot.WriteFieldEnd();
|
||||
|
||||
field.Name = "duration";
|
||||
field.Type = TType.I64;
|
||||
field.ID = 9;
|
||||
|
||||
oprot.WriteFieldBegin(field);
|
||||
oprot.WriteI64(this.Duration);
|
||||
oprot.WriteFieldEnd();
|
||||
|
||||
if (!this.Tags.IsEmpty)
|
||||
{
|
||||
field.Name = "JaegerTags";
|
||||
field.Type = TType.List;
|
||||
field.ID = 10;
|
||||
|
||||
oprot.WriteFieldBegin(field);
|
||||
{
|
||||
oprot.WriteListBegin(new TList(TType.Struct, this.Tags.Count));
|
||||
|
||||
for (int i = 0; i < this.Tags.Count; i++)
|
||||
{
|
||||
this.Tags[i].Write(oprot);
|
||||
}
|
||||
|
||||
oprot.WriteListEnd();
|
||||
}
|
||||
|
||||
oprot.WriteFieldEnd();
|
||||
}
|
||||
|
||||
if (!this.Logs.IsEmpty)
|
||||
{
|
||||
field.Name = "logs";
|
||||
field.Type = TType.List;
|
||||
field.ID = 11;
|
||||
oprot.WriteFieldBegin(field);
|
||||
{
|
||||
oprot.WriteListBegin(new TList(TType.Struct, this.Logs.Count));
|
||||
|
||||
for (int i = 0; i < this.Logs.Count; i++)
|
||||
{
|
||||
this.Logs[i].Write(oprot);
|
||||
}
|
||||
|
||||
oprot.WriteListEnd();
|
||||
}
|
||||
|
||||
oprot.WriteFieldEnd();
|
||||
}
|
||||
|
||||
oprot.WriteFieldStop();
|
||||
oprot.WriteStructEnd();
|
||||
}
|
||||
finally
|
||||
{
|
||||
oprot.DecrementRecursionDepth();
|
||||
}
|
||||
}
|
||||
|
||||
public void Return()
|
||||
{
|
||||
this.References.Return();
|
||||
this.Tags.Return();
|
||||
if (!this.Logs.IsEmpty)
|
||||
{
|
||||
for (int i = 0; i < this.Logs.Count; i++)
|
||||
{
|
||||
this.Logs[i].Fields.Return();
|
||||
}
|
||||
|
||||
this.Logs.Return();
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder("Span(");
|
||||
sb.Append(", TraceIdLow: ");
|
||||
sb.Append(this.TraceIdLow);
|
||||
sb.Append(", TraceIdHigh: ");
|
||||
sb.Append(this.TraceIdHigh);
|
||||
sb.Append(", SpanId: ");
|
||||
sb.Append(this.SpanId);
|
||||
sb.Append(", ParentSpanId: ");
|
||||
sb.Append(this.ParentSpanId);
|
||||
sb.Append(", OperationName: ");
|
||||
sb.Append(this.OperationName);
|
||||
if (!this.References.IsEmpty)
|
||||
{
|
||||
sb.Append(", References: ");
|
||||
sb.Append(this.References);
|
||||
}
|
||||
|
||||
sb.Append(", Flags: ");
|
||||
sb.Append(this.Flags);
|
||||
sb.Append(", StartTime: ");
|
||||
sb.Append(this.StartTime);
|
||||
sb.Append(", Duration: ");
|
||||
sb.Append(this.Duration);
|
||||
if (!this.Tags.IsEmpty)
|
||||
{
|
||||
sb.Append(", JaegerTags: ");
|
||||
sb.Append(this.Tags);
|
||||
}
|
||||
|
||||
if (!this.Logs.IsEmpty)
|
||||
{
|
||||
sb.Append(", Logs: ");
|
||||
sb.Append(this.Logs);
|
||||
}
|
||||
|
||||
sb.Append(')');
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
// <copyright file="JaegerSpanRef.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using System.Text;
|
||||
using Thrift.Protocol;
|
||||
using Thrift.Protocol.Entities;
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Implementation;
|
||||
|
||||
internal readonly struct JaegerSpanRef : TUnionBase
|
||||
{
|
||||
public JaegerSpanRef(JaegerSpanRefType refType, long traceIdLow, long traceIdHigh, long spanId)
|
||||
{
|
||||
this.RefType = refType;
|
||||
this.TraceIdLow = traceIdLow;
|
||||
this.TraceIdHigh = traceIdHigh;
|
||||
this.SpanId = spanId;
|
||||
}
|
||||
|
||||
public JaegerSpanRefType RefType { get; }
|
||||
|
||||
public long TraceIdLow { get; }
|
||||
|
||||
public long TraceIdHigh { get; }
|
||||
|
||||
public long SpanId { get; }
|
||||
|
||||
public void Write(TProtocol oprot)
|
||||
{
|
||||
oprot.IncrementRecursionDepth();
|
||||
try
|
||||
{
|
||||
var struc = new TStruct("SpanRef");
|
||||
oprot.WriteStructBegin(struc);
|
||||
|
||||
var field = new TField
|
||||
{
|
||||
Name = "refType",
|
||||
Type = TType.I32,
|
||||
ID = 1,
|
||||
};
|
||||
|
||||
oprot.WriteFieldBegin(field);
|
||||
oprot.WriteI32((int)this.RefType);
|
||||
oprot.WriteFieldEnd();
|
||||
|
||||
field.Name = "traceIdLow";
|
||||
field.Type = TType.I64;
|
||||
field.ID = 2;
|
||||
|
||||
oprot.WriteFieldBegin(field);
|
||||
oprot.WriteI64(this.TraceIdLow);
|
||||
oprot.WriteFieldEnd();
|
||||
|
||||
field.Name = "traceIdHigh";
|
||||
field.Type = TType.I64;
|
||||
field.ID = 3;
|
||||
|
||||
oprot.WriteFieldBegin(field);
|
||||
oprot.WriteI64(this.TraceIdHigh);
|
||||
oprot.WriteFieldEnd();
|
||||
|
||||
field.Name = "spanId";
|
||||
field.Type = TType.I64;
|
||||
field.ID = 4;
|
||||
|
||||
oprot.WriteFieldBegin(field);
|
||||
oprot.WriteI64(this.SpanId);
|
||||
oprot.WriteFieldEnd();
|
||||
oprot.WriteFieldStop();
|
||||
oprot.WriteStructEnd();
|
||||
}
|
||||
finally
|
||||
{
|
||||
oprot.DecrementRecursionDepth();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <seealso cref="JaegerSpanRefType"/>
|
||||
/// </summary>
|
||||
/// <returns>A string representation of the object.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder("SpanRef(");
|
||||
sb.Append(", RefType: ");
|
||||
sb.Append(this.RefType);
|
||||
sb.Append(", TraceIdLow: ");
|
||||
sb.Append(this.TraceIdLow);
|
||||
sb.Append(", TraceIdHigh: ");
|
||||
sb.Append(this.TraceIdHigh);
|
||||
sb.Append(", SpanId: ");
|
||||
sb.Append(this.SpanId);
|
||||
sb.Append(')');
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
// <copyright file="JaegerSpanRefType.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Implementation;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the different types of Jaeger Spans.
|
||||
/// </summary>
|
||||
internal enum JaegerSpanRefType
|
||||
{
|
||||
/// <summary>
|
||||
/// A child span.
|
||||
/// </summary>
|
||||
CHILD_OF = 0,
|
||||
|
||||
/// <summary>
|
||||
/// A sibling span.
|
||||
/// </summary>
|
||||
FOLLOWS_FROM = 1,
|
||||
}
|
||||
|
|
@ -1,180 +0,0 @@
|
|||
// <copyright file="JaegerTag.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using System.Text;
|
||||
using Thrift.Protocol;
|
||||
using Thrift.Protocol.Entities;
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Implementation;
|
||||
|
||||
internal readonly struct JaegerTag : TUnionBase
|
||||
{
|
||||
public JaegerTag(
|
||||
string key,
|
||||
JaegerTagType vType,
|
||||
string vStr = null,
|
||||
double? vDouble = null,
|
||||
bool? vBool = null,
|
||||
long? vLong = null,
|
||||
byte[] vBinary = null)
|
||||
{
|
||||
this.Key = key;
|
||||
this.VType = vType;
|
||||
|
||||
this.VStr = vStr;
|
||||
this.VDouble = vDouble;
|
||||
this.VBool = vBool;
|
||||
this.VLong = vLong;
|
||||
this.VBinary = vBinary;
|
||||
}
|
||||
|
||||
public string Key { get; }
|
||||
|
||||
public JaegerTagType VType { get; }
|
||||
|
||||
public string VStr { get; }
|
||||
|
||||
public double? VDouble { get; }
|
||||
|
||||
public bool? VBool { get; }
|
||||
|
||||
public long? VLong { get; }
|
||||
|
||||
public byte[] VBinary { get; }
|
||||
|
||||
public void Write(TProtocol oprot)
|
||||
{
|
||||
oprot.IncrementRecursionDepth();
|
||||
try
|
||||
{
|
||||
var struc = new TStruct("Tag");
|
||||
oprot.WriteStructBegin(struc);
|
||||
|
||||
var field = new TField
|
||||
{
|
||||
Name = "key",
|
||||
Type = TType.String,
|
||||
ID = 1,
|
||||
};
|
||||
|
||||
oprot.WriteFieldBegin(field);
|
||||
oprot.WriteString(this.Key);
|
||||
oprot.WriteFieldEnd();
|
||||
|
||||
field.Name = "vType";
|
||||
field.Type = TType.I32;
|
||||
field.ID = 2;
|
||||
|
||||
oprot.WriteFieldBegin(field);
|
||||
oprot.WriteI32((int)this.VType);
|
||||
oprot.WriteFieldEnd();
|
||||
|
||||
if (this.VStr != null)
|
||||
{
|
||||
field.Name = "vStr";
|
||||
field.Type = TType.String;
|
||||
field.ID = 3;
|
||||
oprot.WriteFieldBegin(field);
|
||||
oprot.WriteString(this.VStr);
|
||||
oprot.WriteFieldEnd();
|
||||
}
|
||||
else if (this.VDouble.HasValue)
|
||||
{
|
||||
field.Name = "vDouble";
|
||||
field.Type = TType.Double;
|
||||
field.ID = 4;
|
||||
oprot.WriteFieldBegin(field);
|
||||
oprot.WriteDouble(this.VDouble.Value);
|
||||
oprot.WriteFieldEnd();
|
||||
}
|
||||
else if (this.VBool.HasValue)
|
||||
{
|
||||
field.Name = "vBool";
|
||||
field.Type = TType.Bool;
|
||||
field.ID = 5;
|
||||
oprot.WriteFieldBegin(field);
|
||||
oprot.WriteBool(this.VBool.Value);
|
||||
oprot.WriteFieldEnd();
|
||||
}
|
||||
else if (this.VLong.HasValue)
|
||||
{
|
||||
field.Name = "vLong";
|
||||
field.Type = TType.I64;
|
||||
field.ID = 6;
|
||||
oprot.WriteFieldBegin(field);
|
||||
oprot.WriteI64(this.VLong.Value);
|
||||
oprot.WriteFieldEnd();
|
||||
}
|
||||
else if (this.VBinary != null)
|
||||
{
|
||||
field.Name = "vBinary";
|
||||
field.Type = TType.String;
|
||||
field.ID = 7;
|
||||
oprot.WriteFieldBegin(field);
|
||||
oprot.WriteBinary(this.VBinary, 0, this.VBinary.Length);
|
||||
oprot.WriteFieldEnd();
|
||||
}
|
||||
|
||||
oprot.WriteFieldStop();
|
||||
oprot.WriteStructEnd();
|
||||
}
|
||||
finally
|
||||
{
|
||||
oprot.DecrementRecursionDepth();
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder("Tag(");
|
||||
sb.Append(", Key: ");
|
||||
sb.Append(this.Key);
|
||||
sb.Append(", VType: ");
|
||||
sb.Append(this.VType);
|
||||
if (this.VStr != null)
|
||||
{
|
||||
sb.Append(", VStr: ");
|
||||
sb.Append(this.VStr);
|
||||
}
|
||||
|
||||
if (this.VDouble.HasValue)
|
||||
{
|
||||
sb.Append(", VDouble: ");
|
||||
sb.Append(this.VDouble);
|
||||
}
|
||||
|
||||
if (this.VBool.HasValue)
|
||||
{
|
||||
sb.Append(", VBool: ");
|
||||
sb.Append(this.VBool);
|
||||
}
|
||||
|
||||
if (this.VLong.HasValue)
|
||||
{
|
||||
sb.Append(", VLong: ");
|
||||
sb.Append(this.VLong);
|
||||
}
|
||||
|
||||
if (this.VBinary != null)
|
||||
{
|
||||
sb.Append(", VBinary: ");
|
||||
sb.Append(this.VBinary);
|
||||
}
|
||||
|
||||
sb.Append(')');
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
// <copyright file="JaegerTagTransformer.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using OpenTelemetry.Internal;
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Implementation;
|
||||
|
||||
internal sealed class JaegerTagTransformer : TagTransformer<JaegerTag>
|
||||
{
|
||||
private JaegerTagTransformer()
|
||||
{
|
||||
}
|
||||
|
||||
public static JaegerTagTransformer Instance { get; } = new();
|
||||
|
||||
protected override JaegerTag TransformIntegralTag(string key, long value)
|
||||
{
|
||||
return new JaegerTag(key, JaegerTagType.LONG, vLong: value);
|
||||
}
|
||||
|
||||
protected override JaegerTag TransformFloatingPointTag(string key, double value)
|
||||
{
|
||||
return new JaegerTag(key, JaegerTagType.DOUBLE, vDouble: value);
|
||||
}
|
||||
|
||||
protected override JaegerTag TransformBooleanTag(string key, bool value)
|
||||
{
|
||||
return new JaegerTag(key, JaegerTagType.BOOL, vBool: value);
|
||||
}
|
||||
|
||||
protected override JaegerTag TransformStringTag(string key, string value)
|
||||
{
|
||||
return new JaegerTag(key, JaegerTagType.STRING, vStr: value);
|
||||
}
|
||||
|
||||
protected override JaegerTag TransformArrayTag(string key, Array array)
|
||||
=> this.TransformStringTag(key, TagTransformerJsonHelper.JsonSerializeArrayTag(array));
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
// <copyright file="JaegerTagType.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Implementation;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the data type of a Jaeger tag.
|
||||
/// </summary>
|
||||
internal enum JaegerTagType
|
||||
{
|
||||
/// <summary>
|
||||
/// Tag contains a string.
|
||||
/// </summary>
|
||||
STRING = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Tag contains a double.
|
||||
/// </summary>
|
||||
DOUBLE = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Tag contains a boolean.
|
||||
/// </summary>
|
||||
BOOL = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Tag contains a long.
|
||||
/// </summary>
|
||||
LONG = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Tag contains binary data.
|
||||
/// </summary>
|
||||
BINARY = 4,
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
// <copyright file="JaegerUdpClient.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Implementation;
|
||||
|
||||
internal sealed class JaegerUdpClient : IJaegerClient
|
||||
{
|
||||
private readonly string host;
|
||||
private readonly int port;
|
||||
private readonly UdpClient client;
|
||||
private bool disposed;
|
||||
|
||||
public JaegerUdpClient(string host, int port)
|
||||
{
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.client = new UdpClient();
|
||||
}
|
||||
|
||||
public bool Connected => this.client.Client.Connected;
|
||||
|
||||
public void Close() => this.client.Close();
|
||||
|
||||
public void Connect() => this.client.Connect(this.host, this.port);
|
||||
|
||||
public int Send(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return this.client.Client.Send(buffer, offset, count, SocketFlags.None);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
if (this.disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.client.Dispose();
|
||||
|
||||
this.disposed = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
// <copyright file="Process.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using System.Text;
|
||||
using Thrift.Protocol;
|
||||
using Thrift.Protocol.Entities;
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Implementation;
|
||||
|
||||
internal sealed class Process
|
||||
{
|
||||
public string ServiceName { get; set; }
|
||||
|
||||
public Dictionary<string, JaegerTag> Tags { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder("Process(");
|
||||
sb.Append(", ServiceName: ");
|
||||
sb.Append(this.ServiceName);
|
||||
|
||||
if (this.Tags != null)
|
||||
{
|
||||
sb.Append(", Tags: ");
|
||||
sb.Append(this.Tags);
|
||||
}
|
||||
|
||||
sb.Append(')');
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public void Write(TProtocol oprot)
|
||||
{
|
||||
oprot.IncrementRecursionDepth();
|
||||
|
||||
try
|
||||
{
|
||||
var struc = new TStruct("Process");
|
||||
oprot.WriteStructBegin(struc);
|
||||
|
||||
var field = new TField
|
||||
{
|
||||
Name = "serviceName",
|
||||
Type = TType.String,
|
||||
ID = 1,
|
||||
};
|
||||
|
||||
oprot.WriteFieldBegin(field);
|
||||
oprot.WriteString(this.ServiceName);
|
||||
oprot.WriteFieldEnd();
|
||||
|
||||
if (this.Tags != null)
|
||||
{
|
||||
field.Name = "tags";
|
||||
field.Type = TType.List;
|
||||
field.ID = 2;
|
||||
|
||||
oprot.WriteFieldBegin(field);
|
||||
{
|
||||
oprot.WriteListBegin(new TList(TType.Struct, this.Tags.Count));
|
||||
|
||||
foreach (var jt in this.Tags)
|
||||
{
|
||||
jt.Value.Write(oprot);
|
||||
}
|
||||
|
||||
oprot.WriteListEnd();
|
||||
}
|
||||
|
||||
oprot.WriteFieldEnd();
|
||||
}
|
||||
|
||||
oprot.WriteFieldStop();
|
||||
oprot.WriteStructEnd();
|
||||
}
|
||||
finally
|
||||
{
|
||||
oprot.DecrementRecursionDepth();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
// <copyright file="ShimExtensions.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
#if NETSTANDARD2_0 || NETFRAMEWORK
|
||||
namespace System;
|
||||
|
||||
internal static class ShimExtensions
|
||||
{
|
||||
public static byte[] ToArray(this ArraySegment<byte> arraySegment)
|
||||
{
|
||||
int count = arraySegment.Count;
|
||||
if (count == 0)
|
||||
{
|
||||
return Array.Empty<byte>();
|
||||
}
|
||||
|
||||
var array = new byte[count];
|
||||
Array.Copy(arraySegment.Array, arraySegment.Offset, array, 0, count);
|
||||
return array;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
// <copyright file="JaegerExportProtocol.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
namespace OpenTelemetry.Exporter;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the exporter protocols supported by the <see cref="JaegerExporter"/>.
|
||||
/// </summary>
|
||||
public enum JaegerExportProtocol : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Compact thrift protocol over UDP.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note: Supported by Jaeger Agents only.
|
||||
/// </remarks>
|
||||
UdpCompactThrift = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Binary thrift protocol over HTTP.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note: Supported by Jaeger Collectors only.
|
||||
/// </remarks>
|
||||
HttpBinaryThrift = 1,
|
||||
}
|
||||
|
|
@ -1,287 +0,0 @@
|
|||
// <copyright file="JaegerExporter.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using OpenTelemetry.Exporter.Jaeger.Implementation;
|
||||
using OpenTelemetry.Internal;
|
||||
using OpenTelemetry.Resources;
|
||||
using Thrift.Protocol;
|
||||
using Process = OpenTelemetry.Exporter.Jaeger.Implementation.Process;
|
||||
|
||||
namespace OpenTelemetry.Exporter;
|
||||
|
||||
public class JaegerExporter : BaseExporter<Activity>
|
||||
{
|
||||
internal uint NumberOfSpansInCurrentBatch;
|
||||
|
||||
private readonly byte[] uInt32Storage = new byte[8];
|
||||
private readonly int maxPayloadSizeInBytes;
|
||||
private readonly IJaegerClient client;
|
||||
private readonly TProtocol batchWriter;
|
||||
private readonly TProtocol spanWriter;
|
||||
private readonly bool sendUsingEmitBatchArgs;
|
||||
private int minimumBatchSizeInBytes;
|
||||
private int currentBatchSizeInBytes;
|
||||
private int spanStartPosition;
|
||||
private uint sequenceId;
|
||||
private bool disposed;
|
||||
|
||||
public JaegerExporter(JaegerExporterOptions options)
|
||||
: this(options, null)
|
||||
{
|
||||
}
|
||||
|
||||
internal JaegerExporter(JaegerExporterOptions options, TProtocolFactory protocolFactory = null, IJaegerClient client = null)
|
||||
{
|
||||
Guard.ThrowIfNull(options);
|
||||
|
||||
this.maxPayloadSizeInBytes = (!options.MaxPayloadSizeInBytes.HasValue || options.MaxPayloadSizeInBytes <= 0)
|
||||
? JaegerExporterOptions.DefaultMaxPayloadSizeInBytes
|
||||
: options.MaxPayloadSizeInBytes.Value;
|
||||
|
||||
if (options.Protocol == JaegerExportProtocol.UdpCompactThrift)
|
||||
{
|
||||
protocolFactory ??= new TCompactProtocol.Factory();
|
||||
client ??= new JaegerUdpClient(options.AgentHost, options.AgentPort);
|
||||
this.sendUsingEmitBatchArgs = true;
|
||||
}
|
||||
else if (options.Protocol == JaegerExportProtocol.HttpBinaryThrift)
|
||||
{
|
||||
protocolFactory ??= new TBinaryProtocol.Factory();
|
||||
client ??= new JaegerHttpClient(
|
||||
options.Endpoint,
|
||||
options.HttpClientFactory?.Invoke() ?? throw new InvalidOperationException("JaegerExporterOptions was missing HttpClientFactory or it returned null."));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
JaegerTagTransformer.LogUnsupportedAttributeType = (string tagValueType, string tagKey) =>
|
||||
{
|
||||
JaegerExporterEventSource.Log.UnsupportedAttributeType(tagValueType, tagKey);
|
||||
};
|
||||
|
||||
ConfigurationExtensions.LogInvalidEnvironmentVariable = (string key, string value) =>
|
||||
{
|
||||
JaegerExporterEventSource.Log.InvalidEnvironmentVariable(key, value);
|
||||
};
|
||||
|
||||
this.client = client;
|
||||
this.batchWriter = protocolFactory.GetProtocol(this.maxPayloadSizeInBytes * 2);
|
||||
this.spanWriter = protocolFactory.GetProtocol(this.maxPayloadSizeInBytes);
|
||||
|
||||
this.Process = new();
|
||||
|
||||
client.Connect();
|
||||
}
|
||||
|
||||
internal Process Process { get; }
|
||||
|
||||
internal EmitBatchArgs EmitBatchArgs { get; private set; }
|
||||
|
||||
internal Batch Batch { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override ExportResult Export(in Batch<Activity> activityBatch)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (this.Batch == null)
|
||||
{
|
||||
this.SetResourceAndInitializeBatch(this.ParentProvider.GetResource());
|
||||
}
|
||||
|
||||
foreach (var activity in activityBatch)
|
||||
{
|
||||
var jaegerSpan = activity.ToJaegerSpan();
|
||||
this.AppendSpan(jaegerSpan);
|
||||
jaegerSpan.Return();
|
||||
}
|
||||
|
||||
this.SendCurrentBatch();
|
||||
|
||||
return ExportResult.Success;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
JaegerExporterEventSource.Log.FailedExport(ex);
|
||||
|
||||
return ExportResult.Failure;
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetResourceAndInitializeBatch(Resource resource)
|
||||
{
|
||||
Guard.ThrowIfNull(resource);
|
||||
|
||||
var process = this.Process;
|
||||
|
||||
string serviceName = null;
|
||||
string serviceNamespace = null;
|
||||
foreach (var label in resource.Attributes)
|
||||
{
|
||||
string key = label.Key;
|
||||
|
||||
if (label.Value is string strVal)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case ResourceSemanticConventions.AttributeServiceName:
|
||||
serviceName = strVal;
|
||||
continue;
|
||||
case ResourceSemanticConventions.AttributeServiceNamespace:
|
||||
serviceNamespace = strVal;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (JaegerTagTransformer.Instance.TryTransformTag(label, out var result))
|
||||
{
|
||||
if (process.Tags == null)
|
||||
{
|
||||
process.Tags = new Dictionary<string, JaegerTag>();
|
||||
}
|
||||
|
||||
process.Tags[key] = result;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(serviceName))
|
||||
{
|
||||
serviceName = string.IsNullOrEmpty(serviceNamespace)
|
||||
? serviceName
|
||||
: serviceNamespace + "." + serviceName;
|
||||
}
|
||||
else
|
||||
{
|
||||
serviceName = (string)this.ParentProvider.GetDefaultResource().Attributes.FirstOrDefault(
|
||||
pair => pair.Key == ResourceSemanticConventions.AttributeServiceName).Value;
|
||||
}
|
||||
|
||||
process.ServiceName = serviceName;
|
||||
|
||||
this.Batch = new Batch(process, this.batchWriter);
|
||||
if (this.sendUsingEmitBatchArgs)
|
||||
{
|
||||
this.EmitBatchArgs = new EmitBatchArgs(this.batchWriter);
|
||||
this.Batch.SpanCountPosition += this.EmitBatchArgs.EmitBatchArgsBeginMessage.Length;
|
||||
this.batchWriter.WriteRaw(this.EmitBatchArgs.EmitBatchArgsBeginMessage);
|
||||
}
|
||||
|
||||
this.batchWriter.WriteRaw(this.Batch.BatchBeginMessage);
|
||||
this.spanStartPosition = this.batchWriter.Position;
|
||||
|
||||
this.minimumBatchSizeInBytes = this.EmitBatchArgs?.MinimumMessageSize ?? 0
|
||||
+ this.Batch.MinimumMessageSize;
|
||||
|
||||
this.ResetBatch();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal void AppendSpan(JaegerSpan jaegerSpan)
|
||||
{
|
||||
jaegerSpan.Write(this.spanWriter);
|
||||
try
|
||||
{
|
||||
var spanTotalBytesNeeded = this.spanWriter.Length;
|
||||
|
||||
if (this.NumberOfSpansInCurrentBatch > 0
|
||||
&& this.currentBatchSizeInBytes + spanTotalBytesNeeded >= this.maxPayloadSizeInBytes)
|
||||
{
|
||||
this.SendCurrentBatch();
|
||||
}
|
||||
|
||||
var spanData = this.spanWriter.WrittenData;
|
||||
this.batchWriter.WriteRaw(spanData);
|
||||
|
||||
this.NumberOfSpansInCurrentBatch++;
|
||||
this.currentBatchSizeInBytes += spanTotalBytesNeeded;
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.spanWriter.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
internal void SendCurrentBatch()
|
||||
{
|
||||
try
|
||||
{
|
||||
this.batchWriter.WriteRaw(this.Batch.BatchEndMessage);
|
||||
|
||||
if (this.sendUsingEmitBatchArgs)
|
||||
{
|
||||
this.batchWriter.WriteRaw(this.EmitBatchArgs.EmitBatchArgsEndMessage);
|
||||
|
||||
this.WriteUInt32AtPosition(this.EmitBatchArgs.SeqIdPosition, ++this.sequenceId);
|
||||
}
|
||||
|
||||
this.WriteUInt32AtPosition(this.Batch.SpanCountPosition, this.NumberOfSpansInCurrentBatch);
|
||||
|
||||
var writtenData = this.batchWriter.WrittenData;
|
||||
|
||||
this.client.Send(writtenData.Array, writtenData.Offset, writtenData.Count);
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.ResetBatch();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (!this.disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.client.Close();
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
this.client.Dispose();
|
||||
this.batchWriter.Dispose();
|
||||
this.spanWriter.Dispose();
|
||||
}
|
||||
|
||||
this.disposed = true;
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void WriteUInt32AtPosition(int position, uint value)
|
||||
{
|
||||
this.batchWriter.Position = position;
|
||||
int numberOfBytes = this.batchWriter.WriteUI32(value, this.uInt32Storage);
|
||||
this.batchWriter.WriteRaw(this.uInt32Storage, 0, numberOfBytes);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void ResetBatch()
|
||||
{
|
||||
this.currentBatchSizeInBytes = this.minimumBatchSizeInBytes;
|
||||
this.NumberOfSpansInCurrentBatch = 0;
|
||||
this.batchWriter.Clear(this.spanStartPosition);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
// <copyright file="JaegerExporterHelperExtensions.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using System.Diagnostics;
|
||||
#if NETFRAMEWORK
|
||||
using System.Net.Http;
|
||||
#endif
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using OpenTelemetry.Exporter;
|
||||
using OpenTelemetry.Internal;
|
||||
|
||||
namespace OpenTelemetry.Trace;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods to simplify registering a Jaeger exporter.
|
||||
/// </summary>
|
||||
public static class JaegerExporterHelperExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds Jaeger exporter to the TracerProvider.
|
||||
/// </summary>
|
||||
/// <param name="builder"><see cref="TracerProviderBuilder"/> builder to use.</param>
|
||||
/// <returns>The instance of <see cref="TracerProviderBuilder"/> to chain the calls.</returns>
|
||||
public static TracerProviderBuilder AddJaegerExporter(this TracerProviderBuilder builder)
|
||||
=> AddJaegerExporter(builder, name: null, configure: null);
|
||||
|
||||
/// <summary>
|
||||
/// Adds Jaeger exporter to the TracerProvider.
|
||||
/// </summary>
|
||||
/// <param name="builder"><see cref="TracerProviderBuilder"/> builder to use.</param>
|
||||
/// <param name="configure">Callback action for configuring <see cref="JaegerExporterOptions"/>.</param>
|
||||
/// <returns>The instance of <see cref="TracerProviderBuilder"/> to chain the calls.</returns>
|
||||
public static TracerProviderBuilder AddJaegerExporter(this TracerProviderBuilder builder, Action<JaegerExporterOptions> configure)
|
||||
=> AddJaegerExporter(builder, name: null, configure);
|
||||
|
||||
/// <summary>
|
||||
/// Adds Jaeger exporter to the TracerProvider.
|
||||
/// </summary>
|
||||
/// <param name="builder"><see cref="TracerProviderBuilder"/> builder to use.</param>
|
||||
/// <param name="name">Name which is used when retrieving options.</param>
|
||||
/// <param name="configure">Callback action for configuring <see cref="JaegerExporterOptions"/>.</param>
|
||||
/// <returns>The instance of <see cref="TracerProviderBuilder"/> to chain the calls.</returns>
|
||||
public static TracerProviderBuilder AddJaegerExporter(
|
||||
this TracerProviderBuilder builder,
|
||||
string name,
|
||||
Action<JaegerExporterOptions> configure)
|
||||
{
|
||||
Guard.ThrowIfNull(builder);
|
||||
|
||||
name ??= Options.DefaultName;
|
||||
|
||||
builder.ConfigureServices(services =>
|
||||
{
|
||||
if (configure != null)
|
||||
{
|
||||
services.Configure(name, configure);
|
||||
}
|
||||
|
||||
services.RegisterOptionsFactory(
|
||||
(sp, configuration, name) => new JaegerExporterOptions(
|
||||
configuration,
|
||||
sp.GetRequiredService<IOptionsMonitor<BatchExportActivityProcessorOptions>>().Get(name)));
|
||||
});
|
||||
|
||||
return builder.AddProcessor(sp =>
|
||||
{
|
||||
var options = sp.GetRequiredService<IOptionsMonitor<JaegerExporterOptions>>().Get(name);
|
||||
|
||||
return BuildJaegerExporterProcessor(options, sp);
|
||||
});
|
||||
}
|
||||
|
||||
private static BaseProcessor<Activity> BuildJaegerExporterProcessor(
|
||||
JaegerExporterOptions options,
|
||||
IServiceProvider serviceProvider)
|
||||
{
|
||||
if (options.Protocol == JaegerExportProtocol.HttpBinaryThrift
|
||||
&& options.HttpClientFactory == JaegerExporterOptions.DefaultHttpClientFactory)
|
||||
{
|
||||
options.HttpClientFactory = () =>
|
||||
{
|
||||
Type httpClientFactoryType = Type.GetType("System.Net.Http.IHttpClientFactory, Microsoft.Extensions.Http", throwOnError: false);
|
||||
if (httpClientFactoryType != null)
|
||||
{
|
||||
object httpClientFactory = serviceProvider.GetService(httpClientFactoryType);
|
||||
if (httpClientFactory != null)
|
||||
{
|
||||
MethodInfo createClientMethod = httpClientFactoryType.GetMethod(
|
||||
"CreateClient",
|
||||
BindingFlags.Public | BindingFlags.Instance,
|
||||
binder: null,
|
||||
new Type[] { typeof(string) },
|
||||
modifiers: null);
|
||||
if (createClientMethod != null)
|
||||
{
|
||||
return (HttpClient)createClientMethod.Invoke(httpClientFactory, new object[] { "JaegerExporter" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new HttpClient();
|
||||
};
|
||||
}
|
||||
|
||||
var jaegerExporter = new JaegerExporter(options);
|
||||
|
||||
if (options.ExportProcessorType == ExportProcessorType.Simple)
|
||||
{
|
||||
return new SimpleActivityExportProcessor(jaegerExporter);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new BatchActivityExportProcessor(
|
||||
jaegerExporter,
|
||||
options.BatchExportProcessorOptions.MaxQueueSize,
|
||||
options.BatchExportProcessorOptions.ScheduledDelayMilliseconds,
|
||||
options.BatchExportProcessorOptions.ExporterTimeoutMilliseconds,
|
||||
options.BatchExportProcessorOptions.MaxExportBatchSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
// <copyright file="JaegerExporterOptions.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using System.Diagnostics;
|
||||
#if NETFRAMEWORK
|
||||
using System.Net.Http;
|
||||
#endif
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using OpenTelemetry.Internal;
|
||||
using OpenTelemetry.Trace;
|
||||
|
||||
namespace OpenTelemetry.Exporter;
|
||||
|
||||
/// <summary>
|
||||
/// Jaeger exporter options.
|
||||
/// OTEL_EXPORTER_JAEGER_AGENT_HOST, OTEL_EXPORTER_JAEGER_AGENT_PORT
|
||||
/// environment variables are parsed during object construction.
|
||||
/// </summary>
|
||||
public class JaegerExporterOptions
|
||||
{
|
||||
internal const int DefaultMaxPayloadSizeInBytes = 4096;
|
||||
|
||||
internal const string OTelProtocolEnvVarKey = "OTEL_EXPORTER_JAEGER_PROTOCOL";
|
||||
internal const string OTelAgentHostEnvVarKey = "OTEL_EXPORTER_JAEGER_AGENT_HOST";
|
||||
internal const string OTelAgentPortEnvVarKey = "OTEL_EXPORTER_JAEGER_AGENT_PORT";
|
||||
internal const string OTelEndpointEnvVarKey = "OTEL_EXPORTER_JAEGER_ENDPOINT";
|
||||
internal const string DefaultJaegerEndpoint = "http://localhost:14268/api/traces";
|
||||
|
||||
internal static readonly Func<HttpClient> DefaultHttpClientFactory = () => new HttpClient();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JaegerExporterOptions"/> class.
|
||||
/// </summary>
|
||||
public JaegerExporterOptions()
|
||||
: this(new ConfigurationBuilder().AddEnvironmentVariables().Build(), new())
|
||||
{
|
||||
}
|
||||
|
||||
internal JaegerExporterOptions(
|
||||
IConfiguration configuration,
|
||||
BatchExportActivityProcessorOptions defaultBatchOptions)
|
||||
{
|
||||
Debug.Assert(configuration != null, "configuration was null");
|
||||
Debug.Assert(defaultBatchOptions != null, "defaultBatchOptions was null");
|
||||
|
||||
if (configuration.TryGetValue<JaegerExportProtocol>(
|
||||
OTelProtocolEnvVarKey,
|
||||
JaegerExporterProtocolParser.TryParse,
|
||||
out var protocol))
|
||||
{
|
||||
this.Protocol = protocol;
|
||||
}
|
||||
|
||||
if (configuration.TryGetStringValue(OTelAgentHostEnvVarKey, out var agentHost))
|
||||
{
|
||||
this.AgentHost = agentHost;
|
||||
}
|
||||
|
||||
if (configuration.TryGetIntValue(OTelAgentPortEnvVarKey, out var agentPort))
|
||||
{
|
||||
this.AgentPort = agentPort;
|
||||
}
|
||||
|
||||
if (configuration.TryGetUriValue(OTelEndpointEnvVarKey, out var endpoint))
|
||||
{
|
||||
this.Endpoint = endpoint;
|
||||
}
|
||||
|
||||
this.BatchExportProcessorOptions = defaultBatchOptions;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="JaegerExportProtocol"/> to use when
|
||||
/// communicating to Jaeger. Default value: <see
|
||||
/// cref="JaegerExportProtocol.UdpCompactThrift"/>.
|
||||
/// </summary>
|
||||
public JaegerExportProtocol Protocol { get; set; } = JaegerExportProtocol.UdpCompactThrift;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Jaeger agent host. Default value: localhost.
|
||||
/// </summary>
|
||||
public string AgentHost { get; set; } = "localhost";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Jaeger agent port. Default value: 6831.
|
||||
/// </summary>
|
||||
public int AgentPort { get; set; } = 6831;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Jaeger HTTP endpoint. Default value: "http://localhost:14268/api/traces".
|
||||
/// Typically https://jaeger-server-name:14268/api/traces.
|
||||
/// </summary>
|
||||
public Uri Endpoint { get; set; } = new Uri(DefaultJaegerEndpoint);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum payload size in bytes. Default value: 4096.
|
||||
/// </summary>
|
||||
public int? MaxPayloadSizeInBytes { get; set; } = DefaultMaxPayloadSizeInBytes;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the export processor type to be used with Jaeger Exporter. The default value is <see cref="ExportProcessorType.Batch"/>.
|
||||
/// </summary>
|
||||
public ExportProcessorType ExportProcessorType { get; set; } = ExportProcessorType.Batch;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the BatchExportProcessor options. Ignored unless ExportProcessorType is BatchExporter.
|
||||
/// </summary>
|
||||
public BatchExportProcessorOptions<Activity> BatchExportProcessorOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the factory function called to create the <see
|
||||
/// cref="HttpClient"/> instance that will be used at runtime to
|
||||
/// transmit spans over HTTP. The returned instance will be reused for
|
||||
/// all export invocations.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Notes:
|
||||
/// <list type="bullet">
|
||||
/// <item>This is only invoked for the <see
|
||||
/// cref="JaegerExportProtocol.HttpBinaryThrift"/> protocol.</item>
|
||||
/// <item>The default behavior when using the <see
|
||||
/// cref="JaegerExporterHelperExtensions.AddJaegerExporter(TracerProviderBuilder,
|
||||
/// Action{JaegerExporterOptions})"/> extension is if an <a
|
||||
/// href="https://docs.microsoft.com/dotnet/api/system.net.http.ihttpclientfactory">IHttpClientFactory</a>
|
||||
/// instance can be resolved through the application <see
|
||||
/// cref="IServiceProvider"/> then an <see cref="HttpClient"/> will be
|
||||
/// created through the factory with the name "JaegerExporter" otherwise
|
||||
/// an <see cref="HttpClient"/> will be instantiated directly.</item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
public Func<HttpClient> HttpClientFactory { get; set; } = DefaultHttpClientFactory;
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
// <copyright file="JaegerExporterProtocolParser.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
namespace OpenTelemetry.Exporter;
|
||||
|
||||
internal static class JaegerExporterProtocolParser
|
||||
{
|
||||
public static bool TryParse(string value, out JaegerExportProtocol result)
|
||||
{
|
||||
switch (value.Trim().ToLower())
|
||||
{
|
||||
case "udp/thrift.compact":
|
||||
result = JaegerExportProtocol.UdpCompactThrift;
|
||||
return true;
|
||||
case "http/thrift.binary":
|
||||
result = JaegerExportProtocol.HttpBinaryThrift;
|
||||
return true;
|
||||
default:
|
||||
result = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>$(DefaultTargetFrameworks);netstandard2.1</TargetFrameworks>
|
||||
<Description>Jaeger exporter for OpenTelemetry .NET</Description>
|
||||
<PackageTags>$(PackageTags);Jaeger;distributed-tracing</PackageTags>
|
||||
<MinVerTagPrefix>core-</MinVerTagPrefix>
|
||||
|
||||
<!-- this is temporary. will remove in future PR. -->
|
||||
<Nullable>disable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<NoWarn>$(NoWarn),1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="$(RepoRoot)\src\Shared\Guard.cs" Link="Includes\Guard.cs" />
|
||||
<Compile Include="$(RepoRoot)\src\Shared\PooledList.cs" Link="Includes\PooledList.cs" />
|
||||
<Compile Include="$(RepoRoot)\src\Shared\ResourceSemanticConventions.cs" Link="Includes\ResourceSemanticConventions.cs" />
|
||||
<Compile Include="$(RepoRoot)\src\Shared\ActivityHelperExtensions.cs" Link="Includes\ActivityHelperExtensions.cs" />
|
||||
<Compile Include="$(RepoRoot)\src\Shared\EnvironmentVariables\*.cs" Link="Includes\EnvironmentVariables\%(Filename).cs" />
|
||||
<Compile Include="$(RepoRoot)\src\Shared\ExceptionExtensions.cs" Link="Includes\ExceptionExtensions.cs" />
|
||||
<Compile Include="$(RepoRoot)\src\Shared\PeerServiceResolver.cs" Link="Includes\PeerServiceResolver.cs" />
|
||||
<Compile Include="$(RepoRoot)\src\Shared\Options\*.cs" Link="Includes\Options\%(Filename).cs" />
|
||||
<Compile Include="$(RepoRoot)\src\Shared\SemanticConventions.cs" Link="Includes\SemanticConventions.cs" />
|
||||
<Compile Include="$(RepoRoot)\src\Shared\SpanAttributeConstants.cs" Link="Includes\SpanAttributeConstants.cs" />
|
||||
<Compile Include="$(RepoRoot)\src\Shared\StatusHelper.cs" Link="Includes\StatusHelper.cs" />
|
||||
<Compile Include="$(RepoRoot)\src\Shared\TagTransformer.cs" Link="Includes\TagTransformer.cs" />
|
||||
<Compile Include="$(RepoRoot)\src\Shared\TagTransformerJsonHelper.cs" Link="Includes\TagTransformerJsonHelper.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Threading.Tasks.Extensions" Condition="'$(TargetFramework)' != 'netstandard2.1'" />
|
||||
<PackageReference Include="System.Text.Encodings.Web" Condition="'$(TargetFramework)' != 'net6.0'" />
|
||||
<PackageReference Include="System.Text.Json" Condition="'$(TargetFramework)' != 'net6.0'" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry\OpenTelemetry.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
# Jaeger Exporter for OpenTelemetry .NET
|
||||
|
||||
[](https://www.nuget.org/packages/OpenTelemetry.Exporter.Jaeger)
|
||||
[](https://www.nuget.org/packages/OpenTelemetry.Exporter.Jaeger)
|
||||
|
||||
The Jaeger exporter converts OpenTelemetry traces into the Jaeger model
|
||||
following the [OpenTelemetry specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk_exporters/jaeger.md).
|
||||
|
||||
The exporter communicates to a Jaeger Agent through the Thrift protocol on
|
||||
the Compact Thrift API port, and as such only supports Thrift over UDP.
|
||||
|
||||
> **Note** This component is scheduled to be
|
||||
> [deprecated](https://github.com/open-telemetry/opentelemetry-specification/pull/2858)
|
||||
and users are advised to move to [OTLP
|
||||
Exporter](../OpenTelemetry.Exporter.OpenTelemetryProtocol/README.md). The
|
||||
[getting started with Jaeger](../../docs/trace/getting-started-jaeger/README.md)
|
||||
tutorial shows how to use OTLP Exporter to export traces to Jaeger.
|
||||
|
||||
## Installation
|
||||
|
||||
```shell
|
||||
dotnet add package OpenTelemetry.Exporter.Jaeger
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
You can configure the `JaegerExporter` through `JaegerExporterOptions`
|
||||
and environment variables. The `JaegerExporterOptions` setters
|
||||
take precedence over the environment variables.
|
||||
|
||||
## Options Properties
|
||||
|
||||
The `JaegerExporter` can be configured using the `JaegerExporterOptions`
|
||||
properties:
|
||||
|
||||
* `AgentHost`: The Jaeger Agent host (default `localhost`). Used for
|
||||
`UdpCompactThrift` protocol.
|
||||
|
||||
* `AgentPort`: The Jaeger Agent port (default `6831`). Used for
|
||||
`UdpCompactThrift` protocol.
|
||||
|
||||
* `BatchExportProcessorOptions`: Configuration options for the batch exporter.
|
||||
Only used if `ExportProcessorType` is set to `Batch`.
|
||||
|
||||
* `Endpoint`: The Jaeger Collector HTTP endpoint (default
|
||||
`http://localhost:14268`). Used for `HttpBinaryThrift` protocol.
|
||||
|
||||
* `ExportProcessorType`: Whether the exporter should use [Batch or Simple
|
||||
exporting
|
||||
processor](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk.md#built-in-span-processors)
|
||||
(default `ExportProcessorType.Batch`).
|
||||
|
||||
* `HttpClientFactory`: A factory function called to create the `HttpClient`
|
||||
instance that will be used at runtime to transmit spans over HTTP when the
|
||||
`HttpBinaryThrift` protocol is configured. See [Configure
|
||||
HttpClient](#configure-httpclient) for more details.
|
||||
|
||||
* `MaxPayloadSizeInBytes`: The maximum size of each batch that gets sent to the
|
||||
agent or collector (default `4096`).
|
||||
|
||||
* `Protocol`: The protocol to use. The default value is `UdpCompactThrift`.
|
||||
|
||||
| Protocol | Description |
|
||||
|------------------|-------------------------------------------------------|
|
||||
|`UdpCompactThrift`| Apache Thrift compact over UDP to a Jaeger Agent. |
|
||||
|`HttpBinaryThrift`| Apache Thrift binary over HTTP to a Jaeger Collector. |
|
||||
|
||||
## Environment Variables
|
||||
|
||||
The following environment variables can be used to override the default
|
||||
values of the `JaegerExporterOptions`
|
||||
(following the [OpenTelemetry specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/sdk-environment-variables.md#jaeger-exporter)).
|
||||
|
||||
| Environment variable | `JaegerExporterOptions` property |
|
||||
|-----------------------------------|-----------------------------------------------------------|
|
||||
| `OTEL_EXPORTER_JAEGER_AGENT_HOST` | `AgentHost` |
|
||||
| `OTEL_EXPORTER_JAEGER_AGENT_PORT` | `AgentPort` |
|
||||
| `OTEL_EXPORTER_JAEGER_ENDPOINT` | `Endpoint` |
|
||||
| `OTEL_EXPORTER_JAEGER_PROTOCOL` | `Protocol` (`udp/thrift.compact` or `http/thrift.binary`) |
|
||||
|
||||
## Configure HttpClient
|
||||
|
||||
The `HttpClientFactory` option is provided on `JaegerExporterOptions` for users
|
||||
who want to configure the `HttpClient` used by the `JaegerExporter` when
|
||||
`HttpBinaryThrift` protocol is used. Simply replace the function with your own
|
||||
implementation if you want to customize the generated `HttpClient`:
|
||||
|
||||
```csharp
|
||||
services.AddOpenTelemetry()
|
||||
.WithTracing(builder => builder
|
||||
.AddJaegerExporter(o =>
|
||||
{
|
||||
o.Protocol = JaegerExportProtocol.HttpBinaryThrift;
|
||||
o.HttpClientFactory = () =>
|
||||
{
|
||||
HttpClient client = new HttpClient();
|
||||
client.DefaultRequestHeaders.Add("X-MyCustomHeader", "value");
|
||||
return client;
|
||||
};
|
||||
}));
|
||||
```
|
||||
|
||||
For users using
|
||||
[IHttpClientFactory](https://docs.microsoft.com/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests)
|
||||
you may also customize the named "JaegerExporter" `HttpClient` using the
|
||||
built-in `AddHttpClient` extension:
|
||||
|
||||
```csharp
|
||||
services.AddHttpClient(
|
||||
"JaegerExporter",
|
||||
configureClient: (client) =>
|
||||
client.DefaultRequestHeaders.Add("X-MyCustomHeader", "value"));
|
||||
```
|
||||
|
||||
Note: The single instance returned by `HttpClientFactory` is reused by all
|
||||
export requests.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
This component uses an
|
||||
[EventSource](https://docs.microsoft.com/dotnet/api/system.diagnostics.tracing.eventsource)
|
||||
with the name "OpenTelemetry-Exporter-Jaeger" for its internal logging. Please
|
||||
refer to [SDK troubleshooting](../OpenTelemetry/README.md#troubleshooting) for
|
||||
instructions on seeing these internal logs.
|
||||
|
||||
## References
|
||||
|
||||
* [Jaeger](https://www.jaegertracing.io)
|
||||
* [OpenTelemetry Project](https://opentelemetry.io/)
|
||||
|
|
@ -34,7 +34,6 @@
|
|||
<ItemGroup>
|
||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry\OpenTelemetry.csproj" />
|
||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.InMemory\OpenTelemetry.Exporter.InMemory.csproj" />
|
||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Jaeger\OpenTelemetry.Exporter.Jaeger.csproj" Aliases="Jaeger" />
|
||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj" Aliases="OpenTelemetryProtocol" />
|
||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Zipkin\OpenTelemetry.Exporter.Zipkin.csproj" Aliases="Zipkin" />
|
||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Instrumentation.Http\OpenTelemetry.Instrumentation.Http.csproj" />
|
||||
|
|
|
|||
|
|
@ -1,90 +0,0 @@
|
|||
// <copyright file="JaegerExporterBenchmarks.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
extern alias Jaeger;
|
||||
|
||||
using System.Diagnostics;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Benchmarks.Helper;
|
||||
using Jaeger::OpenTelemetry.Exporter;
|
||||
using Jaeger::OpenTelemetry.Exporter.Jaeger.Implementation;
|
||||
using Jaeger::Thrift.Protocol;
|
||||
using OpenTelemetry;
|
||||
using OpenTelemetry.Internal;
|
||||
|
||||
namespace Benchmarks.Exporter;
|
||||
|
||||
public class JaegerExporterBenchmarks
|
||||
{
|
||||
private Activity activity;
|
||||
private CircularBuffer<Activity> activityBatch;
|
||||
|
||||
[Params(1, 10, 100)]
|
||||
public int NumberOfBatches { get; set; }
|
||||
|
||||
[Params(10000)]
|
||||
public int NumberOfSpans { get; set; }
|
||||
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
this.activity = ActivityHelper.CreateTestActivity();
|
||||
this.activityBatch = new CircularBuffer<Activity>(this.NumberOfSpans);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void JaegerExporter_Batching()
|
||||
{
|
||||
using JaegerExporter exporter = new JaegerExporter(
|
||||
new JaegerExporterOptions(),
|
||||
new TCompactProtocol.Factory(),
|
||||
new NoopJaegerClient());
|
||||
|
||||
for (int i = 0; i < this.NumberOfBatches; i++)
|
||||
{
|
||||
for (int c = 0; c < this.NumberOfSpans; c++)
|
||||
{
|
||||
this.activityBatch.Add(this.activity);
|
||||
}
|
||||
|
||||
exporter.Export(new Batch<Activity>(this.activityBatch, this.NumberOfSpans));
|
||||
}
|
||||
|
||||
exporter.Shutdown();
|
||||
}
|
||||
|
||||
private sealed class NoopJaegerClient : IJaegerClient
|
||||
{
|
||||
public bool Connected => true;
|
||||
|
||||
public void Close()
|
||||
{
|
||||
}
|
||||
|
||||
public void Connect()
|
||||
{
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public int Send(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,7 +17,6 @@
|
|||
<TrimmerRootAssembly Include="OpenTelemetry.Api" />
|
||||
<TrimmerRootAssembly Include="OpenTelemetry.Exporter.Console" />
|
||||
<TrimmerRootAssembly Include="OpenTelemetry.Exporter.InMemory" />
|
||||
<TrimmerRootAssembly Include="OpenTelemetry.Exporter.Jaeger" />
|
||||
<TrimmerRootAssembly Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" />
|
||||
<TrimmerRootAssembly Include="OpenTelemetry.Exporter.Prometheus.HttpListener" />
|
||||
<TrimmerRootAssembly Include="OpenTelemetry.Exporter.Zipkin" />
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
// <copyright file="EventSourceTest.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using OpenTelemetry.Exporter.Jaeger.Implementation;
|
||||
using OpenTelemetry.Tests;
|
||||
using Xunit;
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Tests;
|
||||
|
||||
public class EventSourceTest
|
||||
{
|
||||
[Fact]
|
||||
public void EventSourceTest_JaegerExporterEventSource()
|
||||
{
|
||||
EventSourceTestHelper.MethodsAreImplementedConsistentlyWithTheirAttributes(JaegerExporterEventSource.Log);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
// <copyright file="Int128Test.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using System.Diagnostics;
|
||||
using Xunit;
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Implementation.Tests;
|
||||
|
||||
public class Int128Test
|
||||
{
|
||||
[Fact]
|
||||
public void Int128ConversionWorksAsExpected()
|
||||
{
|
||||
var id = ActivityTraceId.CreateFromBytes(new byte[] { 0x1a, 0x0f, 0x54, 0x63, 0x25, 0xa8, 0x56, 0x43, 0x1a, 0x4c, 0x24, 0xea, 0xa8, 0x60, 0xb0, 0xe8 });
|
||||
var int128 = new Int128(id);
|
||||
|
||||
Assert.Equal(unchecked(0x1a0f546325a85643), int128.High);
|
||||
Assert.Equal(unchecked(0x1a4c24eaa860b0e8), int128.Low);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,861 +0,0 @@
|
|||
// <copyright file="JaegerActivityConversionTest.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using System.Diagnostics;
|
||||
using OpenTelemetry.Internal;
|
||||
using OpenTelemetry.Resources;
|
||||
using OpenTelemetry.Trace;
|
||||
using Xunit;
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Implementation.Tests;
|
||||
|
||||
public class JaegerActivityConversionTest
|
||||
{
|
||||
static JaegerActivityConversionTest()
|
||||
{
|
||||
Activity.DefaultIdFormat = ActivityIdFormat.W3C;
|
||||
Activity.ForceDefaultIdFormat = true;
|
||||
|
||||
var listener = new ActivityListener
|
||||
{
|
||||
ShouldListenTo = _ => true,
|
||||
Sample = (ref ActivityCreationOptions<ActivityContext> options) => ActivitySamplingResult.AllData,
|
||||
};
|
||||
|
||||
ActivitySource.AddActivityListener(listener);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void JaegerActivityConverterTest_ConvertActivityToJaegerSpan_AllPropertiesSet(bool isRootSpan)
|
||||
{
|
||||
using var activity = CreateTestActivity(isRootSpan: isRootSpan);
|
||||
var traceIdAsInt = new Int128(activity.Context.TraceId);
|
||||
var spanIdAsInt = new Int128(activity.Context.SpanId);
|
||||
var linkTraceIdAsInt = new Int128(activity.Links.Single().Context.TraceId);
|
||||
var linkSpanIdAsInt = new Int128(activity.Links.Single().Context.SpanId);
|
||||
|
||||
var jaegerSpan = activity.ToJaegerSpan();
|
||||
|
||||
Assert.Equal("Name", jaegerSpan.OperationName);
|
||||
Assert.Equal(2, jaegerSpan.Logs.Count);
|
||||
|
||||
Assert.Equal(traceIdAsInt.High, jaegerSpan.TraceIdHigh);
|
||||
Assert.Equal(traceIdAsInt.Low, jaegerSpan.TraceIdLow);
|
||||
Assert.Equal(spanIdAsInt.Low, jaegerSpan.SpanId);
|
||||
Assert.Equal(new Int128(activity.ParentSpanId).Low, jaegerSpan.ParentSpanId);
|
||||
|
||||
Assert.Equal(activity.Links.Count(), jaegerSpan.References.Count);
|
||||
var references = jaegerSpan.References.ToArray();
|
||||
var jaegerRef = references[0];
|
||||
Assert.Equal(linkTraceIdAsInt.High, jaegerRef.TraceIdHigh);
|
||||
Assert.Equal(linkTraceIdAsInt.Low, jaegerRef.TraceIdLow);
|
||||
Assert.Equal(linkSpanIdAsInt.Low, jaegerRef.SpanId);
|
||||
|
||||
Assert.Equal(0x1, jaegerSpan.Flags);
|
||||
|
||||
Assert.Equal(activity.StartTimeUtc.ToEpochMicroseconds(), jaegerSpan.StartTime);
|
||||
Assert.Equal(TimeSpanToMicroseconds(activity.Duration), jaegerSpan.Duration);
|
||||
|
||||
var tags = jaegerSpan.Tags.ToArray();
|
||||
var tag = tags[0];
|
||||
Assert.Equal(JaegerTagType.STRING, tag.VType);
|
||||
Assert.Equal("stringKey", tag.Key);
|
||||
Assert.Equal("value", tag.VStr);
|
||||
tag = tags[1];
|
||||
Assert.Equal(JaegerTagType.LONG, tag.VType);
|
||||
Assert.Equal("longKey", tag.Key);
|
||||
Assert.Equal(1, tag.VLong);
|
||||
tag = tags[2];
|
||||
Assert.Equal(JaegerTagType.LONG, tag.VType);
|
||||
Assert.Equal("longKey2", tag.Key);
|
||||
Assert.Equal(1, tag.VLong);
|
||||
tag = tags[3];
|
||||
Assert.Equal(JaegerTagType.DOUBLE, tag.VType);
|
||||
Assert.Equal("doubleKey", tag.Key);
|
||||
Assert.Equal(1, tag.VDouble);
|
||||
tag = tags[4];
|
||||
Assert.Equal(JaegerTagType.DOUBLE, tag.VType);
|
||||
Assert.Equal("doubleKey2", tag.Key);
|
||||
Assert.Equal(1, tag.VDouble);
|
||||
tag = tags[5];
|
||||
Assert.Equal(JaegerTagType.BOOL, tag.VType);
|
||||
Assert.Equal("boolKey", tag.Key);
|
||||
Assert.Equal(true, tag.VBool);
|
||||
|
||||
var logs = jaegerSpan.Logs.ToArray();
|
||||
var jaegerLog = logs[0];
|
||||
Assert.Equal(activity.Events.First().Timestamp.ToEpochMicroseconds(), jaegerLog.Timestamp);
|
||||
Assert.Equal(3, jaegerLog.Fields.Count);
|
||||
var eventFields = jaegerLog.Fields.ToArray();
|
||||
var eventField = eventFields[0];
|
||||
Assert.Equal("key", eventField.Key);
|
||||
Assert.Equal("value", eventField.VStr);
|
||||
eventField = eventFields[1];
|
||||
Assert.Equal("string_array", eventField.Key);
|
||||
Assert.Equal(@"[""a"",""b""]", eventField.VStr);
|
||||
eventField = eventFields[2];
|
||||
Assert.Equal("event", eventField.Key);
|
||||
Assert.Equal("Event1", eventField.VStr);
|
||||
|
||||
Assert.Equal(activity.Events.First().Timestamp.ToEpochMicroseconds(), jaegerLog.Timestamp);
|
||||
|
||||
jaegerLog = logs[1];
|
||||
Assert.Equal(2, jaegerLog.Fields.Count);
|
||||
eventFields = jaegerLog.Fields.ToArray();
|
||||
eventField = eventFields[0];
|
||||
Assert.Equal("key", eventField.Key);
|
||||
Assert.Equal("value", eventField.VStr);
|
||||
eventField = eventFields[1];
|
||||
Assert.Equal("event", eventField.Key);
|
||||
Assert.Equal("Event2", eventField.VStr);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JaegerActivityConverterTest_ConvertActivityToJaegerSpan_NoAttributes()
|
||||
{
|
||||
using var activity = CreateTestActivity(setAttributes: false);
|
||||
var traceIdAsInt = new Int128(activity.Context.TraceId);
|
||||
var spanIdAsInt = new Int128(activity.Context.SpanId);
|
||||
var linkTraceIdAsInt = new Int128(activity.Links.Single().Context.TraceId);
|
||||
var linkSpanIdAsInt = new Int128(activity.Links.Single().Context.SpanId);
|
||||
|
||||
var jaegerSpan = activity.ToJaegerSpan();
|
||||
|
||||
Assert.Equal("Name", jaegerSpan.OperationName);
|
||||
Assert.Equal(2, jaegerSpan.Logs.Count);
|
||||
|
||||
Assert.Equal(traceIdAsInt.High, jaegerSpan.TraceIdHigh);
|
||||
Assert.Equal(traceIdAsInt.Low, jaegerSpan.TraceIdLow);
|
||||
Assert.Equal(spanIdAsInt.Low, jaegerSpan.SpanId);
|
||||
Assert.Equal(new Int128(activity.ParentSpanId).Low, jaegerSpan.ParentSpanId);
|
||||
|
||||
Assert.Equal(activity.Links.Count(), jaegerSpan.References.Count);
|
||||
var references = jaegerSpan.References.ToArray();
|
||||
var jaegerRef = references[0];
|
||||
Assert.Equal(linkTraceIdAsInt.High, jaegerRef.TraceIdHigh);
|
||||
Assert.Equal(linkTraceIdAsInt.Low, jaegerRef.TraceIdLow);
|
||||
Assert.Equal(linkSpanIdAsInt.Low, jaegerRef.SpanId);
|
||||
|
||||
Assert.Equal(0x1, jaegerSpan.Flags);
|
||||
|
||||
Assert.Equal(activity.StartTimeUtc.ToEpochMicroseconds(), jaegerSpan.StartTime);
|
||||
Assert.Equal(TimeSpanToMicroseconds(activity.Duration), jaegerSpan.Duration);
|
||||
|
||||
// 2 tags: span.kind & library.name.
|
||||
Assert.Equal(2, jaegerSpan.Tags.Count);
|
||||
|
||||
var logs = jaegerSpan.Logs.ToArray();
|
||||
var jaegerLog = logs[0];
|
||||
Assert.Equal(activity.Events.First().Timestamp.ToEpochMicroseconds(), jaegerLog.Timestamp);
|
||||
Assert.Equal(3, jaegerLog.Fields.Count);
|
||||
var eventFields = jaegerLog.Fields.ToArray();
|
||||
var eventField = eventFields[0];
|
||||
Assert.Equal("key", eventField.Key);
|
||||
Assert.Equal("value", eventField.VStr);
|
||||
eventField = eventFields[2];
|
||||
Assert.Equal("event", eventField.Key);
|
||||
Assert.Equal("Event1", eventField.VStr);
|
||||
|
||||
Assert.Equal(activity.Events.First().Timestamp.ToEpochMicroseconds(), jaegerLog.Timestamp);
|
||||
|
||||
jaegerLog = logs[1];
|
||||
Assert.Equal(2, jaegerLog.Fields.Count);
|
||||
eventFields = jaegerLog.Fields.ToArray();
|
||||
eventField = eventFields[0];
|
||||
Assert.Equal("key", eventField.Key);
|
||||
Assert.Equal("value", eventField.VStr);
|
||||
eventField = eventFields[1];
|
||||
Assert.Equal("event", eventField.Key);
|
||||
Assert.Equal("Event2", eventField.VStr);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JaegerActivityConverterTest_ConvertActivityToJaegerSpan_NoEvents()
|
||||
{
|
||||
using var activity = CreateTestActivity(addEvents: false);
|
||||
var traceIdAsInt = new Int128(activity.Context.TraceId);
|
||||
var spanIdAsInt = new Int128(activity.Context.SpanId);
|
||||
var linkTraceIdAsInt = new Int128(activity.Links.Single().Context.TraceId);
|
||||
var linkSpanIdAsInt = new Int128(activity.Links.Single().Context.SpanId);
|
||||
|
||||
var jaegerSpan = activity.ToJaegerSpan();
|
||||
|
||||
Assert.Equal("Name", jaegerSpan.OperationName);
|
||||
Assert.Empty(jaegerSpan.Logs);
|
||||
|
||||
Assert.Equal(traceIdAsInt.High, jaegerSpan.TraceIdHigh);
|
||||
Assert.Equal(traceIdAsInt.Low, jaegerSpan.TraceIdLow);
|
||||
Assert.Equal(spanIdAsInt.Low, jaegerSpan.SpanId);
|
||||
Assert.Equal(new Int128(activity.ParentSpanId).Low, jaegerSpan.ParentSpanId);
|
||||
|
||||
Assert.Equal(activity.Links.Count(), jaegerSpan.References.Count);
|
||||
var references = jaegerSpan.References.ToArray();
|
||||
var jaegerRef = references[0];
|
||||
Assert.Equal(linkTraceIdAsInt.High, jaegerRef.TraceIdHigh);
|
||||
Assert.Equal(linkTraceIdAsInt.Low, jaegerRef.TraceIdLow);
|
||||
Assert.Equal(linkSpanIdAsInt.Low, jaegerRef.SpanId);
|
||||
|
||||
Assert.Equal(0x1, jaegerSpan.Flags);
|
||||
|
||||
Assert.Equal(activity.StartTimeUtc.ToEpochMicroseconds(), jaegerSpan.StartTime);
|
||||
Assert.Equal(TimeSpanToMicroseconds(activity.Duration), jaegerSpan.Duration);
|
||||
|
||||
var tags = jaegerSpan.Tags.ToArray();
|
||||
var tag = tags[0];
|
||||
Assert.Equal(JaegerTagType.STRING, tag.VType);
|
||||
Assert.Equal("stringKey", tag.Key);
|
||||
Assert.Equal("value", tag.VStr);
|
||||
tag = tags[1];
|
||||
Assert.Equal(JaegerTagType.LONG, tag.VType);
|
||||
Assert.Equal("longKey", tag.Key);
|
||||
Assert.Equal(1, tag.VLong);
|
||||
tag = tags[2];
|
||||
Assert.Equal(JaegerTagType.LONG, tag.VType);
|
||||
Assert.Equal("longKey2", tag.Key);
|
||||
Assert.Equal(1, tag.VLong);
|
||||
tag = tags[3];
|
||||
Assert.Equal(JaegerTagType.DOUBLE, tag.VType);
|
||||
Assert.Equal("doubleKey", tag.Key);
|
||||
Assert.Equal(1, tag.VDouble);
|
||||
tag = tags[4];
|
||||
Assert.Equal(JaegerTagType.DOUBLE, tag.VType);
|
||||
Assert.Equal("doubleKey2", tag.Key);
|
||||
Assert.Equal(1, tag.VDouble);
|
||||
tag = tags[5];
|
||||
Assert.Equal(JaegerTagType.BOOL, tag.VType);
|
||||
Assert.Equal("boolKey", tag.Key);
|
||||
Assert.Equal(true, tag.VBool);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JaegerActivityConverterTest_ConvertActivityToJaegerSpan_NoLinks()
|
||||
{
|
||||
using var activity = CreateTestActivity(addLinks: false, ticksToAdd: 8000);
|
||||
var traceIdAsInt = new Int128(activity.Context.TraceId);
|
||||
var spanIdAsInt = new Int128(activity.Context.SpanId);
|
||||
|
||||
var jaegerSpan = activity.ToJaegerSpan();
|
||||
|
||||
Assert.Equal("Name", jaegerSpan.OperationName);
|
||||
Assert.Equal(2, jaegerSpan.Logs.Count);
|
||||
|
||||
Assert.Equal(traceIdAsInt.High, jaegerSpan.TraceIdHigh);
|
||||
Assert.Equal(traceIdAsInt.Low, jaegerSpan.TraceIdLow);
|
||||
Assert.Equal(spanIdAsInt.Low, jaegerSpan.SpanId);
|
||||
Assert.Equal(new Int128(activity.ParentSpanId).Low, jaegerSpan.ParentSpanId);
|
||||
|
||||
Assert.Empty(jaegerSpan.References);
|
||||
|
||||
Assert.Equal(0x1, jaegerSpan.Flags);
|
||||
|
||||
Assert.Equal(activity.StartTimeUtc.ToEpochMicroseconds(), jaegerSpan.StartTime);
|
||||
Assert.Equal(TimeSpanToMicroseconds(activity.Duration), jaegerSpan.Duration);
|
||||
|
||||
var tags = jaegerSpan.Tags.ToArray();
|
||||
var tag = tags[0];
|
||||
Assert.Equal(JaegerTagType.STRING, tag.VType);
|
||||
Assert.Equal("stringKey", tag.Key);
|
||||
Assert.Equal("value", tag.VStr);
|
||||
tag = tags[1];
|
||||
Assert.Equal(JaegerTagType.LONG, tag.VType);
|
||||
Assert.Equal("longKey", tag.Key);
|
||||
Assert.Equal(1, tag.VLong);
|
||||
tag = tags[2];
|
||||
Assert.Equal(JaegerTagType.LONG, tag.VType);
|
||||
Assert.Equal("longKey2", tag.Key);
|
||||
Assert.Equal(1, tag.VLong);
|
||||
tag = tags[3];
|
||||
Assert.Equal(JaegerTagType.DOUBLE, tag.VType);
|
||||
Assert.Equal("doubleKey", tag.Key);
|
||||
Assert.Equal(1, tag.VDouble);
|
||||
tag = tags[4];
|
||||
Assert.Equal(JaegerTagType.DOUBLE, tag.VType);
|
||||
Assert.Equal("doubleKey2", tag.Key);
|
||||
Assert.Equal(1, tag.VDouble);
|
||||
tag = tags[5];
|
||||
Assert.Equal(JaegerTagType.BOOL, tag.VType);
|
||||
Assert.Equal("boolKey", tag.Key);
|
||||
Assert.Equal(true, tag.VBool);
|
||||
|
||||
tag = tags[6];
|
||||
Assert.Equal(JaegerTagType.STRING, tag.VType);
|
||||
Assert.Equal("int_array", tag.Key);
|
||||
Assert.Equal(System.Text.Json.JsonSerializer.Serialize(new[] { 1, 2 }), tag.VStr);
|
||||
|
||||
tag = tags[7];
|
||||
Assert.Equal(JaegerTagType.STRING, tag.VType);
|
||||
Assert.Equal("bool_array", tag.Key);
|
||||
Assert.Equal(System.Text.Json.JsonSerializer.Serialize(new[] { true, false }), tag.VStr);
|
||||
|
||||
tag = tags[8];
|
||||
Assert.Equal(JaegerTagType.STRING, tag.VType);
|
||||
Assert.Equal("double_array", tag.Key);
|
||||
Assert.Equal(System.Text.Json.JsonSerializer.Serialize(new[] { 1, 1.1 }), tag.VStr);
|
||||
|
||||
tag = tags[9];
|
||||
Assert.Equal(JaegerTagType.STRING, tag.VType);
|
||||
Assert.Equal("string_array", tag.Key);
|
||||
Assert.Equal(System.Text.Json.JsonSerializer.Serialize(new[] { "a", "b" }), tag.VStr);
|
||||
|
||||
tag = tags[10];
|
||||
Assert.Equal(JaegerTagType.STRING, tag.VType);
|
||||
Assert.Equal("obj_array", tag.Key);
|
||||
Assert.Equal(System.Text.Json.JsonSerializer.Serialize(new[] { 1.ToString(), false.ToString(), new object().ToString(), "string", string.Empty, null }), tag.VStr);
|
||||
|
||||
// The second to last tag should be span.kind in this case
|
||||
tag = tags[tags.Length - 2];
|
||||
Assert.Equal(JaegerTagType.STRING, tag.VType);
|
||||
Assert.Equal("span.kind", tag.Key);
|
||||
Assert.Equal("client", tag.VStr);
|
||||
|
||||
// The last tag should be library.name in this case
|
||||
tag = tags[tags.Length - 1];
|
||||
Assert.Equal(JaegerTagType.STRING, tag.VType);
|
||||
Assert.Equal("otel.library.name", tag.Key);
|
||||
Assert.Equal(nameof(CreateTestActivity), tag.VStr);
|
||||
|
||||
var logs = jaegerSpan.Logs.ToArray();
|
||||
var jaegerLog = logs[0];
|
||||
Assert.Equal(activity.Events.First().Timestamp.ToEpochMicroseconds(), jaegerLog.Timestamp);
|
||||
Assert.Equal(3, jaegerLog.Fields.Count);
|
||||
var eventFields = jaegerLog.Fields.ToArray();
|
||||
var eventField = eventFields[0];
|
||||
Assert.Equal("key", eventField.Key);
|
||||
Assert.Equal("value", eventField.VStr);
|
||||
eventField = eventFields[2];
|
||||
Assert.Equal("event", eventField.Key);
|
||||
Assert.Equal("Event1", eventField.VStr);
|
||||
Assert.Equal(activity.Events.First().Timestamp.ToEpochMicroseconds(), jaegerLog.Timestamp);
|
||||
|
||||
jaegerLog = logs[1];
|
||||
Assert.Equal(2, jaegerLog.Fields.Count);
|
||||
eventFields = jaegerLog.Fields.ToArray();
|
||||
eventField = eventFields[0];
|
||||
Assert.Equal("key", eventField.Key);
|
||||
Assert.Equal("value", eventField.VStr);
|
||||
eventField = eventFields[1];
|
||||
Assert.Equal("event", eventField.Key);
|
||||
Assert.Equal("Event2", eventField.VStr);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JaegerActivityConverterTest_GenerateJaegerSpan_RemoteEndpointOmittedByDefault()
|
||||
{
|
||||
// Arrange
|
||||
using var span = CreateTestActivity();
|
||||
|
||||
// Act
|
||||
var jaegerSpan = span.ToJaegerSpan();
|
||||
|
||||
// Assert
|
||||
Assert.DoesNotContain(jaegerSpan.Tags, t => t.Key == "peer.service");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JaegerActivityConverterTest_GenerateJaegerSpan_RemoteEndpointResolution()
|
||||
{
|
||||
// Arrange
|
||||
using var span = CreateTestActivity(
|
||||
additionalAttributes: new Dictionary<string, object>
|
||||
{
|
||||
["net.peer.name"] = "RemoteServiceName",
|
||||
});
|
||||
|
||||
// Act
|
||||
var jaegerSpan = span.ToJaegerSpan();
|
||||
|
||||
// Assert
|
||||
Assert.Contains(jaegerSpan.Tags, t => t.Key == "peer.service");
|
||||
Assert.Equal("RemoteServiceName", jaegerSpan.Tags.First(t => t.Key == "peer.service").VStr);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JaegerActivityConverterTest_GenerateJaegerSpan_PeerServiceNameIgnoredForServerSpan()
|
||||
{
|
||||
// Arrange
|
||||
using var span = CreateTestActivity(
|
||||
additionalAttributes: new Dictionary<string, object>
|
||||
{
|
||||
["http.host"] = "DiscardedRemoteServiceName",
|
||||
},
|
||||
kind: ActivityKind.Server);
|
||||
|
||||
// Act
|
||||
var jaegerSpan = span.ToJaegerSpan();
|
||||
|
||||
// Assert
|
||||
Assert.Null(jaegerSpan.PeerServiceName);
|
||||
Assert.Empty(jaegerSpan.Tags.Where(t => t.Key == "peer.service"));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RemoteEndpointPriorityTestCase.GetTestCases), MemberType = typeof(RemoteEndpointPriorityTestCase))]
|
||||
public void JaegerActivityConverterTest_GenerateJaegerSpan_RemoteEndpointResolutionPriority(RemoteEndpointPriorityTestCase testCase)
|
||||
{
|
||||
// Arrange
|
||||
using var activity = CreateTestActivity(additionalAttributes: testCase.RemoteEndpointAttributes);
|
||||
|
||||
// Act
|
||||
var jaegerSpan = activity.ToJaegerSpan();
|
||||
|
||||
// Assert
|
||||
var tags = jaegerSpan.Tags.Where(t => t.Key == "peer.service");
|
||||
Assert.Single(tags);
|
||||
var tag = tags.First();
|
||||
Assert.Equal(testCase.ExpectedResult, tag.VStr);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JaegerActivityConverterTest_NullTagValueTest()
|
||||
{
|
||||
// Arrange
|
||||
using var activity = CreateTestActivity(additionalAttributes: new Dictionary<string, object> { ["nullTag"] = null });
|
||||
|
||||
// Act
|
||||
var jaegerSpan = activity.ToJaegerSpan();
|
||||
|
||||
// Assert
|
||||
Assert.DoesNotContain(jaegerSpan.Tags, t => t.Key == "nullTag");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(StatusCode.Unset, "unset", "")]
|
||||
[InlineData(StatusCode.Ok, "Ok", "")]
|
||||
[InlineData(StatusCode.Error, "ERROR", "error description")]
|
||||
[InlineData(StatusCode.Unset, "iNvAlId", "")]
|
||||
public void JaegerActivityConverterTest_Status_ErrorFlagTest(StatusCode expectedStatusCode, string statusCodeTagValue, string statusDescription)
|
||||
{
|
||||
// Arrange
|
||||
using var activity = CreateTestActivity();
|
||||
activity.SetTag(SpanAttributeConstants.StatusCodeKey, statusCodeTagValue);
|
||||
activity.SetTag(SpanAttributeConstants.StatusDescriptionKey, statusDescription);
|
||||
|
||||
// Act
|
||||
var jaegerSpan = activity.ToJaegerSpan();
|
||||
|
||||
// Assert
|
||||
|
||||
Assert.Equal(expectedStatusCode, activity.GetStatus().StatusCode);
|
||||
|
||||
if (expectedStatusCode == StatusCode.Unset)
|
||||
{
|
||||
Assert.DoesNotContain(jaegerSpan.Tags, t => t.Key == SpanAttributeConstants.StatusCodeKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Equal(
|
||||
StatusHelper.GetTagValueForStatusCode(expectedStatusCode),
|
||||
jaegerSpan.Tags.FirstOrDefault(t => t.Key == SpanAttributeConstants.StatusCodeKey).VStr);
|
||||
}
|
||||
|
||||
if (expectedStatusCode == StatusCode.Error)
|
||||
{
|
||||
Assert.Contains(
|
||||
jaegerSpan.Tags, t =>
|
||||
t.Key == JaegerActivityExtensions.JaegerErrorFlagTagName &&
|
||||
t.VType == JaegerTagType.BOOL && (t.VBool ?? false));
|
||||
Assert.Contains(
|
||||
jaegerSpan.Tags, t =>
|
||||
t.Key == SpanAttributeConstants.StatusDescriptionKey &&
|
||||
t.VType == JaegerTagType.STRING && t.VStr.Equals(statusDescription));
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.DoesNotContain(jaegerSpan.Tags, t => t.Key == JaegerActivityExtensions.JaegerErrorFlagTagName);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(ActivityStatusCode.Unset)]
|
||||
[InlineData(ActivityStatusCode.Ok)]
|
||||
[InlineData(ActivityStatusCode.Error)]
|
||||
public void ToJaegerSpan_Activity_Status_And_StatusDescription_is_Set(ActivityStatusCode expectedStatusCode)
|
||||
{
|
||||
// Arrange
|
||||
using var activity = CreateTestActivity();
|
||||
activity.SetStatus(expectedStatusCode);
|
||||
|
||||
// Act
|
||||
var jaegerSpan = activity.ToJaegerSpan();
|
||||
|
||||
// Assert
|
||||
if (expectedStatusCode == ActivityStatusCode.Unset)
|
||||
{
|
||||
Assert.DoesNotContain(jaegerSpan.Tags, t => t.Key == SpanAttributeConstants.StatusCodeKey);
|
||||
}
|
||||
else if (expectedStatusCode == ActivityStatusCode.Ok)
|
||||
{
|
||||
Assert.Equal("OK", jaegerSpan.Tags.FirstOrDefault(t => t.Key == SpanAttributeConstants.StatusCodeKey).VStr);
|
||||
}
|
||||
|
||||
// expectedStatusCode is Error
|
||||
else
|
||||
{
|
||||
Assert.Equal("ERROR", jaegerSpan.Tags.FirstOrDefault(t => t.Key == SpanAttributeConstants.StatusCodeKey).VStr);
|
||||
}
|
||||
|
||||
if (expectedStatusCode == ActivityStatusCode.Error)
|
||||
{
|
||||
Assert.Contains(
|
||||
jaegerSpan.Tags, t =>
|
||||
t.Key == JaegerActivityExtensions.JaegerErrorFlagTagName &&
|
||||
t.VType == JaegerTagType.BOOL && (t.VBool ?? false));
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.DoesNotContain(
|
||||
jaegerSpan.Tags, t =>
|
||||
t.Key == JaegerActivityExtensions.JaegerErrorFlagTagName);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ActivityStatus_Takes_precedence_Over_Status_Tags_ActivityStatusCodeIsOk()
|
||||
{
|
||||
// Arrange.
|
||||
using var activity = CreateTestActivity();
|
||||
const string TagDescriptionOnError = "Description when TagStatusCode is Error.";
|
||||
activity.SetStatus(ActivityStatusCode.Ok);
|
||||
activity.SetTag(SpanAttributeConstants.StatusCodeKey, "ERROR");
|
||||
activity.SetTag(SpanAttributeConstants.StatusDescriptionKey, TagDescriptionOnError);
|
||||
|
||||
// Enrich activity with additional tags.
|
||||
activity.SetTag("myCustomTag", "myCustomTagValue");
|
||||
|
||||
// Act.
|
||||
var jaegerSpan = activity.ToJaegerSpan();
|
||||
|
||||
// Assert.
|
||||
Assert.Equal("OK", jaegerSpan.Tags.FirstOrDefault(t => t.Key == SpanAttributeConstants.StatusCodeKey).VStr);
|
||||
|
||||
Assert.Contains(jaegerSpan.Tags, t => t.Key == "otel.status_code" && t.VStr == "OK");
|
||||
Assert.DoesNotContain(jaegerSpan.Tags, t => t.Key == "otel.status_code" && t.VStr == "ERROR");
|
||||
Assert.DoesNotContain(jaegerSpan.Tags, t => t.Key == JaegerActivityExtensions.JaegerErrorFlagTagName);
|
||||
Assert.DoesNotContain(jaegerSpan.Tags, t => t.Key == SpanAttributeConstants.StatusDescriptionKey &&
|
||||
t.VType == JaegerTagType.STRING && t.VStr.Equals(TagDescriptionOnError));
|
||||
|
||||
// Ensure additional Activity tags were being converted.
|
||||
Assert.Contains(jaegerSpan.Tags, t => t.Key == "myCustomTag" && t.VStr == "myCustomTagValue");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ActivityStatus_Takes_precedence_Over_Status_Tags_ActivityStatusCodeIsError()
|
||||
{
|
||||
// Arrange.
|
||||
using var activity = CreateTestActivity();
|
||||
const string StatusDescriptionOnError = "Description when ActivityStatusCode is Error.";
|
||||
activity.SetStatus(ActivityStatusCode.Error, StatusDescriptionOnError);
|
||||
activity.SetTag(SpanAttributeConstants.StatusCodeKey, "OK");
|
||||
|
||||
// Enrich activity with additional tags.
|
||||
activity.SetTag("myCustomTag", "myCustomTagValue");
|
||||
|
||||
// Act.
|
||||
var jaegerSpan = activity.ToJaegerSpan();
|
||||
|
||||
// Assert.
|
||||
Assert.Contains(jaegerSpan.Tags, t => t.Key == "otel.status_code" && t.VStr == "ERROR");
|
||||
Assert.Contains(jaegerSpan.Tags, t => t.Key == JaegerActivityExtensions.JaegerErrorFlagTagName);
|
||||
Assert.Contains(jaegerSpan.Tags, t => t.Key == SpanAttributeConstants.StatusDescriptionKey &&
|
||||
t.VType == JaegerTagType.STRING && t.VStr.Equals(StatusDescriptionOnError));
|
||||
|
||||
Assert.DoesNotContain(jaegerSpan.Tags, t => t.Key == "otel.status_code" && t.VStr == "OK");
|
||||
|
||||
// Ensure additional Activity tags were being converted.
|
||||
Assert.Contains(jaegerSpan.Tags, t => t.Key == "myCustomTag" && t.VStr == "myCustomTagValue");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ActivityDescription_Takes_precedence_Over_Status_Tags_When_ActivityStatusCodeIsError()
|
||||
{
|
||||
// Arrange.
|
||||
using var activity = CreateTestActivity();
|
||||
|
||||
const string StatusDescriptionOnError = "Description when ActivityStatusCode is Error.";
|
||||
const string TagDescriptionOnError = "Description when TagStatusCode is Error.";
|
||||
activity.SetStatus(ActivityStatusCode.Error, StatusDescriptionOnError);
|
||||
activity.SetTag(SpanAttributeConstants.StatusCodeKey, "ERROR");
|
||||
activity.SetTag(SpanAttributeConstants.StatusDescriptionKey, TagDescriptionOnError);
|
||||
|
||||
// Enrich activity with additional tags.
|
||||
activity.SetTag("myCustomTag", "myCustomTagValue");
|
||||
|
||||
// Act.
|
||||
var jaegerSpan = activity.ToJaegerSpan();
|
||||
|
||||
// Assert.
|
||||
Assert.Equal("ERROR", jaegerSpan.Tags.FirstOrDefault(t => t.Key == SpanAttributeConstants.StatusCodeKey).VStr);
|
||||
|
||||
Assert.Contains(
|
||||
jaegerSpan.Tags, t =>
|
||||
t.Key == JaegerActivityExtensions.JaegerErrorFlagTagName &&
|
||||
t.VType == JaegerTagType.BOOL && (t.VBool ?? false));
|
||||
|
||||
Assert.Contains(
|
||||
jaegerSpan.Tags, t =>
|
||||
t.Key == SpanAttributeConstants.StatusDescriptionKey &&
|
||||
t.VType == JaegerTagType.STRING && t.VStr.Equals(StatusDescriptionOnError));
|
||||
|
||||
// Ensure additional Activity tags were being converted.
|
||||
Assert.Contains(jaegerSpan.Tags, t => t.Key == "myCustomTag" && t.VStr == "myCustomTagValue");
|
||||
}
|
||||
|
||||
internal static Activity CreateTestActivity(
|
||||
bool setAttributes = true,
|
||||
Dictionary<string, object> additionalAttributes = null,
|
||||
bool addEvents = true,
|
||||
bool addLinks = true,
|
||||
Resource resource = null,
|
||||
ActivityKind kind = ActivityKind.Client,
|
||||
bool isRootSpan = false,
|
||||
Status? status = null,
|
||||
long ticksToAdd = 60 * TimeSpan.TicksPerSecond)
|
||||
{
|
||||
var startTimestamp = DateTime.UtcNow;
|
||||
var endTimestamp = startTimestamp.AddTicks(ticksToAdd);
|
||||
var eventTimestamp = DateTime.UtcNow;
|
||||
var traceId = ActivityTraceId.CreateFromString("e8ea7e9ac72de94e91fabc613f9686b2".AsSpan());
|
||||
|
||||
var parentSpanId = isRootSpan ? default : ActivitySpanId.CreateFromBytes(new byte[] { 12, 23, 34, 45, 56, 67, 78, 89 });
|
||||
|
||||
var attributes = new Dictionary<string, object>
|
||||
{
|
||||
{ "exceptionFromToString", new MyToStringMethodThrowsAnException() },
|
||||
{ "exceptionFromToStringInArray", new MyToStringMethodThrowsAnException[] { new MyToStringMethodThrowsAnException() } },
|
||||
{ "stringKey", "value" },
|
||||
{ "longKey", 1L },
|
||||
{ "longKey2", 1 },
|
||||
{ "doubleKey", 1D },
|
||||
{ "doubleKey2", 1F },
|
||||
{ "boolKey", true },
|
||||
{ "int_array", new int[] { 1, 2 } },
|
||||
{ "bool_array", new bool[] { true, false } },
|
||||
{ "double_array", new double[] { 1.0, 1.1 } },
|
||||
{ "string_array", new string[] { "a", "b" } },
|
||||
{ "obj_array", new object[] { 1, false, new object(), "string", string.Empty, null } },
|
||||
};
|
||||
if (additionalAttributes != null)
|
||||
{
|
||||
foreach (var attribute in additionalAttributes)
|
||||
{
|
||||
attributes.Add(attribute.Key, attribute.Value);
|
||||
}
|
||||
}
|
||||
|
||||
var events = new List<ActivityEvent>
|
||||
{
|
||||
new ActivityEvent(
|
||||
"Event1",
|
||||
eventTimestamp,
|
||||
new ActivityTagsCollection(new Dictionary<string, object>
|
||||
{
|
||||
{ "key", "value" },
|
||||
{ "string_array", new string[] { "a", "b" } },
|
||||
})),
|
||||
new ActivityEvent(
|
||||
"Event2",
|
||||
eventTimestamp,
|
||||
new ActivityTagsCollection(new Dictionary<string, object>
|
||||
{
|
||||
{ "key", "value" },
|
||||
})),
|
||||
};
|
||||
|
||||
var linkedSpanId = ActivitySpanId.CreateFromString("888915b6286b9c41".AsSpan());
|
||||
|
||||
using var activitySource = new ActivitySource(nameof(CreateTestActivity));
|
||||
|
||||
var tags = setAttributes ?
|
||||
attributes
|
||||
: null;
|
||||
var links = addLinks ?
|
||||
new[]
|
||||
{
|
||||
new ActivityLink(new ActivityContext(
|
||||
traceId,
|
||||
linkedSpanId,
|
||||
ActivityTraceFlags.Recorded)),
|
||||
}
|
||||
: null;
|
||||
|
||||
using var activity = activitySource.StartActivity(
|
||||
"Name",
|
||||
kind,
|
||||
parentContext: new ActivityContext(traceId, parentSpanId, ActivityTraceFlags.Recorded),
|
||||
tags,
|
||||
links,
|
||||
startTime: startTimestamp);
|
||||
|
||||
if (addEvents)
|
||||
{
|
||||
foreach (var evnt in events)
|
||||
{
|
||||
activity.AddEvent(evnt);
|
||||
}
|
||||
}
|
||||
|
||||
if (status.HasValue)
|
||||
{
|
||||
activity.SetStatus(status.Value);
|
||||
}
|
||||
|
||||
activity.SetEndTime(endTimestamp);
|
||||
activity.Stop();
|
||||
|
||||
return activity;
|
||||
}
|
||||
|
||||
private static long TimeSpanToMicroseconds(TimeSpan timeSpan)
|
||||
{
|
||||
return timeSpan.Ticks / (TimeSpan.TicksPerMillisecond / 1000);
|
||||
}
|
||||
|
||||
public class RemoteEndpointPriorityTestCase
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public string ExpectedResult { get; set; }
|
||||
|
||||
public Dictionary<string, object> RemoteEndpointAttributes { get; set; }
|
||||
|
||||
public static IEnumerable<object[]> GetTestCases()
|
||||
{
|
||||
yield return new object[]
|
||||
{
|
||||
new RemoteEndpointPriorityTestCase
|
||||
{
|
||||
Name = "Highest priority name = net.peer.name",
|
||||
ExpectedResult = "RemoteServiceName",
|
||||
RemoteEndpointAttributes = new Dictionary<string, object>
|
||||
{
|
||||
["http.host"] = "DiscardedRemoteServiceName",
|
||||
["net.peer.name"] = "RemoteServiceName",
|
||||
["peer.hostname"] = "DiscardedRemoteServiceName",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
new RemoteEndpointPriorityTestCase
|
||||
{
|
||||
Name = "Highest priority name = SemanticConventions.AttributePeerService",
|
||||
ExpectedResult = "RemoteServiceName",
|
||||
RemoteEndpointAttributes = new Dictionary<string, object>
|
||||
{
|
||||
[SemanticConventions.AttributePeerService] = "RemoteServiceName",
|
||||
["http.host"] = "DiscardedRemoteServiceName",
|
||||
["net.peer.name"] = "DiscardedRemoteServiceName",
|
||||
["net.peer.port"] = "1234",
|
||||
["peer.hostname"] = "DiscardedRemoteServiceName",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
new RemoteEndpointPriorityTestCase
|
||||
{
|
||||
Name = "Only has net.peer.name and net.peer.port",
|
||||
ExpectedResult = "RemoteServiceName:1234",
|
||||
RemoteEndpointAttributes = new Dictionary<string, object>
|
||||
{
|
||||
["net.peer.name"] = "RemoteServiceName",
|
||||
["net.peer.port"] = "1234",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
new RemoteEndpointPriorityTestCase
|
||||
{
|
||||
Name = "net.peer.port is an int",
|
||||
ExpectedResult = "RemoteServiceName:1234",
|
||||
RemoteEndpointAttributes = new Dictionary<string, object>
|
||||
{
|
||||
["net.peer.name"] = "RemoteServiceName",
|
||||
["net.peer.port"] = 1234,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
new RemoteEndpointPriorityTestCase
|
||||
{
|
||||
Name = "Has net.peer.name and net.peer.port",
|
||||
ExpectedResult = "RemoteServiceName:1234",
|
||||
RemoteEndpointAttributes = new Dictionary<string, object>
|
||||
{
|
||||
["http.host"] = "DiscardedRemoteServiceName",
|
||||
["net.peer.name"] = "RemoteServiceName",
|
||||
["net.peer.port"] = "1234",
|
||||
["peer.hostname"] = "DiscardedRemoteServiceName",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
new RemoteEndpointPriorityTestCase
|
||||
{
|
||||
Name = "Has net.peer.ip and net.peer.port",
|
||||
ExpectedResult = "1.2.3.4:1234",
|
||||
RemoteEndpointAttributes = new Dictionary<string, object>
|
||||
{
|
||||
["http.host"] = "DiscardedRemoteServiceName",
|
||||
["net.peer.ip"] = "1.2.3.4",
|
||||
["net.peer.port"] = "1234",
|
||||
["peer.hostname"] = "DiscardedRemoteServiceName",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
new RemoteEndpointPriorityTestCase
|
||||
{
|
||||
Name = "Has net.peer.name, net.peer.ip, and net.peer.port",
|
||||
ExpectedResult = "RemoteServiceName:1234",
|
||||
RemoteEndpointAttributes = new Dictionary<string, object>
|
||||
{
|
||||
["http.host"] = "DiscardedRemoteServiceName",
|
||||
["net.peer.name"] = "RemoteServiceName",
|
||||
["net.peer.ip"] = "1.2.3.4",
|
||||
["net.peer.port"] = "1234",
|
||||
["peer.hostname"] = "DiscardedRemoteServiceName",
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return this.Name;
|
||||
}
|
||||
}
|
||||
|
||||
private class MyToStringMethodThrowsAnException
|
||||
{
|
||||
public override string ToString()
|
||||
{
|
||||
throw new Exception("Nope.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,156 +0,0 @@
|
|||
// <copyright file="JaegerExporterOptionsTests.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using OpenTelemetry.Trace;
|
||||
using Xunit;
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Tests;
|
||||
|
||||
public class JaegerExporterOptionsTests : IDisposable
|
||||
{
|
||||
public JaegerExporterOptionsTests()
|
||||
{
|
||||
ClearEnvVars();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ClearEnvVars();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JaegerExporterOptions_Defaults()
|
||||
{
|
||||
var options = new JaegerExporterOptions();
|
||||
|
||||
Assert.Equal("localhost", options.AgentHost);
|
||||
Assert.Equal(6831, options.AgentPort);
|
||||
Assert.Equal(4096, options.MaxPayloadSizeInBytes);
|
||||
Assert.Equal(ExportProcessorType.Batch, options.ExportProcessorType);
|
||||
Assert.Equal(JaegerExportProtocol.UdpCompactThrift, options.Protocol);
|
||||
Assert.Equal(JaegerExporterOptions.DefaultJaegerEndpoint, options.Endpoint.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JaegerExporterOptions_EnvironmentVariableOverride()
|
||||
{
|
||||
Environment.SetEnvironmentVariable(JaegerExporterOptions.OTelAgentHostEnvVarKey, "jaeger-host");
|
||||
Environment.SetEnvironmentVariable(JaegerExporterOptions.OTelAgentPortEnvVarKey, "123");
|
||||
Environment.SetEnvironmentVariable(JaegerExporterOptions.OTelProtocolEnvVarKey, "http/thrift.binary");
|
||||
Environment.SetEnvironmentVariable(JaegerExporterOptions.OTelEndpointEnvVarKey, "http://custom-endpoint:12345");
|
||||
|
||||
var options = new JaegerExporterOptions();
|
||||
|
||||
Assert.Equal("jaeger-host", options.AgentHost);
|
||||
Assert.Equal(123, options.AgentPort);
|
||||
Assert.Equal(JaegerExportProtocol.HttpBinaryThrift, options.Protocol);
|
||||
Assert.Equal(new Uri("http://custom-endpoint:12345"), options.Endpoint);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JaegerExporterOptions_InvalidEnvironmentVariableOverride()
|
||||
{
|
||||
Environment.SetEnvironmentVariable(JaegerExporterOptions.OTelAgentPortEnvVarKey, "invalid");
|
||||
Environment.SetEnvironmentVariable(JaegerExporterOptions.OTelProtocolEnvVarKey, "invalid");
|
||||
|
||||
var options = new JaegerExporterOptions();
|
||||
|
||||
Assert.Equal("localhost", options.AgentHost);
|
||||
Assert.Equal(default(JaegerExportProtocol), options.Protocol);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JaegerExporterOptions_SetterOverridesEnvironmentVariable()
|
||||
{
|
||||
Environment.SetEnvironmentVariable(JaegerExporterOptions.OTelAgentHostEnvVarKey, "envvar-host");
|
||||
|
||||
var options = new JaegerExporterOptions
|
||||
{
|
||||
AgentHost = "incode-host",
|
||||
};
|
||||
|
||||
Assert.Equal("incode-host", options.AgentHost);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JaegerExporterOptions_EnvironmentVariableNames()
|
||||
{
|
||||
Assert.Equal("OTEL_EXPORTER_JAEGER_PROTOCOL", JaegerExporterOptions.OTelProtocolEnvVarKey);
|
||||
Assert.Equal("OTEL_EXPORTER_JAEGER_AGENT_HOST", JaegerExporterOptions.OTelAgentHostEnvVarKey);
|
||||
Assert.Equal("OTEL_EXPORTER_JAEGER_AGENT_PORT", JaegerExporterOptions.OTelAgentPortEnvVarKey);
|
||||
Assert.Equal("OTEL_EXPORTER_JAEGER_ENDPOINT", JaegerExporterOptions.OTelEndpointEnvVarKey);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JaegerExporterOptions_FromConfigurationTest()
|
||||
{
|
||||
var values = new Dictionary<string, string>()
|
||||
{
|
||||
[JaegerExporterOptions.OTelProtocolEnvVarKey] = "http/thrift.binary",
|
||||
[JaegerExporterOptions.OTelAgentHostEnvVarKey] = "jaeger-host",
|
||||
[JaegerExporterOptions.OTelAgentPortEnvVarKey] = "123",
|
||||
[JaegerExporterOptions.OTelEndpointEnvVarKey] = "http://custom-endpoint:12345",
|
||||
["OTEL_BSP_MAX_QUEUE_SIZE"] = "18",
|
||||
["OTEL_BSP_MAX_EXPORT_BATCH_SIZE"] = "2",
|
||||
["Jaeger:BatchExportProcessorOptions:MaxExportBatchSize"] = "5",
|
||||
};
|
||||
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(values)
|
||||
.Build();
|
||||
|
||||
IServiceCollection services = null;
|
||||
|
||||
using var provider = Sdk.CreateTracerProviderBuilder()
|
||||
.ConfigureServices(s =>
|
||||
{
|
||||
services = s;
|
||||
services.AddSingleton<IConfiguration>(configuration);
|
||||
services.Configure<JaegerExporterOptions>(configuration.GetSection("Jaeger"));
|
||||
})
|
||||
.AddJaegerExporter()
|
||||
.Build();
|
||||
|
||||
Assert.NotNull(services);
|
||||
|
||||
using var serviceProvider = services.BuildServiceProvider();
|
||||
|
||||
var options = serviceProvider.GetRequiredService<IOptionsMonitor<JaegerExporterOptions>>().CurrentValue;
|
||||
|
||||
Assert.Equal("jaeger-host", options.AgentHost);
|
||||
Assert.Equal(123, options.AgentPort);
|
||||
Assert.Equal(JaegerExportProtocol.HttpBinaryThrift, options.Protocol);
|
||||
Assert.Equal(new Uri("http://custom-endpoint:12345"), options.Endpoint);
|
||||
Assert.Equal(18, options.BatchExportProcessorOptions.MaxQueueSize);
|
||||
|
||||
// Note:
|
||||
// 1. OTEL_BSP_MAX_EXPORT_BATCH_SIZE is processed in BatchExportActivityProcessorOptions ctor and sets MaxExportBatchSize to 2.
|
||||
// 2. Jaeger:BatchExportProcessorOptions:MaxExportBatchSize is processed by options binder after ctor and sets MaxExportBatchSize to 5.
|
||||
Assert.Equal(5, options.BatchExportProcessorOptions.MaxExportBatchSize);
|
||||
}
|
||||
|
||||
private static void ClearEnvVars()
|
||||
{
|
||||
Environment.SetEnvironmentVariable(JaegerExporterOptions.OTelProtocolEnvVarKey, null);
|
||||
Environment.SetEnvironmentVariable(JaegerExporterOptions.OTelAgentHostEnvVarKey, null);
|
||||
Environment.SetEnvironmentVariable(JaegerExporterOptions.OTelAgentPortEnvVarKey, null);
|
||||
Environment.SetEnvironmentVariable(JaegerExporterOptions.OTelEndpointEnvVarKey, null);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
// <copyright file="JaegerExporterProtocolParserTests.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using Xunit;
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Tests;
|
||||
|
||||
public class JaegerExporterProtocolParserTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("udp/thrift.compact", true, JaegerExportProtocol.UdpCompactThrift)]
|
||||
[InlineData("http/thrift.binary", true, JaegerExportProtocol.HttpBinaryThrift)]
|
||||
[InlineData("unsupported", false, default(JaegerExportProtocol))]
|
||||
public void TryParse_Protocol_MapsToCorrectValue(string protocol, bool expectedResult, JaegerExportProtocol expectedExportProtocol)
|
||||
{
|
||||
var result = JaegerExporterProtocolParser.TryParse(protocol, out var exportProtocol);
|
||||
|
||||
Assert.Equal(expectedExportProtocol, exportProtocol);
|
||||
Assert.Equal(expectedResult, result);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,425 +0,0 @@
|
|||
// <copyright file="JaegerExporterTests.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using OpenTelemetry.Exporter.Jaeger.Implementation;
|
||||
using OpenTelemetry.Exporter.Jaeger.Implementation.Tests;
|
||||
using OpenTelemetry.Resources;
|
||||
using OpenTelemetry.Tests;
|
||||
using OpenTelemetry.Trace;
|
||||
using Thrift.Protocol;
|
||||
using Xunit;
|
||||
|
||||
namespace OpenTelemetry.Exporter.Jaeger.Tests;
|
||||
|
||||
public class JaegerExporterTests
|
||||
{
|
||||
[Fact]
|
||||
public void AddJaegerExporterNamedOptionsSupported()
|
||||
{
|
||||
int defaultExporterOptionsConfigureOptionsInvocations = 0;
|
||||
int namedExporterOptionsConfigureOptionsInvocations = 0;
|
||||
|
||||
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.Configure<JaegerExporterOptions>(o => defaultExporterOptionsConfigureOptionsInvocations++);
|
||||
|
||||
services.Configure<JaegerExporterOptions>("Exporter2", o => namedExporterOptionsConfigureOptionsInvocations++);
|
||||
})
|
||||
.AddJaegerExporter()
|
||||
.AddJaegerExporter("Exporter2", o => { })
|
||||
.Build();
|
||||
|
||||
Assert.Equal(1, defaultExporterOptionsConfigureOptionsInvocations);
|
||||
Assert.Equal(1, namedExporterOptionsConfigureOptionsInvocations);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JaegerExporter_BadArgs()
|
||||
{
|
||||
TracerProviderBuilder builder = null;
|
||||
Assert.Throws<ArgumentNullException>(() => builder.AddJaegerExporter());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JaegerTraceExporter_ctor_NullServiceNameAllowed()
|
||||
{
|
||||
using var jaegerTraceExporter = new JaegerExporter(new JaegerExporterOptions());
|
||||
Assert.NotNull(jaegerTraceExporter);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UserHttpFactoryCalled()
|
||||
{
|
||||
JaegerExporterOptions options = new JaegerExporterOptions();
|
||||
|
||||
var defaultFactory = options.HttpClientFactory;
|
||||
|
||||
int invocations = 0;
|
||||
options.Protocol = JaegerExportProtocol.HttpBinaryThrift;
|
||||
options.HttpClientFactory = () =>
|
||||
{
|
||||
invocations++;
|
||||
return defaultFactory();
|
||||
};
|
||||
|
||||
using (var exporter = new JaegerExporter(options))
|
||||
{
|
||||
Assert.Equal(1, invocations);
|
||||
}
|
||||
|
||||
using (var provider = Sdk.CreateTracerProviderBuilder()
|
||||
.AddJaegerExporter(o =>
|
||||
{
|
||||
o.Protocol = JaegerExportProtocol.HttpBinaryThrift;
|
||||
o.HttpClientFactory = options.HttpClientFactory;
|
||||
})
|
||||
.Build())
|
||||
{
|
||||
Assert.Equal(2, invocations);
|
||||
}
|
||||
|
||||
options.HttpClientFactory = null;
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
using var exporter = new JaegerExporter(options);
|
||||
});
|
||||
|
||||
options.HttpClientFactory = () => null;
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
using var exporter = new JaegerExporter(options);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ServiceProviderHttpClientFactoryInvoked()
|
||||
{
|
||||
IServiceCollection services = new ServiceCollection();
|
||||
|
||||
services.AddHttpClient();
|
||||
|
||||
int invocations = 0;
|
||||
|
||||
services.AddHttpClient("JaegerExporter", configureClient: (client) => invocations++);
|
||||
|
||||
services.AddOpenTelemetry().WithTracing(builder => builder
|
||||
.AddJaegerExporter(o => o.Protocol = JaegerExportProtocol.HttpBinaryThrift));
|
||||
|
||||
using var serviceProvider = services.BuildServiceProvider();
|
||||
|
||||
var tracerProvider = serviceProvider.GetRequiredService<TracerProvider>();
|
||||
|
||||
Assert.Equal(1, invocations);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("/api/traces")]
|
||||
[InlineData("/foo/bar")]
|
||||
[InlineData("/")]
|
||||
public void HttpClient_Posts_To_Configured_Endpoint(string uriPath)
|
||||
{
|
||||
// Arrange
|
||||
ConcurrentDictionary<Guid, string> responses = new ConcurrentDictionary<Guid, string>();
|
||||
using var testServer = TestHttpServer.RunServer(
|
||||
context =>
|
||||
{
|
||||
context.Response.StatusCode = 200;
|
||||
|
||||
using StreamReader readStream = new StreamReader(context.Request.InputStream);
|
||||
|
||||
string requestContent = readStream.ReadToEnd();
|
||||
|
||||
responses.TryAdd(
|
||||
Guid.Parse(context.Request.QueryString["requestId"]),
|
||||
context.Request.Url.LocalPath);
|
||||
|
||||
context.Response.OutputStream.Close();
|
||||
},
|
||||
out var testServerHost,
|
||||
out var testServerPort);
|
||||
|
||||
var requestId = Guid.NewGuid();
|
||||
var options = new JaegerExporterOptions
|
||||
{
|
||||
Endpoint = new Uri($"http://{testServerHost}:{testServerPort}{uriPath}?requestId={requestId}"),
|
||||
Protocol = JaegerExportProtocol.HttpBinaryThrift,
|
||||
ExportProcessorType = ExportProcessorType.Simple,
|
||||
};
|
||||
|
||||
using var jaegerExporter = new JaegerExporter(options);
|
||||
|
||||
// Act
|
||||
jaegerExporter.SetResourceAndInitializeBatch(Resource.Empty);
|
||||
jaegerExporter.AppendSpan(CreateTestJaegerSpan());
|
||||
jaegerExporter.SendCurrentBatch();
|
||||
|
||||
// Assert
|
||||
Assert.True(responses.ContainsKey(requestId));
|
||||
Assert.Equal(uriPath, responses[requestId]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JaegerTraceExporter_SetResource_UpdatesServiceName()
|
||||
{
|
||||
using var jaegerTraceExporter = new JaegerExporter(new JaegerExporterOptions());
|
||||
var process = jaegerTraceExporter.Process;
|
||||
|
||||
jaegerTraceExporter.SetResourceAndInitializeBatch(Resource.Empty);
|
||||
|
||||
Assert.StartsWith("unknown_service:", process.ServiceName);
|
||||
|
||||
jaegerTraceExporter.SetResourceAndInitializeBatch(ResourceBuilder.CreateEmpty().AddService("MyService").Build());
|
||||
|
||||
Assert.Equal("MyService", process.ServiceName);
|
||||
|
||||
jaegerTraceExporter.SetResourceAndInitializeBatch(ResourceBuilder.CreateEmpty().AddService("MyService", "MyNamespace").Build());
|
||||
|
||||
Assert.Equal("MyNamespace.MyService", process.ServiceName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JaegerTraceExporter_SetResource_CreatesTags()
|
||||
{
|
||||
using var jaegerTraceExporter = new JaegerExporter(new JaegerExporterOptions());
|
||||
var process = jaegerTraceExporter.Process;
|
||||
|
||||
jaegerTraceExporter.SetResourceAndInitializeBatch(ResourceBuilder.CreateEmpty().AddAttributes(new Dictionary<string, object>
|
||||
{
|
||||
["Tag"] = "value",
|
||||
}).Build());
|
||||
|
||||
Assert.NotNull(process.Tags);
|
||||
Assert.Single(process.Tags);
|
||||
Assert.Equal("value", process.Tags["Tag"].VStr);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JaegerTraceExporter_SetResource_CombinesTags()
|
||||
{
|
||||
using var jaegerTraceExporter = new JaegerExporter(new JaegerExporterOptions());
|
||||
var process = jaegerTraceExporter.Process;
|
||||
|
||||
JaegerTagTransformer.Instance.TryTransformTag(new KeyValuePair<string, object>("Tag1", "value1"), out var result);
|
||||
process.Tags = new Dictionary<string, JaegerTag> { ["Tag1"] = result };
|
||||
|
||||
jaegerTraceExporter.SetResourceAndInitializeBatch(ResourceBuilder.CreateEmpty().AddAttributes(new Dictionary<string, object>
|
||||
{
|
||||
["Tag2"] = "value2",
|
||||
}).Build());
|
||||
|
||||
Assert.NotNull(process.Tags);
|
||||
Assert.Equal(2, process.Tags.Count);
|
||||
Assert.Equal("value1", process.Tags["Tag1"].VStr);
|
||||
Assert.Equal("value2", process.Tags["Tag2"].VStr);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JaegerTraceExporter_SetResource_IgnoreServiceResources()
|
||||
{
|
||||
using var jaegerTraceExporter = new JaegerExporter(new JaegerExporterOptions());
|
||||
var process = jaegerTraceExporter.Process;
|
||||
|
||||
jaegerTraceExporter.SetResourceAndInitializeBatch(ResourceBuilder.CreateEmpty().AddAttributes(new Dictionary<string, object>
|
||||
{
|
||||
[ResourceSemanticConventions.AttributeServiceName] = "servicename",
|
||||
[ResourceSemanticConventions.AttributeServiceNamespace] = "servicenamespace",
|
||||
}).Build());
|
||||
|
||||
Assert.Null(process.Tags);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JaegerTraceExporter_SetResource_UpdatesServiceNameFromIConfiguration()
|
||||
{
|
||||
var tracerProviderBuilder = Sdk.CreateTracerProviderBuilder()
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
Dictionary<string, string> configuration = new()
|
||||
{
|
||||
["OTEL_SERVICE_NAME"] = "myservicename",
|
||||
};
|
||||
|
||||
services.AddSingleton<IConfiguration>(
|
||||
new ConfigurationBuilder().AddInMemoryCollection(configuration).Build());
|
||||
});
|
||||
|
||||
var jaegerTraceExporter = new JaegerExporter(new JaegerExporterOptions());
|
||||
|
||||
tracerProviderBuilder.AddProcessor(new BatchActivityExportProcessor(jaegerTraceExporter));
|
||||
|
||||
using var provider = tracerProviderBuilder.Build();
|
||||
|
||||
var process = jaegerTraceExporter.Process;
|
||||
|
||||
jaegerTraceExporter.SetResourceAndInitializeBatch(Resource.Empty);
|
||||
|
||||
Assert.Equal("myservicename", process.ServiceName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JaegerTraceExporter_BuildBatchesToTransmit_FlushedBatch()
|
||||
{
|
||||
// Arrange
|
||||
using var jaegerExporter = new JaegerExporter(new JaegerExporterOptions { MaxPayloadSizeInBytes = 1500 });
|
||||
jaegerExporter.SetResourceAndInitializeBatch(Resource.Empty);
|
||||
|
||||
// Act
|
||||
jaegerExporter.AppendSpan(CreateTestJaegerSpan());
|
||||
jaegerExporter.AppendSpan(CreateTestJaegerSpan());
|
||||
jaegerExporter.AppendSpan(CreateTestJaegerSpan());
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1U, jaegerExporter.NumberOfSpansInCurrentBatch);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Compact", 1500)]
|
||||
[InlineData("Binary", 2200)]
|
||||
public void JaegerTraceExporter_SpansSplitToBatches_SpansIncludedInBatches(string protocolType, int maxPayloadSizeInBytes)
|
||||
{
|
||||
TProtocolFactory protocolFactory = protocolType == "Compact"
|
||||
? new TCompactProtocol.Factory()
|
||||
: new TBinaryProtocol.Factory();
|
||||
var client = new TestJaegerClient();
|
||||
|
||||
// Arrange
|
||||
using var jaegerExporter = new JaegerExporter(
|
||||
new JaegerExporterOptions { MaxPayloadSizeInBytes = maxPayloadSizeInBytes },
|
||||
protocolFactory,
|
||||
client);
|
||||
jaegerExporter.SetResourceAndInitializeBatch(Resource.Empty);
|
||||
|
||||
// Create six spans, each taking more space than the previous one
|
||||
var spans = new JaegerSpan[6];
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
spans[i] = CreateTestJaegerSpan(
|
||||
additionalAttributes: new Dictionary<string, object>
|
||||
{
|
||||
["foo"] = new string('_', 10 * i),
|
||||
});
|
||||
}
|
||||
|
||||
var protocol = protocolFactory.GetProtocol();
|
||||
var serializedSpans = spans.Select(s =>
|
||||
{
|
||||
s.Write(protocol);
|
||||
var data = protocol.WrittenData.ToArray();
|
||||
protocol.Clear();
|
||||
return data;
|
||||
}).ToArray();
|
||||
|
||||
// Act
|
||||
var sentBatches = new List<byte[]>();
|
||||
foreach (var span in spans)
|
||||
{
|
||||
jaegerExporter.AppendSpan(span);
|
||||
var sentBatch = client.LastWrittenData;
|
||||
if (sentBatch != null)
|
||||
{
|
||||
sentBatches.Add(sentBatch);
|
||||
client.LastWrittenData = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Assert
|
||||
|
||||
// Appending the six spans will send two batches with the first four spans
|
||||
Assert.Equal(2, sentBatches.Count);
|
||||
Assert.True(
|
||||
ContainsSequence(sentBatches[0], serializedSpans[0]),
|
||||
"Expected span data not found in sent batch");
|
||||
Assert.True(
|
||||
ContainsSequence(sentBatches[0], serializedSpans[1]),
|
||||
"Expected span data not found in sent batch");
|
||||
|
||||
Assert.True(
|
||||
ContainsSequence(sentBatches[1], serializedSpans[2]),
|
||||
"Expected span data not found in sent batch");
|
||||
Assert.True(
|
||||
ContainsSequence(sentBatches[1], serializedSpans[3]),
|
||||
"Expected span data not found in sent batch");
|
||||
|
||||
// jaegerExporter.Batch should contain the two remaining spans
|
||||
Assert.Equal(2U, jaegerExporter.NumberOfSpansInCurrentBatch);
|
||||
jaegerExporter.SendCurrentBatch();
|
||||
Assert.True(client.LastWrittenData != null);
|
||||
var serializedBatch = client.LastWrittenData;
|
||||
Assert.True(
|
||||
ContainsSequence(serializedBatch, serializedSpans[4]),
|
||||
"Expected span data not found in unsent batch");
|
||||
Assert.True(
|
||||
ContainsSequence(serializedBatch, serializedSpans[5]),
|
||||
"Expected span data not found in unsent batch");
|
||||
}
|
||||
|
||||
internal static JaegerSpan CreateTestJaegerSpan(
|
||||
bool setAttributes = true,
|
||||
Dictionary<string, object> additionalAttributes = null,
|
||||
bool addEvents = true,
|
||||
bool addLinks = true,
|
||||
Resource resource = null,
|
||||
ActivityKind kind = ActivityKind.Client)
|
||||
{
|
||||
return JaegerActivityConversionTest
|
||||
.CreateTestActivity(
|
||||
setAttributes, additionalAttributes, addEvents, addLinks, resource, kind)
|
||||
.ToJaegerSpan();
|
||||
}
|
||||
|
||||
private static bool ContainsSequence(byte[] source, byte[] pattern)
|
||||
{
|
||||
for (var start = 0; start < (source.Length - pattern.Length + 1); start++)
|
||||
{
|
||||
if (source.Skip(start).Take(pattern.Length).SequenceEqual(pattern))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private sealed class TestJaegerClient : IJaegerClient
|
||||
{
|
||||
public bool Connected => true;
|
||||
|
||||
public byte[] LastWrittenData { get; set; }
|
||||
|
||||
public void Close()
|
||||
{
|
||||
}
|
||||
|
||||
public void Connect()
|
||||
{
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public int Send(byte[] buffer, int offset, int count)
|
||||
{
|
||||
this.LastWrittenData = new ArraySegment<byte>(buffer, offset, count).ToArray();
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<Description>Unit test project for Jaeger Exporter for OpenTelemetry</Description>
|
||||
<!-- OmniSharp/VS Code requires TargetFrameworks to be in descending order for IntelliSense and analysis. -->
|
||||
<TargetFrameworks>net7.0;net6.0</TargetFrameworks>
|
||||
<TargetFrameworks Condition="$(OS) == 'Windows_NT'">$(TargetFrameworks);net462</TargetFrameworks>
|
||||
|
||||
<!-- this is temporary. will remove in future PR. -->
|
||||
<Nullable>disable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Http" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="Moq" />
|
||||
<PackageReference Include="xunit" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" PrivateAssets="All">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Jaeger\OpenTelemetry.Exporter.Jaeger.csproj" />
|
||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Extensions.Hosting\OpenTelemetry.Extensions.Hosting.csproj" />
|
||||
|
||||
<Compile Include="$(RepoRoot)\test\OpenTelemetry.Tests\Shared\EventSourceTestHelper.cs" Link="Includes\EventSourceTestHelper.cs" />
|
||||
<Compile Include="$(RepoRoot)\test\OpenTelemetry.Tests\Shared\TestActivityProcessor.cs" Link="Includes\TestActivityProcessor.cs" />
|
||||
<Compile Include="$(RepoRoot)\test\OpenTelemetry.Tests\Shared\TestEventListener.cs" Link="Includes\TestEventListener.cs" />
|
||||
<Compile Include="$(RepoRoot)\test\OpenTelemetry.Tests\Shared\TestHttpServer.cs" Link="Includes\TestHttpServer.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Loading…
Reference in New Issue