@@ -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; | |||
} | |||
@@ -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, | |||
@@ -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>(); | |||
JsonPropertyAttribute attr = prop.GetCustomAttribute<JsonPropertyAttribute>()!; | |||
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. | |||
@@ -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<ThreadInfoEnricher>(); | |||
} | |||
} | |||
} |
@@ -8,6 +8,8 @@ | |||
<ItemGroup> | |||
<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" /> | |||
<PackageReference Include="Serilog.Expressions" Version="3.4.0" /> | |||
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" /> | |||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" /> | |||
<PackageReference Include="TelpoDataService.Util" Version="1.6.9.16-beta1" /> | |||
</ItemGroup> | |||
@@ -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<HttpMessageHandlerBuilder> Configure(Action<HttpMessageHandlerBuilder> 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)); | |||
}; | |||
} | |||
} | |||
} |
@@ -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<HttpResponseMessage> 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<ILogger, HttpMethod, Uri, string, IDisposable> _beginRequestPipelineScope = | |||
LoggerMessage.DefineScope<HttpMethod, Uri, string>( | |||
"HTTP {HttpMethod} {Uri} {CorrelationId}"); | |||
private static readonly Action<ILogger, HttpMethod, Uri, string, Exception> _requestPipelineStart = | |||
LoggerMessage.Define<HttpMethod, Uri, string>( | |||
LogLevel.Information, | |||
EventIds.PipelineStart, | |||
"Start processing HTTP request {HttpMethod} {Uri} [Correlation: {CorrelationId}]"); | |||
private static readonly Action<ILogger, HttpStatusCode, Exception> _requestPipelineEnd = | |||
LoggerMessage.Define<HttpStatusCode>( | |||
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; | |||
} | |||
} | |||
} | |||
} |
@@ -21,6 +21,7 @@ namespace HealthMonitor.WebApi | |||
public async Task<bool> 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}"); | |||
} | |||
@@ -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<Worker>(); | |||
#endregion | |||
builder.Host.UseSerilog(); | |||
builder.Services.Replace(ServiceDescriptor.Singleton<IHttpMessageHandlerBuilderFilter, CustomLoggingFilter>()); | |||
// 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(); | |||
@@ -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": "*" | |||
} |