Commit 36d7ff5c authored by linkinshi's avatar linkinshi Committed by Lemon

新增对于mysql.data组件的监控功能 (#114)

parent d503cb84
......@@ -12,6 +12,18 @@
<AssemblyName>SkyWalking.Sample.AspNet</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>4.0</OldToolsVersion>
<UseIISExpress>true</UseIISExpress>
<Use64BitIISExpress />
<IISExpressSSLPort />
<IISExpressAnonymousAuthentication />
<IISExpressWindowsAuthentication />
<IISExpressUseClassicPipelineMode />
<UseGlobalApplicationHostFile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
......@@ -114,6 +126,25 @@
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\Grpc.Core.1.12.0\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Grpc.Core.1.12.0\build\net45\Grpc.Core.targets'))" />
</Target>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v15.0\WebApplications\Microsoft.WebApplication.targets" />
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{349C5851-65DF-11DA-9384-00065B846F21}">
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>0</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:6768/</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
......
This diff is collapsed.
......@@ -53,5 +53,7 @@ namespace SkyWalking.Components
public static readonly IComponent InMemoryDatabase = new OfficialComponent(3014, "InMemoryDatabase");
public static readonly IComponent AspNet = new OfficialComponent(3015, "AspNet");
public static readonly IComponent MySqlData = new OfficialComponent(3016, "MySql.Data");
}
}
/*
* Licensed to the OpenSkywalking 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 System.Linq;
using MySql.Data.MySqlClient;
using SkyWalking.Components;
using SkyWalking.Context;
using SkyWalking.Context.Tag;
using SkyWalking.Context.Trace;
namespace SkyWalking.Diagnostics.MySqlData
{
public class MySqlDataDiagnosticProcessor : DefaultTraceListener, ITracingDiagnosticProcessor
{
private Dictionary<long, MySqlConnectionStringBuilder> _dbConn =
new Dictionary<long, MySqlConnectionStringBuilder>();
public MySqlDataDiagnosticProcessor()
{
MySqlTrace.Listeners.Clear();
MySqlTrace.Listeners.Add(this);
MySqlTrace.Switch.Level = SourceLevels.Information;
MySqlTrace.QueryAnalysisEnabled = true;
}
private static string ResolveOperationName(MySqlDataTraceCommand sqlCommand)
{
var commandType = sqlCommand.SqlText?.Split(' ');
return $"{MySqlDataDiagnosticStrings.MySqlDataPrefix}{commandType?.FirstOrDefault()}";
}
public string ListenerName { get; } = MySqlDataDiagnosticStrings.DiagnosticListenerName;
public void BeforeExecuteCommand(MySqlDataTraceCommand sqlCommand)
{
var peer = sqlCommand.DbServer;
var span = ContextManager.CreateExitSpan(ResolveOperationName(sqlCommand), peer);
span.SetLayer(SpanLayer.DB);
span.SetComponent(ComponentsDefine.MySqlData);
Tags.DbType.Set(span, "MySql");
Tags.DbInstance.Set(span, sqlCommand.Database);
Tags.DbStatement.Set(span, sqlCommand.SqlText);
}
public void AfterExecuteCommand()
{
ContextManager.StopSpan();
}
public void ErrorExecuteCommand(Exception ex)
{
var span = ContextManager.ActiveSpan;
span?.ErrorOccurred();
span?.Log(ex);
span?.Log(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), new Dictionary<string, object>()
{
{ "event", "error"},
{ "error.kind", "MySqlException"},
{ "message", ex.Message}
});
}
/// <summary>
///
/// </summary>
/// <param name="eventCache"></param>
/// <param name="source"></param>
/// <param name="eventType"></param>
/// <param name="id"></param>
/// <param name="format"></param>
/// <param name="args"></param>
public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id,
string format, params object[] args)
{
switch ((MySqlTraceEventType)id)
{
case MySqlTraceEventType.ConnectionOpened:
var driverId = (long)args[0];
var connStr = args[1].ToString();
_dbConn[driverId] = new MySqlConnectionStringBuilder(connStr);
break;
case MySqlTraceEventType.ConnectionClosed:
//TODO
break;
case MySqlTraceEventType.QueryOpened:
BeforeExecuteCommand(GetCommand(args[0], args[2]));
break;
case MySqlTraceEventType.ResultOpened:
//TODO
break;
case MySqlTraceEventType.ResultClosed:
//TODO
break;
case MySqlTraceEventType.QueryClosed:
AfterExecuteCommand();
break;
case MySqlTraceEventType.StatementPrepared:
//TODO
break;
case MySqlTraceEventType.StatementExecuted:
//TODO
break;
case MySqlTraceEventType.StatementClosed:
//TODO
break;
case MySqlTraceEventType.NonQuery:
//TODO
break;
case MySqlTraceEventType.UsageAdvisorWarning:
//TODO
break;
case MySqlTraceEventType.Warning:
//TODO
break;
case MySqlTraceEventType.Error:
ErrorExecuteCommand(GetMySqlErrorException(args[1], args[2]));
break;
case MySqlTraceEventType.QueryNormalized:
//TODO
break;
}
}
private MySqlDataTraceCommand GetCommand(object driverIdObj, object cmd)
{
var command = new MySqlDataTraceCommand();
if (_dbConn.TryGetValue((long)driverIdObj, out var database))
{
command.Database = database.Database;
command.DbServer = database.Server;
}
command.SqlText = (cmd == null ? "" : cmd.ToString());
return command;
}
private Exception GetMySqlErrorException(object errorCode, object errorMsg)
{
//TODO handle errorcode
return new Exception($"{errorMsg}");
}
}
}
/*
* Licensed to the OpenSkywalking 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 SkyWalking.Diagnostics.MySqlData
{
internal static class MySqlDataDiagnosticStrings
{
public const string DiagnosticListenerName = "MySqlDiagnosticListener";
public const string MySqlDataPrefix = "mySqlData ";
}
}
\ No newline at end of file
/*
* Licensed to the OpenSkywalking 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.Text;
namespace SkyWalking.Diagnostics.MySqlData
{
public class MySqlDataTraceCommand
{
public string Database { get; set; }
public string SqlText { get; set; }
public string DbServer { get; set; }
}
}
\ No newline at end of file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MySql.Data" Version="6.10.7" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SkyWalking.Abstractions\SkyWalking.Abstractions.csproj" />
<ProjectReference Include="..\SkyWalking.Core\SkyWalking.Core.csproj" />
<ProjectReference Include="..\SkyWalking.Utilities.DependencyInjection\SkyWalking.Utilities.DependencyInjection.csproj" />
</ItemGroup>
</Project>
/*
* Licensed to the OpenSkywalking 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.Text;
using Microsoft.Extensions.DependencyInjection;
using SkyWalking.Utilities.DependencyInjection;
namespace SkyWalking.Diagnostics.MySqlData
{
public static class SkyWalkingBuilderExtensions
{
public static SkyWalkingExtensions AddMySqlData(this SkyWalkingExtensions builder)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Services.AddSingleton<ITracingDiagnosticProcessor, MySqlDataDiagnosticProcessor>();
return builder;
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment