-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathExtensions.Logs.cs
More file actions
126 lines (115 loc) · 4.1 KB
/
Extensions.Logs.cs
File metadata and controls
126 lines (115 loc) · 4.1 KB
1
2
3
4
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
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#region Related components
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Channels;
using System.Collections.Generic;
using System.Collections.Concurrent;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using net.vieapps.Components.Utility;
#endregion
namespace net.vieapps.Services
{
public static partial class Extensions
{
static string LogsPath { get; } = UtilityService.GetAppSetting("Path:Logs", "logs");
static Channel<((DateTime Time, string CorrelationID, string DeveloperID, string AppID, string NodeID, string ServiceName, string ObjectName) Info, List<string> Logs, string Stack)> LogsQueue { get; } = Channel.CreateBounded<((DateTime, string, string, string, string, string, string), List<string>, string)>(new BoundedChannelOptions(4096)
{
SingleReader = true,
SingleWriter = false,
FullMode = BoundedChannelFullMode.Wait
});
static Task LogsWritter { get; } = Task.Run(Extensions.WriteLogsAsync);
static SemaphoreSlim LogsLocker { get; } = new SemaphoreSlim(1, 1);
static bool IsLogsWritting { get; set; } = false;
static bool UseChannel { get; } = "Channel".IsEquals(UtilityService.GetAppSetting("Logs:Mode", "Channel"));
static async Task WriteLogAsync(this ((DateTime Time, string CorrelationID, string DeveloperID, string AppID, string NodeID, string ServiceName, string ObjectName) Info, List<string> Logs, string Stack) log)
{
try
{
await new JObject
{
{ "Time", log.Info.Time },
{ "CorrelationID", log.Info.CorrelationID },
{ "DeveloperID", log.Info.DeveloperID },
{ "AppID", log.Info.AppID },
{ "NodeID", log.Info.NodeID },
{ "ServiceName", log.Info.ServiceName },
{ "ObjectName", log.Info.ObjectName },
{ "Logs", log.Logs?.Join("\r\n") ?? "" },
{ "Stack", log.Stack }
}.SaveAsTextAsync(Path.Combine(Extensions.LogsPath, $"zlogs.services.{log.Info.Time:yyyyMMddHHmmssffffff}.{UtilityService.NewUUID}.json")).ConfigureAwait(false);
}
catch { }
}
static async Task WriteLogsAsync()
{
while (await Extensions.LogsQueue.Reader.WaitToReadAsync().ConfigureAwait(false))
{
while (Extensions.LogsQueue.Reader.TryRead(out var log))
await log.WriteLogAsync().ConfigureAwait(false);
}
}
/// <summary>
/// Writes the log messages into centerlized log storage
/// </summary>
/// <param name="logs"></param>
/// <param name="cancellationToken"></param>
/// <param name="logger"></param>
/// <returns></returns>
public static async Task WriteLogsAsync(this ConcurrentQueue<((DateTime Time, string CorrelationID, string DeveloperID, string AppID, string NodeID, string ServiceName, string ObjectName) Info, List<string> Logs, string Stack)> logs, ILogger logger = null, CancellationToken cancellationToken = default)
{
if (Extensions.UseChannel)
try
{
while (logs.TryDequeue(out var log))
await Extensions.LogsQueue.Writer.WriteAsync(log, cancellationToken).ConfigureAwait(false);
}
catch (TaskCanceledException) { }
catch (OperationCanceledException) { }
catch (ObjectDisposedException) { }
catch (Exception ex)
{
logger?.LogError(ex, $"Error occurred while writting logs => {ex.Message}");
}
else if (!Extensions.IsLogsWritting)
{
Extensions.IsLogsWritting = true;
await Extensions.LogsLocker.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
while (logs.TryDequeue(out var log))
await log.WriteLogAsync().ConfigureAwait(false);
}
catch (TaskCanceledException) { }
catch (OperationCanceledException) { }
catch (ObjectDisposedException) { }
catch (Exception ex)
{
logger?.LogError(ex, $"Error occurred while writting logs => {ex.Message}");
}
finally
{
try
{
Extensions.LogsLocker.Release();
}
catch { }
Extensions.IsLogsWritting = false;
}
}
}
/// <summary>
/// Shutdowns the logs
/// </summary>
/// <returns></returns>
public static Task ShutdownLogsAsync()
{
Extensions.LogsQueue.Writer.TryComplete();
return Extensions.LogsWritter;
}
}
}