diff --git a/test/Benchmarks/Benchmarks.csproj b/test/Benchmarks/Benchmarks.csproj
index 084e1efd288..4a311573f13 100644
--- a/test/Benchmarks/Benchmarks.csproj
+++ b/test/Benchmarks/Benchmarks.csproj
@@ -21,6 +21,7 @@
+
diff --git a/test/Benchmarks/Exporter/OtlpLogExporterBenchmarks.cs b/test/Benchmarks/Exporter/OtlpLogExporterBenchmarks.cs
new file mode 100644
index 00000000000..06d980782c0
--- /dev/null
+++ b/test/Benchmarks/Exporter/OtlpLogExporterBenchmarks.cs
@@ -0,0 +1,154 @@
+//
+// 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.
+//
+
+#if !NETFRAMEWORK
+extern alias OpenTelemetryProtocol;
+
+using BenchmarkDotNet.Attributes;
+using Benchmarks.Helper;
+using Grpc.Core;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using OpenTelemetry;
+using OpenTelemetry.Internal;
+using OpenTelemetry.Logs;
+using OpenTelemetry.Tests;
+using OpenTelemetryProtocol::OpenTelemetry.Exporter;
+using OtlpCollector = OpenTelemetryProtocol::OpenTelemetry.Proto.Collector.Logs.V1;
+
+/*
+BenchmarkDotNet v0.13.6, Windows 11 (10.0.22621.2134/22H2/2022Update/SunValley2) (Hyper-V)
+AMD EPYC 7763, 1 CPU, 16 logical and 8 physical cores
+.NET SDK 7.0.400
+ [Host] : .NET 7.0.10 (7.0.1023.36312), X64 RyuJIT AVX2
+ DefaultJob : .NET 7.0.10 (7.0.1023.36312), X64 RyuJIT AVX2
+
+
+| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
+|--------------------- |---------:|--------:|--------:|-------:|-------:|----------:|
+| OtlpLogExporter_Http | 138.7 us | 2.08 us | 1.95 us | 0.4883 | 0.2441 | 9.85 KB |
+| OtlpLogExporter_Grpc | 268.3 us | 2.57 us | 2.28 us | 0.4883 | - | 9.54 KB |
+*/
+
+namespace Benchmarks.Exporter;
+
+public class OtlpLogExporterBenchmarks
+{
+ private OtlpLogExporter exporter;
+ private LogRecord logRecord;
+ private CircularBuffer logRecordBatch;
+
+ private IHost host;
+ private IDisposable server;
+ private string serverHost;
+ private int serverPort;
+
+ [GlobalSetup(Target = nameof(OtlpLogExporter_Grpc))]
+ public void GlobalSetupGrpc()
+ {
+ this.host = new HostBuilder()
+ .ConfigureWebHostDefaults(webBuilder => webBuilder
+ .ConfigureKestrel(options =>
+ {
+ options.ListenLocalhost(4317, listenOptions => listenOptions.Protocols = Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols.Http2);
+ })
+ .ConfigureServices(services =>
+ {
+ services.AddGrpc();
+ })
+ .Configure(app =>
+ {
+ app.UseRouting();
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapGrpcService();
+ });
+ }))
+ .Start();
+
+ var options = new OtlpExporterOptions();
+ this.exporter = new OtlpLogExporter(options);
+
+ this.logRecord = LogRecordHelper.CreateTestLogRecord();
+ this.logRecordBatch = new CircularBuffer(1);
+ this.logRecordBatch.Add(this.logRecord);
+ }
+
+ [GlobalSetup(Target = nameof(OtlpLogExporter_Http))]
+ public void GlobalSetupHttp()
+ {
+ this.server = TestHttpServer.RunServer(
+ (ctx) =>
+ {
+ ctx.Response.StatusCode = 200;
+ ctx.Response.OutputStream.Close();
+ },
+ out this.serverHost,
+ out this.serverPort);
+
+ var options = new OtlpExporterOptions
+ {
+ Endpoint = new Uri($"http://{this.serverHost}:{this.serverPort}"),
+ Protocol = OtlpExportProtocol.HttpProtobuf,
+ };
+ this.exporter = new OtlpLogExporter(options);
+
+ this.logRecord = LogRecordHelper.CreateTestLogRecord();
+ this.logRecordBatch = new CircularBuffer(1);
+ this.logRecordBatch.Add(this.logRecord);
+ }
+
+ [GlobalCleanup(Target = nameof(OtlpLogExporter_Grpc))]
+ public void GlobalCleanupGrpc()
+ {
+ this.exporter.Shutdown();
+ this.exporter.Dispose();
+ this.host.Dispose();
+ }
+
+ [GlobalCleanup(Target = nameof(OtlpLogExporter_Http))]
+ public void GlobalCleanupHttp()
+ {
+ this.exporter.Shutdown();
+ this.exporter.Dispose();
+ this.server.Dispose();
+ }
+
+ [Benchmark]
+ public void OtlpLogExporter_Http()
+ {
+ this.exporter.Export(new Batch(this.logRecordBatch, 1));
+ }
+
+ [Benchmark]
+ public void OtlpLogExporter_Grpc()
+ {
+ this.exporter.Export(new Batch(this.logRecordBatch, 1));
+ }
+
+ private sealed class MockLogService : OtlpCollector.LogsService.LogsServiceBase
+ {
+ private static OtlpCollector.ExportLogsServiceResponse response = new OtlpCollector.ExportLogsServiceResponse();
+
+ public override Task Export(OtlpCollector.ExportLogsServiceRequest request, ServerCallContext context)
+ {
+ return Task.FromResult(response);
+ }
+ }
+}
+#endif
diff --git a/test/Benchmarks/Exporter/OtlpTraceExporterBenchmarks.cs b/test/Benchmarks/Exporter/OtlpTraceExporterBenchmarks.cs
new file mode 100644
index 00000000000..a833e7073d4
--- /dev/null
+++ b/test/Benchmarks/Exporter/OtlpTraceExporterBenchmarks.cs
@@ -0,0 +1,156 @@
+//
+// 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.
+//
+
+#if !NETFRAMEWORK
+extern alias OpenTelemetryProtocol;
+
+using System.Diagnostics;
+using BenchmarkDotNet.Attributes;
+using Benchmarks.Helper;
+using Grpc.Core;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using OpenTelemetry;
+using OpenTelemetry.Internal;
+using OpenTelemetry.Tests;
+using OpenTelemetryProtocol::OpenTelemetry.Exporter;
+using OtlpCollector = OpenTelemetryProtocol::OpenTelemetry.Proto.Collector.Trace.V1;
+
+/*
+BenchmarkDotNet v0.13.6, Windows 11 (10.0.22621.2134/22H2/2022Update/SunValley2) (Hyper-V)
+AMD EPYC 7763, 1 CPU, 16 logical and 8 physical cores
+.NET SDK 7.0.400
+ [Host] : .NET 7.0.10 (7.0.1023.36312), X64 RyuJIT AVX2
+ DefaultJob : .NET 7.0.10 (7.0.1023.36312), X64 RyuJIT AVX2
+
+
+| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
+|----------------------- |---------:|--------:|--------:|-------:|-------:|----------:|
+| OtlpTraceExporter_Http | 139.4 us | 1.41 us | 1.32 us | 0.4883 | 0.2441 | 9.8 KB |
+| OtlpTraceExporter_Grpc | 263.0 us | 3.47 us | 3.24 us | 0.4883 | - | 9.34 KB |
+*/
+
+namespace Benchmarks.Exporter;
+
+public class OtlpTraceExporterBenchmarks
+{
+ private OtlpTraceExporter exporter;
+ private Activity activity;
+ private CircularBuffer activityBatch;
+
+ private IHost host;
+ private IDisposable server;
+ private string serverHost;
+ private int serverPort;
+
+ [GlobalSetup(Target = nameof(OtlpTraceExporter_Grpc))]
+ public void GlobalSetupGrpc()
+ {
+ this.host = new HostBuilder()
+ .ConfigureWebHostDefaults(webBuilder => webBuilder
+ .ConfigureKestrel(options =>
+ {
+ options.ListenLocalhost(4317, listenOptions => listenOptions.Protocols = Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols.Http2);
+ })
+ .ConfigureServices(services =>
+ {
+ services.AddGrpc();
+ })
+ .Configure(app =>
+ {
+ app.UseRouting();
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapGrpcService();
+ });
+ }))
+ .Start();
+
+ var options = new OtlpExporterOptions();
+ this.exporter = new OtlpTraceExporter(options);
+
+ this.activity = ActivityHelper.CreateTestActivity();
+ this.activityBatch = new CircularBuffer(1);
+ this.activityBatch.Add(this.activity);
+ }
+
+ [GlobalSetup(Target = nameof(OtlpTraceExporter_Http))]
+ public void GlobalSetupHttp()
+ {
+ this.server = TestHttpServer.RunServer(
+ (ctx) =>
+ {
+ ctx.Response.StatusCode = 200;
+ ctx.Response.OutputStream.Close();
+ },
+ out this.serverHost,
+ out this.serverPort);
+
+ var options = new OtlpExporterOptions
+ {
+ Endpoint = new Uri($"http://{this.serverHost}:{this.serverPort}"),
+ Protocol = OtlpExportProtocol.HttpProtobuf,
+ };
+ this.exporter = new OtlpTraceExporter(options);
+
+ this.activity = ActivityHelper.CreateTestActivity();
+ this.activityBatch = new CircularBuffer(1);
+ this.activityBatch.Add(this.activity);
+ }
+
+ [GlobalCleanup(Target = nameof(OtlpTraceExporter_Grpc))]
+ public void GlobalCleanupGrpc()
+ {
+ this.exporter.Shutdown();
+ this.exporter.Dispose();
+ this.activity.Dispose();
+ this.host.Dispose();
+ }
+
+ [GlobalCleanup(Target = nameof(OtlpTraceExporter_Http))]
+ public void GlobalCleanupHttp()
+ {
+ this.exporter.Shutdown();
+ this.exporter.Dispose();
+ this.server.Dispose();
+ this.activity.Dispose();
+ }
+
+ [Benchmark]
+ public void OtlpTraceExporter_Http()
+ {
+ this.exporter.Export(new Batch(this.activityBatch, 1));
+ }
+
+ [Benchmark]
+ public void OtlpTraceExporter_Grpc()
+ {
+ this.exporter.Export(new Batch(this.activityBatch, 1));
+ }
+
+ private sealed class MockTraceService : OtlpCollector.TraceService.TraceServiceBase
+ {
+ private static OtlpCollector.ExportTraceServiceResponse response = new OtlpCollector.ExportTraceServiceResponse();
+
+ public override Task Export(OtlpCollector.ExportTraceServiceRequest request, ServerCallContext context)
+ {
+ return Task.FromResult(response);
+ }
+ }
+}
+#endif
diff --git a/test/Benchmarks/Helper/LogRecordHelper.cs b/test/Benchmarks/Helper/LogRecordHelper.cs
new file mode 100644
index 00000000000..57d3b1e6f5d
--- /dev/null
+++ b/test/Benchmarks/Helper/LogRecordHelper.cs
@@ -0,0 +1,37 @@
+//
+// 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.
+//
+
+using Microsoft.Extensions.Logging;
+using OpenTelemetry.Logs;
+
+namespace Benchmarks.Helper;
+
+internal class LogRecordHelper
+{
+ internal static LogRecord CreateTestLogRecord()
+ {
+ var items = new List(1);
+ using var factory = LoggerFactory.Create(builder => builder
+ .AddOpenTelemetry(loggerOptions =>
+ {
+ loggerOptions.AddInMemoryExporter(items);
+ }));
+
+ var logger = factory.CreateLogger("TestLogger");
+ logger.LogInformation("Hello from {Food} {Price}.", "artichoke", 3.99);
+ return items[0];
+ }
+}