未验证 提交 10b7aaba 编写于 作者: L Lemon 提交者: GitHub

Feature/clr metrics (#185)

* Add clr metrics report

* mark smartsql as manual plug-in

* Update CpuHelpers
上级 e6ca59fd
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.3" /> <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.3" />
...@@ -14,8 +14,7 @@ ...@@ -14,8 +14,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite"> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite">
<Version>2.1.0</Version> <Version>2.1.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.0" /> <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Update="appsettings.json"> <Content Update="appsettings.json">
......
...@@ -6,7 +6,6 @@ using Microsoft.Data.Sqlite; ...@@ -6,7 +6,6 @@ using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using SkyApm.Sample.Backend.Models; using SkyApm.Sample.Backend.Models;
using SkyApm.Sample.Backend.Sampling; using SkyApm.Sample.Backend.Sampling;
using SkyApm.Tracing; using SkyApm.Tracing;
...@@ -32,7 +31,6 @@ namespace SkyApm.Sample.Backend ...@@ -32,7 +31,6 @@ namespace SkyApm.Sample.Backend
services.AddEntityFrameworkSqlite().AddDbContext<SampleDbContext>(c => c.UseSqlite(sqliteConnection)); services.AddEntityFrameworkSqlite().AddDbContext<SampleDbContext>(c => c.UseSqlite(sqliteConnection));
services.AddSingleton<ISamplingInterceptor, CustomSamplingInterceptor>(); services.AddSingleton<ISamplingInterceptor, CustomSamplingInterceptor>();
} }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
......
...@@ -82,8 +82,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.DotNet.CLI", "src\Sk ...@@ -82,8 +82,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.DotNet.CLI", "src\Sk
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.Diagnostics.SmartSql", "src\SkyApm.Diagnostics.SmartSql\SkyApm.Diagnostics.SmartSql.csproj", "{B43160C8-C9E3-43F6-83E9-A9A45B32F022}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.Diagnostics.SmartSql", "src\SkyApm.Diagnostics.SmartSql\SkyApm.Diagnostics.SmartSql.csproj", "{B43160C8-C9E3-43F6-83E9-A9A45B32F022}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.Sample.SmartSql", "sample\SkyApm.Sample.SmartSql\SkyApm.Sample.SmartSql.csproj", "{8E2B336B-8138-4179-A754-A1D0C0471654}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.Agent.GeneralHost", "src\SkyApm.Agent.GeneralHost\SkyApm.Agent.GeneralHost.csproj", "{4C1CF0E7-4CD3-4731-9A56-E033D5216D58}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.Agent.GeneralHost", "src\SkyApm.Agent.GeneralHost\SkyApm.Agent.GeneralHost.csproj", "{4C1CF0E7-4CD3-4731-9A56-E033D5216D58}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.Sample.GeneralHost", "sample\SkyApm.Sample.GeneralHost\SkyApm.Sample.GeneralHost.csproj", "{477D705E-576B-46C8-8F1E-9A86EDAE9D86}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.Sample.GeneralHost", "sample\SkyApm.Sample.GeneralHost\SkyApm.Sample.GeneralHost.csproj", "{477D705E-576B-46C8-8F1E-9A86EDAE9D86}"
...@@ -182,10 +180,6 @@ Global ...@@ -182,10 +180,6 @@ Global
{B43160C8-C9E3-43F6-83E9-A9A45B32F022}.Debug|Any CPU.Build.0 = Debug|Any CPU {B43160C8-C9E3-43F6-83E9-A9A45B32F022}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B43160C8-C9E3-43F6-83E9-A9A45B32F022}.Release|Any CPU.ActiveCfg = Release|Any CPU {B43160C8-C9E3-43F6-83E9-A9A45B32F022}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B43160C8-C9E3-43F6-83E9-A9A45B32F022}.Release|Any CPU.Build.0 = Release|Any CPU {B43160C8-C9E3-43F6-83E9-A9A45B32F022}.Release|Any CPU.Build.0 = Release|Any CPU
{8E2B336B-8138-4179-A754-A1D0C0471654}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8E2B336B-8138-4179-A754-A1D0C0471654}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8E2B336B-8138-4179-A754-A1D0C0471654}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8E2B336B-8138-4179-A754-A1D0C0471654}.Release|Any CPU.Build.0 = Release|Any CPU
{4C1CF0E7-4CD3-4731-9A56-E033D5216D58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4C1CF0E7-4CD3-4731-9A56-E033D5216D58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4C1CF0E7-4CD3-4731-9A56-E033D5216D58}.Debug|Any CPU.Build.0 = Debug|Any CPU {4C1CF0E7-4CD3-4731-9A56-E033D5216D58}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4C1CF0E7-4CD3-4731-9A56-E033D5216D58}.Release|Any CPU.ActiveCfg = Release|Any CPU {4C1CF0E7-4CD3-4731-9A56-E033D5216D58}.Release|Any CPU.ActiveCfg = Release|Any CPU
...@@ -229,7 +223,6 @@ Global ...@@ -229,7 +223,6 @@ Global
{2F7EEC69-35F4-4D31-B52A-7465D65E9DE0} = {A4E67E09-3156-4D30-B451-F24F706E96C4} {2F7EEC69-35F4-4D31-B52A-7465D65E9DE0} = {A4E67E09-3156-4D30-B451-F24F706E96C4}
{E909EEF5-5EBF-43F3-AB4A-6B2FB56EF89B} = {1B0865AF-369E-493C-AA6F-C56D3E520A22} {E909EEF5-5EBF-43F3-AB4A-6B2FB56EF89B} = {1B0865AF-369E-493C-AA6F-C56D3E520A22}
{B43160C8-C9E3-43F6-83E9-A9A45B32F022} = {B5E677CF-2920-4B0A-A056-E73F6B2CF2BC} {B43160C8-C9E3-43F6-83E9-A9A45B32F022} = {B5E677CF-2920-4B0A-A056-E73F6B2CF2BC}
{8E2B336B-8138-4179-A754-A1D0C0471654} = {844CEACD-4C85-4B15-9E2B-892B01FDA4BB}
{4C1CF0E7-4CD3-4731-9A56-E033D5216D58} = {EF6194B2-9ACB-49B9-8049-DD6AFAEB0399} {4C1CF0E7-4CD3-4731-9A56-E033D5216D58} = {EF6194B2-9ACB-49B9-8049-DD6AFAEB0399}
{477D705E-576B-46C8-8F1E-9A86EDAE9D86} = {844CEACD-4C85-4B15-9E2B-892B01FDA4BB} {477D705E-576B-46C8-8F1E-9A86EDAE9D86} = {844CEACD-4C85-4B15-9E2B-892B01FDA4BB}
EndGlobalSection EndGlobalSection
......
/*
* 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.
*
*/
namespace SkyApm.Transport
{
public class CLRStatsRequest
{
public CPUStatsRequest CPU { get; set; }
public GCStatsRequest GC { get; set; }
public ThreadStatsRequest Thread { get; set; }
}
public class CPUStatsRequest
{
public double UsagePercent { get; set; }
}
public class GCStatsRequest
{
public long Gen0CollectCount { get; set; }
public long Gen1CollectCount { get; set; }
public long Gen2CollectCount { get; set; }
public long HeapMemory { get; set; }
}
public class ThreadStatsRequest
{
public int AvailableCompletionPortThreads { get; set; }
public int AvailableWorkerThreads { get; set; }
public int MaxCompletionPortThreads { get; set; }
public int MaxWorkerThreads { get; set; }
}
}
\ No newline at end of file
/*
* 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.Threading;
using System.Threading.Tasks;
namespace SkyApm.Transport
{
public interface ICLRStatsReporter
{
Task ReportAsync(CLRStatsRequest statsRequest,
CancellationToken cancellationToken = default(CancellationToken));
}
}
\ No newline at end of file
...@@ -61,10 +61,10 @@ namespace SkyApm.Agent.AspNetCore ...@@ -61,10 +61,10 @@ namespace SkyApm.Agent.AspNetCore
services.AddSingleton<IConfigurationFactory, ConfigurationFactory>(); services.AddSingleton<IConfigurationFactory, ConfigurationFactory>();
services.AddSingleton<IHostedService, InstrumentationHostedService>(); services.AddSingleton<IHostedService, InstrumentationHostedService>();
services.AddSingleton<IEnvironmentProvider, HostingEnvironmentProvider>(); services.AddSingleton<IEnvironmentProvider, HostingEnvironmentProvider>();
services.AddSingleton<IExecutionService, CLRStatsService>();
services.AddTracing().AddSampling().AddGrpcTransport().AddLogging(); services.AddTracing().AddSampling().AddGrpcTransport().AddLogging();
services.AddSkyApmExtensions().AddAspNetCoreHosting().AddHttpClient().AddSqlClient() services.AddSkyApmExtensions().AddAspNetCoreHosting().AddHttpClient().AddSqlClient()
.AddEntityFrameworkCore(c => c.AddPomeloMysql().AddNpgsql().AddSqlite()) .AddEntityFrameworkCore(c => c.AddPomeloMysql().AddNpgsql().AddSqlite());
.AddSmartSql();
return services; return services;
} }
...@@ -103,6 +103,7 @@ namespace SkyApm.Agent.AspNetCore ...@@ -103,6 +103,7 @@ namespace SkyApm.Agent.AspNetCore
services.AddSingleton<IPingCaller, PingCaller>(); services.AddSingleton<IPingCaller, PingCaller>();
services.AddSingleton<IServiceRegister, ServiceRegister>(); services.AddSingleton<IServiceRegister, ServiceRegister>();
services.AddSingleton<IExecutionService, ConnectService>(); services.AddSingleton<IExecutionService, ConnectService>();
services.AddSingleton<ICLRStatsReporter, CLRStatsReporter>();
return services; return services;
} }
......
/*
* 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.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace SkyApm.Common
{
internal static class CpuHelpers
{
private const int interval = 1000;
private static double _usagePercent;
private static readonly Task _task;
public static double UsagePercent => _usagePercent;
static CpuHelpers()
{
var process = Process.GetCurrentProcess();
_task = Task.Factory.StartNew(async () =>
{
var _prevCpuTime = process.TotalProcessorTime.TotalMilliseconds;
while (true)
{
var prevCpuTime = _prevCpuTime;
var currentCpuTime = process.TotalProcessorTime;
var usagePercent = (currentCpuTime.TotalMilliseconds - prevCpuTime) / interval;
Interlocked.Exchange(ref _prevCpuTime, currentCpuTime.TotalMilliseconds);
Interlocked.Exchange(ref _usagePercent, usagePercent);
await Task.Delay(1000);
}
});
}
}
}
\ No newline at end of file
/*
* 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.Threading;
namespace SkyApm.Common
{
internal static class GCHelpers
{
private static long _prevGen0CollectCount;
private static long _prevGen1CollectCount;
private static long _prevGen2CollectCount;
private static readonly int _maxGen = GC.MaxGeneration;
public static long Gen0CollectCount
{
get
{
var count = GC.CollectionCount(0);
var prevCount = _prevGen0CollectCount;
Interlocked.Exchange(ref _prevGen0CollectCount, count);
return count - prevCount;
}
}
public static long Gen1CollectCount
{
get
{
if (_maxGen < 1)
{
return 0;
}
var count = GC.CollectionCount(1);
var prevCount = _prevGen1CollectCount;
Interlocked.Exchange(ref _prevGen1CollectCount, count);
return count - prevCount;
}
}
public static long Gen2CollectCount
{
get
{
if (_maxGen < 2)
{
return 0;
}
var count = GC.CollectionCount(2);
var prevCount = _prevGen2CollectCount;
Interlocked.Exchange(ref _prevGen2CollectCount, count);
return count - prevCount;
}
}
public static long TotalMemory => GC.GetTotalMemory(false);
}
}
\ No newline at end of file
/*
* 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.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using SkyApm.Common;
using SkyApm.Logging;
using SkyApm.Transport;
namespace SkyApm.Service
{
public class CLRStatsService : ExecutionService
{
private readonly ICLRStatsReporter _reporter;
public CLRStatsService(ICLRStatsReporter reporter, IRuntimeEnvironment runtimeEnvironment,
ILoggerFactory loggerFactory)
: base(runtimeEnvironment, loggerFactory)
{
_reporter = reporter;
}
protected override TimeSpan DueTime { get; } = TimeSpan.FromSeconds(30);
protected override TimeSpan Period { get; } = TimeSpan.FromSeconds(30);
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
{
var cpuStats = new CPUStatsRequest
{
UsagePercent = CpuHelpers.UsagePercent
};
var gcStats = new GCStatsRequest
{
Gen0CollectCount = GCHelpers.Gen0CollectCount,
Gen1CollectCount = GCHelpers.Gen1CollectCount,
Gen2CollectCount = GCHelpers.Gen2CollectCount,
HeapMemory = GCHelpers.TotalMemory
};
ThreadPool.GetAvailableThreads(out var availableWorkerThreads, out var availableCompletionPortThreads);
ThreadPool.GetMaxThreads(out var maxWorkerThreads, out var maxCompletionPortThreads);
var threadStats = new ThreadStatsRequest
{
MaxCompletionPortThreads = maxCompletionPortThreads,
MaxWorkerThreads = maxWorkerThreads,
AvailableCompletionPortThreads = availableCompletionPortThreads,
AvailableWorkerThreads = availableWorkerThreads
};
var statsRequest = new CLRStatsRequest
{
CPU = cpuStats,
GC = gcStats,
Thread = threadStats
};
try
{
await _reporter.ReportAsync(statsRequest, cancellationToken);
Logger.Information(
$"Report CLR Stats. CPU UsagePercent {cpuStats.UsagePercent} GenCollectCount {gcStats.Gen0CollectCount} {gcStats.Gen1CollectCount} {gcStats.Gen2CollectCount} {gcStats.HeapMemory / (1024 * 1024)}M ThreadPool {threadStats.AvailableWorkerThreads} {threadStats.MaxWorkerThreads} {threadStats.AvailableCompletionPortThreads} {threadStats.MaxCompletionPortThreads}");
}
catch (Exception exception)
{
Logger.Error("Report CLR Stats error.", exception);
}
}
}
}
\ No newline at end of file
Subproject commit b66fa070fd647662f06497e4ed3657eb258cb6e9 Subproject commit c91b65dd8fac2c5866d79834ae73c3c445ce11cf
/*
* 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.Threading;
using System.Threading.Tasks;
using SkyApm.Config;
using SkyApm.Logging;
using SkyWalking.NetworkProtocol;
namespace SkyApm.Transport.Grpc.V6
{
public class CLRStatsReporter : ICLRStatsReporter
{
private readonly ConnectionManager _connectionManager;
private readonly ILogger _logger;
private readonly GrpcConfig _config;
private readonly IRuntimeEnvironment _runtimeEnvironment;
public CLRStatsReporter(ConnectionManager connectionManager, ILoggerFactory loggerFactory,
IConfigAccessor configAccessor, IRuntimeEnvironment runtimeEnvironment)
{
_connectionManager = connectionManager;
_logger = loggerFactory.CreateLogger(typeof(CLRStatsReporter));
_config = configAccessor.Get<GrpcConfig>();
_runtimeEnvironment = runtimeEnvironment;
}
public async Task ReportAsync(CLRStatsRequest statsRequest,
CancellationToken cancellationToken = default(CancellationToken))
{
if (!_connectionManager.Ready)
{
return;
}
var connection = _connectionManager.GetConnection();
try
{
var request = new CLRMetricCollection
{
ServiceInstanceId = _runtimeEnvironment.ServiceInstanceId.Value
};
var metric = new CLRMetric
{
Cpu = new CPU
{
UsagePercent = statsRequest.CPU.UsagePercent
},
Gc = new ClrGC
{
Gen0CollectCount = statsRequest.GC.Gen0CollectCount,
Gen1CollectCount = statsRequest.GC.Gen1CollectCount,
Gen2CollectCount = statsRequest.GC.Gen2CollectCount,
HeapMemory = statsRequest.GC.HeapMemory
},
Thread = new ClrThread
{
AvailableWorkerThreads = statsRequest.Thread.MaxWorkerThreads,
AvailableCompletionPortThreads = statsRequest.Thread.MaxCompletionPortThreads,
MaxWorkerThreads = statsRequest.Thread.MaxWorkerThreads,
MaxCompletionPortThreads = statsRequest.Thread.MaxCompletionPortThreads
},
Time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
};
request.Metrics.Add(metric);
var client = new CLRMetricReportService.CLRMetricReportServiceClient(connection);
await client.collectAsync(request, null, _config.GetTimeout(), cancellationToken);
}
catch (Exception e)
{
_logger.Warning("Report CLR Stats error. " + e);
}
}
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册