diff --git a/skyapm-dotnet.sln b/skyapm-dotnet.sln index c53ba7eb..5529cf08 100644 --- a/skyapm-dotnet.sln +++ b/skyapm-dotnet.sln @@ -117,6 +117,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.Diagnostics.MassTran EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.Utilities.StaticAccessor", "src\SkyApm.Utilities.StaticAccessor\SkyApm.Utilities.StaticAccessor.csproj", "{F82B5819-0CED-4C9B-9305-7E62DBFB1219}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PeerFormatters", "PeerFormatters", "{D122E6AE-6FE7-4C1A-826F-5964ABBF2C9D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkyApm.PeerFormatters.SqlClient", "src\SkyApm.PeerFormatters.SqlClient\SkyApm.PeerFormatters.SqlClient.csproj", "{5DBE2053-EBAE-404F-A7B3-9CE3CD2152D9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkyApm.PeerFormatters.MySqlConnector", "src\SkyApm.PeerFormatters.MySqlConnector\SkyApm.PeerFormatters.MySqlConnector.csproj", "{2A313B7E-CC41-4556-8055-D87266C398BF}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -267,6 +273,14 @@ Global {F82B5819-0CED-4C9B-9305-7E62DBFB1219}.Debug|Any CPU.Build.0 = Debug|Any CPU {F82B5819-0CED-4C9B-9305-7E62DBFB1219}.Release|Any CPU.ActiveCfg = Release|Any CPU {F82B5819-0CED-4C9B-9305-7E62DBFB1219}.Release|Any CPU.Build.0 = Release|Any CPU + {5DBE2053-EBAE-404F-A7B3-9CE3CD2152D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5DBE2053-EBAE-404F-A7B3-9CE3CD2152D9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5DBE2053-EBAE-404F-A7B3-9CE3CD2152D9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5DBE2053-EBAE-404F-A7B3-9CE3CD2152D9}.Release|Any CPU.Build.0 = Release|Any CPU + {2A313B7E-CC41-4556-8055-D87266C398BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A313B7E-CC41-4556-8055-D87266C398BF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A313B7E-CC41-4556-8055-D87266C398BF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A313B7E-CC41-4556-8055-D87266C398BF}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -317,6 +331,9 @@ Global {136EAD07-A501-4308-9972-82E44F655735} = {844CEACD-4C85-4B15-9E2B-892B01FDA4BB} {1C6A8B34-BB6A-44E0-A395-05ADFB094367} = {B5E677CF-2920-4B0A-A056-E73F6B2CF2BC} {F82B5819-0CED-4C9B-9305-7E62DBFB1219} = {4BD917BC-D579-4C75-9939-41BF012A4EE2} + {D122E6AE-6FE7-4C1A-826F-5964ABBF2C9D} = {05BF0D4E-C824-4EC8-8330-36C1FC49910E} + {5DBE2053-EBAE-404F-A7B3-9CE3CD2152D9} = {D122E6AE-6FE7-4C1A-826F-5964ABBF2C9D} + {2A313B7E-CC41-4556-8055-D87266C398BF} = {D122E6AE-6FE7-4C1A-826F-5964ABBF2C9D} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {94C0DA2C-CCCB-4314-93A2-9809B5DD0583} diff --git a/src/SkyApm.Abstractions/Config/TracingConfig.cs b/src/SkyApm.Abstractions/Config/TracingConfig.cs index e3a79950..b5fa583e 100644 --- a/src/SkyApm.Abstractions/Config/TracingConfig.cs +++ b/src/SkyApm.Abstractions/Config/TracingConfig.cs @@ -8,5 +8,7 @@ namespace SkyApm.Config public class TracingConfig { public int ExceptionMaxDepth { get; set; } = 3; + + public bool DbPeerSimpleFormat { get; set; } = false; } } diff --git a/src/SkyApm.Abstractions/Tracing/IDbPeerFormatter.cs b/src/SkyApm.Abstractions/Tracing/IDbPeerFormatter.cs new file mode 100644 index 00000000..888972de --- /dev/null +++ b/src/SkyApm.Abstractions/Tracing/IDbPeerFormatter.cs @@ -0,0 +1,29 @@ +/* + * Licensed to the SkyAPM under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The SkyAPM 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.Data.Common; + +namespace SkyApm.Tracing +{ + public interface IDbPeerFormatter + { + bool Match(DbConnection connection); + + string GetPeer(DbConnection connection); + } +} diff --git a/src/SkyApm.Abstractions/Tracing/IPeerFormatter.cs b/src/SkyApm.Abstractions/Tracing/IPeerFormatter.cs new file mode 100644 index 00000000..b99cb136 --- /dev/null +++ b/src/SkyApm.Abstractions/Tracing/IPeerFormatter.cs @@ -0,0 +1,30 @@ +/* + * Licensed to the SkyAPM under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The SkyAPM 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.Data.Common; +using System.Text; + +namespace SkyApm.Tracing +{ + public interface IPeerFormatter + { + string GetDbPeer(DbConnection connection); + } +} diff --git a/src/SkyApm.Agent.Hosting/Extensions/ServiceCollectionExtensions.cs b/src/SkyApm.Agent.Hosting/Extensions/ServiceCollectionExtensions.cs index 11658a0a..9f45a156 100644 --- a/src/SkyApm.Agent.Hosting/Extensions/ServiceCollectionExtensions.cs +++ b/src/SkyApm.Agent.Hosting/Extensions/ServiceCollectionExtensions.cs @@ -36,6 +36,8 @@ using SkyApm; using SkyApm.Agent.Hosting; using SkyApm.Diagnostics.MSLogging; +using SkyApm.PeerFormatters.SqlClient; +using SkyApm.PeerFormatters.MySqlConnector; using ILoggerFactory = SkyApm.Logging.ILoggerFactory; namespace Microsoft.Extensions.DependencyInjection @@ -69,6 +71,7 @@ private static IServiceCollection AddSkyAPMCore(this IServiceCollection services services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); services.AddTracing().AddSampling().AddGrpcTransport().AddSkyApmLogging(); var extensions = services.AddSkyApmExtensions() .AddHttpClient() @@ -76,7 +79,9 @@ private static IServiceCollection AddSkyAPMCore(this IServiceCollection services .AddSqlClient() .AddGrpc() .AddEntityFrameworkCore(c => c.AddPomeloMysql().AddNpgsql().AddSqlite()) - .AddMSLogging(); + .AddMSLogging() + .AddSqlClientPeerFormatter() + .AddMySqlConnectorPeerFormatter(); extensionsSetup?.Invoke(extensions); diff --git a/src/SkyApm.Agent.Hosting/SkyApm.Agent.Hosting.csproj b/src/SkyApm.Agent.Hosting/SkyApm.Agent.Hosting.csproj index 59bf3710..4b7ec419 100644 --- a/src/SkyApm.Agent.Hosting/SkyApm.Agent.Hosting.csproj +++ b/src/SkyApm.Agent.Hosting/SkyApm.Agent.Hosting.csproj @@ -35,6 +35,8 @@ + + diff --git a/src/SkyApm.Core/Tracing/PeerFormatter.cs b/src/SkyApm.Core/Tracing/PeerFormatter.cs new file mode 100644 index 00000000..1c5ebc2c --- /dev/null +++ b/src/SkyApm.Core/Tracing/PeerFormatter.cs @@ -0,0 +1,57 @@ +using SkyApm.Config; +using System.Collections.Concurrent; +using System.Collections.Generic; +/* + * Licensed to the SkyAPM under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The SkyAPM 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.Data.Common; + +namespace SkyApm.Tracing +{ + public class PeerFormatter : IPeerFormatter + { + private readonly ConcurrentDictionary _peerMap = new ConcurrentDictionary(); + + private readonly IEnumerable _dbPeerFormatters; + private readonly TracingConfig _tracingConfig; + + public PeerFormatter(IEnumerable dbPeerFormatters, IConfigAccessor configAccessor) + { + _dbPeerFormatters= dbPeerFormatters; + _tracingConfig = configAccessor.Get(); + } + + public string GetDbPeer(DbConnection connection) + { + if (!_tracingConfig.DbPeerSimpleFormat) return connection.DataSource; + + return _peerMap.GetOrAdd($"{connection.GetType()}_{connection.DataSource}", k => + { + foreach (var formatter in _dbPeerFormatters) + { + if (formatter.Match(connection)) + { + return formatter.GetPeer(connection); + } + } + + return connection.DataSource; + }); + } + } +} diff --git a/src/SkyApm.Diagnostics.EntityFrameworkCore.Npgsql/NpgsqlEntityFrameworkCoreSpanMetadataProvider.cs b/src/SkyApm.Diagnostics.EntityFrameworkCore.Npgsql/NpgsqlEntityFrameworkCoreSpanMetadataProvider.cs index 3edefeb6..c4665cf6 100644 --- a/src/SkyApm.Diagnostics.EntityFrameworkCore.Npgsql/NpgsqlEntityFrameworkCoreSpanMetadataProvider.cs +++ b/src/SkyApm.Diagnostics.EntityFrameworkCore.Npgsql/NpgsqlEntityFrameworkCoreSpanMetadataProvider.cs @@ -17,12 +17,20 @@ */ using SkyApm.Common; +using SkyApm.Tracing; using System.Data.Common; namespace SkyApm.Diagnostics.EntityFrameworkCore { public class NpgsqlEntityFrameworkCoreSpanMetadataProvider : IEntityFrameworkCoreSpanMetadataProvider { + private readonly IPeerFormatter _peerFormatter; + + public NpgsqlEntityFrameworkCoreSpanMetadataProvider(IPeerFormatter peerFormatter) + { + _peerFormatter = peerFormatter; + } + public StringOrIntValue Component { get; } = Common.Components.NPGSQL_ENTITYFRAMEWORKCORE_POSTGRESQL; public bool Match(DbConnection connection) @@ -32,7 +40,7 @@ public bool Match(DbConnection connection) public string GetPeer(DbConnection connection) { - return connection.DataSource; + return _peerFormatter.GetDbPeer(connection); } } } \ No newline at end of file diff --git a/src/SkyApm.Diagnostics.EntityFrameworkCore.Pomelo.MySql/MySqlEntityFrameworkCoreSpanMetadataProvider.cs b/src/SkyApm.Diagnostics.EntityFrameworkCore.Pomelo.MySql/MySqlEntityFrameworkCoreSpanMetadataProvider.cs index be750753..dd71e73d 100644 --- a/src/SkyApm.Diagnostics.EntityFrameworkCore.Pomelo.MySql/MySqlEntityFrameworkCoreSpanMetadataProvider.cs +++ b/src/SkyApm.Diagnostics.EntityFrameworkCore.Pomelo.MySql/MySqlEntityFrameworkCoreSpanMetadataProvider.cs @@ -17,12 +17,20 @@ */ using SkyApm.Common; +using SkyApm.Tracing; using System.Data.Common; namespace SkyApm.Diagnostics.EntityFrameworkCore { public class MySqlEntityFrameworkCoreSpanMetadataProvider : IEntityFrameworkCoreSpanMetadataProvider { + private readonly IPeerFormatter _peerFormatter; + + public MySqlEntityFrameworkCoreSpanMetadataProvider(IPeerFormatter peerFormatter) + { + _peerFormatter = peerFormatter; + } + public StringOrIntValue Component { get; } = Common.Components.POMELO_ENTITYFRAMEWORKCORE_MYSQL; public bool Match(DbConnection connection) @@ -32,7 +40,7 @@ public bool Match(DbConnection connection) public string GetPeer(DbConnection connection) { - return connection.DataSource; + return _peerFormatter.GetDbPeer(connection); } } } \ No newline at end of file diff --git a/src/SkyApm.Diagnostics.EntityFrameworkCore.Sqlite/SqliteEntityFrameworkCoreSpanMetadataProvider.cs b/src/SkyApm.Diagnostics.EntityFrameworkCore.Sqlite/SqliteEntityFrameworkCoreSpanMetadataProvider.cs index e8c7a718..af9c26f2 100644 --- a/src/SkyApm.Diagnostics.EntityFrameworkCore.Sqlite/SqliteEntityFrameworkCoreSpanMetadataProvider.cs +++ b/src/SkyApm.Diagnostics.EntityFrameworkCore.Sqlite/SqliteEntityFrameworkCoreSpanMetadataProvider.cs @@ -17,12 +17,20 @@ */ using SkyApm.Common; +using SkyApm.Tracing; using System.Data.Common; namespace SkyApm.Diagnostics.EntityFrameworkCore { public class SqliteEntityFrameworkCoreSpanMetadataProvider : IEntityFrameworkCoreSpanMetadataProvider { + private readonly IPeerFormatter _peerFormatter; + + public SqliteEntityFrameworkCoreSpanMetadataProvider(IPeerFormatter peerFormatter) + { + _peerFormatter = peerFormatter; + } + public StringOrIntValue Component { get; } = Common.Components.ENTITYFRAMEWORKCORE_SQLITE; public bool Match(DbConnection connection) @@ -32,18 +40,13 @@ public bool Match(DbConnection connection) public string GetPeer(DbConnection connection) { - string dataSource; switch (connection.DataSource) { case "": - dataSource = "sqlite:memory:db"; - break; + return "sqlite:memory:db"; default: - dataSource = connection.DataSource; - break; + return _peerFormatter.GetDbPeer(connection); } - - return $"{dataSource}"; } } } \ No newline at end of file diff --git a/src/SkyApm.Diagnostics.SmartSql/SmartSqlTracingDiagnosticProcessor.cs b/src/SkyApm.Diagnostics.SmartSql/SmartSqlTracingDiagnosticProcessor.cs index 55d00df6..77dfd010 100644 --- a/src/SkyApm.Diagnostics.SmartSql/SmartSqlTracingDiagnosticProcessor.cs +++ b/src/SkyApm.Diagnostics.SmartSql/SmartSqlTracingDiagnosticProcessor.cs @@ -37,13 +37,16 @@ public class SmartSqlTracingDiagnosticProcessor : ITracingDiagnosticProcessor private readonly ITracingContext _tracingContext; private readonly ILocalSegmentContextAccessor _localSegmentContextAccessor; private readonly TracingConfig _tracingConfig; + private readonly IPeerFormatter _peerFormatter; public SmartSqlTracingDiagnosticProcessor(ITracingContext tracingContext, - ILocalSegmentContextAccessor localSegmentContextAccessor, IConfigAccessor configAccessor) + ILocalSegmentContextAccessor localSegmentContextAccessor, IConfigAccessor configAccessor, + IPeerFormatter peerFormatter) { _tracingContext = tracingContext; _localSegmentContextAccessor = localSegmentContextAccessor; _tracingConfig = configAccessor.Get(); + _peerFormatter = peerFormatter; } private void AddConnectionTag(SegmentContext context, DbConnection dbConnection) { @@ -53,7 +56,7 @@ private void AddConnectionTag(SegmentContext context, DbConnection dbConnection) } if (dbConnection.DataSource != null) { - context.Span.Peer = new Common.StringOrIntValue(dbConnection.DataSource); + context.Span.Peer = _peerFormatter.GetDbPeer(dbConnection); } if (dbConnection.Database != null) { diff --git a/src/SkyApm.Diagnostics.SqlClient/SqlClientDiagnosticProcessor.cs b/src/SkyApm.Diagnostics.SqlClient/SqlClientDiagnosticProcessor.cs index 4f94ec96..f89610ea 100644 --- a/src/SkyApm.Diagnostics.SqlClient/SqlClientDiagnosticProcessor.cs +++ b/src/SkyApm.Diagnostics.SqlClient/SqlClientDiagnosticProcessor.cs @@ -29,13 +29,16 @@ public class SqlClientTracingDiagnosticProcessor : ITracingDiagnosticProcessor private readonly ITracingContext _tracingContext; private readonly IExitSegmentContextAccessor _contextAccessor; private readonly TracingConfig _tracingConfig; + private readonly IPeerFormatter _peerFormatter; public SqlClientTracingDiagnosticProcessor(ITracingContext tracingContext, - IExitSegmentContextAccessor contextAccessor, IConfigAccessor configAccessor) + IExitSegmentContextAccessor contextAccessor, IConfigAccessor configAccessor, + IPeerFormatter peerFormatter) { _tracingContext = tracingContext; _contextAccessor = contextAccessor; _tracingConfig = configAccessor.Get(); + _peerFormatter = peerFormatter; } @@ -52,7 +55,7 @@ private static string ResolveOperationName(DbCommand sqlCommand) public void BeforeExecuteCommand([Property(Name = "Command")] DbCommand sqlCommand) { var context = _tracingContext.CreateExitSegmentContext(ResolveOperationName(sqlCommand), - sqlCommand.Connection.DataSource); + _peerFormatter.GetDbPeer(sqlCommand.Connection)); context.Span.SpanLayer = Tracing.Segments.SpanLayer.DB; context.Span.Component = Common.Components.SQLCLIENT; context.Span.AddTag(Common.Tags.DB_TYPE, "sql"); diff --git a/src/SkyApm.PeerFormatters.MySqlConnector/MySqlConnectorPeerFormatter.cs b/src/SkyApm.PeerFormatters.MySqlConnector/MySqlConnectorPeerFormatter.cs new file mode 100644 index 00000000..fb26ff1f --- /dev/null +++ b/src/SkyApm.PeerFormatters.MySqlConnector/MySqlConnectorPeerFormatter.cs @@ -0,0 +1,60 @@ +/* + * Licensed to the SkyAPM under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The SkyAPM 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 SkyApm.Tracing; +using System.Data.Common; +using System.Text.RegularExpressions; + +namespace SkyApm.PeerFormatters.MySqlConnector +{ + internal class MySqlConnectorPeerFormatter : IDbPeerFormatter + { + private readonly Regex _serverRegex = new Regex(@"server=(?:([^;]+?);|([^;]+?)$)", RegexOptions.IgnoreCase); + private readonly Regex _portRegex = new Regex(@"port=(\d+)"); + + public bool Match(DbConnection connection) + { + var fullName = connection.GetType().FullName; + return fullName == "MySql.Data.MySqlClient.MySqlConnection" || fullName == "MySqlConnector.MySqlConnection"; + } + + public string GetPeer(DbConnection connection) + { + if (connection.ConnectionString == null) return connection.DataSource; + + var serverMatch = _serverRegex.Match(connection.ConnectionString); + var portMatch = _portRegex.Match(connection.ConnectionString); + + var port = portMatch.Success ? portMatch.Groups[1].Value : "3306"; + + if (serverMatch.Success && serverMatch.Groups.Count == 3) + { + if (serverMatch.Groups[1].Success) + { + return $"{serverMatch.Groups[1].Value}:{port}"; + } + if (serverMatch.Groups[2].Success) + { + return $"{serverMatch.Groups[2].Value}:{port}"; + } + } + + return connection.DataSource; + } + } +} diff --git a/src/SkyApm.PeerFormatters.MySqlConnector/MySqlConnectorPeerFormatterExtensions.cs b/src/SkyApm.PeerFormatters.MySqlConnector/MySqlConnectorPeerFormatterExtensions.cs new file mode 100644 index 00000000..c5a1b7e7 --- /dev/null +++ b/src/SkyApm.PeerFormatters.MySqlConnector/MySqlConnectorPeerFormatterExtensions.cs @@ -0,0 +1,41 @@ +/* + * Licensed to the SkyAPM under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The SkyAPM 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 Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using SkyApm.Tracing; +using SkyApm.Utilities.DependencyInjection; +using System; + +namespace SkyApm.PeerFormatters.MySqlConnector +{ + public static class MySqlConnectorPeerFormatterExtensions + { + public static SkyApmExtensions AddMySqlConnectorPeerFormatter(this SkyApmExtensions extensions) + { + if (extensions == null) + { + throw new ArgumentNullException(nameof(extensions)); + } + + extensions.Services.TryAddEnumerable(ServiceDescriptor.Singleton()); + + return extensions; + } + } +} diff --git a/src/SkyApm.PeerFormatters.MySqlConnector/SkyApm.PeerFormatters.MySqlConnector.csproj b/src/SkyApm.PeerFormatters.MySqlConnector/SkyApm.PeerFormatters.MySqlConnector.csproj new file mode 100644 index 00000000..f9d5f1db --- /dev/null +++ b/src/SkyApm.PeerFormatters.MySqlConnector/SkyApm.PeerFormatters.MySqlConnector.csproj @@ -0,0 +1,21 @@ + + + + + $(Product) MySqlConnector peer formatter. + $(PackagePrefix).PeerFormatters.MySqlConnector + $(PackagePrefix).PeerFormatters.MySqlConnector + $(PackagePrefix).PeerFormatters.MySqlConnector + SkyWalking;APM;MySqlConnector + + + SkyApm.PeerFormatters.MySqlConnector + netcoreapp3.1;net5.0;net6.0;net7.0 + + + + + + + + diff --git a/src/SkyApm.PeerFormatters.SqlClient/SkyApm.PeerFormatters.SqlClient.csproj b/src/SkyApm.PeerFormatters.SqlClient/SkyApm.PeerFormatters.SqlClient.csproj new file mode 100644 index 00000000..c4e6caf8 --- /dev/null +++ b/src/SkyApm.PeerFormatters.SqlClient/SkyApm.PeerFormatters.SqlClient.csproj @@ -0,0 +1,21 @@ + + + + + $(Product) System.Data.SqlClient and Microsoft.Data.SqlClient peer formatter. + $(PackagePrefix).PeerFormatters.SqlClient + $(PackagePrefix).PeerFormatters.SqlClient + $(PackagePrefix).PeerFormatters.SqlClient + SkyWalking;APM;SqlClient + + + SkyApm.PeerFormatters.SqlClient + netcoreapp3.1;net5.0;net6.0;net7.0 + + + + + + + + diff --git a/src/SkyApm.PeerFormatters.SqlClient/SqlClientPeerFormatter.cs b/src/SkyApm.PeerFormatters.SqlClient/SqlClientPeerFormatter.cs new file mode 100644 index 00000000..6f969f09 --- /dev/null +++ b/src/SkyApm.PeerFormatters.SqlClient/SqlClientPeerFormatter.cs @@ -0,0 +1,64 @@ +/* + * Licensed to the SkyAPM under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The SkyAPM 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 SkyApm.Tracing; +using System.Data.Common; +using System.Text.RegularExpressions; + +namespace SkyApm.PeerFormatters.SqlClient +{ + internal class SqlClientPeerFormatter : IDbPeerFormatter + { + private readonly Regex _conStrRegex = new Regex(@"Data Source=(?:([^;,]+?)(?:,(\d+))?;|([^,]+?)(?:,(\d+))?$)", RegexOptions.IgnoreCase); + + public bool Match(DbConnection connection) + { + var fullName = connection.GetType().FullName; + return fullName == "System.Data.SqlClient.SqlConnection" || fullName == "Microsoft.Data.SqlClient.SqlConnection"; + } + + public string GetPeer(DbConnection connection) + { + if (connection.ConnectionString == null) return connection.DataSource; + + var match = _conStrRegex.Match(connection.ConnectionString); + + if (match.Success && match.Groups.Count == 5) + { + if (match.Groups[1].Success) + { + if (match.Groups[2].Success) + { + return $"{match.Groups[1].Value}:{match.Groups[2].Value}"; + } + return match.Groups[1].Value + ":1433"; + } + if (match.Groups[3].Success) + { + if (match.Groups[4].Success) + { + return $"{match.Groups[3].Value}:{match.Groups[4].Value}"; + } + return match.Groups[3].Value + ":1433"; + } + } + + return connection.DataSource; + } + } +} diff --git a/src/SkyApm.PeerFormatters.SqlClient/SqlClientPeerFormatterExtensions.cs b/src/SkyApm.PeerFormatters.SqlClient/SqlClientPeerFormatterExtensions.cs new file mode 100644 index 00000000..22c9e6fe --- /dev/null +++ b/src/SkyApm.PeerFormatters.SqlClient/SqlClientPeerFormatterExtensions.cs @@ -0,0 +1,41 @@ +/* + * Licensed to the SkyAPM under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The SkyAPM 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 Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using SkyApm.Tracing; +using SkyApm.Utilities.DependencyInjection; +using System; + +namespace SkyApm.PeerFormatters.SqlClient +{ + public static class SqlClientPeerFormatterExtensions + { + public static SkyApmExtensions AddSqlClientPeerFormatter(this SkyApmExtensions extensions) + { + if (extensions == null) + { + throw new ArgumentNullException(nameof(extensions)); + } + + extensions.Services.TryAddEnumerable(ServiceDescriptor.Singleton()); + + return extensions; + } + } +}