Skip to content
Merged
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
2 changes: 1 addition & 1 deletion src/EFCore.ClickHouse/EFCore.ClickHouse.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.2" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive" />
<PackageReference Include="ClickHouse.Driver" Version="1.1.0" />
<PackageReference Include="ClickHouse.Driver" Version="1.3.0" />
</ItemGroup>

<ItemGroup>
Expand Down
26 changes: 26 additions & 0 deletions src/EFCore.ClickHouse/Storage/Internal/ClickHouseClientIdentity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using ClickHouse.Driver.ADO;

namespace ClickHouse.EntityFrameworkCore.Storage.Internal;

/// <summary>
/// Tags the ClickHouse client's <c>User-Agent</c> with this provider's identity so that
/// queries it issues are attributable server-side via
/// <see cref="ClickHouseClientSettings.ApplicationInfo"/> (ClickHouse.Driver 1.3.0+).
/// </summary>
internal static class ClickHouseClientIdentity
{
/// <summary>
/// Value of the <c>lib</c> User-Agent tag identifying this library.
/// </summary>
internal const string LibraryName = "ClickHouse.EntityFrameworkCore";

/// <summary>
/// Builds <see cref="ClickHouseClientSettings"/> from a connection string with the
/// <c>lib</c> User-Agent tag set to <see cref="LibraryName"/>.
/// </summary>
internal static ClickHouseClientSettings CreateSettings(string connectionString)
=> new(connectionString)
{
ApplicationInfo = new Dictionary<string, string> { ["lib"] = LibraryName },
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ private ClickHouseDataSource GetOrCreateDataSource(string connectionString, bool
if (_dataSources.TryGetValue(effectiveConnectionString, out var existing))
return existing;

var newDataSource = new ClickHouseDataSource(effectiveConnectionString);
var newDataSource = new ClickHouseDataSource(
ClickHouseClientIdentity.CreateSettings(effectiveConnectionString));
var added = _dataSources.GetOrAdd(effectiveConnectionString, newDataSource);

if (!ReferenceEquals(added, newDataSource))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@ private ClickHouseRelationalConnection(
protected override DbConnection CreateDbConnection()
=> _dataSource?.CreateConnection()
?? new ClickHouseConnection(
_joinNullSemanticsDisabled
? ConnectionString!
: ClickHouseDataSourceManager.EnsureDefaultSettings(ConnectionString!));
ClickHouseClientIdentity.CreateSettings(
_joinNullSemanticsDisabled
? ConnectionString!
: ClickHouseDataSourceManager.EnsureDefaultSettings(ConnectionString!)));

protected override bool SupportsAmbientTransactions => false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.*" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.*" />
<PackageReference Include="Testcontainers.ClickHouse" Version="4.*" />
<PackageReference Include="ClickHouse.Driver" Version="1.1.0" />
<PackageReference Include="ClickHouse.Driver" Version="1.3.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational.Specification.Tests" Version="10.0.2" />
<PackageReference Include="GitHubActionsTestLogger" Version="3.0.1">
<PrivateAssets>all</PrivateAssets>
Expand Down
57 changes: 57 additions & 0 deletions test/EFCore.ClickHouse.FunctionalTests/UserAgentClickHouseTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using ClickHouse.Driver.ADO;
using Microsoft.EntityFrameworkCore.TestUtilities;
using Xunit;

namespace Microsoft.EntityFrameworkCore;

/// <summary>
/// Verifies end-to-end that the provider tags its ClickHouse HTTP requests with the
/// <c>lib</c> User-Agent token, by reading it back from <c>system.query_log</c>.
/// </summary>
public class UserAgentClickHouseTest
{
private sealed class ProbeContext(string connectionString) : DbContext
{
private readonly string _connectionString = connectionString;

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseClickHouse(_connectionString);
}

[Fact]
public async Task Queries_are_tagged_with_lib_in_user_agent()
{
var connectionString = TestEnvironment.DefaultConnection;
var marker = $"ua_probe_{Guid.NewGuid():N}";

// Issue a query through EF Core's (tagged) connection. The marker (a GUID) is
// concatenated rather than interpolated to keep clear of EF1002.
var probeSql = "SELECT 1 /* " + marker + " */";
await using (var context = new ProbeContext(connectionString))
{
await context.Database.ExecuteSqlRawAsync(probeSql);
}

// Use a separate, untagged connection for verification so the lib tag we assert
// on can only have come from the provider's own connection.
await using var connection = new ClickHouseConnection(connectionString);
await connection.OpenAsync();

using (var flush = connection.CreateCommand())
{
flush.CommandText = "SYSTEM FLUSH LOGS";
await flush.ExecuteNonQueryAsync();
}

using var query = connection.CreateCommand();
query.CommandText =
"SELECT count() FROM system.query_log " +
$"WHERE query LIKE '%{marker}%' " +
Comment thread
alex-clickhouse marked this conversation as resolved.
"AND http_user_agent LIKE '%lib:ClickHouse.EntityFrameworkCore%' " +
"AND event_time > now() - INTERVAL 5 MINUTE";

var count = Convert.ToInt64(await query.ExecuteScalarAsync());
Assert.True(count > 0,
"Expected EF Core's query to carry lib:ClickHouse.EntityFrameworkCore in the HTTP User-Agent.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.*" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.*" />
<PackageReference Include="Testcontainers.ClickHouse" Version="4.*" />
<PackageReference Include="ClickHouse.Driver" Version="1.1.0" />
<PackageReference Include="ClickHouse.Driver" Version="1.3.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational.Specification.Tests" Version="10.0.2" />
<PackageReference Include="GitHubActionsTestLogger" Version="3.0.1">
Expand Down
Loading