From a3f6f4b70c423608524ef5d23ad11e9355ff5a26 Mon Sep 17 00:00:00 2001 From: startewho Date: Wed, 19 Jan 2022 10:30:48 +0800 Subject: [PATCH 1/3] Add FreeSql Diagnostics Copy from FreeSql's github --- skyapm-dotnet.sln | 7 + .../FreeSqlTracingDiagnosticProcessor.cs | 161 ++++++++++++++++++ .../SkyApm.Diagnostics.FreeSql.csproj | 22 +++ .../SkyWalkingBuilderExtensions.cs | 84 +++++++++ 4 files changed, 274 insertions(+) create mode 100644 src/SkyApm.Diagnostics.FreeSql/FreeSqlTracingDiagnosticProcessor.cs create mode 100644 src/SkyApm.Diagnostics.FreeSql/SkyApm.Diagnostics.FreeSql.csproj create mode 100644 src/SkyApm.Diagnostics.FreeSql/SkyWalkingBuilderExtensions.cs diff --git a/skyapm-dotnet.sln b/skyapm-dotnet.sln index 94a51a2a..618e3d05 100644 --- a/skyapm-dotnet.sln +++ b/skyapm-dotnet.sln @@ -105,6 +105,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.Sample.GenericHost", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.Diagnostics.MongoDB", "src\SkyApm.Diagnostics.MongoDB\SkyApm.Diagnostics.MongoDB.csproj", "{8D3C5573-C282-45F5-A7F4-2E323F322CB7}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.Diagnostics.FreeSql", "src\SkyApm.Diagnostics.FreeSql\SkyApm.Diagnostics.FreeSql.csproj", "{82580A47-9DBC-43E8-B581-0C35147B4FAD}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -231,6 +233,10 @@ Global {8D3C5573-C282-45F5-A7F4-2E323F322CB7}.Debug|Any CPU.Build.0 = Debug|Any CPU {8D3C5573-C282-45F5-A7F4-2E323F322CB7}.Release|Any CPU.ActiveCfg = Release|Any CPU {8D3C5573-C282-45F5-A7F4-2E323F322CB7}.Release|Any CPU.Build.0 = Release|Any CPU + {82580A47-9DBC-43E8-B581-0C35147B4FAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {82580A47-9DBC-43E8-B581-0C35147B4FAD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {82580A47-9DBC-43E8-B581-0C35147B4FAD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {82580A47-9DBC-43E8-B581-0C35147B4FAD}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -275,6 +281,7 @@ Global {D96279FD-0020-427B-85C5-DC1C2336AA25} = {EF6194B2-9ACB-49B9-8049-DD6AFAEB0399} {71F61C77-E04F-464D-A0B7-E109CE7E30D7} = {844CEACD-4C85-4B15-9E2B-892B01FDA4BB} {8D3C5573-C282-45F5-A7F4-2E323F322CB7} = {B5E677CF-2920-4B0A-A056-E73F6B2CF2BC} + {82580A47-9DBC-43E8-B581-0C35147B4FAD} = {B5E677CF-2920-4B0A-A056-E73F6B2CF2BC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {94C0DA2C-CCCB-4314-93A2-9809B5DD0583} diff --git a/src/SkyApm.Diagnostics.FreeSql/FreeSqlTracingDiagnosticProcessor.cs b/src/SkyApm.Diagnostics.FreeSql/FreeSqlTracingDiagnosticProcessor.cs new file mode 100644 index 00000000..ceae1396 --- /dev/null +++ b/src/SkyApm.Diagnostics.FreeSql/FreeSqlTracingDiagnosticProcessor.cs @@ -0,0 +1,161 @@ +/* + * 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 FreeSql; +using FreeSql.Aop; +using SkyApm.Config; +using SkyApm.Tracing; +using SkyApm.Tracing.Segments; +using System; +using System.Linq; + +namespace SkyApm.Diagnostics.FreeSql +{ + + + /// + /// FreeSqlTracingDiagnosticProcessor + /// + public class FreeSqlTracingDiagnosticProcessor : ITracingDiagnosticProcessor + { + + #region Const + + public const string ComponentName = "FreeSql"; + + public const string FreeSql_CurdBefore = "FreeSql.CurdBefore"; + public const string FreeSql_CurdAfter = "FreeSql.CurdAfter"; + public const string FreeSql_SyncStructureBefore = "FreeSql.SyncStructureBefore"; + public const string FreeSql_SyncStructureAfter = "FreeSql.SyncStructureAfter"; + public const string FreeSql_CommandBefore = "FreeSql.CommandBefore"; + public const string FreeSql_CommandAfter = "FreeSql.CommandAfter"; + public const string FreeSql_TraceBefore = "FreeSql.TraceBefore"; + public const string FreeSql_TraceAfter = "FreeSql.TraceAfter"; + + #endregion + + + public string ListenerName => "FreeSqlDiagnosticListener"; + + private readonly ITracingContext _tracingContext; + private readonly ILocalSegmentContextAccessor _localSegmentContextAccessor; + private readonly TracingConfig _tracingConfig; + public FreeSqlTracingDiagnosticProcessor(ITracingContext tracingContext, + ILocalSegmentContextAccessor localSegmentContextAccessor, IConfigAccessor configAccessor) + { + _tracingContext = tracingContext; + _localSegmentContextAccessor = localSegmentContextAccessor; + _tracingConfig = configAccessor.Get(); + } + + private SegmentContext CreateFreeSqlLocalSegmentContext(string operation) + { + var context = _tracingContext.CreateLocalSegmentContext(operation); + context.Span.SpanLayer = SpanLayer.DB; + context.Span.Component = ComponentName; + context.Span.AddTag(Common.Tags.DB_TYPE, "Sql"); + return context; + } + + #region Curd + [DiagnosticName(FreeSql_CurdBefore)] + public void CurdBefore([Object] CurdBeforeEventArgs eventData) + { + var context = CreateFreeSqlLocalSegmentContext(eventData.CurdType.ToString()); + context.Span.AddTag(Common.Tags.DB_STATEMENT, eventData.Sql); + } + [DiagnosticName(FreeSql_CurdAfter)] + public void CurdAfter([Object] CurdAfterEventArgs eventData) + { + var context = _localSegmentContextAccessor.Context; + if (context != null) + { + if (eventData?.Exception != null) + context.Span.ErrorOccurred(eventData.Exception, _tracingConfig); + _tracingContext.Release(context); + } + } + #endregion + + #region SyncStructure + [DiagnosticName(FreeSql_SyncStructureBefore)] + public void SyncStructureBefore([Object] SyncStructureBeforeEventArgs eventData) + { + var context = CreateFreeSqlLocalSegmentContext("SyncStructure"); + context.Span.AddTag(Common.Tags.DB_STATEMENT, string.Join(", ", eventData.EntityTypes.Select(a => a.Name))); + } + [DiagnosticName(FreeSql_SyncStructureAfter)] + public void SyncStructureAfter([Object] SyncStructureAfterEventArgs eventData) + { + var context = _localSegmentContextAccessor.Context; + if (context != null) + { + if (string.IsNullOrEmpty(eventData.Sql) == false) + context.Span.AddTag(Common.Tags.DB_STATEMENT, eventData.Sql); + if (eventData?.Exception != null) + context.Span.ErrorOccurred(eventData.Exception, _tracingConfig); + _tracingContext.Release(context); + } + } + #endregion + + #region Command + [DiagnosticName(FreeSql_CommandBefore)] + public void CommandBefore([Object] CommandBeforeEventArgs eventData) + { + var context = CreateFreeSqlLocalSegmentContext("Command"); + context.Span.AddTag(Common.Tags.DB_STATEMENT, eventData.Command.CommandText); + } + [DiagnosticName(FreeSql_CommandAfter)] + public void CommandAfter([Object] CommandAfterEventArgs eventData) + { + var context = _localSegmentContextAccessor.Context; + if (context != null) + { + if (string.IsNullOrEmpty(eventData.Log) == false) + context.Span.AddTag(Common.Tags.DB_STATEMENT, eventData.Log); + if (eventData?.Exception != null) + context.Span.ErrorOccurred(eventData.Exception, _tracingConfig); + _tracingContext.Release(context); + } + } + #endregion + + #region Trace + [DiagnosticName(FreeSql_TraceBefore)] + public void TraceBeforeUnitOfWork([Object] TraceBeforeEventArgs eventData) + { + var context = CreateFreeSqlLocalSegmentContext(eventData.Operation); + + } + [DiagnosticName(FreeSql_TraceAfter)] + public void TraceAfterUnitOfWork([Object] TraceAfterEventArgs eventData) + { + var context = _localSegmentContextAccessor.Context; + if (context != null) + { + if (string.IsNullOrEmpty(eventData.Remark) == false) + context.Span.AddTag(Common.Tags.DB_STATEMENT, eventData.Remark); + if (eventData?.Exception != null) + context.Span.ErrorOccurred(eventData.Exception, _tracingConfig); + _tracingContext.Release(context); + } + } + #endregion + } +} diff --git a/src/SkyApm.Diagnostics.FreeSql/SkyApm.Diagnostics.FreeSql.csproj b/src/SkyApm.Diagnostics.FreeSql/SkyApm.Diagnostics.FreeSql.csproj new file mode 100644 index 00000000..19c0c9f8 --- /dev/null +++ b/src/SkyApm.Diagnostics.FreeSql/SkyApm.Diagnostics.FreeSql.csproj @@ -0,0 +1,22 @@ + + + + + netcoreapp3.1;net5.0;net6.0 + $(PackagePrefix).Diagnostics.FreeSql + $(PackagePrefix).Diagnostics.SmartSql + $(PackagePrefix).Diagnostics.FreeSql + SkyWalking;APM;Diagnostics;FreeSql + SkyApm.Diagnostics.FreeSql notifies of FreeSql requests. + SkyApm.Diagnostics.FreeSql + + + + + + + + + + + diff --git a/src/SkyApm.Diagnostics.FreeSql/SkyWalkingBuilderExtensions.cs b/src/SkyApm.Diagnostics.FreeSql/SkyWalkingBuilderExtensions.cs new file mode 100644 index 00000000..5a165e64 --- /dev/null +++ b/src/SkyApm.Diagnostics.FreeSql/SkyWalkingBuilderExtensions.cs @@ -0,0 +1,84 @@ +/* + * 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 FreeSql.Aop; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Diagnostics; + +namespace SkyApm.Diagnostics.FreeSql +{ + + public static class SkyWalkingBuilderExtensions + { + public static readonly DiagnosticListener dl = new DiagnosticListener("FreeSqlDiagnosticListener"); + + /// + /// Use SkyWalking's FreeSql Diagnostic + /// + /// + /// + public static void AddSkyApmFreeSql(this IServiceCollection services, IFreeSql fsql) + { + services.AddSingleton(); + + fsql.Aop.CurdBefore += new EventHandler((s, e) => + { + + dl.Write(FreeSqlTracingDiagnosticProcessor.FreeSql_CurdBefore, e); + }); + fsql.Aop.CurdAfter += new EventHandler((s, e) => + { + dl.Write(FreeSqlTracingDiagnosticProcessor.FreeSql_CurdAfter, e); + }); + + fsql.Aop.SyncStructureBefore += new EventHandler((s, e) => + { + + dl.Write(FreeSqlTracingDiagnosticProcessor.FreeSql_SyncStructureBefore, e); + }); + fsql.Aop.SyncStructureAfter += new EventHandler((s, e) => + { + dl.Write(FreeSqlTracingDiagnosticProcessor.FreeSql_SyncStructureAfter, e); + }); + + fsql.Aop.CommandBefore += new EventHandler((s, e) => + { + + dl.Write(FreeSqlTracingDiagnosticProcessor.FreeSql_CommandBefore, e); + }); + fsql.Aop.CommandAfter += new EventHandler((s, e) => + { + + dl.Write(FreeSqlTracingDiagnosticProcessor.FreeSql_CommandAfter, e); + }); + + fsql.Aop.TraceBefore += new EventHandler((s, e) => + { + + + dl.Write(FreeSqlTracingDiagnosticProcessor.FreeSql_TraceBefore, e); + }); + fsql.Aop.TraceAfter += new EventHandler((s, e) => + { + + dl.Write(FreeSqlTracingDiagnosticProcessor.FreeSql_TraceAfter, e); + }); + } + } +} From c2744c50df507129af17e693aad958278c587c43 Mon Sep 17 00:00:00 2001 From: startewho Date: Wed, 19 Jan 2022 15:21:24 +0800 Subject: [PATCH 2/3] Add FreeSql Sample --- sample/SkyApm.Sample.Backend/Program.cs | 52 ++++++------ .../Controllers/SongController.cs | 82 +++++++++++++++++++ sample/SkyApm.Sample.FreeSql/Entitys/Song.cs | 12 +++ sample/SkyApm.Sample.FreeSql/PagingInfo.cs | 57 +++++++++++++ sample/SkyApm.Sample.FreeSql/Program.cs | 22 +++++ .../Properties/launchSettings.json | 27 ++++++ .../SkyApm.Sample.FreeSqlSqlite.csproj | 29 +++++++ sample/SkyApm.Sample.FreeSql/Startup.cs | 78 ++++++++++++++++++ .../appsettings.Development.json | 10 +++ sample/SkyApm.Sample.FreeSql/appsettings.json | 8 ++ sample/SkyApm.Sample.FreeSql/skyapm.json | 30 +++++++ skyapm-dotnet.sln | 7 ++ src/SkyApm.Abstractions/Common/Components.cs | 2 + .../FreeSqlTracingDiagnosticProcessor.cs | 2 +- .../SkyWalkingBuilderExtensions.cs | 24 ++++-- 15 files changed, 408 insertions(+), 34 deletions(-) create mode 100644 sample/SkyApm.Sample.FreeSql/Controllers/SongController.cs create mode 100644 sample/SkyApm.Sample.FreeSql/Entitys/Song.cs create mode 100644 sample/SkyApm.Sample.FreeSql/PagingInfo.cs create mode 100644 sample/SkyApm.Sample.FreeSql/Program.cs create mode 100644 sample/SkyApm.Sample.FreeSql/Properties/launchSettings.json create mode 100644 sample/SkyApm.Sample.FreeSql/SkyApm.Sample.FreeSqlSqlite.csproj create mode 100644 sample/SkyApm.Sample.FreeSql/Startup.cs create mode 100644 sample/SkyApm.Sample.FreeSql/appsettings.Development.json create mode 100644 sample/SkyApm.Sample.FreeSql/appsettings.json create mode 100644 sample/SkyApm.Sample.FreeSql/skyapm.json diff --git a/sample/SkyApm.Sample.Backend/Program.cs b/sample/SkyApm.Sample.Backend/Program.cs index 2a025085..927e60ef 100644 --- a/sample/SkyApm.Sample.Backend/Program.cs +++ b/sample/SkyApm.Sample.Backend/Program.cs @@ -1,31 +1,31 @@ -using Microsoft.AspNetCore; -using Microsoft.Extensions.Hosting; -using Microsoft.AspNetCore.Hosting; - -namespace SkyApm.Sample.Backend -{ - public class Program - { - public static void Main(string[] args) - { - BuildHost(args).Run(); +using Microsoft.AspNetCore; +using Microsoft.Extensions.Hosting; +using Microsoft.AspNetCore.Hosting; + +namespace SkyApm.Sample.Backend +{ + public class Program + { + public static void Main(string[] args) + { + BuildHost(args).Run(); } -#if NETCOREAPP2_1 +#if NETCOREAPP2_1 + + public static IWebHost BuildHost(string[] args) => + WebHost.CreateDefaultBuilder(args) + .Build(); + +#else - public static IWebHost BuildHost(string[] args) => - WebHost.CreateDefaultBuilder(args) - .Build(); + public static IHost BuildHost(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(builder => + { + builder.UseStartup(); + }).Build(); -#else - - public static IHost BuildHost(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(builder => - { - builder.UseStartup(); - }).Build(); - -#endif - } +#endif + } } \ No newline at end of file diff --git a/sample/SkyApm.Sample.FreeSql/Controllers/SongController.cs b/sample/SkyApm.Sample.FreeSql/Controllers/SongController.cs new file mode 100644 index 00000000..761a5ebe --- /dev/null +++ b/sample/SkyApm.Sample.FreeSql/Controllers/SongController.cs @@ -0,0 +1,82 @@ +using Microsoft.AspNetCore.Mvc; +using SkyApm.Sample.FreeSqlSqlite.Entitys; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace SkyApm.Sample.FreeSqlSqlite.Controllers +{ + + + [Route("api/[controller]")] + public class SongsController : Controller + { + + IFreeSql _fsql; + + public SongsController(IFreeSql fsql) + { + _fsql = fsql; + } + + [HttpGet] + public Task> GetItems([FromQuery] string key, [FromQuery] int page = 1, [FromQuery] int limit = 20) + { + return _fsql.Select().WhereIf(!string.IsNullOrEmpty(key), a => a.Title.Contains(key)).Page(page, limit).ToListAsync(); + } + + /// + /// curl -X GET "http://localhost:5000/restapi/Songs/GetPagingItems?key=FreeSql&PageNumber=2&PageSize=10" -H "accept: text/plain" + /// + /// + /// + /// + [HttpGet("GetPagingItems")] + public Task> GetPagingItems([FromQuery] string key, [FromQuery] PagingInfo pagingInfo) + { + return _fsql.Select().WhereIf(!string.IsNullOrEmpty(key), a => a.Title.Contains(key)).Page(pagingInfo).ToListAsync(); + } + + [HttpGet("{id}")] + public async Task GetItem([FromRoute] int id) + { + var s= await _fsql.Select().Where(a => a.Id == id).ToOneAsync(); + return s; + } + + public class ModelSong + { + public string title { get; set; } + } + + [HttpPost, ProducesResponseType(201)] + async public Task Create([FromBody] ModelSong model) + { + var ret = await _fsql.Insert().AppendData(new Song { Title = model.title }).ExecuteInsertedAsync(); + return ret.FirstOrDefault(); + } + + [HttpPut("{id}")] + async public Task Update([FromRoute] int id, [FromBody] ModelSong model) + { + var ret = await _fsql.Update().SetSource(new Song { Id = id, Title = model.title }).ExecuteUpdatedAsync(); + return ret.FirstOrDefault(); + } + + [HttpPatch("{id}")] + async public Task UpdateDiy([FromRoute] int id, [FromForm] string title) + { + var up = _fsql.Update().Where(a => a.Id == id); + if (!string.IsNullOrEmpty(title)) up.Set(a => a.Title, title); + var ret = await up.ExecuteUpdatedAsync(); + return ret.FirstOrDefault(); + } + + [HttpDelete("{id}"), ProducesResponseType(204)] + async public Task Delete([FromRoute] int id) + { + var ret = await _fsql.Delete().Where(a => a.Id == id).ExecuteDeletedAsync(); + return ret.FirstOrDefault(); + } + } +} diff --git a/sample/SkyApm.Sample.FreeSql/Entitys/Song.cs b/sample/SkyApm.Sample.FreeSql/Entitys/Song.cs new file mode 100644 index 00000000..3b948dc4 --- /dev/null +++ b/sample/SkyApm.Sample.FreeSql/Entitys/Song.cs @@ -0,0 +1,12 @@ +using FreeSql.DataAnnotations; + +namespace SkyApm.Sample.FreeSqlSqlite.Entitys +{ + public class Song + { + + [Column(IsIdentity = true)] + public int Id { get; set; } + public string Title { get; set; } + } +} diff --git a/sample/SkyApm.Sample.FreeSql/PagingInfo.cs b/sample/SkyApm.Sample.FreeSql/PagingInfo.cs new file mode 100644 index 00000000..bc2222a7 --- /dev/null +++ b/sample/SkyApm.Sample.FreeSql/PagingInfo.cs @@ -0,0 +1,57 @@ +using FreeSql.Internal.Model; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace SkyApm.Sample.FreeSqlSqlite +{ + public class PagingInfo : BasePagingInfo + { + /// + /// 无参构造函数 + /// + public PagingInfo() + { + } + /// + /// 当前为第1页,每页大小的构造函数 + /// + /// + public PagingInfo(int pageSize) + { + PageNumber = 1; + PageSize = pageSize; + } + /// + /// 带当前页和每页大小的构造函数 + /// + /// + /// + public PagingInfo(int pageNumber, int pageSize) + { + PageNumber = pageNumber; + PageSize = pageSize; + } + /// + /// 当前有多少页【只读】 + /// + public long PageCount => PageSize == 0 ? 0 : (Count + PageSize - 1) / PageSize; + /// + /// 是否有上一页【只读】 + /// + public bool HasPrevious => PageNumber > 1 && PageNumber <= PageCount; + /// + /// 是否有下一页【只读】 + /// + public bool HasNext => PageNumber < PageCount; + /// + /// 是否在第一页【只读】 + /// + public bool IsFrist => PageNumber == 1; + /// + /// 是否在最后一页【只读】 + /// + public bool IsLast => PageNumber == PageCount; + } +} \ No newline at end of file diff --git a/sample/SkyApm.Sample.FreeSql/Program.cs b/sample/SkyApm.Sample.FreeSql/Program.cs new file mode 100644 index 00000000..32a18294 --- /dev/null +++ b/sample/SkyApm.Sample.FreeSql/Program.cs @@ -0,0 +1,22 @@ +using Microsoft.AspNetCore; +using Microsoft.Extensions.Hosting; +using Microsoft.AspNetCore.Hosting; + +namespace SkyApm.Sample.FreeSqlSqlite +{ + public class Program + { + public static void Main(string[] args) + { + BuildHost(args).Run(); + } + + public static IHost BuildHost(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(builder => + { + builder.UseStartup(); + }).Build(); + + } +} \ No newline at end of file diff --git a/sample/SkyApm.Sample.FreeSql/Properties/launchSettings.json b/sample/SkyApm.Sample.FreeSql/Properties/launchSettings.json new file mode 100644 index 00000000..1210c804 --- /dev/null +++ b/sample/SkyApm.Sample.FreeSql/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:5000/", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "SkyApm.Sample.FreeSqlSqlite": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:5000/" + } + } +} \ No newline at end of file diff --git a/sample/SkyApm.Sample.FreeSql/SkyApm.Sample.FreeSqlSqlite.csproj b/sample/SkyApm.Sample.FreeSql/SkyApm.Sample.FreeSqlSqlite.csproj new file mode 100644 index 00000000..ffbf960c --- /dev/null +++ b/sample/SkyApm.Sample.FreeSql/SkyApm.Sample.FreeSqlSqlite.csproj @@ -0,0 +1,29 @@ + + + netcoreapp3.1;net5.0;net6.0 + + + + + + + + + + + + + + PreserveNewest + Always + + + PreserveNewest + Always + + + PreserveNewest + Always + + + \ No newline at end of file diff --git a/sample/SkyApm.Sample.FreeSql/Startup.cs b/sample/SkyApm.Sample.FreeSql/Startup.cs new file mode 100644 index 00000000..b33562da --- /dev/null +++ b/sample/SkyApm.Sample.FreeSql/Startup.cs @@ -0,0 +1,78 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using FreeSql; +using SkyApm.Diagnostics.FreeSql; +using SkyApm.Sample.FreeSqlSqlite.Entitys; +using System; +using System.Collections.Generic; +using SkyApm.Utilities.DependencyInjection; + +namespace SkyApm.Sample.FreeSqlSqlite +{ + public class Startup + { + private readonly string[] Titles = new string[] { "GetAway", "Candy", "DreamHeaven"}; + public Startup(IConfiguration configuration) + { + Configuration = configuration; + + Fsql = new FreeSql.FreeSqlBuilder() + .UseConnectionString(FreeSql.DataType.Sqlite, @"DataSource=:memory:;Pooling=true;Max Pool Size=10") + .UseAutoSyncStructure(true) + .Build(); + InitData(); + Fsql.Aop.CurdAfter += (s, e) => + { + if (e.ElapsedMilliseconds > 200) + { + //记录日志 + //发送短信给负责人 + } + }; + + + } + + public IConfiguration Configuration { get; } + public IFreeSql Fsql { get; } + + public void ConfigureServices(IServiceCollection services) + { + services.AddSingleton(Fsql); + services.AddControllers(); + services.AddSkyApmExtensions(); + services.AddSkyAPM((e) => + { + e.AddFreeSql(Fsql); + }); + } + + public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) + { + + app.UseHttpMethodOverride(new HttpMethodOverrideOptions { FormFieldName = "X-Http-Method-Override" }); + app.UseDeveloperExceptionPage(); + app.UseRouting(); + app.UseEndpoints(a => a.MapControllers()); + } + + + public void InitData() + { + const int count= 10000; + var rand = new Random(); + var songs = new List(count); + for (int i = 0; i < count; i++) + { + songs.Add(new Song() { Id = i + 1, Title = Titles[rand.Next(Titles.Length - 1)] }); + + } + Fsql.Insert(songs).ExecuteIdentity(); + + + } + } + +} \ No newline at end of file diff --git a/sample/SkyApm.Sample.FreeSql/appsettings.Development.json b/sample/SkyApm.Sample.FreeSql/appsettings.Development.json new file mode 100644 index 00000000..b75c0b04 --- /dev/null +++ b/sample/SkyApm.Sample.FreeSql/appsettings.Development.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "IncludeScopes": false, + "Debug": { + "LogLevel": { + "Default": "Warning" + } + } + } +} \ No newline at end of file diff --git a/sample/SkyApm.Sample.FreeSql/appsettings.json b/sample/SkyApm.Sample.FreeSql/appsettings.json new file mode 100644 index 00000000..d713e815 --- /dev/null +++ b/sample/SkyApm.Sample.FreeSql/appsettings.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Warning" + } + }, + "AllowedHosts": "*" +} \ No newline at end of file diff --git a/sample/SkyApm.Sample.FreeSql/skyapm.json b/sample/SkyApm.Sample.FreeSql/skyapm.json new file mode 100644 index 00000000..163fb019 --- /dev/null +++ b/sample/SkyApm.Sample.FreeSql/skyapm.json @@ -0,0 +1,30 @@ +{ + "SkyWalking": { + "ServiceName": "asp-net-core-backend", + "Namespace": "", + "HeaderVersions": [ + "sw8" + ], + "Sampling": { + "SamplePer3Secs": -1, + "Percentage": -1.0, + "LogSqlParameterValue": false + }, + "Logging": { + "Level": "Information", + "FilePath": "logs/skyapm-{Date}.log" + }, + "Transport": { + "Interval": 3000, + "ProtocolVersion": "v8", + "QueueSize": 30000, + "BatchSize": 3000, + "gRPC": { + "Servers": "10.32.213.187:11800", + "Timeout": 100000, + "ConnectTimeout": 100000, + "ReportTimeout": 600000 + } + } + } +} \ No newline at end of file diff --git a/skyapm-dotnet.sln b/skyapm-dotnet.sln index 618e3d05..f0cac3b8 100644 --- a/skyapm-dotnet.sln +++ b/skyapm-dotnet.sln @@ -107,6 +107,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.Diagnostics.MongoDB" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.Diagnostics.FreeSql", "src\SkyApm.Diagnostics.FreeSql\SkyApm.Diagnostics.FreeSql.csproj", "{82580A47-9DBC-43E8-B581-0C35147B4FAD}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.Sample.FreeSqlSqlite", "sample\SkyApm.Sample.FreeSql\SkyApm.Sample.FreeSqlSqlite.csproj", "{B1EF3295-4BF0-489F-8063-C9E3DAE20AA9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -237,6 +239,10 @@ Global {82580A47-9DBC-43E8-B581-0C35147B4FAD}.Debug|Any CPU.Build.0 = Debug|Any CPU {82580A47-9DBC-43E8-B581-0C35147B4FAD}.Release|Any CPU.ActiveCfg = Release|Any CPU {82580A47-9DBC-43E8-B581-0C35147B4FAD}.Release|Any CPU.Build.0 = Release|Any CPU + {B1EF3295-4BF0-489F-8063-C9E3DAE20AA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B1EF3295-4BF0-489F-8063-C9E3DAE20AA9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B1EF3295-4BF0-489F-8063-C9E3DAE20AA9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B1EF3295-4BF0-489F-8063-C9E3DAE20AA9}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -282,6 +288,7 @@ Global {71F61C77-E04F-464D-A0B7-E109CE7E30D7} = {844CEACD-4C85-4B15-9E2B-892B01FDA4BB} {8D3C5573-C282-45F5-A7F4-2E323F322CB7} = {B5E677CF-2920-4B0A-A056-E73F6B2CF2BC} {82580A47-9DBC-43E8-B581-0C35147B4FAD} = {B5E677CF-2920-4B0A-A056-E73F6B2CF2BC} + {B1EF3295-4BF0-489F-8063-C9E3DAE20AA9} = {844CEACD-4C85-4B15-9E2B-892B01FDA4BB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {94C0DA2C-CCCB-4314-93A2-9809B5DD0583} diff --git a/src/SkyApm.Abstractions/Common/Components.cs b/src/SkyApm.Abstractions/Common/Components.cs index 376d9f4b..10fd9fe0 100644 --- a/src/SkyApm.Abstractions/Common/Components.cs +++ b/src/SkyApm.Abstractions/Common/Components.cs @@ -40,6 +40,8 @@ public static class Components public static readonly StringOrIntValue SMART_SQL = new StringOrIntValue(3016, "SmartSql"); + public static readonly StringOrIntValue Free_SQL = new StringOrIntValue(3017, "FreeSql"); + public static readonly StringOrIntValue GRPC = new StringOrIntValue(23, "GRPC"); public static readonly StringOrIntValue MongoDBCLIENT = new StringOrIntValue(42, "MongoDB.Driver"); diff --git a/src/SkyApm.Diagnostics.FreeSql/FreeSqlTracingDiagnosticProcessor.cs b/src/SkyApm.Diagnostics.FreeSql/FreeSqlTracingDiagnosticProcessor.cs index ceae1396..5817be0c 100644 --- a/src/SkyApm.Diagnostics.FreeSql/FreeSqlTracingDiagnosticProcessor.cs +++ b/src/SkyApm.Diagnostics.FreeSql/FreeSqlTracingDiagnosticProcessor.cs @@ -67,7 +67,7 @@ private SegmentContext CreateFreeSqlLocalSegmentContext(string operation) { var context = _tracingContext.CreateLocalSegmentContext(operation); context.Span.SpanLayer = SpanLayer.DB; - context.Span.Component = ComponentName; + context.Span.Component = Common.Components.Free_SQL; context.Span.AddTag(Common.Tags.DB_TYPE, "Sql"); return context; } diff --git a/src/SkyApm.Diagnostics.FreeSql/SkyWalkingBuilderExtensions.cs b/src/SkyApm.Diagnostics.FreeSql/SkyWalkingBuilderExtensions.cs index 5a165e64..53a31b3a 100644 --- a/src/SkyApm.Diagnostics.FreeSql/SkyWalkingBuilderExtensions.cs +++ b/src/SkyApm.Diagnostics.FreeSql/SkyWalkingBuilderExtensions.cs @@ -18,6 +18,7 @@ using FreeSql.Aop; using Microsoft.Extensions.DependencyInjection; +using SkyApm.Utilities.DependencyInjection; using System; using System.Diagnostics; @@ -28,15 +29,23 @@ public static class SkyWalkingBuilderExtensions { public static readonly DiagnosticListener dl = new DiagnosticListener("FreeSqlDiagnosticListener"); - /// - /// Use SkyWalking's FreeSql Diagnostic - /// - /// - /// - public static void AddSkyApmFreeSql(this IServiceCollection services, IFreeSql fsql) + public static SkyApmExtensions AddFreeSql(this SkyApmExtensions extensions, IFreeSql fsql) { - services.AddSingleton(); + if (extensions == null) + { + throw new ArgumentNullException(nameof(extensions)); + } + extensions.Services.AddSingleton(); + if (fsql != null) + { + ConfigAop(fsql); + } + return extensions; + } + + public static void ConfigAop(IFreeSql fsql) + { fsql.Aop.CurdBefore += new EventHandler((s, e) => { @@ -79,6 +88,7 @@ public static void AddSkyApmFreeSql(this IServiceCollection services, IFreeSql f dl.Write(FreeSqlTracingDiagnosticProcessor.FreeSql_TraceAfter, e); }); + } } } From 6a1e8dcfe15983410a6e5611ba15bfd5e32f2585 Mon Sep 17 00:00:00 2001 From: startewho Date: Wed, 19 Jan 2022 15:37:14 +0800 Subject: [PATCH 3/3] Update skyapm.json --- sample/SkyApm.Sample.FreeSql/skyapm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sample/SkyApm.Sample.FreeSql/skyapm.json b/sample/SkyApm.Sample.FreeSql/skyapm.json index 163fb019..3633f6c4 100644 --- a/sample/SkyApm.Sample.FreeSql/skyapm.json +++ b/sample/SkyApm.Sample.FreeSql/skyapm.json @@ -1,6 +1,6 @@ { "SkyWalking": { - "ServiceName": "asp-net-core-backend", + "ServiceName": "FreeSqlSqliteDemo", "Namespace": "", "HeaderVersions": [ "sw8"