├── src ├── HttpReports.Dashboard.UI │ ├── static │ │ ├── .gitkeep │ │ ├── img.ico │ │ ├── logo3.png │ │ ├── donation.jpg │ │ └── communication.jpg │ ├── config │ │ ├── prod.env.js │ │ ├── dev.env.js │ │ └── index.js │ ├── build │ │ ├── logo.png │ │ ├── vue-loader.conf.js │ │ ├── build.js │ │ ├── check-versions.js │ │ ├── webpack.base.conf.js │ │ └── utils.js │ ├── src │ │ ├── assets │ │ │ ├── images │ │ │ │ └── img.ico │ │ │ └── css │ │ │ │ └── web.css │ │ ├── App.vue │ │ ├── store │ │ │ └── index.js │ │ ├── router │ │ │ └── index.js │ │ └── common │ │ │ └── basic.js │ ├── .editorconfig │ ├── .gitignore │ ├── .babelrc │ ├── .postcssrc.js │ ├── index.html │ ├── README.md │ └── package.json ├── HttpReports.Core │ ├── Diagnostics │ │ ├── DiagnosticHandle.cs │ │ ├── IDiagnosticListener.cs │ │ └── TraceDiagnsticListenerObserver.cs │ ├── ServiceContainer.cs │ ├── IRequestProcesser.cs │ ├── StorageFilters │ │ ├── GroupType.cs │ │ ├── CallCountTaskFilter.cs │ │ ├── ResponseErrorTaskFilter.cs │ │ ├── ResponseTimeTaskFilter.cs │ │ ├── BasicFilter.cs │ │ └── QueryDetailFilter.cs │ ├── IHttpReportsBuilder.cs │ ├── ViewModels │ │ ├── HealthStatusEnum.cs │ │ ├── TopServiceResponse.cs │ │ ├── ServiceInstanceInfo.cs │ │ ├── BaseNode.cs │ │ ├── BaseTimeModel.cs │ │ ├── RequestInfoSearchResult.cs │ │ ├── IndexPageData.cs │ │ ├── ServiceInstanceHealthInfo.cs │ │ └── APPTimeModel.cs │ ├── IReportsTransport.cs │ ├── Models │ │ ├── SysConfig.cs │ │ ├── SysUser.cs │ │ ├── MonitorAlarm.cs │ │ ├── RequestDetail.cs │ │ ├── Performance.cs │ │ ├── MonitorJob.cs │ │ ├── RequestInfo.cs │ │ └── MonitorJobPayload.cs │ ├── ISegmentContext.cs │ ├── IRequestBuilder.cs │ ├── HttpReportsBuilder.cs │ ├── RequestBag.cs │ ├── IRequestSpan.cs │ ├── RequestSpan.cs │ ├── IRequestChain.cs │ ├── RequestChain.cs │ ├── SegmentContext.cs │ ├── HttpReports.Core.csproj │ ├── BasicUtils.cs │ └── BasicConfig.cs ├── HttpReports.Dashboard │ ├── Models │ │ ├── ByIdRequest.cs │ │ ├── ChangeLanguageRequest.cs │ │ ├── BaseResult.cs │ │ ├── ServiceInstanceResponse.cs │ │ ├── RequestTraceTree.cs │ │ ├── UpdateAccountRequest.cs │ │ ├── AlarmOption.cs │ │ ├── QueryDetailRequest.cs │ │ ├── RequestInfoTrace.cs │ │ └── QueryRequest.cs │ ├── Handles │ │ ├── IDashboardHandle.cs │ │ ├── DashboardEmbeddedFiles.cs │ │ └── DashboardHandleBase.cs │ ├── Abstractions │ │ ├── IAlarmService.cs │ │ ├── IAuthService.cs │ │ ├── IHealthCheckService.cs │ │ ├── ILocalizeService.cs │ │ └── IScheduleService.cs │ ├── Implements │ │ ├── ServiceContainer.cs │ │ ├── Utils.cs │ │ └── StringExtensions.cs │ ├── HealthCheckOptions.cs │ ├── Routes │ │ ├── DashboardRoute.cs │ │ ├── DashboardRoutes.cs │ │ └── RouteCollection.cs │ ├── DashboardOptions.cs │ ├── DashboardContext.cs │ ├── MailOptions.cs │ ├── Services │ │ └── ClearReportsDataJob.cs │ └── HttpReports.Dashboard.csproj ├── HttpReports │ ├── Services │ │ ├── IPerformanceService.cs │ │ └── HttpReportsBackgroundService.cs │ ├── HttpReportsOptions.cs │ ├── DefaultRequestProcesser.cs │ └── HttpReports.csproj ├── Storage │ ├── HttpReports.Storage.MySQL │ │ ├── MySqlStorageOptions.cs │ │ ├── MySqlStorage.cs │ │ ├── HttpReports.Storage.MySql.csproj │ │ └── ServiceBuildExtensions.cs │ ├── HttpReports.Storage.SQLServer │ │ ├── SQLServerStorageOptions.cs │ │ ├── SQLServerStorage.cs │ │ ├── HttpReports.Storage.SQLServer.csproj │ │ └── ServiceBuildExtensions.cs │ ├── HttpReports.Storage.Postgre │ │ ├── PostgreStorageOptions.cs │ │ ├── PostgreSQLStorage.cs │ │ ├── HttpReports.Storage.PostgreSQL.csproj │ │ └── ServiceBuildExtensions.cs │ └── HttpReports.Storage.Abstractions │ │ ├── BaseStorageOptions.cs │ │ ├── HttpReports.Storage.Abstractions.csproj │ │ └── IHttpReportsStorage.cs ├── HttpReports.Transport.Grpc │ ├── GrpcTransportOptions.cs │ ├── Models │ │ ├── Performance.cs │ │ ├── RequestInfo.cs │ │ └── RequestDetail.cs │ ├── HttpReports.Transport.Grpc.csproj │ └── DependencyInjectionExtensions.cs ├── HttpReports.Transport.Http │ ├── HttpTransportOptions.cs │ ├── HttpReports.Transport.Http.csproj │ └── DependencyInjectionExtensions.cs ├── HttpReports.Grpc │ ├── HttpReportsMiddlewareExtensions.cs │ ├── HttpReports.Grpc.csproj │ └── GrpcLoggerInterceptor.cs ├── Diagnostics │ ├── HttpReports.Diagnostic.Grpc │ │ ├── HttpReports.Diagnostic.Grpc.csproj │ │ └── GrpcDiagnosticListener.cs │ ├── HttpReports.Diagnostic.MySqlData │ │ ├── HttpReports.Diagnostic.MySqlData.csproj │ │ └── MySqlDataDiagnosticListener.cs │ ├── HttpReports.Diagnostic.SqlClient │ │ ├── HttpReports.Diagnostic.SqlClient.csproj │ │ └── SqlClientDiagnosticListener.cs │ ├── HttpReports.Diagnostic.MySqlConnector │ │ ├── HttpReports.Diagnostic.MySqlConnector.csproj │ │ └── MySqlConnectorDiagnosticListener.cs │ ├── HttpReports.Diagnostic.HttpClient │ │ ├── HttpReports.Diagnostic.HttpClient.csproj │ │ └── HttpClientDiagnosticListener.cs │ └── HttpReports.Diagnostic.AspNetCore │ │ ├── HttpReports.Diagnostic.AspNetCore.csproj │ │ └── AspNetCoreDiagnosticListener.cs ├── HttpReprots.Collector.Http │ ├── DependencyInjectionExtensions.cs │ └── HttpReprots.Collector.Http.csproj ├── HttpReports.Collector.Grpc │ ├── DependencyInjectionExtensions.cs │ └── HttpReports.Collector.Grpc.csproj └── Protos │ └── GrpcCollector.proto ├── .github └── FUNDING.yml ├── .editorconfig ├── example ├── GrpcOrderServer │ ├── appsettings.json │ ├── Properties │ │ └── launchSettings.json │ ├── Protos │ │ └── User.proto │ ├── Program.cs │ ├── GrpcOrderServer.csproj │ ├── Startup.cs │ └── Controllers │ │ └── OrderController.cs ├── Sample.AspNetCore6 │ ├── appsettings.Development.json │ ├── Program.cs │ ├── Sample.AspNetCore6.csproj │ ├── appsettings.json │ └── Properties │ │ └── launchSettings.json ├── HttpReports.Collector.Demo │ ├── appsettings.Development.json │ ├── HttpReports.Collector.Demo.csproj │ ├── appsettings.json │ ├── Properties │ │ └── launchSettings.json │ ├── Program.cs │ └── Startup.cs ├── GrpcUserServer │ ├── Properties │ │ └── launchSettings.json │ ├── Protos │ │ └── User.proto │ ├── appsettings.json │ ├── Program.cs │ ├── Service │ │ └── GrpcUserService.cs │ ├── Controllers │ │ └── UserController.cs │ ├── GrpcUserServer.csproj │ └── Startup.cs └── HttpReports.Demo │ ├── WeatherForecast.cs │ ├── Properties │ └── launchSettings.json │ ├── ErrorMiddleware.cs │ ├── Program.cs │ ├── Controllers │ ├── WeatherForecastController.cs │ └── TraceController.cs │ ├── appsettings.json │ ├── Startup.cs │ └── HttpReports.Demo.csproj ├── test ├── HttpReports.Mock.Console │ ├── Properties │ │ └── launchSettings.json │ └── HttpReports.Mock.Console.csproj └── HttpReports.Test │ ├── FunctionTest.cs │ ├── Utils.cs │ ├── HttpReports.Test.csproj │ ├── MysqlStorageTest.cs │ ├── PostgreSQLStorageTest.cs │ └── SQLServerStorageTest.cs ├── .dockerignore ├── azure-pipelines.yml ├── docs ├── LICENSE └── README.md └── .gitattributes /src/HttpReports.Dashboard.UI/static/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | 4 | open_collective: HttpReports 5 | 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.cs] 2 | 3 | # CS1591: 缺少对公共可见类型或成员的 XML 注释 4 | dotnet_diagnostic.CS1591.severity = none 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/config/prod.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | NODE_ENV: '"production"' 4 | } 5 | -------------------------------------------------------------------------------- /example/GrpcOrderServer/appsettings.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcore/HttpReports/HEAD/example/GrpcOrderServer/appsettings.json -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/build/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcore/HttpReports/HEAD/src/HttpReports.Dashboard.UI/build/logo.png -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/static/img.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcore/HttpReports/HEAD/src/HttpReports.Dashboard.UI/static/img.ico -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/static/logo3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcore/HttpReports/HEAD/src/HttpReports.Dashboard.UI/static/logo3.png -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/static/donation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcore/HttpReports/HEAD/src/HttpReports.Dashboard.UI/static/donation.jpg -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/src/assets/images/img.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcore/HttpReports/HEAD/src/HttpReports.Dashboard.UI/src/assets/images/img.ico -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/static/communication.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcore/HttpReports/HEAD/src/HttpReports.Dashboard.UI/static/communication.jpg -------------------------------------------------------------------------------- /test/HttpReports.Mock.Console/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "HttpReports.Mock.Console": { 4 | "commandName": "Project" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /example/Sample.AspNetCore6/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/config/dev.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const prodEnv = require('./prod.env') 4 | 5 | module.exports = merge(prodEnv, { 6 | NODE_ENV: '"development"' 7 | }) 8 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /example/HttpReports.Collector.Demo/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | /dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Editor directories and files 9 | .idea 10 | .vscode 11 | *.suo 12 | *.ntvs* 13 | *.njsproj 14 | *.sln 15 | -------------------------------------------------------------------------------- /src/HttpReports.Core/Diagnostics/DiagnosticHandle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Core.Diagnostics 6 | { 7 | public static class DiagnosticHandle 8 | { 9 | 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/HttpReports.Core/ServiceContainer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Core 6 | { 7 | public static class ServiceContainer 8 | { 9 | public static IServiceProvider Provider; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Models/ByIdRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Dashboard.Models 6 | { 7 | public class ByIdRequest 8 | { 9 | public string Id { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/HttpReports.Core/IRequestProcesser.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.IO; 3 | using Microsoft.AspNetCore.Http; 4 | 5 | namespace HttpReports 6 | { 7 | 8 | public interface IRequestProcesser 9 | { 10 | void Process(HttpContext context); 11 | 12 | 13 | } 14 | } -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Handles/IDashboardHandle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Dashboard.Handles 6 | { 7 | public interface IDashboardHandle 8 | { 9 | DashboardContext Context { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Models/ChangeLanguageRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Dashboard.Models 6 | { 7 | public class ChangeLanguageRequest 8 | { 9 | public string Language { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "modules": false, 5 | "targets": { 6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] 7 | } 8 | }], 9 | "stage-2" 10 | ], 11 | "plugins": ["transform-vue-jsx", "transform-runtime"] 12 | } 13 | -------------------------------------------------------------------------------- /src/HttpReports.Core/StorageFilters/GroupType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Core.StorageFilters 6 | { 7 | public enum GroupType 8 | { 9 | Service = 0, 10 | Route = 1, 11 | Instance = 2 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/HttpReports.Core/StorageFilters/CallCountTaskFilter.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Core.StorageFilters; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace HttpReports.Core.StorageFilters 7 | { 8 | public class CallCountTaskFilter:BasicFilter 9 | { 10 | 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | "postcss-import": {}, 6 | "postcss-url": {}, 7 | // to edit target browsers: use "browserslist" field in package.json 8 | "autoprefixer": {} 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/HttpReports.Core/StorageFilters/ResponseErrorTaskFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Core.StorageFilters 6 | { 7 | public class ResponseErrorTaskFilter : BasicFilter 8 | { 9 | public int Percentage { get; set; } 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /example/Sample.AspNetCore6/Program.cs: -------------------------------------------------------------------------------- 1 | 2 | var builder = WebApplication.CreateBuilder(args); 3 | 4 | var config = builder.Configuration; 5 | 6 | builder.Services.AddHttpReports().AddHttpTransport(); 7 | 8 | var app = builder.Build(); 9 | 10 | app.UseHttpReports(); 11 | 12 | app.MapGet("/", () => "Hello World!"); 13 | 14 | app.Run(); 15 | -------------------------------------------------------------------------------- /src/HttpReports.Core/IHttpReportsBuilder.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace HttpReports 5 | { 6 | public interface IHttpReportsBuilder 7 | { 8 | IServiceCollection Services { get; } 9 | IConfiguration Configuration { get; } 10 | } 11 | } -------------------------------------------------------------------------------- /src/HttpReports.Core/Diagnostics/IDiagnosticListener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Core.Diagnostics 6 | { 7 | public interface IDiagnosticListener : IObserver> 8 | { 9 | string ListenerName { get; } 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/HttpReports.Core/ViewModels/HealthStatusEnum.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Core.ViewModels 6 | { 7 | public enum HealthStatusEnum 8 | { 9 | None = 0, 10 | IsPassing = 1, 11 | IsWarning = 2, 12 | IsCritical = 3 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/HttpReports.Core/ViewModels/TopServiceResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Core.ViewModels 6 | { 7 | public class TopServiceResponse 8 | { 9 | public string Key { get; set; } 10 | 11 | public int Value { get; set; } 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/src/App.vue: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 24 | -------------------------------------------------------------------------------- /example/GrpcOrderServer/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "GrpcOrderServer": { 4 | "commandName": "Project", 5 | "launchBrowser": true, 6 | "applicationUrl": "https://localhost:5001;", 7 | "environmentVariables": { 8 | "ASPNETCORE_ENVIRONMENT": "Development" 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /example/GrpcUserServer/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "GrpcUserServer": { 4 | "commandName": "Project", 5 | "launchBrowser": true, 6 | "applicationUrl": "https://localhost:5002;", 7 | "environmentVariables": { 8 | "ASPNETCORE_ENVIRONMENT": "Development" 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/HttpReports.Core/IReportsTransport.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Core; 2 | using HttpReports.Core.Models; 3 | using System.Threading.Tasks; 4 | 5 | namespace HttpReports 6 | { 7 | public interface IReportsTransport 8 | { 9 | Task SendDataAsync(RequestBag bag); 10 | 11 | Task SendDataAsync(Performance performance); 12 | 13 | } 14 | } -------------------------------------------------------------------------------- /src/HttpReports.Core/ViewModels/ServiceInstanceInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Core.ViewModels 6 | { 7 | public class ServiceInstanceInfo 8 | { 9 | public string Service { get; set; } 10 | 11 | public string Instance { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/HttpReports.Core/StorageFilters/ResponseTimeTaskFilter.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Core.StorageFilters; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace HttpReports.Core.StorageFilters 7 | { 8 | public class ResponseTimeTaskFilter:BasicFilter 9 | { 10 | public int TimeoutMS { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/HttpReports.Core/Models/SysConfig.cs: -------------------------------------------------------------------------------- 1 | 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace HttpReports.Core.Models 8 | { 9 | public class SysConfig 10 | { 11 | public long Id { get; set; } 12 | public string Key { get; set; } 13 | public string Value { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/HttpReports/Services/IPerformanceService.cs: -------------------------------------------------------------------------------- 1 | 2 | using HttpReports.Core.Models; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace HttpReports.Services 9 | { 10 | public interface IPerformanceService 11 | { 12 | Task GetPerformance(string Instance); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/HttpReports.Core/ViewModels/BaseNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Core.ViewModels 6 | { 7 | public class BaseNode 8 | { 9 | public string Key { get; set; } 10 | 11 | public int Value { get; set; } 12 | 13 | public string StringValue { get; set; } 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Abstractions/IAlarmService.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Dashboard.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace HttpReports.Dashboard.Abstractions 8 | { 9 | public interface IAlarmService 10 | { 11 | Task AlarmAsync(AlarmOption option); 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Models/BaseResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Dashboard.Models 6 | { 7 | public class BaseResult 8 | { 9 | public int Code { get; set; } 10 | 11 | public string Msg { get; set; } 12 | 13 | public object Data { get; set; } 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Models/ServiceInstanceResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Dashboard.Models.ViewModels 6 | { 7 | public class ServiceInstanceResponse 8 | { 9 | public string Service { get; set; } 10 | 11 | public List Instance { get; set; } 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /example/HttpReports.Demo/WeatherForecast.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace HttpReports.Demo 4 | { 5 | public class WeatherForecast 6 | { 7 | public DateTime Date { get; set; } 8 | 9 | public int TemperatureC { get; set; } 10 | 11 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); 12 | 13 | public string Summary { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/HttpReports.Core/Models/SysUser.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace HttpReports.Core.Models 7 | { 8 | public class SysUser 9 | { 10 | 11 | public long Id { get; set; } 12 | 13 | public string UserName { get; set; } 14 | 15 | public string Password { get; set; } 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Implements/ServiceContainer.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace HttpReports.Dashboard.Implements 8 | { 9 | public static class ServiceContainer 10 | { 11 | public static IServiceProvider provider; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/HttpReports.Core/ViewModels/BaseTimeModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Core.ViewModels 6 | { 7 | public class BaseTimeModel 8 | { 9 | public string KeyField { get; set; } 10 | 11 | public string TimeField { get; set; } 12 | 13 | public int ValueField { get; set; } 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Models/RequestTraceTree.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Core.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace HttpReports.Dashboard.Models 7 | { 8 | public class RequestTraceTree 9 | { 10 | public RequestInfo Info { get; set; } 11 | 12 | public List Nodes { get; set; } 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/HttpReports.Core/ISegmentContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Text; 5 | 6 | namespace HttpReports.Core 7 | { 8 | public interface ISegmentContext 9 | { 10 | bool Push(string activity,Segment segment); 11 | 12 | List GetSegments(string Id); 13 | 14 | bool Release(string Id); 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | **/.classpath 2 | **/.dockerignore 3 | **/.env 4 | **/.git 5 | **/.gitignore 6 | **/.project 7 | **/.settings 8 | **/.toolstarget 9 | **/.vs 10 | **/.vscode 11 | **/*.*proj.user 12 | **/*.dbmdl 13 | **/*.jfm 14 | **/azds.yaml 15 | **/bin 16 | **/charts 17 | **/docker-compose* 18 | **/Dockerfile* 19 | **/node_modules 20 | **/npm-debug.log 21 | **/obj 22 | **/secrets.dev.yaml 23 | **/values.dev.yaml 24 | LICENSE 25 | README.md -------------------------------------------------------------------------------- /src/HttpReports.Core/IRequestBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using HttpReports.Core; 6 | using HttpReports.Core.Models; 7 | using Microsoft.AspNetCore.Http; 8 | 9 | namespace HttpReports 10 | { 11 | 12 | public interface IRequestBuilder 13 | { 14 | (RequestInfo,RequestDetail) Build(HttpContext context); 15 | } 16 | } -------------------------------------------------------------------------------- /src/HttpReports.Core/ViewModels/RequestInfoSearchResult.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Core.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace HttpReports.Core.ViewModels 7 | { 8 | public class RequestInfoSearchResult 9 | { 10 | public List List { get; set; } = new List(); 11 | 12 | public int Total { get; set; } 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | HttpReportsWgmf 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/HttpReports.Test/FunctionTest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace HttpReports.Test 7 | { 8 | [TestClass] 9 | public class FunctionTest 10 | { 11 | [TestMethod] 12 | public void EmailTest() 13 | { 14 | Console.WriteLine("222"); 15 | } 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/HttpReports.Core/Models/MonitorAlarm.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace HttpReports.Core.Models 7 | { 8 | public class MonitorAlarm 9 | { 10 | public long Id { get; set; } 11 | 12 | public long JobId { get; set; } 13 | 14 | public string Body { get; set; } 15 | 16 | public DateTime CreateTime { get; set; } 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Models/UpdateAccountRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Dashboard.ViewModels 6 | { 7 | public class UpdateAccountRequest 8 | { 9 | public string Username { get; set; } 10 | 11 | public string NewUserName { get; set; } 12 | 13 | public string OldPwd { get; set; } 14 | 15 | public string NewPwd { get; set; } 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /example/HttpReports.Demo/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "HttpReports.Demo": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": "true", 7 | "launchBrowser": true, 8 | "launchUrl": "", 9 | "applicationUrl": "http://localhost:5010", 10 | "environmentVariables": { 11 | "ASPNETCORE_ENVIRONMENT": "Development" 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Storage/HttpReports.Storage.MySQL/MySqlStorageOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Microsoft.Extensions.Options; 4 | 5 | namespace HttpReports.Storage.MySql 6 | { 7 | public class MySqlStorageOptions : IOptions 8 | { 9 | public string ConnectionString { get; set; } 10 | 11 | public int DeferSecond { get; set; } 12 | 13 | public int DeferThreshold { get; set; } 14 | 15 | public MySqlStorageOptions Value => this; 16 | } 17 | } -------------------------------------------------------------------------------- /example/GrpcOrderServer/Protos/User.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option csharp_namespace = "GrpcUserServer.Protos"; 4 | 5 | package User; 6 | 7 | service UserService{ 8 | rpc GetUserInfo(GetUserInfoRequest) returns (GetUserInfoResponse); 9 | } 10 | 11 | message GetUserInfoRequest{ 12 | int32 Id = 1; 13 | } 14 | 15 | message GetUserInfoResponse{ 16 | 17 | int32 Id = 1; 18 | string Name = 2; 19 | string Sex = 3; 20 | string Phone = 4; 21 | string Address = 5; 22 | 23 | } 24 | 25 | -------------------------------------------------------------------------------- /example/GrpcUserServer/Protos/User.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option csharp_namespace = "GrpcUserServer.Protos"; 4 | 5 | package User; 6 | 7 | service UserService{ 8 | rpc GetUserInfo(GetUserInfoRequest) returns (GetUserInfoResponse); 9 | } 10 | 11 | message GetUserInfoRequest{ 12 | int32 Id = 1; 13 | } 14 | 15 | message GetUserInfoResponse{ 16 | 17 | int32 Id = 1; 18 | string Name = 2; 19 | string Sex = 3; 20 | string Phone = 4; 21 | string Address = 5; 22 | 23 | } 24 | 25 | -------------------------------------------------------------------------------- /example/GrpcUserServer/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "HttpReports": { 3 | "Transport": { 4 | "CollectorAddress": "http://localhost:5010", 5 | "DeferSecond": 1, 6 | "DeferThreshold": 1 7 | }, 8 | "Server": "", 9 | "Service": "User", 10 | "Switch": true, 11 | "MaxBytes": 20000, 12 | "RequestFilter": [ "/api/Health/*", "/HttpReports*" ], 13 | "WithRequest": true, 14 | "WithResponse": true, 15 | "WithCookie": true, 16 | "WithHeader": true 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /example/Sample.AspNetCore6/Sample.AspNetCore6.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/HttpReports.Transport.Grpc/GrpcTransportOptions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Options; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace HttpReports.Transport.Grpc 7 | { 8 | public class GrpcTransportOptions : IOptions 9 | { 10 | public Uri CollectorAddress { get; set; } 11 | 12 | public int DeferSecond { get; set; } 13 | 14 | public int DeferThreshold { get; set; } 15 | 16 | public GrpcTransportOptions Value => this; 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /example/HttpReports.Collector.Demo/HttpReports.Collector.Demo.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Abstractions/IAuthService.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Dashboard.Handles; 2 | using HttpReports.Dashboard.Routes; 3 | using Microsoft.AspNetCore.Http; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace HttpReports.Dashboard.Abstractions 9 | { 10 | public interface IAuthService 11 | { 12 | string BuildToken(); 13 | 14 | bool ValidToken(string token); 15 | 16 | bool ValidToken(HttpContext httpContext, IDashboardHandle handle, DashboardRoute route); 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Abstractions/IHealthCheckService.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Core.ViewModels; 2 | using System; 3 | using System.Collections.Concurrent; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace HttpReports.Dashboard.Abstractions 9 | { 10 | public interface IHealthCheckService 11 | { 12 | Task> GetServiceInstance(); 13 | 14 | Task SetServiceInstance(ConcurrentBag list); 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/HttpReports.Transport.Http/HttpTransportOptions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Options; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace HttpReports.Transport.Http 7 | { 8 | public class HttpTransportOptions : IOptions 9 | { 10 | public Uri CollectorAddress { get; set; } 11 | 12 | public int DeferSecond { get; set; } 13 | 14 | public int DeferThreshold { get; set; } 15 | 16 | public HttpTransportOptions Value => this; 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/HealthCheckOptions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Options; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace HttpReports.Dashboard 7 | { 8 | public class HealthCheckOptions : IOptions 9 | { 10 | public bool Switch { get; set; } 11 | 12 | public string Mode { get; set; } 13 | 14 | public string Endpoint { get; set; } 15 | 16 | public string Range { get; set; } 17 | 18 | public HealthCheckOptions Value => this; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/HttpReports.Test/Utils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Security.Cryptography; 4 | using System.Text; 5 | 6 | namespace HttpReports.Test 7 | { 8 | public static class Utils 9 | { 10 | public static string MD5_16(string source) 11 | { 12 | MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); 13 | string val = BitConverter.ToString(md5.ComputeHash(UTF8Encoding.Default.GetBytes(source)), 4, 8).Replace("-", "").ToLower(); 14 | return val; 15 | } 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/README.md: -------------------------------------------------------------------------------- 1 | # httpreports-ui 2 | 3 | > httpreports-ui 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | npm install 10 | 11 | # serve with hot reload at localhost:8080 12 | npm run dev 13 | 14 | # build for production with minification 15 | npm run build 16 | 17 | # build for production and view the bundle analyzer report 18 | npm run build --report 19 | ``` 20 | 21 | For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). 22 | -------------------------------------------------------------------------------- /src/Storage/HttpReports.Storage.SQLServer/SQLServerStorageOptions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Options; 2 | using System; 3 | 4 | namespace HttpReports.Storage.SQLServer 5 | { 6 | public class SQLServerStorageOptions : IOptions 7 | { 8 | public string ConnectionString { get; set; } 9 | 10 | 11 | public bool EnableDefer { get; set; } 12 | 13 | 14 | public int DeferSecond { get; set; } 15 | 16 | 17 | public int DeferThreshold { get; set; } 18 | 19 | public SQLServerStorageOptions Value => this; 20 | } 21 | } -------------------------------------------------------------------------------- /src/HttpReports.Core/HttpReportsBuilder.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace HttpReports 5 | { 6 | 7 | public class HttpReportsBuilder : IHttpReportsBuilder 8 | { 9 | public IServiceCollection Services { get; private set; } 10 | 11 | public IConfiguration Configuration { get; private set; } 12 | 13 | public HttpReportsBuilder(IServiceCollection services, IConfiguration configuration) 14 | { 15 | Services = services; 16 | Configuration = configuration; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Abstractions/ILocalizeService.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Dashboard.Services; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace HttpReports.Dashboard.Abstractions 8 | { 9 | public interface ILocalizeService 10 | { 11 | Localize Current { get; set; } 12 | 13 | Task InitAsync(); 14 | 15 | bool TryGetLanguage(string language, out Localize localize); 16 | 17 | Task SetLanguageAsync(string language); 18 | 19 | void LoadLocalize(string name, string json); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Storage/HttpReports.Storage.Postgre/PostgreStorageOptions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Options; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace HttpReports.Storage.PostgreSQL 7 | { 8 | public class PostgreStorageOptions : IOptions 9 | { 10 | public string ConnectionString { get; set; } 11 | 12 | public string TablePrefix { get; set; } 13 | 14 | public int DeferSecond { get; set; } 15 | 16 | public int DeferThreshold { get; set; } 17 | 18 | public PostgreStorageOptions Value => this; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/HttpReports.Core/StorageFilters/BasicFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Core.StorageFilters 6 | { 7 | public class BasicFilter 8 | { 9 | public string Service { get; set; } 10 | 11 | public string Instance { get; set; } 12 | 13 | 14 | public DateTime StartTime { get; set; } 15 | 16 | 17 | public DateTime EndTime { get; set; } 18 | 19 | public int Count { get; set; } 20 | 21 | public int PageNumber { get; set; } 22 | 23 | public int PageSize { get; set; } 24 | 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Models/AlarmOption.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Core.Models; 2 | using System.Collections.Generic; 3 | 4 | namespace HttpReports.Dashboard.Models 5 | { 6 | 7 | public class AlarmOption 8 | { 9 | public string WebHook { get; set; } 10 | 11 | 12 | public IEnumerable Emails { get; set; } 13 | 14 | 15 | public IEnumerable Phones { get; set; } 16 | 17 | 18 | public string Content { get; set; } 19 | 20 | 21 | public bool IsHtml { get; set; } 22 | 23 | public MonitorAlarm Alarm { get; set; } 24 | 25 | } 26 | } -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Models/QueryDetailRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Dashboard.Models 6 | { 7 | public class QueryDetailRequest:QueryRequest 8 | { 9 | public string RequestId { get; set; } 10 | 11 | public string Route { get; set; } 12 | 13 | public int StatusCode { get; set; } 14 | 15 | public string Method { get; set; } 16 | 17 | public string RequestBody { get; set; } 18 | 19 | public string ResponseBody { get; set; } 20 | 21 | public int MinMs { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/HttpReports.Core/RequestBag.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Core.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace HttpReports.Core 7 | { 8 | public class RequestBag 9 | { 10 | public RequestInfo RequestInfo { get; set; } 11 | 12 | public RequestDetail RequestDetail { get; set; } 13 | 14 | 15 | public RequestBag() 16 | { 17 | 18 | } 19 | 20 | public RequestBag(RequestInfo info,RequestDetail detail) 21 | { 22 | this.RequestInfo = info; 23 | this.RequestDetail = detail; 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/HttpReports.Core/ViewModels/IndexPageData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Core.ViewModels 6 | { 7 | public class IndexPageData 8 | { 9 | public double AvgResponseTime { get; set; } 10 | 11 | public int Total { get; set; } 12 | 13 | public int NotFound { get; set; } 14 | 15 | public int ServerError { get; set; } 16 | 17 | public int APICount { get; set; } 18 | public double ErrorPercent { get; set; } 19 | 20 | public int Service { get; set; } 21 | 22 | public int Instance { get; set; } 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Implements/Utils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace HttpReports.Dashboard.Implements 4 | { 5 | public static class Utils 6 | { 7 | public static bool ObjToBool(object expression, bool defValue = false) 8 | { 9 | if (expression != null) 10 | { 11 | bool result = false; 12 | bool.TryParse(expression.ToString(), out result); 13 | return result; 14 | } 15 | return defValue; 16 | } 17 | 18 | 19 | public static string ToStandardTime(this DateTime time) => time.ToString("yyyy-MM-dd HH:mm:ss"); 20 | } 21 | } -------------------------------------------------------------------------------- /example/Sample.AspNetCore6/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "HttpReports": { 9 | "Transport": { 10 | "CollectorAddress": "http://localhost:5010", 11 | "DeferSecond": 1, 12 | "DeferThreshold": 1 13 | }, 14 | "Server": "", 15 | "Service": "User", 16 | "Switch": true, 17 | "MaxBytes": 20000, 18 | "RequestFilter": [ "/api/Health/*", "/HttpReports*" ], 19 | "WithRequest": true, 20 | "WithResponse": true, 21 | "WithCookie": true, 22 | "WithHeader": true 23 | }, 24 | "AllowedHosts": "*" 25 | } 26 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Abstractions/IScheduleService.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Core.Models; 2 | using Quartz; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace HttpReports.Dashboard.Abstractions 9 | { 10 | public interface IScheduleService 11 | { 12 | Task InitAsync(); 13 | 14 | Task InitMonitorJobAsync(); 15 | 16 | Task ScheduleJobAsync(MonitorJob model); 17 | 18 | 19 | Task DeleteJobAsync(IJobDetail job); 20 | 21 | 22 | Task UpdateMonitorJobAsync(MonitorJob deleteJob = null); 23 | 24 | Task AutoClearDataJobAsync(); 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Storage/HttpReports.Storage.Abstractions/BaseStorageOptions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Options; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Data; 5 | using System.Text; 6 | 7 | namespace HttpReports.Storage.Abstractions 8 | { 9 | public class BaseStorageOptions:IOptions 10 | { 11 | public string ConnectionString { get; set; } 12 | 13 | public int DeferSecond { get; set; } 14 | 15 | public int DeferThreshold { get; set; } 16 | 17 | 18 | public FreeSql.DataType DataType { get; set; } 19 | 20 | 21 | public BaseStorageOptions Value => this; 22 | 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /example/HttpReports.Demo/ErrorMiddleware.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace HttpReports.Demo 8 | { 9 | public class ErrorMiddleware 10 | { 11 | private readonly RequestDelegate _next; 12 | 13 | public ErrorMiddleware(RequestDelegate next) 14 | { 15 | _next = next; 16 | } 17 | 18 | 19 | public async Task InvokeAsync(HttpContext context) 20 | { 21 | await _next(context); 22 | 23 | throw new Exception("MiddlewareError34234"); 24 | } 25 | 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/HttpReports.Core/IRequestSpan.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Core 6 | { 7 | public interface IRequestSpan 8 | { 9 | string Id { get; set; } 10 | 11 | string ParentId { get; set; } 12 | 13 | string RequestId { get; set; } 14 | 15 | string SpanType { get; set; } 16 | 17 | string Action { get; set; } 18 | 19 | string Input { get; set; } 20 | 21 | string Output { get; set; } 22 | 23 | string Payload { get; set; } 24 | 25 | string Millisecond { get; set; } 26 | 27 | DateTime CreateTime { get; set; } 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/HttpReports.Core/StorageFilters/QueryDetailFilter.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace HttpReports.Core.StorageFilters 7 | { 8 | public class QueryDetailFilter:BasicFilter 9 | { 10 | public long RequestId { get; set; } 11 | 12 | public string Route { get; set; } 13 | 14 | public int StatusCode { get; set; } 15 | 16 | public string Method { get; set; } 17 | 18 | public string RequestBody { get; set; } 19 | 20 | public string ResponseBody { get; set; } 21 | 22 | // 相应时间最小值。0时表示不判断,否则表示取超过这个时间的响应 23 | public int MinMs { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const utils = require('./utils') 3 | const config = require('../config') 4 | const isProduction = process.env.NODE_ENV === 'production' 5 | const sourceMapEnabled = isProduction 6 | ? config.build.productionSourceMap 7 | : config.dev.cssSourceMap 8 | 9 | module.exports = { 10 | loaders: utils.cssLoaders({ 11 | sourceMap: sourceMapEnabled, 12 | extract: isProduction 13 | }), 14 | cssSourceMap: sourceMapEnabled, 15 | cacheBusting: config.dev.cacheBusting, 16 | transformToRequire: { 17 | video: ['src', 'poster'], 18 | source: 'src', 19 | img: 'src', 20 | image: 'xlink:href' 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Models/RequestInfoTrace.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Dashboard.Models 6 | { 7 | public class RequestInfoTrace 8 | { 9 | public string Text { get; set; } 10 | 11 | public string Id { get; set; } 12 | 13 | public string Service { get; set; } 14 | 15 | public string Url { get; set; } 16 | 17 | public int Milliseconds { get; set; } 18 | 19 | public int StatusCode { get; set; } 20 | 21 | public string RequestType { get; set; } 22 | 23 | public List Nodes { get; set; } 24 | 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/HttpReports.Core/RequestSpan.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Core 6 | { 7 | public class RequestSpan:IRequestSpan 8 | { 9 | public string Id { get; set; } 10 | public string ParentId { get; set; } 11 | public string RequestId { get; set; } 12 | public string SpanType { get; set; } 13 | public string Action { get; set; } 14 | public string Input { get; set; } 15 | public string Output { get; set; } 16 | public string Payload { get; set; } 17 | public string Millisecond { get; set; } 18 | public DateTime CreateTime { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Models/QueryRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Security.Principal; 4 | using System.Text; 5 | 6 | namespace HttpReports.Dashboard.Models 7 | { 8 | public class QueryRequest 9 | { 10 | public string Service { get; set; } 11 | 12 | public string Instance { get; set; } 13 | 14 | public string Start { get; set; } 15 | 16 | public string End { get; set; } 17 | 18 | public string LocalIP { get; set; } 19 | 20 | public int LocalPort { get; set; } 21 | 22 | public int PageNumber { get; set; } 23 | 24 | public int PageSize { get; set; } 25 | 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/HttpReports.Grpc/HttpReportsMiddlewareExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using HttpReports; 4 | using HttpReports.Grpc; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.Options; 8 | 9 | namespace Microsoft.Extensions.DependencyInjection 10 | { 11 | public static class HttpReportsMiddlewareExtensions 12 | { 13 | public static IHttpReportsBuilder UseGrpc(this IHttpReportsBuilder builder) 14 | { 15 | builder.Services.AddGrpc(x => { x.Interceptors.Add(); }); 16 | 17 | return builder; 18 | } 19 | 20 | } 21 | } -------------------------------------------------------------------------------- /example/HttpReports.Collector.Demo/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "HttpReports": { 3 | "Transport": { 4 | "CollectorAddress": "http://localhost:5010", 5 | "DeferSecond": 1, 6 | "DeferThreshold": 1 7 | }, 8 | "Server": "", 9 | "Service": "User", 10 | "Switch": true, 11 | "MaxBytes": 20000, 12 | "RequestFilter": [ "/api/Health/*", "/HttpReports*" ], 13 | "WithRequest": true, 14 | "WithResponse": true, 15 | "WithCookie": true, 16 | "WithHeader": true 17 | }, 18 | "Logging": { 19 | "LogLevel": { 20 | "Default": "Information", 21 | "Microsoft": "Warning", 22 | "Microsoft.Hosting.Lifetime": "Information" 23 | } 24 | }, 25 | "AllowedHosts": "*" 26 | } 27 | -------------------------------------------------------------------------------- /src/HttpReports.Core/IRequestChain.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Core 6 | { 7 | public interface IRequestChain 8 | { 9 | string Id { get; set; } 10 | 11 | string ParentId { get; set; } 12 | 13 | string Service { get; set; } 14 | 15 | string Instance { get; set; } 16 | 17 | string Component { get; set; } 18 | 19 | string Error { get; set; } 20 | 21 | string ErrorMessage { get; set; } 22 | 23 | int IsSuccess { get; set; } 24 | 25 | string Value { get; set; } 26 | 27 | int Milliseconds { get; set; } 28 | 29 | DateTime CreateTime { get; set; } 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Routes/DashboardRoute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Dashboard.Routes 6 | { 7 | public class DashboardRoute 8 | { 9 | public DashboardRoute(string key,Type view) 10 | { 11 | HtmlView = view != null; 12 | Key = key; 13 | View = view; 14 | 15 | } 16 | 17 | public DashboardRoute() 18 | { 19 | 20 | } 21 | 22 | public string Key { get; set; } 23 | 24 | public Type View { get; set; } 25 | 26 | public string Handle { get; set; } 27 | 28 | public string Action { get; set; } 29 | 30 | public bool HtmlView { get; set; } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Routes/DashboardRoutes.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Dashboard.Handles; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Text; 7 | 8 | namespace HttpReports.Dashboard.Routes 9 | { 10 | public static class DashboardRoutes 11 | { 12 | public static RouteCollection Routes { get; } 13 | 14 | static DashboardRoutes() 15 | { 16 | Routes = new RouteCollection(); 17 | 18 | typeof(DashboardDataHandle).GetMethods().Select(x => x.Name).ToList().ForEach(action => { 19 | 20 | Routes.AddRoute(new DashboardRoute("/HttpReportsData/" + action, null)); 21 | 22 | }); 23 | 24 | } 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/HttpReports.Transport.Grpc/Models/Performance.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Collector.Grpc 6 | { 7 | public partial class Performance 8 | { 9 | private DateTime? _createTime = null; 10 | 11 | public DateTime CreateTime 12 | { 13 | get 14 | { 15 | if (_createTime == null) 16 | { 17 | _createTime = new DateTime(CreateTimeStamp); 18 | } 19 | return _createTime.Value; 20 | } 21 | set 22 | { 23 | _createTime = value; 24 | CreateTimeStamp = value.Ticks; 25 | } 26 | } 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/HttpReports.Transport.Grpc/Models/RequestInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Collector.Grpc 6 | { 7 | public partial class RequestInfo 8 | { 9 | private DateTime? _createTime = null; 10 | 11 | public new DateTime CreateTime 12 | { 13 | get 14 | { 15 | if (_createTime == null) 16 | { 17 | _createTime = new DateTime(CreateTimeStamp); 18 | } 19 | return _createTime.Value; 20 | } 21 | set 22 | { 23 | _createTime = value; 24 | CreateTimeStamp = value.Ticks; 25 | } 26 | } 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/HttpReports.Transport.Grpc/Models/RequestDetail.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Collector.Grpc 6 | { 7 | public partial class RequestDetail 8 | { 9 | private DateTime? _createTime = null; 10 | 11 | public new DateTime CreateTime 12 | { 13 | get 14 | { 15 | if (_createTime == null) 16 | { 17 | _createTime = new DateTime(CreateTimeStamp); 18 | } 19 | return _createTime.Value; 20 | } 21 | set 22 | { 23 | _createTime = value; 24 | CreateTimeStamp = value.Ticks; 25 | } 26 | } 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/HttpReports.Core/Models/RequestDetail.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace HttpReports.Core.Models 7 | { 8 | public class RequestDetail 9 | { 10 | 11 | public long Id { get; set; } 12 | 13 | public long RequestId { get; set; } 14 | public string Scheme { get; set; } 15 | public string QueryString { get; set; } 16 | public string Header { get; set; } 17 | public string Cookie { get; set; } 18 | public string RequestBody { get; set; } 19 | public string ResponseBody { get; set; } 20 | public string ErrorMessage { get; set; } 21 | public string ErrorStack { get; set; } 22 | public DateTime CreateTime { get; set; } 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/DashboardOptions.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Core; 2 | using Microsoft.Extensions.Options; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace HttpReports.Dashboard 8 | { 9 | public class DashboardOptions : IOptions 10 | { 11 | public MailOptions Mail { get; set; } = new MailOptions(); 12 | 13 | public int ExpireDay { get; set; } = BasicConfig.ExpireDay; 14 | 15 | public int QueryCount { get; set; } = 6; 16 | 17 | public bool Migration { get; set; } = true; 18 | 19 | public HealthCheckOptions Check { get; set; } = new HealthCheckOptions(); 20 | 21 | public bool EnableCors { get; set; } = true; 22 | 23 | public DashboardOptions Value => this; 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Diagnostics/HttpReports.Diagnostic.Grpc/HttpReports.Diagnostic.Grpc.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | SpringLee 6 | HttpReports.Diagnostic.Grpc 7 | HttpReports is a lightweight APM system developed for .NET Core 8 | https://github.com/dotnetcore/HttpReports 9 | https://files-cdn.cnblogs.com/files/myshowtime/img.ico 10 | https://github.com/dotnetcore/HttpReports 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/HttpReports.Core/RequestChain.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Core 6 | { 7 | public class RequestChain : IRequestChain 8 | { 9 | public string Id { get; set; } 10 | 11 | public string ParentId { get; set; } 12 | 13 | public string Service { get; set; } 14 | 15 | public string Instance { get; set; } 16 | 17 | public string Component { get; set; } 18 | 19 | public string Value { get; set; } 20 | 21 | public string Error { get; set; } 22 | 23 | public string ErrorMessage { get; set; } 24 | 25 | public int IsSuccess { get; set; } 26 | 27 | public int Milliseconds { get; set; } 28 | 29 | public DateTime CreateTime { get; set; } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /example/GrpcUserServer/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.Hosting; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace GrpcUserServer 11 | { 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | CreateHostBuilder(args).Build().Run(); 17 | } 18 | 19 | public static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /example/Sample.AspNetCore6/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:44099", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "Sample.AspNetCore6": { 12 | "commandName": "Project", 13 | "dotnetRunMessages": true, 14 | "launchBrowser": true, 15 | "applicationUrl": "http://localhost:5200", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "IIS Express": { 21 | "commandName": "IISExpress", 22 | "launchBrowser": true, 23 | "environmentVariables": { 24 | "ASPNETCORE_ENVIRONMENT": "Development" 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/DashboardContext.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Dashboard.Routes; 2 | using Microsoft.AspNetCore.Http; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace HttpReports.Dashboard 8 | { 9 | public class DashboardContext 10 | { 11 | public HttpContext HttpContext { get; } 12 | 13 | public DashboardRoute Route { get; } 14 | 15 | public DashboardOptions Options { get; } 16 | 17 | 18 | public DashboardContext(HttpContext httpContext, DashboardRoute route, DashboardOptions options) 19 | { 20 | Route = route ?? throw new ArgumentNullException(nameof(route)); 21 | HttpContext = httpContext ?? throw new ArgumentNullException(nameof(httpContext)); 22 | Options = options; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/HttpReports/HttpReportsOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.Extensions.Options; 3 | 4 | namespace HttpReports 5 | { 6 | public class HttpReportsOptions : IOptions 7 | { 8 | public string Service { get; set; } = "Default"; 9 | 10 | public string Server { get; set; } 11 | 12 | public bool Switch { get; set; } = true; 13 | 14 | public int MaxBytes { get; set; } = 20000; 15 | 16 | public bool WithRequest { get; set; } = false; 17 | 18 | public bool WithResponse { get; set; } = false; 19 | 20 | public bool WithCookie { get; set; } = false; 21 | 22 | public bool WithHeader { get; set; } = false; 23 | 24 | public string[] RequestFilter { get; set; } = { }; 25 | 26 | public HttpReportsOptions Value => this; 27 | 28 | } 29 | } -------------------------------------------------------------------------------- /example/GrpcOrderServer/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.Hosting; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace GrpcOrderServer 11 | { 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | CreateHostBuilder(args).Build().Run(); 17 | } 18 | 19 | public static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup().UseUrls(""); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /example/HttpReports.Collector.Demo/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:58535", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "HttpReports.Collector.Demo": { 19 | "commandName": "Project", 20 | "dotnetRunMessages": "true", 21 | "launchBrowser": true, 22 | "applicationUrl": "http://localhost:5000", 23 | "environmentVariables": { 24 | "ASPNETCORE_ENVIRONMENT": "Development" 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /example/GrpcUserServer/Service/GrpcUserService.cs: -------------------------------------------------------------------------------- 1 | using Grpc.Core; 2 | using GrpcUserServer.Protos; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using static GrpcUserServer.Protos.UserService; 8 | 9 | namespace GrpcUserServer.Service 10 | { 11 | public class GrpcUserService:UserServiceBase 12 | { 13 | public override async Task GetUserInfo(GetUserInfoRequest request, ServerCallContext context) 14 | { 15 | var user = new GetUserInfoResponse 16 | { 17 | Id = request.Id, 18 | Name = "张小明", 19 | Phone = "17621499260", 20 | Address = "上海市虹口区" 21 | }; 22 | 23 | return await Task.FromResult(user); 24 | 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /example/HttpReports.Collector.Demo/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Configuration; 3 | using Microsoft.Extensions.Hosting; 4 | using Microsoft.Extensions.Logging; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | 10 | namespace HttpReports.Collector.Demo 11 | { 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | CreateHostBuilder(args).Build().Run(); 17 | } 18 | 19 | public static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/HttpReports.Core/ViewModels/ServiceInstanceHealthInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Core.ViewModels 6 | { 7 | public class ServiceInstanceHealthInfo 8 | { 9 | public ServiceHealthInfo ServiceInfo { get; set; } 10 | 11 | public List Instances { get; set; } 12 | 13 | } 14 | 15 | public class InstanceHealthInfo 16 | { 17 | public string Instance { get; set; } 18 | 19 | public HealthStatusEnum Status { get; set; } 20 | 21 | } 22 | 23 | public class ServiceHealthInfo 24 | { 25 | public string Service { get; set; } 26 | 27 | public int Passing { get; set; } 28 | 29 | public int Warning { get; set; } 30 | 31 | public int Critical { get; set; } 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /example/HttpReports.Demo/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Configuration; 3 | using Microsoft.Extensions.Hosting; 4 | using Microsoft.Extensions.Logging; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | 10 | namespace HttpReports.Demo 11 | { 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | CreateHostBuilder(args).Build().Run(); 17 | } 18 | 19 | public static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup().UseUrls("http://localhost:5010"); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/HttpReports.Core/Models/Performance.cs: -------------------------------------------------------------------------------- 1 | 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace HttpReports.Core.Models 8 | { 9 | public class Performance 10 | { 11 | public long Id { get; set; } 12 | public string Service { get; set; } 13 | 14 | public string Instance { get; set; } 15 | 16 | public int GCGen0 { get; set; } 17 | 18 | public int GCGen1 { get; set; } 19 | 20 | public int GCGen2 { get; set; } 21 | 22 | public double HeapMemory { get; set; } 23 | 24 | public double ProcessCPU { get; set; } 25 | 26 | public double ProcessMemory { get; set; } 27 | 28 | public int ThreadCount { get; set; } 29 | 30 | public int PendingThreadCount { get; set; } 31 | 32 | public DateTime CreateTime { get; set; } 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/HttpReprots.Collector.Http/DependencyInjectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using HttpReports; 2 | using HttpReports.Core; 3 | using HttpReprots.Collector.Http; 4 | using Microsoft.AspNetCore.Builder; 5 | using Microsoft.AspNetCore.Http; 6 | using Microsoft.Extensions.Configuration; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Text; 10 | 11 | namespace Microsoft.Extensions.DependencyInjection 12 | { 13 | public static class DependencyInjectionExtensions 14 | { 15 | public static IApplicationBuilder UseHttpCollector(this IApplicationBuilder app) 16 | { 17 | app.Map("/DataTransportPath",builder => builder.UseMiddleware()); 18 | app.Map(BasicConfig.HttpCollectorEndpoint, builder => builder.UseMiddleware()); 19 | 20 | return app; 21 | } 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/HttpReports.Collector.Grpc/DependencyInjectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using HttpReports; 2 | using HttpReports.Collector.Grpc; 3 | using Microsoft.AspNetCore.Builder; 4 | using Microsoft.AspNetCore.Routing; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | 10 | namespace Microsoft.Extensions.DependencyInjection 11 | { 12 | public static class DependencyInjectionExtensions 13 | { 14 | public static IHttpReportsBuilder AddGrpcCollector(this IHttpReportsBuilder builder) 15 | { 16 | builder.Services.AddGrpc(); 17 | return builder; 18 | } 19 | 20 | public static GrpcServiceEndpointConventionBuilder MapGrpcCollector(this IEndpointRouteBuilder builder) 21 | { 22 | return builder.MapGrpcService(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Diagnostics/HttpReports.Diagnostic.MySqlData/HttpReports.Diagnostic.MySqlData.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | SpringLee 6 | HttpReports.Diagnostic.MySqlData 7 | HttpReports is a lightweight APM system developed for .NET Core 8 | https://github.com/dotnetcore/HttpReports 9 | https://files-cdn.cnblogs.com/files/myshowtime/img.ico 10 | https://github.com/dotnetcore/HttpReports 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Diagnostics/HttpReports.Diagnostic.SqlClient/HttpReports.Diagnostic.SqlClient.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | SpringLee 6 | HttpReports.Diagnostic.SqlClient 7 | HttpReports is a lightweight APM system developed for .NET Core 8 | https://github.com/dotnetcore/HttpReports 9 | https://files-cdn.cnblogs.com/files/myshowtime/img.ico 10 | https://github.com/dotnetcore/HttpReports 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/MailOptions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Options; 2 | 3 | namespace HttpReports.Dashboard 4 | { 5 | public class MailOptions : IOptions 6 | { 7 | /// 8 | /// 邮件服务地址 9 | /// 10 | public string Server { get; set; } 11 | 12 | /// 13 | /// 邮件服务端口 14 | /// 15 | public int Port { get; set; } = 25; 16 | 17 | /// 18 | /// 账户 19 | /// 20 | public string Account { get; set; } 21 | 22 | /// 23 | /// 密码 24 | /// 25 | public string Password { get; set; } 26 | 27 | /// 28 | /// 启用加密连接 29 | /// 30 | public bool EnableSsl { get; set; } = false; 31 | 32 | public bool Switch { get; set; } = true; 33 | 34 | 35 | public MailOptions Value => this; 36 | } 37 | } -------------------------------------------------------------------------------- /example/GrpcOrderServer/GrpcOrderServer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/HttpReports.Core/ViewModels/APPTimeModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Core.ViewModels 6 | { 7 | public class APPTimeModel 8 | { 9 | public string TimeField { get; set; } 10 | 11 | public decimal GcGen0_Raw { get; set; } 12 | 13 | public decimal GcGen1_Raw { get; set; } 14 | 15 | public decimal GcGen2_Raw { get; set; } 16 | 17 | public decimal HeapMemory_Raw { get; set; } 18 | 19 | public decimal ProcessMemory_Raw { get; set; } 20 | 21 | public decimal ThreadCount_Raw { get; set; } 22 | 23 | 24 | public int GcGen0 { get; set; } 25 | 26 | public int GcGen1 { get; set; } 27 | 28 | public int GcGen2 { get; set; } 29 | 30 | public double HeapMemory { get; set; } 31 | 32 | public double ProcessMemory { get; set; } 33 | 34 | public int ThreadCount { get; set; } 35 | 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Storage/HttpReports.Storage.MySQL/MySqlStorage.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Storage.Abstractions; 2 | using Microsoft.Extensions.Logging; 3 | using Microsoft.Extensions.Options; 4 | 5 | namespace HttpReports.Storage.MySql 6 | { 7 | internal class MySqlStorage : BaseStorage 8 | { 9 | public MySqlStorageOptions Options { get; } 10 | 11 | public ILogger Logger { get; } 12 | 13 | public MySqlStorage(IOptions options, ILogger logger) 14 | 15 | : base(new BaseStorageOptions 16 | { 17 | DeferSecond = options.Value.DeferSecond, 18 | DeferThreshold = options.Value.DeferThreshold, 19 | ConnectionString = options.Value.ConnectionString, 20 | DataType = FreeSql.DataType.MySql 21 | 22 | }) 23 | 24 | { 25 | Options = options.Value; 26 | Logger = logger; 27 | } 28 | 29 | } 30 | } -------------------------------------------------------------------------------- /src/HttpReports.Core/Models/MonitorJob.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace HttpReports.Core.Models 7 | { 8 | public class MonitorJob 9 | { 10 | public long Id { get; set; } 11 | 12 | public string Title { get; set; } 13 | 14 | public string Description { get; set; } 15 | 16 | public string CronLike { get; set; } 17 | 18 | public string WebHook { get; set; } 19 | 20 | public string Emails { get; set; } 21 | 22 | public string Mobiles { get; set; } 23 | 24 | public int Status { get; set; } 25 | 26 | public string Service { get; set; } 27 | 28 | public string Instance { get; set; } 29 | 30 | public string Payload { get; set; } 31 | 32 | public string StartTime { get; set; } 33 | 34 | public string EndTime { get; set; } 35 | 36 | public DateTime CreateTime { get; set; } 37 | 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/HttpReports.Core/Models/RequestInfo.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace HttpReports.Core.Models 7 | { 8 | public class RequestInfo 9 | { 10 | 11 | public long Id { get; set; } 12 | 13 | 14 | public long ParentId { get; set; } 15 | 16 | public string Service { get; set; } 17 | 18 | public string ParentService { get; set; } 19 | 20 | 21 | public string Instance { get; set; } 22 | 23 | 24 | public string Route { get; set; } 25 | 26 | public string Url { get; set; } 27 | 28 | public string RequestType { get; set; } 29 | 30 | public string Method { get; set; } 31 | 32 | public int Milliseconds { get; set; } 33 | 34 | public int StatusCode { get; set; } 35 | 36 | public string RemoteIP { get; set; } 37 | 38 | 39 | public string LoginUser { get; set; } 40 | 41 | public DateTime CreateTime { get; set; } 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Services/ClearReportsDataJob.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Storage.Abstractions; 2 | using Microsoft.Extensions.Options; 3 | using Quartz; 4 | using System; 5 | using System.Threading.Tasks; 6 | using ServiceContainer = HttpReports.Dashboard.Implements.ServiceContainer; 7 | 8 | namespace HttpReports.Dashboard.Services 9 | { 10 | public class ClearReportsDataJob : IJob 11 | { 12 | private IHttpReportsStorage _storage; 13 | 14 | private DashboardOptions _options; 15 | 16 | public async Task Execute(IJobExecutionContext context) 17 | { 18 | _storage = _storage ?? ServiceContainer.provider.GetService(typeof(IHttpReportsStorage)) as IHttpReportsStorage; 19 | _options = _options ?? (ServiceContainer.provider.GetService(typeof(IOptions)) as IOptions).Value; 20 | 21 | 22 | await _storage.ClearData(DateTime.Now.AddDays(-_options.ExpireDay).ToString("yyyy-MM-dd")); 23 | 24 | } 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Storage/HttpReports.Storage.Postgre/PostgreSQLStorage.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Storage.Abstractions; 2 | using Microsoft.Extensions.Logging; 3 | using Microsoft.Extensions.Options; 4 | 5 | namespace HttpReports.Storage.PostgreSQL 6 | { 7 | public class PostgreSQLStorage : BaseStorage 8 | { 9 | public PostgreStorageOptions Options { get; } 10 | 11 | public ILogger Logger { get; } 12 | 13 | public PostgreSQLStorage(IOptions options, ILogger logger) 14 | 15 | : base(new BaseStorageOptions { 16 | 17 | DeferSecond = options.Value.DeferSecond, 18 | DeferThreshold = options.Value.DeferThreshold, 19 | ConnectionString = options.Value.ConnectionString, 20 | DataType = FreeSql.DataType.PostgreSQL 21 | 22 | }) 23 | 24 | { 25 | Options = options.Value; 26 | Logger = logger; 27 | 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/HttpReports.Core/Models/MonitorJobPayload.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Core.Models 6 | { 7 | public class MonitorJobPayload 8 | { 9 | public ResponseTimeMonitorRule ResponseTimeMonitor { get; set; } 10 | 11 | public ErrorMonitorRule ErrorMonitor { get; set; } 12 | 13 | public CallMonitorRule CallMonitor { get; set; } 14 | 15 | } 16 | 17 | 18 | public class ResponseTimeMonitorRule 19 | { 20 | public int Status { get; set; } 21 | 22 | public int Timeout { get; set; } 23 | 24 | public int Percentage { get; set; } 25 | } 26 | 27 | public class ErrorMonitorRule 28 | { 29 | public int Status { get; set; } 30 | 31 | public int Percentage { get; set; } 32 | } 33 | 34 | 35 | public class CallMonitorRule 36 | { 37 | public int Status { get; set; } 38 | 39 | public int Min { get; set; } 40 | 41 | public int Max { get; set; } 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /example/GrpcUserServer/Controllers/UserController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.Extensions.Logging; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace GrpcUserServer.Controllers 9 | { 10 | [ApiController] 11 | [Route("api/[controller]/[action]")] 12 | public class UserController : ControllerBase 13 | { 14 | private readonly ILogger _logger; 15 | 16 | public UserController(ILogger logger) 17 | { 18 | _logger = logger; 19 | } 20 | 21 | 22 | [HttpGet("/CC/DD/FF/{id}/{id2}")] 23 | public async Task Index(int Id) 24 | { 25 | var context = HttpContext; 26 | 27 | return await Task.FromResult(Content("Success" + Id)); 28 | } 29 | 30 | public async Task GetUserInfo() 31 | { 32 | return await Task.FromResult(Content("Success")); 33 | } 34 | 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/Diagnostics/HttpReports.Diagnostic.MySqlConnector/HttpReports.Diagnostic.MySqlConnector.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | SpringLee 6 | HttpReports.Diagnostic.MySqlConnector 7 | HttpReports is a lightweight APM system developed for .NET Core 8 | https://github.com/dotnetcore/HttpReports 9 | https://files-cdn.cnblogs.com/files/myshowtime/img.ico 10 | https://github.com/dotnetcore/HttpReports 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/HttpReports.Core/Diagnostics/TraceDiagnsticListenerObserver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace HttpReports.Core.Diagnostics 8 | { 9 | public class TraceDiagnsticListenerObserver : IObserver 10 | { 11 | private IEnumerable _listeners; 12 | 13 | public TraceDiagnsticListenerObserver(IEnumerable listeners) 14 | { 15 | _listeners = listeners; 16 | } 17 | 18 | public void OnCompleted() 19 | { 20 | 21 | } 22 | 23 | public void OnError(Exception error) 24 | { 25 | 26 | } 27 | 28 | public void OnNext(DiagnosticListener listener) 29 | { 30 | IDiagnosticListener diagnosticListener = _listeners.Where(x => x.ListenerName == listener.Name).FirstOrDefault(); 31 | 32 | if (diagnosticListener != null) 33 | { 34 | listener.Subscribe(diagnosticListener); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # ASP.NET Core (.NET Framework) 2 | # Build and test ASP.NET Core projects targeting the full .NET Framework. 3 | # Add steps that publish symbols, save build artifacts, and more: 4 | # https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core 5 | 6 | trigger: 7 | - master 8 | 9 | pool: 10 | vmImage: 'windows-latest' 11 | 12 | variables: 13 | solution: '**/*.sln' 14 | buildPlatform: 'Any CPU' 15 | buildConfiguration: 'Release' 16 | 17 | steps: 18 | - task: NuGetToolInstaller@1 19 | 20 | - task: NuGetCommand@2 21 | inputs: 22 | restoreSolution: '$(solution)' 23 | 24 | - task: VSBuild@1 25 | inputs: 26 | solution: '$(solution)' 27 | msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:DesktopBuildPackageLocation="$(build.artifactStagingDirectory)\WebApp.zip" /p:DeployIisAppPath="Default Web Site"' 28 | platform: '$(buildPlatform)' 29 | configuration: '$(buildConfiguration)' 30 | 31 | - task: VSTest@2 32 | inputs: 33 | platform: '$(buildPlatform)' 34 | configuration: '$(buildConfiguration)' 35 | -------------------------------------------------------------------------------- /docs/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 李帅 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/Storage/HttpReports.Storage.SQLServer/SQLServerStorage.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Storage.Abstractions; 2 | using Microsoft.Extensions.Logging; 3 | using Microsoft.Extensions.Options; 4 | 5 | namespace HttpReports.Storage.SQLServer 6 | { 7 | public class SQLServerStorage : BaseStorage 8 | { 9 | public SQLServerStorageOptions _options; 10 | 11 | public ILogger Logger { get; } 12 | 13 | private string Prefix { get; set; } = string.Empty; 14 | 15 | public SQLServerStorage(IOptions options,ILogger logger) 16 | 17 | : base(new BaseStorageOptions 18 | { 19 | DeferSecond = options.Value.DeferSecond, 20 | DeferThreshold = options.Value.DeferThreshold, 21 | ConnectionString = options.Value.ConnectionString, 22 | DataType = FreeSql.DataType.SqlServer 23 | 24 | }) 25 | 26 | { 27 | _options = options.Value; 28 | 29 | Logger = logger; 30 | 31 | } 32 | 33 | 34 | 35 | 36 | } 37 | } -------------------------------------------------------------------------------- /src/HttpReports/DefaultRequestProcesser.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | using Microsoft.AspNetCore.Http; 4 | using Microsoft.Extensions.Configuration; 5 | 6 | namespace HttpReports 7 | { 8 | internal class DefaultRequestProcesser : IRequestProcesser 9 | { 10 | public IReportsTransport ReportsTransport { get; } 11 | 12 | public IRequestBuilder RequestBuilder { get; } 13 | 14 | public IConfiguration Configuration { get; } 15 | 16 | public DefaultRequestProcesser(IReportsTransport reportsTransport, IRequestBuilder requestBuilder, IConfiguration configuration) 17 | { 18 | ReportsTransport = reportsTransport; 19 | RequestBuilder = requestBuilder; 20 | Configuration = configuration; 21 | } 22 | 23 | public void Process(HttpContext context) 24 | { 25 | var (requestInfo, requestDetail) = RequestBuilder.Build(context); 26 | 27 | if (requestInfo != null && requestDetail != null) 28 | { 29 | ReportsTransport.SendDataAsync(new Core.RequestBag(requestInfo,requestDetail)); 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /example/GrpcUserServer/GrpcUserServer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /test/HttpReports.Mock.Console/HttpReports.Mock.Console.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net5.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Always 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /example/GrpcOrderServer/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Microsoft.AspNetCore.Http; 8 | using Microsoft.Extensions.DependencyInjection; 9 | using Microsoft.Extensions.Hosting; 10 | 11 | namespace GrpcOrderServer 12 | { 13 | public class Startup 14 | { 15 | 16 | public void ConfigureServices(IServiceCollection services) 17 | { 18 | services.AddGrpc(); 19 | services.AddHttpReports().UseMySqlStorage().UseGrpc(); 20 | services.AddControllers(); 21 | } 22 | 23 | 24 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 25 | { 26 | app.UseHttpReports(); 27 | 28 | if (env.IsDevelopment()) 29 | { 30 | app.UseDeveloperExceptionPage(); 31 | } 32 | 33 | app.UseRouting(); 34 | 35 | app.UseAuthorization(); 36 | 37 | app.UseEndpoints(endpoints => 38 | { 39 | endpoints.MapControllers(); 40 | }); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /example/GrpcUserServer/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using GrpcUserServer.Service; 6 | using Microsoft.AspNetCore.Builder; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.AspNetCore.Http; 9 | using Microsoft.Extensions.DependencyInjection; 10 | using Microsoft.Extensions.Hosting; 11 | 12 | namespace GrpcUserServer 13 | { 14 | public class Startup 15 | { 16 | 17 | public void ConfigureServices(IServiceCollection services) 18 | { 19 | services.AddHttpReports().AddHttpTransport(); 20 | services.AddControllers(); 21 | } 22 | 23 | 24 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 25 | { 26 | app.UseHttpReports(); 27 | if (env.IsDevelopment()) 28 | { 29 | app.UseDeveloperExceptionPage(); 30 | } 31 | 32 | app.UseRouting(); 33 | 34 | app.UseAuthorization(); 35 | 36 | app.UseEndpoints(endpoints => 37 | { 38 | endpoints.MapGrpcService(); 39 | 40 | endpoints.MapControllers(); 41 | }); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Diagnostics/HttpReports.Diagnostic.HttpClient/HttpReports.Diagnostic.HttpClient.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | SpringLee 6 | HttpReports.Diagnostic.HttpClient 7 | HttpReports is a lightweight APM system developed for .NET Core 8 | https://github.com/dotnetcore/HttpReports 9 | https://github.com/dotnetcore/HttpReports 10 | logo3.png 11 | true 12 | true 13 | true 14 | snupkg 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | True 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/Diagnostics/HttpReports.Diagnostic.AspNetCore/HttpReports.Diagnostic.AspNetCore.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | SpringLee 6 | HttpReports.Diagnostic.AspNetCore 7 | HttpReports is a lightweight APM system developed for .NET Core 8 | https://github.com/dotnetcore/HttpReports 9 | logo3.png 10 | https://github.com/dotnetcore/HttpReports 11 | logo3.png 12 | true 13 | true 14 | true 15 | snupkg 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | True 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/Diagnostics/HttpReports.Diagnostic.Grpc/GrpcDiagnosticListener.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Core; 2 | using HttpReports.Core.Diagnostics; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace HttpReports.Diagnostic.Grpc 8 | { 9 | public class GrpcDiagnosticListener : IDiagnosticListener 10 | { 11 | public string ListenerName => "Grpc.Net.Client"; 12 | 13 | public IRequestChain Build(string Id) 14 | { 15 | return null; 16 | } 17 | 18 | public void OnCompleted() 19 | { 20 | throw new NotImplementedException(); 21 | } 22 | 23 | public void OnError(Exception error) 24 | { 25 | throw new NotImplementedException(); 26 | } 27 | 28 | public void OnNext(KeyValuePair value) 29 | { 30 | var current = System.Diagnostics.Activity.Current; 31 | 32 | if (value.Key == "Grpc.Net.Client.GrpcOut.Start") 33 | { 34 | var cc = value.Value.GetType(); 35 | 36 | var request = value.Value.GetType().GetProperty("Request").GetValue(value.Value) as System.Net.Http.HttpRequestMessage; 37 | } 38 | 39 | if (value.Key == "Grpc.Net.Client.GrpcOut.Stop") 40 | { 41 | 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/HttpReports.Grpc/HttpReports.Grpc.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.0 5 | HttpReports.Grpc 6 | 1.6.0 7 | SpringLee 8 | HttpReports is a lightweight APM system developed for .NET Core 9 | https://github.com/dotnetcore/HttpReports 10 | https://github.com/dotnetcore/HttpReports 11 | logo3.png 12 | true 13 | true 14 | true 15 | snupkg 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | True 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /example/HttpReports.Demo/Controllers/WeatherForecastController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.Extensions.Logging; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace HttpReports.Demo.Controllers 9 | { 10 | [ApiController] 11 | [Route("[controller]")] 12 | public class WeatherForecastController : ControllerBase 13 | { 14 | private static readonly string[] Summaries = new[] 15 | { 16 | "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" 17 | }; 18 | 19 | private readonly ILogger _logger; 20 | 21 | public WeatherForecastController(ILogger logger) 22 | { 23 | _logger = logger; 24 | } 25 | 26 | [HttpPost] 27 | public IEnumerable Get(WeatherForecast weather) 28 | { 29 | var rng = new Random(); 30 | return Enumerable.Range(1, 5).Select(index => new WeatherForecast 31 | { 32 | Date = DateTime.Now.AddDays(index), 33 | TemperatureC = rng.Next(-20, 55), 34 | Summary = Summaries[rng.Next(Summaries.Length)] 35 | }) 36 | .ToArray(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/build/build.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | require('./check-versions')() 3 | 4 | process.env.NODE_ENV = 'production' 5 | 6 | const ora = require('ora') 7 | const rm = require('rimraf') 8 | const path = require('path') 9 | const chalk = require('chalk') 10 | const webpack = require('webpack') 11 | const config = require('../config') 12 | const webpackConfig = require('./webpack.prod.conf') 13 | 14 | const spinner = ora('building for production...') 15 | spinner.start() 16 | 17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { 18 | if (err) throw err 19 | webpack(webpackConfig, (err, stats) => { 20 | spinner.stop() 21 | if (err) throw err 22 | process.stdout.write(stats.toString({ 23 | colors: true, 24 | modules: false, 25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build. 26 | chunks: false, 27 | chunkModules: false 28 | }) + '\n\n') 29 | 30 | if (stats.hasErrors()) { 31 | console.log(chalk.red(' Build failed with errors.\n')) 32 | process.exit(1) 33 | } 34 | 35 | console.log(chalk.cyan(' Build complete.\n')) 36 | console.log(chalk.yellow( 37 | ' Tip: built files are meant to be served over an HTTP server.\n' + 38 | ' Opening index.html over file:// won\'t work.\n' 39 | )) 40 | }) 41 | }) 42 | -------------------------------------------------------------------------------- /example/GrpcOrderServer/Controllers/OrderController.cs: -------------------------------------------------------------------------------- 1 | using Grpc.Net.Client; 2 | using GrpcUserServer.Protos; 3 | using Microsoft.AspNetCore.Mvc; 4 | using Microsoft.Extensions.Logging; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Net.Http; 9 | using System.Threading.Tasks; 10 | 11 | namespace GrpcOrderServer.Controllers 12 | { 13 | [ApiController] 14 | [Route("api/[controller]/[action]")] 15 | public class OrderController : ControllerBase 16 | { 17 | private readonly ILogger _logger; 18 | 19 | public OrderController(ILogger logger) 20 | { 21 | _logger = logger; 22 | } 23 | 24 | [HttpGet] 25 | [HttpPost] 26 | public async Task GetOrderInfo() 27 | { 28 | using var channel = GrpcChannel.ForAddress("https://localhost:5002"); 29 | 30 | var client = new UserService.UserServiceClient(channel); 31 | 32 | var user = await client.GetUserInfoAsync(new GetUserInfoRequest { Id = 10 }); 33 | 34 | return Ok(user); 35 | } 36 | 37 | [HttpGet] 38 | [HttpPost] 39 | public async Task GetOrderInfo2() 40 | { 41 | var client = new HttpClient(); 42 | 43 | var result = await client.GetStringAsync("https://localhost:5002/api/User/GetUserInfo"); 44 | 45 | return Ok(result); 46 | } 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /test/HttpReports.Test/HttpReports.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | all 16 | runtime; build; native; contentfiles; analyzers; buildtransitive 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/HttpReports.Grpc/GrpcLoggerInterceptor.cs: -------------------------------------------------------------------------------- 1 | using Grpc.Core; 2 | using Grpc.Core.Interceptors; 3 | using HttpReports.Core; 4 | using Microsoft.Extensions.Logging; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace HttpReports.Grpc 11 | { 12 | public class HttpReportsGrpcLoggerInterceptor : Interceptor 13 | { 14 | private readonly ILogger _logger; 15 | 16 | public HttpReportsGrpcLoggerInterceptor(ILogger logger) 17 | { 18 | _logger = logger; 19 | } 20 | 21 | public override async Task UnaryServerHandler(TRequest request, ServerCallContext context, UnaryServerMethod continuation) 22 | { 23 | TResponse response = null; 24 | 25 | try 26 | { 27 | response = await continuation(request, context); 28 | } 29 | catch (Exception ex) 30 | { 31 | _logger.LogError("UnaryServerHandler Error:" + ex.ToString()); 32 | } 33 | finally 34 | { 35 | var httpContext = context.GetHttpContext(); 36 | 37 | httpContext.Items.Add(BasicConfig.HttpReportsGrpcRequest, request); 38 | httpContext.Items.Add(BasicConfig.HttpReportsGrpcResponse, response); 39 | } 40 | 41 | return response; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/build/check-versions.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const chalk = require('chalk') 3 | const semver = require('semver') 4 | const packageConfig = require('../package.json') 5 | const shell = require('shelljs') 6 | 7 | function exec (cmd) { 8 | return require('child_process').execSync(cmd).toString().trim() 9 | } 10 | 11 | const versionRequirements = [ 12 | { 13 | name: 'node', 14 | currentVersion: semver.clean(process.version), 15 | versionRequirement: packageConfig.engines.node 16 | } 17 | ] 18 | 19 | if (shell.which('npm')) { 20 | versionRequirements.push({ 21 | name: 'npm', 22 | currentVersion: exec('npm --version'), 23 | versionRequirement: packageConfig.engines.npm 24 | }) 25 | } 26 | 27 | module.exports = function () { 28 | const warnings = [] 29 | 30 | for (let i = 0; i < versionRequirements.length; i++) { 31 | const mod = versionRequirements[i] 32 | 33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 34 | warnings.push(mod.name + ': ' + 35 | chalk.red(mod.currentVersion) + ' should be ' + 36 | chalk.green(mod.versionRequirement) 37 | ) 38 | } 39 | } 40 | 41 | if (warnings.length) { 42 | console.log('') 43 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 44 | console.log() 45 | 46 | for (let i = 0; i < warnings.length; i++) { 47 | const warning = warnings[i] 48 | console.log(' ' + warning) 49 | } 50 | 51 | console.log() 52 | process.exit(1) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /example/HttpReports.Demo/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Error", 5 | "Microsoft": "Error", 6 | "Microsoft.Hosting.Lifetime": "Error" 7 | } 8 | }, 9 | "HttpReports": { 10 | "Transport": { 11 | "CollectorAddress": "http://localhost:5010", 12 | "DeferSecond": 1, 13 | "DeferThreshold": 1 14 | }, 15 | "Server": "", 16 | "Service": "User", 17 | "Switch": true, 18 | "MaxBytes": 20000, 19 | "RequestFilter": [ "/api/Health/*","/HttpReports*"], 20 | "WithRequest": true, 21 | "WithResponse": true, 22 | "WithCookie": true, 23 | "WithHeader": true 24 | }, 25 | "HttpReportsDashboard": { 26 | "QueryCount":6, 27 | "ExpireDay": 3, 28 | "Storage": { 29 | "ConnectionString": "DataBase=HttpReports;Data Source=localhost;User Id=root;Password=root;", 30 | //"ConnectionString": "Max Pool Size = 512;server=.;uid=sa;pwd=123456;database=HttpReports;Connection Timeout=900;", 31 | //"ConnectionString": "Host=127.0.0.1;Port=5430;Username=postgres;Password=123456;Database=HttpReports;", 32 | "DeferSecond": 10, 33 | "DeferThreshold": 1 34 | }, 35 | "Check": { 36 | "Mode": "Self", 37 | "Switch": true, 38 | "Endpoint": "", 39 | "Range": "500,2000" 40 | }, 41 | "Mail": { 42 | "Server": "smtp.163.com", 43 | "Port": 465, 44 | "Account": "HttpReports@163.com", 45 | "Password": "XNPGDVUVOMYHIDKE", 46 | "EnableSsL": true, 47 | "Switch": true 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/HttpReprots.Collector.Http/HttpReprots.Collector.Http.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | HttpReports is a lightweight APM system developed for .NET Core 6 | SpringLee 7 | HttpReports 8 | https://github.com/dotnetcore/HttpReports 9 | https://github.com/dotnetcore/HttpReports 10 | logo3.png 11 | true 12 | true 13 | true 14 | snupkg 15 | true 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | True 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/Storage/HttpReports.Storage.Abstractions/HttpReports.Storage.Abstractions.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | HttpReports.Storage.Abstractions 6 | HttpReports.Storage.Abstractions 7 | SpringLee 8 | SpringLee 9 | HttpReports is a lightweight APM system developed for .NET Core , it is also suitable for use in a micro-service architecture. 10 | https://github.com/dotnetcore/HttpReports 11 | https://github.com/dotnetcore/HttpReports 12 | logo3.png 13 | true 14 | true 15 | true 16 | snupkg 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | True 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /example/HttpReports.Demo/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.AspNetCore.Mvc; 4 | using Microsoft.Extensions.Configuration; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Microsoft.Extensions.Hosting; 7 | using Microsoft.OpenApi.Models; 8 | 9 | namespace HttpReports.Demo 10 | { 11 | public class Startup 12 | { 13 | public Startup(IConfiguration configuration) 14 | { 15 | Configuration = configuration; 16 | } 17 | 18 | public IConfiguration Configuration { get; } 19 | 20 | 21 | public void ConfigureServices(IServiceCollection services) 22 | { 23 | services.AddHttpReports().AddHttpTransport(); 24 | 25 | services.AddHttpReportsDashboard().AddMySqlStorage(); 26 | 27 | services.AddControllers(); 28 | services.AddSwaggerGen(c => 29 | { 30 | c.SwaggerDoc("v1", new OpenApiInfo { Title = "HttpReports.Demo", Version = "v1" }); 31 | }); 32 | 33 | } 34 | 35 | 36 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 37 | { 38 | app.UseHttpReports(); 39 | //app.UseMiddleware(); 40 | 41 | app.UseHttpReportsDashboard(); 42 | 43 | app.UseSwagger(); 44 | app.UseSwaggerUI(); 45 | 46 | app.UseRouting(); 47 | 48 | app.UseEndpoints(endpoints => 49 | { 50 | //endpoints.MapGrpcCollector(); 51 | endpoints.MapControllers(); 52 | 53 | }); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /test/HttpReports.Test/MysqlStorageTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using HttpReports.Core; 4 | using HttpReports.Storage.Abstractions; 5 | using HttpReports.Storage.MySql; 6 | 7 | using Microsoft.Extensions.DependencyInjection; 8 | using Microsoft.VisualStudio.TestTools.UnitTesting; 9 | 10 | namespace HttpReports.Test 11 | { 12 | [TestClass] 13 | public class MysqlStorageTest : StorageTest 14 | { 15 | private MySqlStorage _storage; 16 | 17 | public override IHttpReportsStorage Storage => _storage; 18 | 19 | 20 | [TestInitialize] 21 | public override async Task Init() 22 | { 23 | var services = new ServiceCollection(); 24 | services.AddOptions(); 25 | services.AddLogging(); 26 | 27 | services.Configure(o => 28 | { 29 | o.ConnectionString = "DataBase=HttpReports;Data Source=localhost;User Id=root;Password=123456;"; 30 | o.DeferSecond = 3; 31 | o.DeferThreshold = 5; 32 | }); 33 | services.AddTransient(); 34 | 35 | _storage = services.BuildServiceProvider().GetRequiredService(); 36 | await _storage.InitAsync(); 37 | } 38 | 39 | [TestMethod] 40 | public new async Task GetRequestInfoDetail() 41 | { 42 | var ids = new[] { 0L, 0L, 0L }; 43 | 44 | var id = ids[new Random().Next(0, ids.Length - 1)]; 45 | 46 | var result = await Storage.GetRequestInfo(id); 47 | 48 | Assert.IsTrue(true); 49 | } 50 | 51 | 52 | } 53 | } -------------------------------------------------------------------------------- /src/HttpReports.Collector.Grpc/HttpReports.Collector.Grpc.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | HttpReports is a lightweight APM system developed for .NET Core 6 | https://github.com/dotnetcore/HttpReports 7 | https://github.com/dotnetcore/HttpReports 8 | logo3.png 9 | true 10 | true 11 | true 12 | snupkg 13 | 14 | 15 | 16 | 17 | 18 | True 19 | 20 | 21 | 22 | 23 | 24 | 25 | all 26 | runtime; build; native; contentfiles; analyzers; buildtransitive 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/HttpReports.Transport.Http/HttpReports.Transport.Http.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | HttpReports is a lightweight APM system developed for .NET Core 6 | https://github.com/dotnetcore/HttpReports 7 | https://github.com/dotnetcore/HttpReports 8 | logo3.png 9 | true 10 | true 11 | true 12 | snupkg 13 | 14 | 15 | 16 | 17 | 18 | 19 | all 20 | runtime; build; native; contentfiles; analyzers; buildtransitive 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | True 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /test/HttpReports.Test/PostgreSQLStorageTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using HttpReports.Core; 4 | using HttpReports.Storage.Abstractions; 5 | using HttpReports.Storage.PostgreSQL; 6 | 7 | using Microsoft.Extensions.DependencyInjection; 8 | using Microsoft.VisualStudio.TestTools.UnitTesting; 9 | 10 | namespace HttpReports.Test 11 | { 12 | [TestClass] 13 | public class PostgreSQLStorageTest : StorageTest 14 | { 15 | private PostgreSQLStorage _storage; 16 | 17 | public override IHttpReportsStorage Storage => _storage; 18 | 19 | [TestInitialize] 20 | public override async Task Init() 21 | { 22 | var services = new ServiceCollection(); 23 | services.AddOptions(); 24 | services.AddLogging(); 25 | 26 | services.Configure(o => 27 | { 28 | o.ConnectionString = "Host=localhost;Port=5432;Username=postgres;Password=123456;Database=HttpReports;"; 29 | o.DeferSecond = 5; 30 | o.DeferThreshold = 5; 31 | 32 | 33 | }); 34 | services.AddTransient(); 35 | 36 | _storage = services.BuildServiceProvider().GetRequiredService(); 37 | await _storage.InitAsync(); 38 | } 39 | 40 | 41 | [TestMethod] 42 | public new async Task GetRequestInfoDetail() 43 | { 44 | var ids = new[] { 0 }; 45 | 46 | var id = ids[new Random().Next(0, ids.Length - 1)]; 47 | 48 | var result = await Storage.GetRequestInfo(id); 49 | 50 | Assert.IsNotNull(result); 51 | 52 | } 53 | 54 | } 55 | } -------------------------------------------------------------------------------- /example/HttpReports.Demo/HttpReports.Demo.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/Diagnostics/HttpReports.Diagnostic.MySqlConnector/MySqlConnectorDiagnosticListener.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Core; 2 | using HttpReports.Core.Diagnostics; 3 | using HttpReports.Storage.Abstractions; 4 | using Microsoft.Extensions.Logging; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Diagnostics; 8 | using System.Text; 9 | 10 | namespace HttpReports.Diagnostic.MySqlConnector 11 | { 12 | public class MySqlConnectorDiagnosticListener : DefaultTraceListener, IDiagnosticListener 13 | { 14 | private ILogger _logger; 15 | 16 | private IReportsTransport _transport; 17 | 18 | private ISegmentContext _context; 19 | 20 | private IHttpReportsStorage _storage; 21 | 22 | 23 | public MySqlConnectorDiagnosticListener(ILogger logger, IReportsTransport transport, ISegmentContext context) 24 | { 25 | _logger = logger; 26 | _transport = transport; 27 | _context = context; 28 | 29 | } 30 | 31 | public string ListenerName => "MySqlDiagnosticListener"; 32 | 33 | public IRequestChain Build(string Id) 34 | { 35 | return null; 36 | } 37 | 38 | public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args) 39 | { 40 | 41 | } 42 | 43 | public void OnCompleted() 44 | { 45 | 46 | } 47 | 48 | public void OnError(Exception error) 49 | { 50 | 51 | } 52 | 53 | public void OnNext(KeyValuePair value) 54 | { 55 | 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/HttpReports.Core/SegmentContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.Linq; 6 | using System.Text; 7 | 8 | namespace HttpReports.Core 9 | { 10 | public class SegmentContext:ISegmentContext 11 | { 12 | private ConcurrentDictionary> _concurrent; 13 | 14 | public SegmentContext() 15 | { 16 | _concurrent = new ConcurrentDictionary>(); 17 | } 18 | 19 | public List GetSegments(string Id) 20 | { 21 | List segments = new List(); 22 | 23 | _concurrent.TryGetValue(Id,out segments); 24 | 25 | return segments; 26 | } 27 | 28 | public bool Push(string Id, Segment segment) 29 | { 30 | if (_concurrent.ContainsKey(Id)) 31 | { 32 | List segments; 33 | 34 | _concurrent.TryGetValue(Id,out segments); 35 | 36 | _concurrent.TryRemove(Id,out _); 37 | 38 | segments.Add(segment); 39 | 40 | return _concurrent.TryAdd(Id, segments); 41 | 42 | } 43 | else 44 | { 45 | return _concurrent.TryAdd(Id,new List { segment }); 46 | } 47 | } 48 | 49 | public bool Release(string Id) => _concurrent.TryRemove(Id, out _); 50 | 51 | } 52 | 53 | public class Segment 54 | { 55 | public DateTime CreateTime { get; set; } 56 | 57 | public object Value { get; set; } 58 | 59 | public Activity activity { get; set; } 60 | 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/Protos/GrpcCollector.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option csharp_namespace = "HttpReports.Collector.Grpc"; 4 | 5 | service GrpcCollector { 6 | rpc WriteRequest (RequestInfoPack) returns (WriteReply); 7 | rpc WritePerformance (Performance) returns (WriteReply); 8 | } 9 | 10 | message RequestInfoPack { 11 | repeated RequestInfoWithDetail Data = 1; 12 | } 13 | 14 | message RequestInfoWithDetail { 15 | RequestInfo RequestInfo = 1; 16 | RequestDetail RequestDetail = 2; 17 | } 18 | 19 | message Performance { 20 | int64 Id = 1; 21 | string Service = 2; 22 | string Instance = 3; 23 | int32 GCGen0 = 4; 24 | int32 GCGen1 = 5; 25 | int32 GCGen2 = 6; 26 | double HeapMemory = 7; 27 | double ProcessCPU = 8; 28 | double ProcessMemory = 9; 29 | int32 ThreadCount = 10; 30 | int32 PendingThreadCount = 11; 31 | int64 CreateTimeStamp = 12; 32 | } 33 | 34 | 35 | 36 | message RequestInfo { 37 | int64 Id = 1; 38 | int64 ParentId = 2; 39 | string Service = 3; 40 | string ParentService = 4; 41 | string Instance = 5; 42 | string Route = 6; 43 | string Url = 7; 44 | string RequestType = 8; 45 | string Method = 9; 46 | int32 Milliseconds = 10; 47 | int32 StatusCode = 11; 48 | string RemoteIP = 12; 49 | string LoginUser = 13; 50 | int64 CreateTimeStamp = 14; 51 | } 52 | 53 | message RequestDetail { 54 | int64 Id = 1; 55 | int64 RequestId = 2; 56 | string Scheme = 3; 57 | string QueryString = 4; 58 | string Header = 5; 59 | string Cookie = 6; 60 | string RequestBody = 7; 61 | string ResponseBody = 8; 62 | string ErrorMessage = 9; 63 | string ErrorStack = 10; 64 | int64 CreateTimeStamp = 11; 65 | } 66 | 67 | 68 | message WriteReply { 69 | int32 code = 1; 70 | } 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /test/HttpReports.Test/SQLServerStorageTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using HttpReports.Core; 4 | using HttpReports.Storage.Abstractions; 5 | using HttpReports.Storage.SQLServer; 6 | 7 | using Microsoft.Extensions.DependencyInjection; 8 | using Microsoft.VisualStudio.TestTools.UnitTesting; 9 | 10 | namespace HttpReports.Test 11 | { 12 | [TestClass] 13 | public class SQLServerStorageTest : StorageTest 14 | { 15 | private SQLServerStorage _storage; 16 | 17 | public override IHttpReportsStorage Storage => _storage; 18 | 19 | [TestInitialize] 20 | public override async Task Init() 21 | { 22 | var services = new ServiceCollection(); 23 | services.AddOptions(); 24 | services.AddLogging(); 25 | 26 | services.Configure(o => 27 | { 28 | o.ConnectionString = "Max Pool Size = 512;server=localhost;uid=sa;pwd=123456;database=HttpReports;Connection Timeout=900;"; 29 | o.DeferSecond = 5; 30 | o.DeferThreshold = 5; 31 | }); 32 | services.AddSingleton(); 33 | 34 | _storage = services.BuildServiceProvider().GetRequiredService(); 35 | await _storage.InitAsync(); 36 | } 37 | 38 | 39 | 40 | [TestMethod] 41 | public new async Task GetRequestInfoDetail() 42 | { 43 | var ids = new[] { 0L, 0L, 0L }; 44 | 45 | var id = ids[new Random().Next(0, ids.Length - 1)]; 46 | 47 | var result = await Storage.GetRequestInfo(id); 48 | 49 | Assert.IsNotNull(result); 50 | 51 | } 52 | 53 | } 54 | } -------------------------------------------------------------------------------- /src/Diagnostics/HttpReports.Diagnostic.MySqlData/MySqlDataDiagnosticListener.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Core; 2 | using HttpReports.Core.Diagnostics; 3 | using Microsoft.Extensions.Logging; 4 | using MySql.Data.MySqlClient; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Diagnostics; 8 | using System.Text; 9 | 10 | namespace HttpReports.Diagnostic.MySqlData 11 | { 12 | public class MySqlDataDiagnosticListener : DefaultTraceListener, IDiagnosticListener 13 | { 14 | private ILogger _logger; 15 | 16 | private IReportsTransport _transport; 17 | 18 | private ISegmentContext _context; 19 | 20 | public MySqlDataDiagnosticListener(ILogger logger, IReportsTransport transport, ISegmentContext context) 21 | { 22 | _logger = logger; 23 | _transport = transport; 24 | _context = context; 25 | 26 | MySqlTrace.Listeners.Clear(); 27 | MySqlTrace.Listeners.Add(this); 28 | MySqlTrace.Switch.Level = SourceLevels.Information; 29 | MySqlTrace.QueryAnalysisEnabled = true; 30 | 31 | } 32 | 33 | public string ListenerName => "MySqlDiagnosticListener"; 34 | 35 | public IRequestChain Build(string Id) 36 | { 37 | return null; 38 | } 39 | 40 | public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args) 41 | { 42 | 43 | } 44 | 45 | public void OnCompleted() 46 | { 47 | 48 | } 49 | 50 | public void OnError(Exception error) 51 | { 52 | 53 | } 54 | 55 | public void OnNext(KeyValuePair value) 56 | { 57 | 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/HttpReports.Transport.Grpc/HttpReports.Transport.Grpc.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.1 5 | HttpReports is a lightweight APM system developed for .NET Core 6 | https://github.com/dotnetcore/HttpReports 7 | https://github.com/dotnetcore/HttpReports 8 | logo3.png 9 | true 10 | true 11 | true 12 | snupkg 13 | 14 | 15 | 16 | 17 | 18 | True 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | all 27 | runtime; build; native; contentfiles; analyzers; buildtransitive 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /example/HttpReports.Collector.Demo/Startup.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Transport.Http; 2 | using Microsoft.AspNetCore.Builder; 3 | using Microsoft.AspNetCore.Hosting; 4 | using Microsoft.AspNetCore.Http; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.Hosting; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Linq; 11 | using System.Threading.Tasks; 12 | 13 | namespace HttpReports.Collector.Demo 14 | { 15 | public class Startup 16 | { 17 | public Startup(IConfiguration configuration) 18 | { 19 | Configuration = configuration; 20 | } 21 | /// 22 | /// 23 | /// 24 | public IConfiguration Configuration { get; } 25 | 26 | public void ConfigureServices(IServiceCollection services) 27 | { 28 | //services.AddHttpReports().AddHttpTransport(); 29 | services.Configure(Configuration.GetSection("HttpReports")); 30 | services.Configure(Configuration.GetSection("HttpReports").GetSection("Transport")); 31 | services.AddHttpReports().AddHttpTransport(); 32 | } 33 | 34 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 35 | { 36 | app.UseHttpReports(); 37 | 38 | if (env.IsDevelopment()) 39 | { 40 | app.UseDeveloperExceptionPage(); 41 | } 42 | 43 | app.UseRouting(); 44 | 45 | app.UseEndpoints(endpoints => 46 | { 47 | endpoints.MapGet("/", async context => 48 | { 49 | await context.Response.WriteAsync("Hello World!"); 50 | }); 51 | }); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuex from 'vuex'; 3 | 4 | Vue.use(Vuex); 5 | import { basic } from '@/common/basic.js' 6 | 7 | const store = new Vuex.Store({ 8 | state: { 9 | tag: {}, 10 | token: "", 11 | lang: {}, 12 | route:"/", 13 | query:{ 14 | service:"", 15 | instance:"", 16 | start:basic.dateFormat(basic.getLastTime()), 17 | end:basic.dateFormat(new Date()) 18 | }, 19 | basic_loading:false, 20 | service_loading:false, 21 | detail_loading:false, 22 | topology_loading:false, 23 | alarm_loading:false, 24 | health_loading:false, 25 | index_loading_timestamp:0 26 | }, 27 | mutations: { 28 | set_token: (state, data) => state.token = data, 29 | set_lang: (state, data) => { 30 | state.lang = data; 31 | }, 32 | set_tag: (state, data) => state.tag = data, 33 | set_query(state,data) { 34 | 35 | if (data != null) { 36 | if (data.service == "ALL") { 37 | data.service = ""; 38 | } 39 | 40 | if (data.instance == "ALL") { 41 | data.instance = ""; 42 | } 43 | 44 | } 45 | 46 | state.query = data; 47 | 48 | }, 49 | set_basic_loading:(state,data) => state.basic_loading = data, 50 | set_detail_loading:(state,data) => state.detail_loading = data, 51 | set_topology_loading:(state,data) => state.topology_loading = data, 52 | set_service_loading:(state,data) => state.service_loading = data, 53 | set_alarm_loading:(state,data) => state.alarm_loading = data, 54 | set_health_loading:(state,data) => state.health_loading = data, 55 | set_index_loading_timestamp:(state,data) => state.index_loading_timestamp = data, 56 | set_route:(state,data) => state.route = data, 57 | 58 | } 59 | 60 | }) 61 | 62 | export default store; 63 | 64 | -------------------------------------------------------------------------------- /src/Storage/HttpReports.Storage.Postgre/HttpReports.Storage.PostgreSQL.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | HttpReports.PostgreSQL 6 | SpringLee 7 | SpringLee 8 | HttpReports is a lightweight APM system developed for .NET Core 9 | https://github.com/dotnetcore/HttpReports 10 | https://github.com/dotnetcore/HttpReports 11 | HttpReports.Storage.PostgreSQL 12 | HttpReports.PostgreSQL 13 | logo3.png 14 | true 15 | true 16 | true 17 | snupkg 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | True 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/HttpReports.Core/HttpReports.Core.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | HttpReports.Core 6 | HttpReports is a lightweight APM system developed for .NET Core 7 | https://github.com/dotnetcore/HttpReports 8 | https://github.com/dotnetcore/HttpReports 9 | SpringLee 10 | logo3.png 11 | true 12 | true 13 | true 14 | snupkg 15 | true 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | True 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/Storage/HttpReports.Storage.MySQL/HttpReports.Storage.MySql.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | HttpReports.MySQL 6 | SpringLee 7 | SpringLee 8 | HttpReports is a lightweight APM system developed for .NET Core 9 | https://github.com/dotnetcore/HttpReports 10 | https://github.com/dotnetcore/HttpReports 11 | logo3.png 12 | true 13 | true 14 | true 15 | snupkg 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | True 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/Storage/HttpReports.Storage.SQLServer/HttpReports.Storage.SQLServer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | HttpReports.SQLServer 6 | SpringLee 7 | SpringLee 8 | HttpReports is a lightweight APM system developed for .NET Core 9 | https://github.com/dotnetcore/HttpReports 10 | https://github.com/dotnetcore/HttpReports 11 | logo3.png 12 | true 13 | true 14 | true 15 | snupkg 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | True 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | 4 | import Login from '@/view/login' 5 | import Index from '@/view/index' 6 | import Basic from '@/view/basic' 7 | import Service from '@/view/service' 8 | import Detail from '@/view/detail' 9 | import Alarm from '@/view/alarm' 10 | import Topology from '@/view/topology' 11 | import Health from '@/view/health' 12 | import LimitApi from '@/view/limitapi' 13 | import roleBasedAccess from '@/view/roleBasedAccess' 14 | 15 | Vue.use(Router) 16 | 17 | //push 18 | const VueRouterPush = Router.prototype.push 19 | Router.prototype.push = function push (to) { 20 | return VueRouterPush.call(this, to).catch(err => err) 21 | } 22 | 23 | //replace 24 | const VueRouterReplace = Router.prototype.replace 25 | Router.prototype.replace = function replace (to) { 26 | return VueRouterReplace.call(this, to).catch(err => err) 27 | } 28 | 29 | 30 | export default new Router({ 31 | routes: [ 32 | { 33 | path: '/', 34 | name: 'index', 35 | component: Index, 36 | children: [ 37 | { 38 | path: '/', 39 | component: Basic 40 | }, 41 | { 42 | path: '/service', 43 | component: Service 44 | }, 45 | { 46 | path: '/topology', 47 | component: Topology 48 | }, 49 | { 50 | path: '/detail', 51 | component: Detail 52 | }, 53 | { 54 | path: '/alarm', 55 | component: Alarm 56 | }, 57 | { 58 | path: '/health', 59 | component: Health 60 | }, 61 | { 62 | path: '/limitapi', 63 | component: LimitApi 64 | }, 65 | { 66 | path: '/rolebasedaccess', 67 | component: roleBasedAccess 68 | } 69 | ] 70 | }, 71 | { 72 | path: '/login', 73 | name: 'login', 74 | component: Login 75 | } 76 | ] 77 | }) 78 | 79 | 80 | -------------------------------------------------------------------------------- /src/HttpReports.Transport.Grpc/DependencyInjectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using HttpReports; 2 | using HttpReports.Transport.Grpc; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using Microsoft.Extensions.DependencyInjection.Extensions; 5 | using System; 6 | 7 | namespace Microsoft.Extensions.DependencyInjection 8 | { 9 | public static class DependencyInjectionExtensions 10 | { 11 | public static IHttpReportsBuilder AddGrpcTransport(this IHttpReportsBuilder builder) 12 | { 13 | builder.Services.AddOptions().Configure(builder.Configuration.GetSection("Transport")); 14 | return builder.AddGrpcTransportService(); 15 | } 16 | 17 | public static IHttpReportsBuilder AddGrpcTransport(this IHttpReportsBuilder builder, Action options) 18 | { 19 | builder.Services.AddOptions().Configure(options); 20 | return builder.AddGrpcTransportService(); 21 | } 22 | 23 | private static IHttpReportsBuilder AddGrpcTransportService(this IHttpReportsBuilder builder) 24 | { 25 | builder.Services.RemoveAll(); 26 | builder.Services.AddSingleton(); 27 | return builder; 28 | } 29 | 30 | 31 | [Obsolete("Use AddGrpcTransport instead")] 32 | public static IHttpReportsBuilder UseGrpcTransport(this IHttpReportsBuilder builder) 33 | { 34 | builder.Services.AddOptions().Configure(builder.Configuration.GetSection("Transport")); 35 | return builder.AddGrpcTransportService(); 36 | } 37 | 38 | 39 | [Obsolete("Use AddGrpcTransport instead")] 40 | public static IHttpReportsBuilder UseGrpcTransport(this IHttpReportsBuilder builder, Action options) 41 | { 42 | builder.Services.AddOptions().Configure(options); 43 | return builder.AddGrpcTransportService(); 44 | } 45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Storage/HttpReports.Storage.SQLServer/ServiceBuildExtensions.cs: -------------------------------------------------------------------------------- 1 | using HttpReports; 2 | using HttpReports.Core; 3 | using HttpReports.Storage.Abstractions; 4 | using HttpReports.Storage.SQLServer; 5 | using System; 6 | 7 | namespace Microsoft.Extensions.DependencyInjection 8 | { 9 | public static class ServiceBuildExtensions 10 | { 11 | public static IHttpReportsBuilder AddSQLServerStorage(this IHttpReportsBuilder builder) 12 | { 13 | builder.Services.AddOptions(); 14 | builder.Services.Configure(builder.Configuration.GetSection("Storage")); 15 | 16 | return builder.AddSQLServerStorageService(); 17 | } 18 | 19 | public static IHttpReportsBuilder AddSQLServerStorage(this IHttpReportsBuilder builder,Action options) 20 | { 21 | builder.Services.AddOptions(); 22 | builder.Services.Configure(options); 23 | 24 | return builder.AddSQLServerStorageService(); 25 | } 26 | 27 | private static IHttpReportsBuilder AddSQLServerStorageService(this IHttpReportsBuilder builder) 28 | { 29 | builder.Services.AddSingleton(); 30 | 31 | return builder; 32 | } 33 | 34 | 35 | [Obsolete("Use AddSQLServerStorage instead")] 36 | public static IHttpReportsBuilder UseSQLServerStorage(this IHttpReportsBuilder builder) 37 | { 38 | builder.Services.AddOptions(); 39 | builder.Services.Configure(builder.Configuration.GetSection("Storage")); 40 | 41 | return builder.AddSQLServerStorageService(); 42 | } 43 | 44 | 45 | [Obsolete("Use AddSQLServerStorage instead")] 46 | public static IHttpReportsBuilder UseSQLServerStorage(this IHttpReportsBuilder builder, Action options) 47 | { 48 | builder.Services.AddOptions(); 49 | builder.Services.Configure(options); 50 | 51 | return builder.AddSQLServerStorageService(); 52 | } 53 | 54 | 55 | 56 | } 57 | } -------------------------------------------------------------------------------- /src/Storage/HttpReports.Storage.MySQL/ServiceBuildExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.CompilerServices; 3 | 4 | using HttpReports; 5 | using HttpReports.Core; 6 | using HttpReports.Storage.Abstractions; 7 | using HttpReports.Storage.MySql; 8 | 9 | [assembly: InternalsVisibleTo("HttpReports.Test")] 10 | 11 | namespace Microsoft.Extensions.DependencyInjection 12 | { 13 | public static class ServiceBuildExtensions 14 | { 15 | 16 | 17 | public static IHttpReportsBuilder AddMySqlStorage(this IHttpReportsBuilder builder,Action options) 18 | { 19 | builder.Services.AddOptions(); 20 | builder.Services.Configure(options); 21 | 22 | return builder.AddMySqlStorageService(); 23 | } 24 | 25 | internal static IHttpReportsBuilder AddMySqlStorageService(this IHttpReportsBuilder builder) 26 | { 27 | builder.Services.AddSingleton(); 28 | 29 | return builder; 30 | 31 | } 32 | 33 | 34 | public static IHttpReportsBuilder AddMySqlStorage(this IHttpReportsBuilder builder) 35 | { 36 | builder.Services.AddOptions(); 37 | builder.Services.Configure(builder.Configuration.GetSection("Storage")); 38 | return builder.AddMySqlStorageService(); 39 | } 40 | 41 | [Obsolete("Use AddMySqlStorage instead")] 42 | public static IHttpReportsBuilder UseMySqlStorage(this IHttpReportsBuilder builder) 43 | { 44 | builder.Services.AddOptions(); 45 | builder.Services.Configure(builder.Configuration.GetSection("Storage")); 46 | return builder.AddMySqlStorageService(); 47 | } 48 | 49 | 50 | [Obsolete("Use AddMySqlStorage instead")] 51 | public static IHttpReportsBuilder UseMySqlStorage(this IHttpReportsBuilder builder, Action options) 52 | { 53 | builder.Services.AddOptions(); 54 | builder.Services.Configure(options); 55 | 56 | return builder.AddMySqlStorageService(); 57 | } 58 | 59 | 60 | 61 | } 62 | } -------------------------------------------------------------------------------- /src/Storage/HttpReports.Storage.Postgre/ServiceBuildExtensions.cs: -------------------------------------------------------------------------------- 1 | using HttpReports; 2 | using HttpReports.Core; 3 | using HttpReports.Storage.Abstractions; 4 | using HttpReports.Storage.PostgreSQL; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | 9 | namespace Microsoft.Extensions.DependencyInjection 10 | { 11 | public static class ServiceBuildExtensions 12 | { 13 | public static IHttpReportsBuilder AddPostgreSQLStorage(this IHttpReportsBuilder builder) 14 | { 15 | builder.Services.AddOptions(); 16 | builder.Services.Configure(builder.Configuration.GetSection("Storage")); 17 | 18 | return builder.AddPostgreSQLStorageService(); 19 | } 20 | 21 | public static IHttpReportsBuilder AddPostgreSQLStorage(this IHttpReportsBuilder builder,Action options) 22 | { 23 | builder.Services.AddOptions(); 24 | builder.Services.Configure(options); 25 | 26 | return builder.AddPostgreSQLStorageService(); 27 | } 28 | 29 | internal static IHttpReportsBuilder AddPostgreSQLStorageService(this IHttpReportsBuilder builder) 30 | { 31 | builder.Services.AddSingleton(); 32 | 33 | return builder; 34 | } 35 | 36 | 37 | [Obsolete("Use AddPostgreSQLStorage instead")] 38 | public static IHttpReportsBuilder UsePostgreSQLStorage(this IHttpReportsBuilder builder) 39 | { 40 | builder.Services.AddOptions(); 41 | builder.Services.Configure(builder.Configuration.GetSection("Storage")); 42 | 43 | return builder.AddPostgreSQLStorageService(); 44 | } 45 | 46 | 47 | [Obsolete("Use AddPostgreSQLStorage instead")] 48 | public static IHttpReportsBuilder UsePostgreSQLStorage(this IHttpReportsBuilder builder, Action options) 49 | { 50 | builder.Services.AddOptions(); 51 | builder.Services.Configure(options); 52 | 53 | return builder.AddPostgreSQLStorageService(); 54 | } 55 | 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/HttpReports.Transport.Http/DependencyInjectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using HttpReports; 2 | using HttpReports.Core; 3 | using HttpReports.Transport.Http; 4 | using Microsoft.Extensions.Configuration; 5 | using Microsoft.Extensions.DependencyInjection.Extensions; 6 | using System; 7 | 8 | namespace Microsoft.Extensions.DependencyInjection 9 | { 10 | public static class DependencyInjectionExtensions 11 | { 12 | [Obsolete("Use AddHttpTransport instead")] 13 | public static IHttpReportsBuilder UseHttpTransport(this IHttpReportsBuilder builder) 14 | { 15 | builder.Services.AddOptions().Configure(builder.Configuration.GetSection("Transport")); 16 | return builder.AddHttpTransportService(); 17 | } 18 | 19 | [Obsolete("Use AddHttpTransport instead")] 20 | public static IHttpReportsBuilder UseHttpTransport(this IHttpReportsBuilder builder, Action options) 21 | { 22 | builder.Services.AddOptions().Configure(options); 23 | return builder.AddHttpTransportService(); 24 | } 25 | 26 | public static IHttpReportsBuilder AddHttpTransport(this IHttpReportsBuilder builder) 27 | { 28 | builder.Services.AddOptions().Configure(builder.Configuration.GetSection("Transport")); 29 | return builder.AddHttpTransportService(); 30 | } 31 | 32 | public static IHttpReportsBuilder AddHttpTransport(this IHttpReportsBuilder builder, Action options) 33 | { 34 | builder.Services.AddOptions().Configure(options); 35 | return builder.AddHttpTransportService(); 36 | } 37 | 38 | private static IHttpReportsBuilder AddHttpTransportService(this IHttpReportsBuilder builder) 39 | { 40 | builder.Services.AddHttpClient(BasicConfig.HttpReportsHttpClient, client => 41 | { 42 | client.DefaultRequestHeaders.Clear(); 43 | client.Timeout = TimeSpan.FromSeconds(5); 44 | 45 | }); 46 | 47 | builder.Services.RemoveAll(); 48 | builder.Services.AddSingleton(); 49 | return builder; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Handles/DashboardEmbeddedFiles.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Core; 2 | using Microsoft.AspNetCore.Http; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Net; 8 | using System.Reflection; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | namespace HttpReports.Dashboard.Handles 13 | { 14 | public class DashboardEmbeddedFiles 15 | { 16 | static readonly Dictionary ResponseType = new Dictionary 17 | { 18 | { ".css","text/css"}, 19 | { ".html","text/html"}, 20 | { ".ico","image/x-icon"}, 21 | { ".png","image/png"}, 22 | { ".jpg","image/jpg"}, 23 | { ".js","application/javascript"}, 24 | { ".json","application/json;charset=utf-8"}, 25 | {".woff2","font/woff2" }, 26 | {".woff","font/woff" }, 27 | {".ttf","application/octet-stream" }, 28 | {".map","application/octet-stream" } 29 | }; 30 | 31 | private static Assembly _assembly; 32 | 33 | static DashboardEmbeddedFiles() 34 | { 35 | _assembly = Assembly.GetExecutingAssembly(); 36 | } 37 | 38 | public static async Task IncludeEmbeddedFile(HttpContext context, string path) 39 | { 40 | 41 | context.Response.OnStarting(() => 42 | { 43 | if (context.Response.StatusCode == (int)HttpStatusCode.OK) 44 | { 45 | context.Response.ContentType = ResponseType[Path.GetExtension(path)]; 46 | } 47 | 48 | return Task.CompletedTask; 49 | }); 50 | 51 | path = BasicConfig.StaticFilesRoot + path.Replace("/","."); 52 | 53 | var list = _assembly.GetManifestResourceNames().ToList(); 54 | 55 | using (var inputStream = _assembly.GetManifestResourceStream(path)) 56 | { 57 | if (inputStream == null) 58 | { 59 | context.Response.StatusCode = (int)HttpStatusCode.NotFound; 60 | return; 61 | } 62 | await inputStream.CopyToAsync(context.Response.Body).ConfigureAwait(false); 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /example/HttpReports.Demo/Controllers/TraceController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Net.Http; 6 | using System.Threading.Tasks; 7 | 8 | namespace HttpReports.Demo.Controllers 9 | { 10 | [Route("[controller]/[action]")] 11 | public class TraceController : Controller 12 | { 13 | //private readonly string url = "http://122.51.188.23:8080"; 14 | private readonly string url = "http://localhost:5010"; 15 | 16 | [HttpGet] 17 | public async Task Get() 18 | { 19 | await Task.Delay(new Random().Next(100,1000)); 20 | 21 | HttpClient client = new HttpClient(); 22 | 23 | var result = await client.GetStringAsync($"{url}/Trace/Get1"); 24 | 25 | return Content(result); 26 | 27 | } 28 | 29 | 30 | [HttpGet] 31 | public async Task Get1() 32 | { 33 | var c = HttpContext; 34 | 35 | await Task.Delay(new Random().Next(100, 1000)); 36 | 37 | HttpClient client = new HttpClient(); 38 | 39 | _ = Task.Run(async ()=> { 40 | 41 | var result = await client.GetStringAsync($"{url}/Trace/Get4"); 42 | 43 | }); 44 | 45 | 46 | var result = await client.GetStringAsync($"{url}/Trace/Get2"); 47 | 48 | return Content(result); 49 | 50 | } 51 | 52 | 53 | [HttpGet] 54 | public async Task Get2() 55 | { 56 | await Task.Delay(new Random().Next(100, 1000)); 57 | 58 | HttpClient client = new HttpClient(); 59 | 60 | var result = await client.GetStringAsync($"{url}/Trace/Get3"); 61 | 62 | return Content(result); 63 | 64 | } 65 | 66 | 67 | [HttpGet] 68 | public async Task Get3() 69 | { 70 | await Task.Delay(new Random().Next(100, 1000)); 71 | 72 | return Ok(new { code = 1,msg = "ok" }); 73 | 74 | } 75 | 76 | 77 | [HttpGet] 78 | public async Task Get4() 79 | { 80 | await Task.Delay(new Random().Next(5000, 8000)); 81 | 82 | return Ok(new { code = 1, msg = "ok" }); 83 | 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/src/assets/css/web.css: -------------------------------------------------------------------------------- 1 | 2 | /*==================== 网站基本样式 ==========================*/ 3 | 4 | body{ 5 | 6 | margin: 0; 7 | 8 | } 9 | 10 | 11 | .icon-rounded { 12 | width: 52px; 13 | height: 52px; 14 | line-height: 52px; 15 | display: inline-block; 16 | text-align: center; 17 | color: #ffffff; 18 | border-radius: 50%; 19 | font-size: 26px; 20 | margin-top: 12px; 21 | } 22 | 23 | .pull-right { 24 | float: right; 25 | margin-left: 5%; 26 | } 27 | 28 | .pull-left { 29 | float: left; 30 | margin-right: 5%; 31 | } 32 | 33 | .stats { 34 | display: block; 35 | overflow: hidden; 36 | } 37 | 38 | .stats h5 { 39 | margin: 10px 0 5px 0; 40 | color: #000; 41 | font-weight: 600; 42 | font-size: 20px; 43 | } 44 | 45 | .stats span { 46 | color: #777; 47 | font-size: 16px; 48 | } 49 | 50 | .bgc1 { 51 | background-color: #7460ee; 52 | } 53 | 54 | .bgc2 { 55 | background-color: #fc4b6c; 56 | } 57 | 58 | .bgc3 { 59 | background-color: #1e88e5; 60 | } 61 | 62 | .bgc4 { 63 | background-color: #ffb22b; 64 | } 65 | 66 | .bgc5 { 67 | background-color: #00ad45; 68 | } 69 | 70 | .navbar-right { 71 | float: right; 72 | margin-top: -60px; 73 | } 74 | 75 | .navbar-right .nav-item { 76 | float: right; 77 | margin-left: 12px; 78 | } 79 | 80 | .navbar-right .nav-user span { 81 | color: #fff; 82 | } 83 | 84 | 85 | .nav-item { 86 | cursor: pointer; 87 | } 88 | 89 | .navbar-left { 90 | display: block; 91 | float: left; 92 | text-align: center; 93 | } 94 | 95 | .navbar-left .logo { 96 | width:200px; 97 | } 98 | 99 | 100 | .navbar-left .title { 101 | width: 64px; 102 | } 103 | 104 | .el-header { 105 | padding: 0; 106 | background-color:#2b3852 !important; 107 | } 108 | 109 | .navbar-center .arrow { 110 | 111 | padding: 5px; 112 | color:#fbf8f8; 113 | font-size: 20px; 114 | cursor: pointer; 115 | margin-left: 15px; 116 | margin-right: 0; 117 | margin-top: 16px; 118 | } 119 | 120 | .navbar-center .refresh { 121 | 122 | padding: 5px; 123 | color:#fbf8f8; 124 | font-size: 20px; 125 | cursor: pointer; 126 | margin-top: 16px; 127 | } 128 | 129 | .box-card{ 130 | 131 | margin-top: 20px; 132 | 133 | } 134 | -------------------------------------------------------------------------------- /src/Diagnostics/HttpReports.Diagnostic.AspNetCore/AspNetCoreDiagnosticListener.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Core; 2 | using HttpReports.Core.Diagnostics; 3 | using Microsoft.AspNetCore.Http; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Logging; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Net; 9 | using System.Text; 10 | 11 | namespace HttpReports.Diagnostic.AspNetCore 12 | { 13 | public class AspNetCoreDiagnosticListener : IDiagnosticListener 14 | { 15 | private ILogger _logger; 16 | 17 | private IReportsTransport _transport; 18 | 19 | private ISegmentContext _context; 20 | private IHttpContextAccessor _httpContextAccessor; 21 | 22 | 23 | public AspNetCoreDiagnosticListener(ILogger logger, IReportsTransport transport, ISegmentContext context,IHttpContextAccessor httpContextAccessor) 24 | { 25 | _logger = logger; 26 | _transport = transport; 27 | _context = context; 28 | _httpContextAccessor = httpContextAccessor; 29 | } 30 | 31 | 32 | public string ListenerName => "Microsoft.AspNetCore"; 33 | 34 | public void OnCompleted() 35 | { 36 | 37 | } 38 | 39 | public void OnError(Exception error) 40 | { 41 | 42 | } 43 | 44 | public void OnNext(KeyValuePair value) 45 | { 46 | if (value.Key == "Microsoft.AspNetCore.Diagnostics.UnhandledException" || value.Key == "Microsoft.AspNetCore.Hosting.UnhandledException") 47 | { 48 | HttpContext context = _httpContextAccessor.HttpContext; 49 | 50 | if (value.Value.GetType().GetProperty("exception").GetValue(value.Value) is Exception exception) 51 | { 52 | if (context != null && exception != null) 53 | { 54 | if (!context.Items.ContainsKey(BasicConfig.HttpReportsGlobalException)) 55 | { 56 | context.Items.Add(BasicConfig.HttpReportsGlobalException, exception); 57 | 58 | } 59 | } 60 | } 61 | } 62 | 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/config/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | // Template version: 1.3.1 3 | // see http://vuejs-templates.github.io/webpack for documentation. 4 | 5 | const path = require('path') 6 | 7 | module.exports = { 8 | dev: { 9 | 10 | // Paths 11 | assetsSubDirectory: 'static', 12 | assetsPublicPath: '/', 13 | proxyTable: {}, 14 | 15 | // Various Dev Server settings 16 | host: 'localhost', // can be overwritten by process.env.HOST 17 | port: 5050, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined 18 | autoOpenBrowser: false, 19 | errorOverlay: true, 20 | notifyOnErrors: true, 21 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- 22 | 23 | 24 | /** 25 | * Source Maps 26 | */ 27 | 28 | // https://webpack.js.org/configuration/devtool/#development 29 | devtool: 'cheap-module-eval-source-map', 30 | 31 | // If you have problems debugging vue-files in devtools, 32 | // set this to false - it *may* help 33 | // https://vue-loader.vuejs.org/en/options.html#cachebusting 34 | cacheBusting: true, 35 | 36 | cssSourceMap: true 37 | }, 38 | 39 | build: { 40 | // Template for index.html 41 | index: path.resolve(__dirname, '../../HttpReports.Dashboard/HttpReportsStaticFiles/UI/index.html'), 42 | 43 | // Paths 44 | assetsRoot: path.resolve(__dirname, '../../HttpReports.Dashboard/HttpReportsStaticFiles/UI'), 45 | assetsSubDirectory: 'static', 46 | assetsPublicPath: '/', 47 | 48 | /** 49 | * Source Maps 50 | */ 51 | 52 | productionSourceMap: true, 53 | // https://webpack.js.org/configuration/devtool/#production 54 | devtool: '#source-map', 55 | 56 | // Gzip off by default as many popular static hosts such as 57 | // Surge or Netlify already gzip all static assets for you. 58 | // Before setting to `true`, make sure to: 59 | // npm install --save-dev compression-webpack-plugin 60 | productionGzip: false, 61 | productionGzipExtensions: ['js', 'css'], 62 | 63 | // Run the build command with an extra argument to 64 | // View the bundle analyzer report after build finishes: 65 | // `npm run build --report` 66 | // Set to `true` or `false` to always turn it on or off 67 | bundleAnalyzerReport: process.env.npm_config_report 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/src/common/basic.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | const basic = { 4 | DOMAIN:"http://127.0.0.1:5005/api", 5 | isEmpty: (str) => { 6 | 7 | if (str == null || str == undefined || str.length == 0) { 8 | return true; 9 | } 10 | else { 11 | return false; 12 | } 13 | 14 | }, 15 | 16 | ToInt:(str) => { 17 | 18 | if (str == null || str == undefined || str.length == 0) { 19 | return 0; 20 | } 21 | 22 | try { 23 | 24 | return parseInt(str); 25 | 26 | } catch (error) { 27 | return 0 28 | } 29 | 30 | }, 31 | 32 | isMobile: (str) => { 33 | if (!(/^1(3|4|5|6|7|8|9)\d{9}$/.test(str))) { 34 | return false; 35 | } 36 | else { 37 | return true; 38 | } 39 | }, 40 | 41 | isEmail: (str) => { 42 | 43 | if (!(/^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/.test(str))) { 44 | return false; 45 | } 46 | else { 47 | return true; 48 | } 49 | }, 50 | getTimeSpan() { 51 | return Math.round(new Date().getTime() / 1000); 52 | }, 53 | dateFormat(time) { 54 | var date = new Date(time); 55 | var year = date.getFullYear(); 56 | /* 在日期格式中,月份是从0开始的,因此要加0 57 | * 使用三元表达式在小于10的前面加0,以达到格式统一 如 09:11:05 58 | * */ 59 | var month = date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1; 60 | var day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate(); 61 | var hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours(); 62 | var minutes = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes(); 63 | var seconds = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds(); 64 | // 拼接 65 | return year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds; 66 | }, 67 | getLastTime(minutes = 30){ 68 |         var now = new Date; 69 |         now.setMinutes (now.getMinutes () - minutes); 70 |         return now; 71 | }, 72 | 73 | addSecond(now,second){ 74 |         now.setSeconds(now.getSeconds() + second); 75 |         return now; 76 | }, 77 | 78 | 79 | numberFormat(val){ 80 | 81 | if(val >= 1000000){ 82 | 83 | val = val.substring(0,val.length - 4) + "w" 84 | return val 85 | 86 | } 87 | 88 | return val; 89 | 90 | } 91 | 92 | }; 93 | 94 | export { basic } 95 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const utils = require('./utils') 4 | const config = require('../config') 5 | const vueLoaderConfig = require('./vue-loader.conf') 6 | 7 | function resolve (dir) { 8 | return path.join(__dirname, '..', dir) 9 | } 10 | 11 | 12 | 13 | module.exports = { 14 | context: path.resolve(__dirname, '../'), 15 | entry: { 16 | app: './src/main.js' 17 | }, 18 | output: { 19 | path: config.build.assetsRoot, 20 | filename: '[name].js', 21 | publicPath: process.env.NODE_ENV === 'production' 22 | ? config.build.assetsPublicPath 23 | : config.dev.assetsPublicPath 24 | }, 25 | resolve: { 26 | extensions: ['.js', '.vue', '.json'], 27 | alias: { 28 | 'vue$': 'vue/dist/vue.esm.js', 29 | '@': resolve('src'), 30 | } 31 | }, 32 | module: { 33 | rules: [ 34 | { 35 | test: /\.vue$/, 36 | loader: 'vue-loader', 37 | options: vueLoaderConfig 38 | }, 39 | { 40 | test: /\.js$/, 41 | loader: 'babel-loader', 42 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')] 43 | }, 44 | { 45 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 46 | loader: 'url-loader', 47 | options: { 48 | limit: 10000, 49 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 50 | } 51 | }, 52 | { 53 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, 54 | loader: 'url-loader', 55 | options: { 56 | limit: 10000, 57 | name: utils.assetsPath('media/[name].[hash:7].[ext]') 58 | } 59 | }, 60 | { 61 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 62 | loader: 'url-loader', 63 | options: { 64 | limit: 10000, 65 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 66 | } 67 | } 68 | ] 69 | }, 70 | node: { 71 | // prevent webpack from injecting useless setImmediate polyfill because Vue 72 | // source contains it (although only uses it if it's native). 73 | setImmediate: false, 74 | // prevent webpack from injecting mocks to Node native modules 75 | // that does not make sense for the client 76 | dgram: 'empty', 77 | fs: 'empty', 78 | net: 'empty', 79 | tls: 'empty', 80 | child_process: 'empty' 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Routes/RouteCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace HttpReports.Dashboard.Routes 7 | { 8 | public class RouteCollection 9 | { 10 | private static readonly List Routes = new List(); 11 | 12 | public void AddRoute(DashboardRoute route) 13 | { 14 | if (route == null) 15 | { 16 | throw new ArgumentNullException(nameof(route)); 17 | } 18 | 19 | if (string.IsNullOrWhiteSpace(route.Key)) 20 | { 21 | throw new ArgumentNullException("route key can not be null"); 22 | } 23 | 24 | if (route.HtmlView) 25 | { 26 | if (route.View == null) 27 | { 28 | throw new ArgumentNullException("route view can not be null"); 29 | } 30 | } 31 | 32 | 33 | if (string.IsNullOrWhiteSpace(route.Handle) || string.IsNullOrWhiteSpace(route.Action)) 34 | { 35 | try 36 | { 37 | var routeArray = route.Key.Split('/'); 38 | route.Handle = routeArray[1]; 39 | route.Action = routeArray[2]; 40 | } 41 | catch (Exception ex) 42 | { 43 | if (route.HtmlView) 44 | { 45 | throw new ArgumentException("route key fotmat handle/action", ex); 46 | } 47 | 48 | } 49 | 50 | 51 | } 52 | 53 | if (Routes.Exists(x => x.Key == route.Key)) 54 | { 55 | Routes[Routes.IndexOf(Routes.FirstOrDefault(x => x.Key == route.Key))] = route; 56 | } 57 | else 58 | { 59 | Routes.Add(route); 60 | } 61 | 62 | } 63 | 64 | public DashboardRoute FindRoute(string url) 65 | { 66 | if (url.Length > 1 && url.Last() == '/') 67 | { 68 | url = url.Substring(0, url.Length - 1); 69 | } 70 | 71 | return string.IsNullOrWhiteSpace(url) ? Routes.FirstOrDefault(x => x.Key.ToLower() == "/Dashboard/Index".ToLower()) : Routes.FirstOrDefault(x => x.Key.ToLower() == url.ToLower()); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Handles/DashboardHandleBase.cs: -------------------------------------------------------------------------------- 1 | 2 | using HttpReports.Dashboard.Models; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text.Json; 7 | 8 | namespace HttpReports.Dashboard.Handles 9 | { 10 | public abstract class DashboardHandleBase : IDashboardHandle 11 | { 12 | protected DashboardHandleBase(IServiceProvider serviceProvider) 13 | { 14 | ServiceProvider = serviceProvider; 15 | ViewData = new Dictionary(); 16 | } 17 | 18 | public DashboardContext Context { get; set; } 19 | 20 | public IServiceProvider ServiceProvider { get; } 21 | 22 | public Dictionary ViewData { get; set; } 23 | 24 | 25 | public virtual string Json(bool state) 26 | { 27 | BaseResult baseResult = new BaseResult 28 | { 29 | Code = state ? 1 : -1, 30 | Msg = state ? "ok" : "error", 31 | Data = null 32 | }; 33 | 34 | Context.HttpContext.Response.ContentType = "application/json;charset=utf-8"; 35 | var setting = ServiceProvider.GetRequiredService(); 36 | return System.Text.Json.JsonSerializer.Serialize(baseResult,setting); 37 | 38 | } 39 | 40 | public virtual string Json(bool state,object data) 41 | { 42 | BaseResult baseResult = new BaseResult 43 | { 44 | Code = state ? 1 : -1, 45 | Msg = state ? "ok" : "error", 46 | Data = data 47 | }; 48 | 49 | Context.HttpContext.Response.ContentType = "application/json;charset=utf-8"; 50 | var setting = ServiceProvider.GetRequiredService(); 51 | return System.Text.Json.JsonSerializer.Serialize(baseResult, setting); 52 | } 53 | 54 | public virtual string Json(bool state, string msg,object data) 55 | { 56 | BaseResult baseResult = new BaseResult 57 | { 58 | Code = state ? 1 : -1, 59 | Msg = state ? "ok" : msg, 60 | Data = data 61 | }; 62 | 63 | var setting = ServiceProvider.GetRequiredService(); 64 | return System.Text.Json.JsonSerializer.Serialize(baseResult, setting); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "httpreports-ui", 3 | "version": "1.0.0", 4 | "description": "httpreports-ui", 5 | "author": "Spring Lee <1028789852@qq.com>", 6 | "private": true, 7 | "scripts": { 8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", 9 | "start": "npm run dev", 10 | "build": "node build/build.js" 11 | }, 12 | "dependencies": { 13 | "@antv/g2": "^4.0.14", 14 | "@antv/g2plot": "^1.1.19", 15 | "@antv/g6": "^3.7.0", 16 | "animate.css": "^4.1.0", 17 | "element-ui": "^2.13.2", 18 | "font-awesome": "^4.7.0", 19 | "particles.js": "^2.0.0", 20 | "screenfull": "^5.0.2", 21 | "vue": "^2.6.11", 22 | "vue-awesome": "^4.1.0", 23 | "vue-i18n": "^8.21.0", 24 | "vue-particles": "^1.0.9", 25 | "vue-resource": "^1.5.1", 26 | "vue-router": "^3.0.1", 27 | "vuex": "^3.5.1", 28 | "webpack-dev-server": "^2.9.7" 29 | }, 30 | "devDependencies": { 31 | "autoprefixer": "^7.1.2", 32 | "babel-core": "^6.22.1", 33 | "babel-helper-vue-jsx-merge-props": "^2.0.3", 34 | "babel-loader": "^7.1.1", 35 | "babel-plugin-syntax-jsx": "^6.18.0", 36 | "babel-plugin-transform-runtime": "^6.22.0", 37 | "babel-plugin-transform-vue-jsx": "^3.5.0", 38 | "babel-preset-env": "^1.3.2", 39 | "babel-preset-stage-2": "^6.22.0", 40 | "chalk": "^2.0.1", 41 | "copy-webpack-plugin": "^4.0.1", 42 | "css-loader": "^0.28.0", 43 | "extract-text-webpack-plugin": "^3.0.0", 44 | "file-loader": "^1.1.4", 45 | "friendly-errors-webpack-plugin": "^1.6.1", 46 | "html-webpack-plugin": "^2.30.1", 47 | "node-notifier": "^5.1.2", 48 | "optimize-css-assets-webpack-plugin": "^3.2.0", 49 | "ora": "^1.2.0", 50 | "portfinder": "^1.0.13", 51 | "postcss-import": "^11.0.0", 52 | "postcss-loader": "^2.0.8", 53 | "postcss-url": "^7.2.1", 54 | "rimraf": "^2.6.0", 55 | "semver": "^5.3.0", 56 | "shelljs": "^0.7.6", 57 | "uglifyjs-webpack-plugin": "^1.1.1", 58 | "url-loader": "^0.5.8", 59 | "vue-loader": "^13.3.0", 60 | "vue-style-loader": "^3.0.1", 61 | "vue-template-compiler": "^2.5.2", 62 | "webpack": "^3.6.0", 63 | "webpack-bundle-analyzer": "^2.9.0", 64 | "webpack-cli": "^3.3.12", 65 | "webpack-merge": "^4.1.0" 66 | }, 67 | "engines": { 68 | "node": ">= 6.0.0", 69 | "npm": ">= 3.0.0" 70 | }, 71 | "browserslist": [ 72 | "> 1%", 73 | "last 2 versions", 74 | "not ie <= 8" 75 | ] 76 | } 77 | -------------------------------------------------------------------------------- /src/HttpReports.Core/BasicUtils.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Security.Cryptography; 5 | using System.Text; 6 | 7 | namespace HttpReports.Core 8 | { 9 | public static class BasicUtils 10 | { 11 | public static string GetUniqueId() 12 | { 13 | MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); 14 | string val = BitConverter.ToString(md5.ComputeHash(UTF8Encoding.Default.GetBytes( Guid.NewGuid().ToString() )), 4, 8).Replace("-", "").ToLower(); 15 | return val; 16 | } 17 | 18 | 19 | public static string GetUniqueId(this HttpContext context) 20 | { 21 | MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); 22 | string val = BitConverter.ToString(md5.ComputeHash(UTF8Encoding.Default.GetBytes(Guid.NewGuid().ToString())), 4, 8).Replace("-", "").ToLower(); 23 | return val; 24 | } 25 | 26 | public static string GetTraceId(this HttpContext context) 27 | { 28 | if (context.Items.ContainsKey(BasicConfig.ActiveSpanId)) 29 | { 30 | return context.Items[BasicConfig.ActiveSpanId].ToString(); 31 | } 32 | else 33 | { 34 | return string.Empty; 35 | } 36 | } 37 | 38 | 39 | 40 | public static long GetSpanId(this HttpContext context) 41 | { 42 | if (context.Items.ContainsKey(BasicConfig.ActiveTraceId)) 43 | { 44 | return context.Items[BasicConfig.ActiveTraceId].ToString().Split('-')[2].ToLong(); 45 | } 46 | else 47 | { 48 | return 0; 49 | } 50 | } 51 | 52 | 53 | public static long GetTraceParentId(this HttpContext context) 54 | { 55 | if (context.Items.ContainsKey(BasicConfig.ActiveParentSpanId)) 56 | { 57 | return context.Items[BasicConfig.ActiveParentSpanId].ToString().ToLong(); 58 | } 59 | else 60 | { 61 | return 0; 62 | } 63 | } 64 | 65 | public static string GetTraceParentService(this HttpContext context) 66 | { 67 | if (context.Items.ContainsKey(BasicConfig.ActiveParentSpanService)) 68 | { 69 | return context.Items[BasicConfig.ActiveParentSpanService].ToString(); 70 | } 71 | else 72 | { 73 | return string.Empty; 74 | } 75 | } 76 | 77 | 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/HttpReports/HttpReports.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | SpringLee 6 | HttpReports is a lightweight APM system developed for .NET Core 7 | 8 | https://github.com/dotnetcore/HttpReports 9 | https://github.com/dotnetcore/HttpReports 10 | 11 | HttpReports 12 | HttpReports 13 | HttpReports 14 | logo3.png 15 | true 16 | true 17 | true 18 | snupkg 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | True 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/Diagnostics/HttpReports.Diagnostic.SqlClient/SqlClientDiagnosticListener.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Core; 2 | using HttpReports.Core.Diagnostics; 3 | using Microsoft.Extensions.Logging; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace HttpReports.Diagnostic.SqlClient 9 | { 10 | public class SqlClientDiagnosticListener : IDiagnosticListener 11 | { 12 | private ILogger _logger; 13 | 14 | private IReportsTransport _transport; 15 | 16 | private ISegmentContext _context; 17 | 18 | public SqlClientDiagnosticListener(ILogger logger, IReportsTransport transport, ISegmentContext context) 19 | { 20 | _logger = logger; 21 | _transport = transport; 22 | _context = context; 23 | } 24 | 25 | 26 | 27 | public string ListenerName => "SqlClientDiagnosticListener"; 28 | 29 | 30 | 31 | public void OnCompleted() 32 | { 33 | 34 | } 35 | 36 | public void OnError(Exception error) 37 | { 38 | 39 | } 40 | 41 | public void OnNext(KeyValuePair value) 42 | { 43 | var activity = System.Diagnostics.Activity.Current; 44 | 45 | if (activity == null) return; 46 | 47 | if (value.Key == "System.Data.SqlClient.WriteCommandBefore") 48 | { 49 | var SqlCommand = value.Value.GetType().GetProperty("Command").GetValue(value.Value) as System.Data.SqlClient.SqlCommand; 50 | 51 | _context.Push(activity?.SpanId.ToHexString(), new Segment 52 | { 53 | activity = activity, 54 | CreateTime = DateTime.Now, 55 | Value = SqlCommand 56 | 57 | }); 58 | 59 | } 60 | 61 | if (value.Key == "System.Data.SqlClient.WriteCommandAfter") 62 | { 63 | 64 | var SqlCommand = value.Value.GetType().GetProperty("Command").GetValue(value.Value) as System.Data.SqlClient.SqlCommand; 65 | 66 | _context.Push(activity?.SpanId.ToHexString(), new Segment 67 | { 68 | activity = activity, 69 | CreateTime = DateTime.Now, 70 | Value = SqlCommand 71 | 72 | }); 73 | 74 | Build(activity.SpanId.ToHexString()); 75 | 76 | } 77 | 78 | if (value.Key == "System.Data.SqlClient.WriteCommandError") 79 | { 80 | 81 | } 82 | } 83 | 84 | public IRequestChain Build(string Id) 85 | { 86 | return null; 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/Implements/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Security.Cryptography; 3 | using System.Text; 4 | 5 | namespace System 6 | { 7 | public static class StringExtensions 8 | { 9 | public static int ToInt(this string str) 10 | { 11 | try 12 | { 13 | return Convert.ToInt32(str); 14 | } 15 | catch (Exception ex) 16 | { 17 | return 0; 18 | } 19 | } 20 | 21 | 22 | public static int ToInt(this double dou) 23 | { 24 | return Convert.ToInt32(dou); 25 | } 26 | 27 | 28 | public static bool IsNumber(this string str) 29 | { 30 | double i = 0; 31 | 32 | try 33 | { 34 | i = Convert.ToDouble(str); 35 | } 36 | catch (Exception ex) 37 | { 38 | return false; 39 | } 40 | 41 | return true; 42 | } 43 | 44 | public static string MD5(this string source) 45 | { 46 | MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); 47 | byte[] bytes = Encoding.UTF8.GetBytes(source); 48 | string result = BitConverter.ToString(md5.ComputeHash(bytes)); 49 | return result.Replace("-", "").ToLower(); 50 | } 51 | 52 | public static double ToDouble(this string str) 53 | { 54 | try 55 | { 56 | return Convert.ToDouble(str); 57 | } 58 | catch (Exception) 59 | { 60 | return 0; 61 | } 62 | } 63 | 64 | public static bool IsEmpty(this string str) 65 | { 66 | if (string.IsNullOrEmpty(str)) 67 | { 68 | return true; 69 | } 70 | 71 | if (string.IsNullOrWhiteSpace(str)) 72 | { 73 | return true; 74 | } 75 | 76 | return false; 77 | } 78 | 79 | public static DateTime ToDateTime(this string str) 80 | { 81 | try 82 | { 83 | return Convert.ToDateTime(str); 84 | } 85 | catch (Exception) 86 | { 87 | return DateTime.Now; 88 | } 89 | } 90 | 91 | [DebuggerStepThrough] 92 | public static DateTime ToDateTimeOrNow(this string value) => DateTime.TryParse(value, out var time) ? time : DateTime.Now; 93 | 94 | [DebuggerStepThrough] 95 | public static DateTime ToDateTimeOrDefault(this string value, Func func) => DateTime.TryParse(value, out var time) ? time : func(); 96 | } 97 | } -------------------------------------------------------------------------------- /src/HttpReports/Services/HttpReportsBackgroundService.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Core; 2 | using HttpReports.Core.Models; 3 | using Microsoft.AspNetCore.Builder; 4 | using Microsoft.AspNetCore.Hosting.Server.Features; 5 | using Microsoft.AspNetCore.Http; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.DependencyInjection; 8 | using Microsoft.Extensions.Hosting; 9 | using Microsoft.Extensions.Logging; 10 | using Microsoft.Extensions.Options; 11 | using System; 12 | using System.Collections.Generic; 13 | using System.Linq; 14 | using System.Net.Http; 15 | using System.Text; 16 | using System.Threading; 17 | using System.Threading.Tasks; 18 | 19 | namespace HttpReports.Services 20 | { 21 | public class HttpReportsBackgroundService : IHostedService 22 | { 23 | private ILogger _logger { get; } 24 | private IReportsTransport _transport { get; } 25 | 26 | private IPerformanceService _performanceService; 27 | 28 | private IConfiguration _config; 29 | 30 | private HttpReportsOptions _options; 31 | 32 | public HttpReportsBackgroundService(IOptions options, IConfiguration configuration, ILogger logger,IReportsTransport reportsTransport, IPerformanceService performanceService) 33 | { 34 | _logger = logger; 35 | _performanceService = performanceService; 36 | _transport = reportsTransport; 37 | _config = configuration; 38 | _options = options?.Value; 39 | } 40 | 41 | public Task StartAsync(CancellationToken token = default) 42 | { 43 | try 44 | { 45 | _ = Task.Run(async () => { 46 | 47 | while (!token.IsCancellationRequested) 48 | { 49 | await Task.Delay(TimeSpan.FromSeconds(10), token); 50 | 51 | Uri uri = new Uri(_options.Server); 52 | 53 | Performance performance = await _performanceService.GetPerformance(uri.Host + ":" + uri.Port); 54 | 55 | if (performance != null) 56 | { 57 | await _transport.SendDataAsync(performance); 58 | } 59 | 60 | } 61 | 62 | }); 63 | 64 | } 65 | catch (Exception ex) 66 | { 67 | _logger.LogError($"HttpReports BackgroundService Error,ex:{ex.ToString()}"); 68 | } 69 | 70 | return Task.CompletedTask; 71 | } 72 | 73 | 74 | public Task StopAsync(CancellationToken cancellationToken) 75 | { 76 | return Task.CompletedTask; 77 | } 78 | 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | [![Member project of .NET Core Community](https://img.shields.io/badge/member%20project%20of-NCC-9e20c9.svg?style=flat-square)](https://github.com/dotnetcore) 5 | [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](https://github.com/dotnetcore/HttpReports/blob/master/LICENSE) 6 | ![Nuget](https://img.shields.io/nuget/dt/HttpReports?style=flat-square) 7 | 8 |

