diff --git a/HealthMonitor.Service/Biz/db/TDengineService.cs b/HealthMonitor.Service/Biz/db/TDengineService.cs index 9ea183a..8960154 100644 --- a/HealthMonitor.Service/Biz/db/TDengineService.cs +++ b/HealthMonitor.Service/Biz/db/TDengineService.cs @@ -40,22 +40,15 @@ namespace HealthMonitor.Service.Biz.db short port = _configTDengineService.Port; string password = _configTDengineService.Password; IntPtr conn = TDengine.Connect(host, user, password, db, port); - - //string host = "172.16.255.180"; - //short port = 6030; - //string user = "root"; - //string password = "taosdata"; - //string db = "health_monitor"; - - //IntPtr conn = TDengine.Connect(host, user, password, db, port); - // Check if get connection success if (conn == IntPtr.Zero) { - Console.WriteLine("Connect to TDengine failed"); + _logger.LogError($"连接 TDengine 失败...."); + // Console.WriteLine("Connect to TDengine failed"); } else { - Console.WriteLine("Connect to TDengine success"); + _logger.LogInformation($"连接 TDengine 成功...."); + // Console.WriteLine("Connect to TDengine success"); } return conn; } diff --git a/HealthMonitor.Service/Cache/BloodPressReferenceValueCacheManager.cs b/HealthMonitor.Service/Cache/BloodPressReferenceValueCacheManager.cs index 4147eca..739140c 100644 --- a/HealthMonitor.Service/Cache/BloodPressReferenceValueCacheManager.cs +++ b/HealthMonitor.Service/Cache/BloodPressReferenceValueCacheManager.cs @@ -64,6 +64,10 @@ namespace HealthMonitor.Service.Cache catch (Exception ex) { Console.WriteLine(ex.ToString() ); + + // _logger.LogError($"连接 TDengine 成功...."); + + _logger.LogError($"{nameof(GetBloodPressReferenceValueAsync)}发生异常:{ex.Message}, {ex.StackTrace}"); return new HmBloodPressReferenceValue { Age = 0, diff --git a/HealthMonitor.Service/Sub/TDengineDataSubcribe.cs b/HealthMonitor.Service/Sub/TDengineDataSubcribe.cs index 102de70..c8c362d 100644 --- a/HealthMonitor.Service/Sub/TDengineDataSubcribe.cs +++ b/HealthMonitor.Service/Sub/TDengineDataSubcribe.cs @@ -8,6 +8,7 @@ using HealthMonitor.Service.Resolver.Interface; using HealthMonitor.Service.Sub.Topic.Model; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; + using Newtonsoft.Json; using System; using System.Collections.Concurrent; @@ -88,11 +89,12 @@ namespace HealthMonitor.Service.Sub if (conn == IntPtr.Zero) { _logger.LogError("reason:" + TDengine.Error(conn)); - throw new Exception("Connect to TDengine failed"+DateTime.Now.ToString()); + //throw new Exception("Connect to TDengine failed"+DateTime.Now.ToString()); } else { - Console.WriteLine("Connect to TDengine success"); + _logger.LogInformation($"连接 TDengine 成功...."); + //Console.WriteLine("Connect to TDengine success"); } DoReceive(conn); } @@ -116,7 +118,7 @@ namespace HealthMonitor.Service.Sub string attributes = ""; foreach (PropertyInfo prop in props) { - JsonPropertyAttribute attr = prop.GetCustomAttribute(); + JsonPropertyAttribute attr = prop.GetCustomAttribute()!; if (attr != null) { attributes += attr.PropertyName + ","; @@ -171,14 +173,16 @@ namespace HealthMonitor.Service.Sub } catch (Exception ex) { - Console.WriteLine(ex.Message); + _logger.LogError($"解析包发生异常:{ex.Message}, {ex.StackTrace}"); + // Console.WriteLine(ex.Message); } } } } consumer.Commit(consumeRes); - Console.WriteLine("监听中...."); + // Console.WriteLine("监听中...."); + _logger.LogInformation($"监听中...."); } // close consumer after use.Otherwise will lead memory leak. diff --git a/HealthMonitor.WebApi/Configs/ThreadInfoEnricher.cs b/HealthMonitor.WebApi/Configs/ThreadInfoEnricher.cs new file mode 100644 index 0000000..6e3b2b2 --- /dev/null +++ b/HealthMonitor.WebApi/Configs/ThreadInfoEnricher.cs @@ -0,0 +1,28 @@ +using Serilog; +using Serilog.Configuration; +using Serilog.Core; +using Serilog.Events; +using System; +using System.Threading; + +namespace HealthMonitor.WebApi.Configs +{ + public class ThreadInfoEnricher : ILogEventEnricher + { + public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) + { + + logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("ThreadId", Thread.CurrentThread.ManagedThreadId)); + } + } + + public static class EnricherExtensions + { + public static LoggerConfiguration WithThreadInfo(this LoggerEnrichmentConfiguration enrich) + { + if (enrich == null) + throw new ArgumentNullException(nameof(enrich)); + return enrich.With(); + } + } +} diff --git a/HealthMonitor.WebApi/HealthMonitor.WebApi.csproj b/HealthMonitor.WebApi/HealthMonitor.WebApi.csproj index 64a0a6b..02e3c52 100644 --- a/HealthMonitor.WebApi/HealthMonitor.WebApi.csproj +++ b/HealthMonitor.WebApi/HealthMonitor.WebApi.csproj @@ -8,6 +8,8 @@ + + diff --git a/HealthMonitor.WebApi/HttpLog/CustomLoggingFilter.cs b/HealthMonitor.WebApi/HttpLog/CustomLoggingFilter.cs new file mode 100644 index 0000000..f309062 --- /dev/null +++ b/HealthMonitor.WebApi/HttpLog/CustomLoggingFilter.cs @@ -0,0 +1,38 @@ +using Microsoft.Extensions.Http; +using Microsoft.Extensions.Http.Logging; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Text; + +namespace HealthMonitor.WebApi.HttpLog +{ + public class CustomLoggingFilter : IHttpMessageHandlerBuilderFilter + { + private readonly ILoggerFactory _loggerFactory; + + public CustomLoggingFilter(ILoggerFactory loggerFactory) + { + _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); + } + + public Action Configure(Action next) + { + if (next == null) + { + throw new ArgumentNullException(nameof(next)); + } + + return (builder) => + { + // Run other configuration first, we want to decorate. + next(builder); + + var outerLogger = _loggerFactory.CreateLogger($"HttpClient.{builder.Name}.LogicalHandler"); + + //builder.AdditionalHandlers.Insert(0, new CustomLoggingScopeHttpMessageHandler(outerLogger)); + builder.AdditionalHandlers.Insert(0, new LoggingScopeHttpMessageHandler(outerLogger)); + }; + } + } +} diff --git a/HealthMonitor.WebApi/HttpLog/CustomLoggingScopeHttpMessageHandler.cs b/HealthMonitor.WebApi/HttpLog/CustomLoggingScopeHttpMessageHandler.cs new file mode 100644 index 0000000..307afed --- /dev/null +++ b/HealthMonitor.WebApi/HttpLog/CustomLoggingScopeHttpMessageHandler.cs @@ -0,0 +1,100 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace HealthMonitor.WebApi.HttpLog +{ + public class CustomLoggingScopeHttpMessageHandler : DelegatingHandler + { + private readonly ILogger _logger; + + public CustomLoggingScopeHttpMessageHandler(ILogger logger) + { + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } + + protected override async Task SendAsync(HttpRequestMessage request, + CancellationToken cancellationToken) + { + if (request == null) + { + throw new ArgumentNullException(nameof(request)); + } + + using (Log.BeginRequestPipelineScope(_logger, request)) + { + Log.RequestPipelineStart(_logger, request); + var response = await base.SendAsync(request, cancellationToken); + Log.RequestPipelineEnd(_logger, response); + + return response; + } + } + + private static class Log + { + private static class EventIds + { + public static readonly EventId PipelineStart = new EventId(100, "RequestPipelineStart"); + public static readonly EventId PipelineEnd = new EventId(101, "RequestPipelineEnd"); + } + + private static readonly Func _beginRequestPipelineScope = + LoggerMessage.DefineScope( + "HTTP {HttpMethod} {Uri} {CorrelationId}"); + + private static readonly Action _requestPipelineStart = + LoggerMessage.Define( + LogLevel.Information, + EventIds.PipelineStart, + "Start processing HTTP request {HttpMethod} {Uri} [Correlation: {CorrelationId}]"); + + private static readonly Action _requestPipelineEnd = + LoggerMessage.Define( + LogLevel.Information, + EventIds.PipelineEnd, + "End processing HTTP request - {StatusCode}"); + + public static IDisposable BeginRequestPipelineScope(ILogger logger, HttpRequestMessage request) + { + var correlationId = GetCorrelationIdFromRequest(request); + return _beginRequestPipelineScope(logger, request.Method, request.RequestUri, correlationId); + } + + public static void RequestPipelineStart(ILogger logger, HttpRequestMessage request) + { + if (logger.IsEnabled(LogLevel.Trace)) + { + var correlationId = GetCorrelationIdFromRequest(request); + _requestPipelineStart(logger, request.Method, request.RequestUri, correlationId, null); + } + } + + public static void RequestPipelineEnd(ILogger logger, HttpResponseMessage response) + { + if (logger.IsEnabled(LogLevel.Trace)) + { + _requestPipelineEnd(logger, response.StatusCode, null); + } + } + + private static string GetCorrelationIdFromRequest(HttpRequestMessage request) + { + var correlationId = "Not set"; + + if (request.Headers.TryGetValues("X-Correlation-ID", out var values)) + { + correlationId = values.First(); + } + + return correlationId; + } + } + } +} \ No newline at end of file diff --git a/HealthMonitor.WebApi/PackageProcess.cs b/HealthMonitor.WebApi/PackageProcess.cs index db03112..ae4561e 100644 --- a/HealthMonitor.WebApi/PackageProcess.cs +++ b/HealthMonitor.WebApi/PackageProcess.cs @@ -21,6 +21,7 @@ namespace HealthMonitor.WebApi public async Task ResolveAsync() { var resolver = _msgQueueManager.GetMsgResolver(); + try { @@ -33,7 +34,7 @@ namespace HealthMonitor.WebApi catch (Exception ex) { - Console.WriteLine(ex.Message); + //Console.WriteLine(ex.Message); _logger.LogError($"未处理异常 message: {ex.Message}\n {ex.StackTrace}"); } diff --git a/HealthMonitor.WebApi/Program.cs b/HealthMonitor.WebApi/Program.cs index 1c0fd97..5fd2a29 100644 --- a/HealthMonitor.WebApi/Program.cs +++ b/HealthMonitor.WebApi/Program.cs @@ -26,6 +26,11 @@ using HealthMonitor.Service.Sub; using HealthMonitor.Service.Resolver; using HealthMonitor.Service.Resolver.Factory; using HealthMonitor.Service.Resolver.Interface; +using Serilog; +using Serilog.Core; +using HealthMonitor.WebApi.HttpLog; +using Microsoft.Extensions.Http; +using Microsoft.Extensions.DependencyInjection.Extensions; namespace HealthMonitor.WebApi { @@ -33,6 +38,17 @@ namespace HealthMonitor.WebApi { public static void Main(string[] args) { + + //ѡļappsetting.json + var config = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) + .Build(); + Log.Logger = new LoggerConfiguration() + .ReadFrom.Configuration(config).Enrich.WithThreadInfo() + .CreateLogger(); + + var builder = WebApplication.CreateBuilder(args); // Add services to the container. @@ -176,8 +192,13 @@ namespace HealthMonitor.WebApi .AddHostedService(); #endregion - - + + builder.Host.UseSerilog(); + + builder.Services.Replace(ServiceDescriptor.Singleton()); + + + // Register the Swagger generator, defining 1 or more Swagger documents builder.Services.AddSwaggerGen(c => @@ -196,6 +217,8 @@ namespace HealthMonitor.WebApi }); + + var app = builder.Build(); @@ -235,6 +258,7 @@ namespace HealthMonitor.WebApi c.SwaggerEndpoint($"{sub}/{AppConsts.SWAGGER_DOC_HealthMonitor}/api-docs/", "HealthMonitorģ"); //ʾ c.RoutePrefix = string.Empty; }); + @@ -249,6 +273,7 @@ namespace HealthMonitor.WebApi var csredisDb7 = new CSRedis.CSRedisClient(csredisDb7Con.ToString()); RedisHelperDb7.Initialization(csredisDb7); + app.UseHttpsRedirection(); app.UseAuthorization(); diff --git a/HealthMonitor.WebApi/appsettings.json b/HealthMonitor.WebApi/appsettings.json index 10f68b8..279362f 100644 --- a/HealthMonitor.WebApi/appsettings.json +++ b/HealthMonitor.WebApi/appsettings.json @@ -2,8 +2,124 @@ "Logging": { "LogLevel": { "Default": "Information", - "Microsoft.AspNetCore": "Warning" + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information", + "HttpClient": "Information" } }, + "Serilog": { + "Using": [ "Serilog.Sinks.File", "Serilog.Sinks.Console", "Serilog.Expressions" ], + "MinimumLevel": { + "Default": "Information", + "Override": { + "Microsoft": "Warning", + "System": "Warning" + } + }, + "Enrich": [ + "FromLogContext", + "WithThreadId" + ], + "WriteTo": [ + { + "Name": "Console", + "Args": { + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level}] [Thread-{ThreadId}] [{SourceContext:l}] [{RequestId}]{NewLine}{Message}{NewLine}" + } + }, + { + "Name": "Logger", + "Args": { + "ConfigureLogger": { + "WriteTo": [ + { + "Name": "File", + "Args": { + "restrictedToMinimumLevel": "Information", + "path": "/var/health_monitor/logs/infos/info.log", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level}] [Thread-{ThreadId}] [{SourceContext:l}] [{RequestId}] {Message}{NewLine}{Exception}", + //"fileSizeLimitBytes": 524288000, + "rollingInterval": "Day", + "rollOnFileSizeLimit": "true", + "retainedFileCountLimit": 7 + } + } + ], + "Filter": [ + { + "Name": "ByIncludingOnly", + "Args": { + "Expression": "@l = 'Information'" + } + } + ] + } + } + }, + { + "Name": "Logger", + "Args": { + "ConfigureLogger": { + "WriteTo": [ + { + "Name": "File", + "Args": { + "RestrictedToMinimumLevel": "Warning", + "RollingInterval": "Day", + "RollOnFileSizeLimit": "true", + "OutputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff }[{Level:u3}] [Thread-{ThreadId}] [{SourceContext:l}] [{RequestId}] {Message:lj}{NewLine}", + "Path": "/var/health_monitor/logs/warnings/warn.log", + "RetainedFileCountLimit": 10 + } + } + ], + "Filter": [ + { + "Name": "ByIncludingOnly", + "Args": { + "Expression": "@l = 'Warning'" + } + } + ] + } + } + }, + { + "Name": "Logger", + "Args": { + "ConfigureLogger": { + "WriteTo": [ + { + "Name": "File", + "Args": { + "restrictedToMinimumLevel": "Error", + "path": "/var/health_monitor/logs/errors/error.log", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level}] [Thread-{ThreadId}] [{SourceContext:l}] [{RequestId}] {Message}{NewLine}{Exception}", + //"fileSizeLimitBytes": 524288000, + "rollingInterval": "Day", + "rollOnFileSizeLimit": "true", + "retainedFileCountLimit": 7 + } + } + ], + "Filter": [ + { + "Name": "ByIncludingOnly", + "Args": { + "Expression": "@l = 'Error'" + } + } + ] + } + } + } + ] + }, + //"Logging": { + // "LogLevel": { + // "Default": "Information", + // "Microsoft.AspNetCore": "Warning" + // } + //}, "AllowedHosts": "*" }