Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions PhenX.EntityFrameworkCore.BulkInsert.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<Project Path="src/PhenX.EntityFrameworkCore.BulkInsert.Sqlite/PhenX.EntityFrameworkCore.BulkInsert.Sqlite.csproj" />
<Project Path="src/PhenX.EntityFrameworkCore.BulkInsert.SqlServer/PhenX.EntityFrameworkCore.BulkInsert.SqlServer.csproj" />
<Project Path="src/PhenX.EntityFrameworkCore.BulkInsert/PhenX.EntityFrameworkCore.BulkInsert.csproj" />
<Project Path="src/OpenTelemetry.Instrumentation.PhenX.EntityFrameworkCore.BulkInsert/OpenTelemetry.Instrumentation.PhenX.EntityFrameworkCore.BulkInsert.csproj" />
</Folder>
<Folder Name="/tests/">
<Project Path="tests/PhenX.EntityFrameworkCore.BulkInsert.Benchmark/PhenX.EntityFrameworkCore.BulkInsert.Benchmark.csproj" />
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ but they are in [the roadmap](#roadmap).
| `PhenX.EntityFrameworkCore.BulkInsert.MySql` | For MySql | [![NuGet](https://img.shields.io/nuget/v/PhenX.EntityFrameworkCore.BulkInsert.Sqlite.svg)](https://www.nuget.org/packages/PhenX.EntityFrameworkCore.BulkInsert.MySql) |
| `PhenX.EntityFrameworkCore.BulkInsert.Oracle` | For Oracle | [![NuGet](https://img.shields.io/nuget/v/PhenX.EntityFrameworkCore.BulkInsert.Oracle.svg)](https://www.nuget.org/packages/PhenX.EntityFrameworkCore.BulkInsert.Oracle) |
| `PhenX.EntityFrameworkCore.BulkInsert` | Common library | [![NuGet](https://img.shields.io/nuget/v/PhenX.EntityFrameworkCore.BulkInsert.svg)](https://www.nuget.org/packages/PhenX.EntityFrameworkCore.BulkInsert) |
| `OpenTelemetry.Instrumentation.PhenX.EntityFrameworkCore.BulkInsert` | OpenTelemetry instrumentation | [![NuGet](https://img.shields.io/nuget/v/OpenTelemetry.Instrumentation.PhenX.EntityFrameworkCore.BulkInsert.svg)](https://www.nuget.org/packages/OpenTelemetry.Instrumentation.PhenX.EntityFrameworkCore.BulkInsert) |

### Dependencies

Expand Down Expand Up @@ -51,6 +52,9 @@ Install-Package PhenX.EntityFrameworkCore.BulkInsert.MySql

# For Oracle
Install-Package PhenX.EntityFrameworkCore.BulkInsert.Oracle

# For OpenTelemetry instrumentation
Install-Package OpenTelemetry.Instrumentation.PhenX.EntityFrameworkCore.BulkInsert
```

## Usage
Expand Down
6 changes: 6 additions & 0 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ export default defineConfig({
{
text: 'Documentation',
link: '/documentation',
items: [
{
text: 'OpenTelemetry',
link: '/opentelemetry',
},
],
},
{
text: 'Limitations',
Expand Down
87 changes: 87 additions & 0 deletions docs/opentelemetry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
title: OpenTelemetry Instrumentation
lang: en-US
---

# OpenTelemetry Instrumentation

PhenX.EntityFrameworkCore.BulkInsert has built-in support for [OpenTelemetry](https://opentelemetry.io/) tracing via the `OpenTelemetry.Instrumentation.PhenX.EntityFrameworkCore.BulkInsert` package.

Each bulk insert operation is automatically tracked as an [Activity](https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.activity) using the `PhenX.EntityFrameworkCore.BulkInsert` activity source, enabling distributed tracing and performance monitoring in your application.

## Installation

Install the instrumentation NuGet package:

```shell
Install-Package OpenTelemetry.Instrumentation.PhenX.EntityFrameworkCore.BulkInsert
```

## Configuration

Register the instrumentation when configuring your OpenTelemetry `TracerProvider` by calling `AddPhenXEntityFrameworkCoreBulkInsertInstrumentation()`:

```csharp
using OpenTelemetry.Trace;

builder.Services.AddOpenTelemetry()
.WithTracing(tracing => tracing
.AddAspNetCoreInstrumentation()
.AddPhenXEntityFrameworkCoreBulkInsertInstrumentation() // <-- add this
.AddOtlpExporter()
);
```

## `TracerProviderBuilderExtensions`

### `AddPhenXEntityFrameworkCoreBulkInsertInstrumentation`

```csharp
public static TracerProviderBuilder AddPhenXEntityFrameworkCoreBulkInsertInstrumentation(
this TracerProviderBuilder builder)
```

Adds the `PhenX.EntityFrameworkCore.BulkInsert` activity source to the given `TracerProviderBuilder`.

**Parameters**

| Parameter | Type | Description |
|-----------|------------------------|-----------------------------------------------------------|
| `builder` | `TracerProviderBuilder` | The `TracerProviderBuilder` to add the instrumentation to. |

**Returns**

The `TracerProviderBuilder` with the `PhenX.EntityFrameworkCore.BulkInsert` instrumentation registered.

## Traced Operations

The following bulk insert operations produce OpenTelemetry traces:

| Operation | Description |
|--------------------------------------|----------------------------------------------------------|
| `ExecuteBulkInsert` | Synchronous bulk insert without entity return |
| `ExecuteBulkInsertAsync` | Asynchronous bulk insert without entity return |
| `ExecuteBulkInsertReturnEntities` | Synchronous bulk insert with entity return |
| `ExecuteBulkInsertReturnEntitiesAsync` | Asynchronous bulk insert with entity return |

## Activity Source

The activity source name used by this library is:

```
PhenX.EntityFrameworkCore.BulkInsert
```

You can use this name to subscribe directly to the activity source if you need lower-level access:

```csharp
using System.Diagnostics;

ActivitySource.AddActivityListener(new ActivityListener
{
ShouldListenTo = source => source.Name == "PhenX.EntityFrameworkCore.BulkInsert",
Sample = (ref ActivityCreationOptions<ActivityContext> _) => ActivitySamplingResult.AllDataAndRecorded,
ActivityStarted = activity => Console.WriteLine($"Started: {activity.DisplayName}"),
ActivityStopped = activity => Console.WriteLine($"Stopped: {activity.DisplayName} ({activity.Duration})"),
});
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="OpenTelemetry.Api" Version="1.*" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using OpenTelemetry.Trace;
namespace OpenTelemetry.Instrumentation.PhenX.EntityFrameworkCore.BulkInsert;

/// <summary>
/// Extension methods for <see cref="TracerProviderBuilder"/> to add instrumentation for PhenX.EntityFrameworkCore.BulkInsert.
/// </summary>
public static class TracerProviderBuilderExtensions
{
/// <summary>
/// Adds instrumentation for PhenX.EntityFrameworkCore.BulkInsert to the OpenTelemetry TracerProviderBuilder.
/// </summary>
/// <param name="builder">The TracerProviderBuilder to add the instrumentation to.</param>
/// <returns>The TracerProviderBuilder with the PhenX.EntityFrameworkCore.BulkInsert instrumentation added.</returns>
public static TracerProviderBuilder AddPhenXEntityFrameworkCoreBulkInsertInstrumentation(this TracerProviderBuilder builder)
{
return builder.AddSource("PhenX.EntityFrameworkCore.BulkInsert");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,14 @@ protected override Task BulkInsert<T>(

using var bulkCopy = new OracleBulkCopy(connection, options.CopyOptions);

bulkCopy.DestinationTableName = tableName;
// When tableName is the SQL-quoted fully qualified name (direct insert path), use the
// unquoted plain table name so ODP.NET does not apply double schema qualification
// (e.g. SchemaX.SchemaX.TABLE_NAME) when a default schema is configured via HasDefaultSchema.
var destinationTableName = tableName == tableInfo.QuotedTableName
? tableInfo.TableName
: tableName;

bulkCopy.DestinationTableName = destinationTableName;
bulkCopy.BatchSize = options.BatchSize;
bulkCopy.BulkCopyTimeout = options.GetCopyTimeoutInSeconds();

Expand Down