HttpReports APM

9 | 10 |
11 | 12 | 13 | ![](https://httpreports2-1259586045.cos.ap-shanghai.myqcloud.com/index1.png) 14 | 15 | 16 | ## Introduce 17 | 18 | **HttpReports** is an APM (application performance monitor) system for Net Core. Based on MIT open source protocol, The main functions include statistics, analysis, visualization, monitoring, tracking, etc,It is very suitable for use in microservices. 19 | 20 | **Github** :**https://github.com/dotnetcore/HttpReports** 21 | **Docs** 22 | zh-cn: **https://www.yuque.com/httpreports/docs** 23 | en-us: **https://www.yuque.com/httpreports/docs?language=en-us** 24 | 25 | **The online preview**: **http://apm.nonop.cn/** 26 | 27 | account: **admin** password **123456 ** 28 | 29 | [MIT](https://github.com/dotnetcore/HttpReports/blob/master/LICENSE "MIT") 30 | 31 | 32 | ## Main features 33 | 34 | - Service, instance, endpoint metrics analysis 35 | - Slow request, error request analysis 36 | - Service call parameter query 37 | - Multi dimensional early warning and monitoring 38 | - HTTP, grpc call analysis 39 | - Service topology map analysis 40 | - Distributed tracing 41 | - Multi database support, easy integration 42 | 43 | ![](https://httpreports2-1259586045.cos.ap-shanghai.myqcloud.com/jiagou.png) 44 | 45 | 46 | ## Database support 47 | Database | Nuget 48 | ---|--- 49 | **SqlServer** | HttpReports.SqlServer 50 | **MySql** | HttpReports.MySQL 51 | **PostgreSQL** | HttpReports.PostgreSQL 52 | 53 | 54 | 55 | ## Conclusion 56 | 57 | **HttpReports** is an open source APM system in the.net Core environment, which is very suitable for microservice environment. If it is a small or medium-sized project, then HttpReports is a good choice, open source is not easy, if it can help you, please give us a star, thank you 😆 58 | 59 | 60 | ## Communication feedback 61 | 62 | If you use HttpReports in the project, or if you are interested, you can join the QQ group, News about HttpReports are published in QQ group. If You have any questions you can also add me on WeChat. 63 | 64 | ![](https://lee-1259586045.cos.ap-shanghai.myqcloud.com/mywechat3.jpg) 65 | 66 | ## Donation 67 | 68 | This project is an MIT-licensed open source project. In order to achieve better and sustainable development of the project, we expect to gain more backers. We will use the proceeds for community operations and promotion. 69 | 70 | 71 | ![](https://lee-1259586045.cos.ap-shanghai.myqcloud.com/juanzheng.jpg) 72 | 73 | 74 | Donation details:**https://www.yuque.com/httpreports/docs/pl212y** 75 | 76 | 77 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard/HttpReports.Dashboard.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | HttpReports.Dashboard 6 | HttpReports.Dashboard 7 | HttpReports.Dashboard 8 | 9 | HttpReports is a lightweight APM system developed for .NET Core 10 | https://github.com/dotnetcore/HttpReports 11 | https://github.com/dotnetcore/HttpReports 12 | logo3.png 13 | true 14 | true 15 | true 16 | snupkg 17 | true 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | True 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /src/HttpReports.Dashboard.UI/build/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const config = require('../config') 4 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 5 | const packageConfig = require('../package.json') 6 | 7 | exports.assetsPath = function (_path) { 8 | const assetsSubDirectory = process.env.NODE_ENV === 'production' 9 | ? config.build.assetsSubDirectory 10 | : config.dev.assetsSubDirectory 11 | 12 | return path.posix.join(assetsSubDirectory, _path) 13 | } 14 | 15 | exports.cssLoaders = function (options) { 16 | options = options || {} 17 | 18 | const cssLoader = { 19 | loader: 'css-loader', 20 | options: { 21 | sourceMap: options.sourceMap 22 | } 23 | } 24 | 25 | const postcssLoader = { 26 | loader: 'postcss-loader', 27 | options: { 28 | sourceMap: options.sourceMap 29 | } 30 | } 31 | 32 | // generate loader string to be used with extract text plugin 33 | function generateLoaders (loader, loaderOptions) { 34 | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader] 35 | 36 | if (loader) { 37 | loaders.push({ 38 | loader: loader + '-loader', 39 | options: Object.assign({}, loaderOptions, { 40 | sourceMap: options.sourceMap 41 | }) 42 | }) 43 | } 44 | 45 | // Extract CSS when that option is specified 46 | // (which is the case during production build) 47 | if (options.extract) { 48 | return ExtractTextPlugin.extract({ 49 | use: loaders, 50 | fallback: 'vue-style-loader' 51 | }) 52 | } else { 53 | return ['vue-style-loader'].concat(loaders) 54 | } 55 | } 56 | 57 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html 58 | return { 59 | css: generateLoaders(), 60 | postcss: generateLoaders(), 61 | less: generateLoaders('less'), 62 | sass: generateLoaders('sass', { indentedSyntax: true }), 63 | scss: generateLoaders('sass'), 64 | stylus: generateLoaders('stylus'), 65 | styl: generateLoaders('stylus') 66 | } 67 | } 68 | 69 | // Generate loaders for standalone style files (outside of .vue) 70 | exports.styleLoaders = function (options) { 71 | const output = [] 72 | const loaders = exports.cssLoaders(options) 73 | 74 | for (const extension in loaders) { 75 | const loader = loaders[extension] 76 | output.push({ 77 | test: new RegExp('\\.' + extension + '$'), 78 | use: loader 79 | }) 80 | } 81 | 82 | return output 83 | } 84 | 85 | exports.createNotifierCallback = () => { 86 | const notifier = require('node-notifier') 87 | 88 | return (severity, errors) => { 89 | if (severity !== 'error') return 90 | 91 | const error = errors[0] 92 | const filename = error.file && error.file.split('!').pop() 93 | 94 | notifier.notify({ 95 | title: packageConfig.name, 96 | message: severity + ': ' + error.name, 97 | subtitle: filename || '', 98 | icon: path.join(__dirname, 'logo.png') 99 | }) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/Diagnostics/HttpReports.Diagnostic.HttpClient/HttpClientDiagnosticListener.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Core; 2 | using HttpReports.Core.Diagnostics; 3 | using Microsoft.AspNetCore.Http; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Logging; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | 10 | namespace HttpReports.Diagnostic.HttpClient 11 | { 12 | public class HttpClientDiagnosticListener : IDiagnosticListener 13 | { 14 | private ILogger _logger; 15 | 16 | private IReportsTransport _transport; 17 | 18 | private ISegmentContext _context; 19 | 20 | private IHttpContextAccessor _httpContextAccessor; 21 | 22 | 23 | public HttpClientDiagnosticListener(ILogger logger, IHttpContextAccessor httpContextAccessor, IReportsTransport transport, ISegmentContext context) 24 | { 25 | _logger = logger; 26 | _transport = transport; 27 | _context = context; 28 | _httpContextAccessor = httpContextAccessor; 29 | } 30 | 31 | 32 | public string ListenerName => "HttpHandlerDiagnosticListener"; 33 | 34 | public void OnCompleted() 35 | { 36 | 37 | } 38 | 39 | public void OnError(Exception error) 40 | { 41 | 42 | } 43 | 44 | public void OnNext(KeyValuePair value) 45 | { 46 | if (value.Key == "System.Net.Http.HttpRequestOut.Start") 47 | { 48 | HandleHttpRequest(value.Value); 49 | } 50 | } 51 | 52 | private void HandleHttpRequest(object value) 53 | { 54 | try 55 | { 56 | HttpContext context = _httpContextAccessor.HttpContext; 57 | 58 | var request = value.GetType().GetProperty("Request").GetValue(value) as System.Net.Http.HttpRequestMessage; 59 | 60 | if (context != null && request != null && !request.RequestUri.ToString().Contains(BasicConfig.HttpCollectorEndpoint)) 61 | { 62 | if (!request.Headers.Contains(BasicConfig.ActiveTraceId) && context.Items.ContainsKey(BasicConfig.ActiveTraceId) ) 63 | { 64 | var traceId = context.Items[BasicConfig.ActiveTraceId].ToString(); 65 | 66 | request.Headers.Add(BasicConfig.ActiveTraceId, traceId); 67 | } 68 | 69 | if (!request.Headers.Contains(BasicConfig.ActiveSpanService) && context.Items.ContainsKey(BasicConfig.ActiveSpanService)) 70 | { 71 | var service = context.Items[BasicConfig.ActiveSpanService].ToString(); 72 | 73 | request.Headers.Add(BasicConfig.ActiveParentSpanService, service); 74 | } 75 | } 76 | 77 | } 78 | catch (Exception ex) 79 | { 80 | _logger.LogError("HandleHttpRequest:" + ex.ToString()); 81 | } 82 | } 83 | 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/Storage/HttpReports.Storage.Abstractions/IHttpReportsStorage.cs: -------------------------------------------------------------------------------- 1 | using HttpReports.Core; 2 | using HttpReports.Core.Models; 3 | using HttpReports.Core.StorageFilters; 4 | using HttpReports.Core.ViewModels; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | 11 | namespace HttpReports.Storage.Abstractions 12 | { 13 | public interface IHttpReportsStorage 14 | { 15 | Task InitAsync(); 16 | 17 | Task PrintSQLAsync(); 18 | 19 | Task AddRequestInfoAsync(RequestBag bag); 20 | 21 | 22 | Task AddRequestInfoAsync(List list, CancellationToken token); 23 | 24 | 25 | Task GetIndexBasicDataAsync(BasicFilter filter); 26 | 27 | Task> GetServiceTrend(BasicFilter filter, List Time); 28 | 29 | Task> GetServiceHeatMap(BasicFilter filter, List Time); 30 | 31 | 32 | Task> GetTopServiceLoad(BasicFilter filter); 33 | 34 | 35 | Task>> GetGroupData(BasicFilter filter, GroupType groupType); 36 | 37 | 38 | Task> GetTopologyData(BasicFilter filter); 39 | 40 | 41 | 42 | Task> GetAppStatus(BasicFilter filter, List range); 43 | 44 | 45 | Task> GetServiceInstance(DateTime startTime); 46 | 47 | 48 | Task GetSearchRequestInfoAsync(QueryDetailFilter filter); 49 | 50 | Task AddMonitorJob(MonitorJob job); 51 | 52 | Task AddMonitorAlarm(MonitorAlarm alarm); 53 | 54 | Task> GetMonitorAlarms(BasicFilter filter); 55 | 56 | Task UpdateMonitorJob(MonitorJob job); 57 | 58 | Task DeleteMonitorJob(long Id); 59 | 60 | Task GetMonitorJob(long Id); 61 | 62 | Task> GetEndpoints(BasicFilter filter); 63 | 64 | Task> GetMonitorJobs(); 65 | 66 | Task<(int timeout, int total)> GetTimeoutResponeCountAsync(ResponseTimeTaskFilter filter); 67 | 68 | Task<(int error, int total)> GetErrorResponeCountAsync(ResponseErrorTaskFilter filter); 69 | 70 | Task GetCallCountAsync(CallCountTaskFilter filter); 71 | 72 | 73 | Task CheckLogin(string Username, string Password); 74 | 75 | Task GetSysUser(string UserName); 76 | 77 | Task UpdateLoginUser(SysUser model); 78 | 79 | Task<(RequestInfo, RequestDetail)> GetRequestInfoDetail(long Id); 80 | 81 | Task GetRequestInfo(long Id); 82 | 83 | Task> GetRequestInfoByParentId(long ParentId); 84 | 85 | Task ClearData(string StartTime); 86 | 87 | Task SetLanguage(string Language); 88 | 89 | Task GetSysConfig(string Key); 90 | 91 | Task AddPerformanceAsync(Performance performance); 92 | 93 | Task GetPerformanceAsync(DateTime start,DateTime end,string Service,string Instance); 94 | 95 | 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/HttpReports.Core/BasicConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace HttpReports.Core 6 | { 7 | public static class BasicConfig 8 | { 9 | public const string DefaultUserName = "admin"; 10 | 11 | public const string DefaultPassword = "e10adc3949ba59abbe56e057f20f883e"; 12 | 13 | public const string LoginCookieId = "HttpReports.Login.User"; 14 | 15 | public const string CurrentControllers = "HttpReports,HttpReportsData"; 16 | 17 | public const string ElasticSearchIndexName = "httpreports_index_"; 18 | 19 | public const string HttpReportsGlobalException = "HttpReportsGlobalException"; 20 | 21 | public const string HttpReportsRequestBody = "HttpReportsRequestBody"; 22 | 23 | public const string HttpReportsResponseBody = "HttpReportsResponseBody"; 24 | 25 | public const int HttpReportsFieldMaxLength = 80000; 26 | 27 | public const int ExpireDay = 7; 28 | 29 | public const string ActiveTraceName = "HttpReports-Trace-Context"; 30 | 31 | public const string ActiveTraceId = "HttpReports-Trace-Id"; 32 | 33 | public const string ActiveSpanId = "HttpReports-Trace-SpanId"; 34 | 35 | public const string HttpReportsSpanId = "HttpReports-Trace-Id"; 36 | 37 | public const string ActiveParentSpanId = "HttpReports-Trace-ParentSpan-Id"; 38 | 39 | public const string Policy = "HttpReports.Dashboard.Policy"; 40 | 41 | public const string HttpReportsDefaultHealth = "/HttpReportsDefaultHealth"; 42 | 43 | public const int DeferTaskMinutes = 3; 44 | 45 | public const string ActiveParentSpanService = "HttpReports-Trace-ParentSpan-Service"; 46 | 47 | 48 | public const string ActiveSpanService = "HttpReports-Trace-Span-Service"; 49 | 50 | 51 | public const string AuthToken = "HttpReports-AuthToken"; 52 | 53 | 54 | public const string ALLTag = "ALL"; 55 | 56 | public const string ActiveTraceCreateTime = "HttpReports.Trace.CreateDateTime"; 57 | 58 | 59 | public const string HttpReportsTraceCost = "HttpReports.Trace.Cost"; 60 | 61 | 62 | public const string HttpReportsHttpClient = "HttpReports.HttpClient"; 63 | 64 | public const string ClearDataCornLike = "0 0 0 * * ? "; 65 | 66 | public const string HealthCheckCornLike = "0 0/1 * * * ? "; 67 | 68 | public const string HttpReportsGrpcRequest = "HttpReports.GrpcRequest"; 69 | 70 | public const string HttpReportsGrpcResponse = "HttpReports.GrpcResponse"; 71 | 72 | public const string Language = "Language"; 73 | 74 | public const string DefaultLanguage = "zh-cn"; 75 | 76 | public const string StaticFilesRoot = "HttpReports.Dashboard"; 77 | 78 | public const string StaticUIRoot = "/HttpReportsStaticFiles/UI"; 79 | 80 | public const string HttpReportsServerRegister = "/HttpReportsServerRegister"; 81 | 82 | public const int PerformanceInerval = 10000; 83 | 84 | public const string TransportType = "TransportType"; 85 | 86 | public const string HttpCollectorEndpoint = "/HttpReportsHttpCollector"; 87 | 88 | } 89 | } 90 | --------------------------------------------------------------------------------