Skip to content

Commit e82a18f

Browse files
Refactor logger grouping (#716)
* Refactors IProxyLogger to ILogger * Prints grouped log messages to console * Code fixes
1 parent aa2de7a commit e82a18f

File tree

63 files changed

+1179
-1009
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1179
-1009
lines changed

dev-proxy-abstractions/BaseProxyPlugin.cs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,26 @@
33

44
using System.CommandLine;
55
using Microsoft.Extensions.Configuration;
6+
using Microsoft.Extensions.Logging;
67

78
namespace Microsoft.DevProxy.Abstractions;
89

910
public abstract class BaseProxyPlugin : IProxyPlugin
1011
{
11-
protected ISet<UrlToWatch>? _urlsToWatch;
12-
protected IProxyLogger? _logger;
12+
protected ISet<UrlToWatch> UrlsToWatch { get; }
13+
protected ILogger Logger { get; }
14+
protected IConfigurationSection? ConfigSection { get; }
15+
protected IPluginEvents PluginEvents { get; }
16+
protected IProxyContext Context { get; }
1317

1418
public virtual string Name => throw new NotImplementedException();
1519

1620
public virtual Option[] GetOptions() => Array.Empty<Option>();
1721
public virtual Command[] GetCommands() => Array.Empty<Command>();
1822

19-
public virtual void Register(IPluginEvents pluginEvents,
23+
public BaseProxyPlugin(IPluginEvents pluginEvents,
2024
IProxyContext context,
25+
ILogger logger,
2126
ISet<UrlToWatch> urlsToWatch,
2227
IConfigurationSection? configSection = null)
2328
{
@@ -26,18 +31,29 @@ public virtual void Register(IPluginEvents pluginEvents,
2631
throw new ArgumentNullException(nameof(pluginEvents));
2732
}
2833

29-
if (context is null || context.Logger is null)
34+
if (context is null)
3035
{
31-
throw new ArgumentException($"{nameof(context)} must not be null and must supply a non-null Logger", nameof(context));
36+
throw new ArgumentNullException(nameof(context));
37+
}
3238

39+
if (logger is null)
40+
{
41+
throw new ArgumentNullException(nameof(logger));
3342
}
3443

35-
if (urlsToWatch is null || urlsToWatch.Count == 0)
44+
if (urlsToWatch is null || !urlsToWatch.Any())
3645
{
3746
throw new ArgumentException($"{nameof(urlsToWatch)} cannot be null or empty", nameof(urlsToWatch));
3847
}
3948

40-
_urlsToWatch = urlsToWatch;
41-
_logger = context.Logger;
49+
UrlsToWatch = urlsToWatch;
50+
Context = context;
51+
Logger = logger;
52+
ConfigSection = configSection;
53+
PluginEvents = pluginEvents;
54+
}
55+
56+
public virtual void Register()
57+
{
4258
}
4359
}

dev-proxy-abstractions/BaseReportingPlugin.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

4+
using Microsoft.Extensions.Configuration;
5+
using Microsoft.Extensions.Logging;
6+
47
namespace Microsoft.DevProxy.Abstractions;
58

69
public abstract class BaseReportingPlugin : BaseProxyPlugin
710
{
11+
protected BaseReportingPlugin(IPluginEvents pluginEvents, IProxyContext context, ILogger logger, ISet<UrlToWatch> urlsToWatch, IConfigurationSection? configSection = null) : base(pluginEvents, context, logger, urlsToWatch, configSection)
12+
{
13+
}
14+
815
protected virtual void StoreReport(object report, ProxyEventArgsBase e)
916
{
1017
if (report is null)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System.Text.Json;
2+
using Microsoft.DevProxy.Abstractions;
3+
4+
namespace Microsoft.Extensions.Logging;
5+
6+
public static class ILoggerExtensions
7+
{
8+
public static void LogRequest(this ILogger logger, string[] message, MessageType messageType, LoggingContext? context = null)
9+
{
10+
logger.Log(new RequestLog(message, messageType, context));
11+
}
12+
13+
public static void LogRequest(this ILogger logger, string[] message, MessageType messageType, string method, string url)
14+
{
15+
logger.Log(new RequestLog(message, messageType, method, url));
16+
}
17+
18+
public static void Log(this ILogger logger, RequestLog message)
19+
{
20+
logger.Log(LogLevel.Information, 0, message, exception: null, (m, _) => JsonSerializer.Serialize(m));
21+
}
22+
}

dev-proxy-abstractions/IProxyLogger.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ public enum MessageType
1515
Failed,
1616
Chaos,
1717
Mocked,
18-
InterceptedResponse
18+
InterceptedResponse,
19+
FinishedProcessingRequest
1920
}
2021

2122
public class LoggingContext

dev-proxy-abstractions/IProxyPlugin.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// Licensed under the MIT License.
33

44
using System.CommandLine;
5-
using Microsoft.Extensions.Configuration;
65

76
namespace Microsoft.DevProxy.Abstractions;
87

@@ -11,8 +10,5 @@ public interface IProxyPlugin
1110
string Name { get; }
1211
Option[] GetOptions();
1312
Command[] GetCommands();
14-
void Register(IPluginEvents pluginEvents,
15-
IProxyContext context,
16-
ISet<UrlToWatch> urlsToWatch,
17-
IConfigurationSection? configSection = null);
13+
void Register();
1814
}

dev-proxy-abstractions/MSGraphDbUtils.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public static SqliteConnection MSGraphDbConnection
3232
}
3333
}
3434

35-
public static async Task<int> GenerateMSGraphDb(IProxyLogger logger, bool skipIfUpdatedToday = false)
35+
public static async Task<int> GenerateMSGraphDb(ILogger logger, bool skipIfUpdatedToday = false)
3636
{
3737
var appFolder = ProxyUtils.AppFolder;
3838
if (string.IsNullOrEmpty(appFolder))
@@ -75,7 +75,7 @@ public static async Task<int> GenerateMSGraphDb(IProxyLogger logger, bool skipIf
7575

7676
}
7777

78-
private static void CreateDb(SqliteConnection dbConnection, IProxyLogger logger)
78+
private static void CreateDb(SqliteConnection dbConnection, ILogger logger)
7979
{
8080
logger.LogInformation("Creating database...");
8181

@@ -97,7 +97,7 @@ private static void CreateDb(SqliteConnection dbConnection, IProxyLogger logger)
9797
createIndex.ExecuteNonQuery();
9898
}
9999

100-
private static void FillData(SqliteConnection dbConnection, IProxyLogger logger)
100+
private static void FillData(SqliteConnection dbConnection, ILogger logger)
101101
{
102102
logger.LogInformation("Filling database...");
103103

@@ -118,20 +118,20 @@ private static void FillData(SqliteConnection dbConnection, IProxyLogger logger)
118118

119119
foreach (var path in document.Paths)
120120
{
121-
logger.LogDebug("Endpoint {graphVersion}{key}...", graphVersion, path.Key);
121+
logger.LogTrace("Endpoint {graphVersion}{key}...", graphVersion, path.Key);
122122

123123
// Get the GET operation for this path
124124
var getOperation = path.Value.Operations.FirstOrDefault(o => o.Key == OperationType.Get).Value;
125125
if (getOperation == null)
126126
{
127-
logger.LogDebug("No GET operation found for {graphVersion}{key}", graphVersion, path.Key);
127+
logger.LogTrace("No GET operation found for {graphVersion}{key}", graphVersion, path.Key);
128128
continue;
129129
}
130130

131131
// Check if the GET operation has a $select parameter
132132
var hasSelect = getOperation.Parameters.Any(p => p.Name == "$select");
133133

134-
logger.LogDebug("Inserting endpoint {graphVersion}{key} with hasSelect={hasSelect}...", graphVersion, path.Key, hasSelect);
134+
logger.LogTrace("Inserting endpoint {graphVersion}{key} with hasSelect={hasSelect}...", graphVersion, path.Key, hasSelect);
135135
insertEndpoint.Parameters["@path"].Value = path.Key;
136136
insertEndpoint.Parameters["@graphVersion"].Value = graphVersion;
137137
insertEndpoint.Parameters["@hasSelect"].Value = hasSelect;
@@ -143,7 +143,7 @@ private static void FillData(SqliteConnection dbConnection, IProxyLogger logger)
143143
logger.LogInformation("Inserted {endpointCount} endpoints in the database", i);
144144
}
145145

146-
private static async Task UpdateOpenAPIGraphFilesIfNecessary(string folder, IProxyLogger logger)
146+
private static async Task UpdateOpenAPIGraphFilesIfNecessary(string folder, ILogger logger)
147147
{
148148
logger.LogInformation("Checking for updated OpenAPI files...");
149149

@@ -176,7 +176,7 @@ private static async Task UpdateOpenAPIGraphFilesIfNecessary(string folder, IPro
176176
}
177177
}
178178

179-
private static async Task LoadOpenAPIFiles(string folder, IProxyLogger logger)
179+
private static async Task LoadOpenAPIFiles(string folder, ILogger logger)
180180
{
181181
logger.LogInformation("Loading OpenAPI files...");
182182

dev-proxy-abstractions/PluginEvents.cs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.CommandLine;
55
using System.CommandLine.Invocation;
66
using System.Security.Cryptography.X509Certificates;
7+
using System.Text.Json.Serialization;
78
using Titanium.Web.Proxy;
89
using Titanium.Web.Proxy.EventArguments;
910
using Titanium.Web.Proxy.Http;
@@ -13,7 +14,6 @@ namespace Microsoft.DevProxy.Abstractions;
1314
public interface IProxyContext
1415
{
1516
IProxyConfiguration Configuration { get; }
16-
IProxyLogger Logger { get; }
1717
X509Certificate2? Certificate { get; }
1818
}
1919

@@ -126,13 +126,37 @@ public class RequestLog
126126
{
127127
public string[] MessageLines { get; set; }
128128
public MessageType MessageType { get; set; }
129+
[JsonIgnore]
129130
public LoggingContext? Context { get; set; }
131+
public string? Method { get; init; }
132+
public string? Url { get; init; }
130133

131-
public RequestLog(string[] messageLines, MessageType messageType, LoggingContext? context)
134+
public RequestLog(string[] messageLines, MessageType messageType, LoggingContext? context) :
135+
this(messageLines, messageType, context?.Session.HttpClient.Request.Method, context?.Session.HttpClient.Request.Url, context)
136+
{
137+
}
138+
139+
public RequestLog(string[] messageLines, MessageType messageType, string method, string url) :
140+
this(messageLines, messageType, method, url, context: null)
141+
{
142+
}
143+
144+
private RequestLog(string[] messageLines, MessageType messageType, string? method, string? url, LoggingContext? context)
132145
{
133146
MessageLines = messageLines ?? throw new ArgumentNullException(nameof(messageLines));
134147
MessageType = messageType;
135148
Context = context;
149+
Method = method;
150+
Url = url;
151+
}
152+
153+
public void Deconstruct(out string[] message, out MessageType messageType, out LoggingContext? context, out string? method, out string? url)
154+
{
155+
message = MessageLines;
156+
messageType = MessageType;
157+
context = Context;
158+
method = Method;
159+
url = Url;
136160
}
137161
}
138162

dev-proxy-plugins/Behavior/RateLimitingCustomResponseLoader.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ namespace Microsoft.DevProxy.Plugins.Behavior;
99

1010
internal class RateLimitingCustomResponseLoader : IDisposable
1111
{
12-
private readonly IProxyLogger _logger;
12+
private readonly ILogger _logger;
1313
private readonly RateLimitConfiguration _configuration;
1414

15-
public RateLimitingCustomResponseLoader(IProxyLogger logger, RateLimitConfiguration configuration)
15+
public RateLimitingCustomResponseLoader(ILogger logger, RateLimitConfiguration configuration)
1616
{
1717
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
1818
_configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));

dev-proxy-plugins/Behavior/RateLimitingPlugin.cs

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33

44
using Microsoft.Extensions.Configuration;
5+
using Microsoft.Extensions.Logging;
56
using Microsoft.DevProxy.Abstractions;
67
using System.Net;
78
using System.Text.Json;
@@ -49,6 +50,10 @@ public class RateLimitingPlugin : BaseProxyPlugin
4950
private DateTime _resetTime = DateTime.MinValue;
5051
private RateLimitingCustomResponseLoader? _loader = null;
5152

53+
public RateLimitingPlugin(IPluginEvents pluginEvents, IProxyContext context, ILogger logger, ISet<UrlToWatch> urlsToWatch, IConfigurationSection? configSection = null) : base(pluginEvents, context, logger, urlsToWatch, configSection)
54+
{
55+
}
56+
5257
private ThrottlingInfo ShouldThrottle(Request request, string throttlingKey)
5358
{
5459
var throttleKeyForRequest = BuildThrottleKey(request);
@@ -123,31 +128,28 @@ private string BuildThrottleKey(Request r)
123128
}
124129
}
125130

126-
public override void Register(IPluginEvents pluginEvents,
127-
IProxyContext context,
128-
ISet<UrlToWatch> urlsToWatch,
129-
IConfigurationSection? configSection = null)
131+
public override void Register()
130132
{
131-
base.Register(pluginEvents, context, urlsToWatch, configSection);
133+
base.Register();
132134

133-
configSection?.Bind(_configuration);
135+
ConfigSection?.Bind(_configuration);
134136
if (_configuration.WhenLimitExceeded == RateLimitResponseWhenLimitExceeded.Custom)
135137
{
136-
_configuration.CustomResponseFile = Path.GetFullPath(ProxyUtils.ReplacePathTokens(_configuration.CustomResponseFile), Path.GetDirectoryName(context.Configuration?.ConfigFile ?? string.Empty) ?? string.Empty);
137-
_loader = new RateLimitingCustomResponseLoader(_logger!, _configuration);
138+
_configuration.CustomResponseFile = Path.GetFullPath(ProxyUtils.ReplacePathTokens(_configuration.CustomResponseFile), Path.GetDirectoryName(Context.Configuration.ConfigFile ?? string.Empty) ?? string.Empty);
139+
_loader = new RateLimitingCustomResponseLoader(Logger, _configuration);
138140
// load the responses from the configured mocks file
139141
_loader.InitResponsesWatcher();
140142
}
141143

142-
pluginEvents.BeforeRequest += OnRequest;
143-
pluginEvents.BeforeResponse += OnResponse;
144+
PluginEvents.BeforeRequest += OnRequest;
145+
PluginEvents.BeforeResponse += OnResponse;
144146
}
145147

146148
// add rate limiting headers to the response from the API
147149
private Task OnResponse(object? sender, ProxyResponseArgs e)
148150
{
149-
if (_urlsToWatch is null ||
150-
!e.HasRequestUrlMatch(_urlsToWatch))
151+
if (UrlsToWatch is null ||
152+
!e.HasRequestUrlMatch(UrlsToWatch))
151153
{
152154
return Task.CompletedTask;
153155
}
@@ -161,8 +163,8 @@ private Task OnRequest(object? sender, ProxyRequestArgs e)
161163
var session = e.Session;
162164
var state = e.ResponseState;
163165
if (e.ResponseState.HasBeenSet ||
164-
_urlsToWatch is null ||
165-
!e.ShouldExecute(_urlsToWatch))
166+
UrlsToWatch is null ||
167+
!e.ShouldExecute(UrlsToWatch))
166168
{
167169
return Task.CompletedTask;
168170
}
@@ -191,7 +193,7 @@ _urlsToWatch is null ||
191193
_resourcesRemaining = 0;
192194
var request = e.Session.HttpClient.Request;
193195

194-
_logger?.LogRequest([$"Exceeded resource limit when calling {request.Url}.", "Request will be throttled"], MessageType.Failed, new LoggingContext(e.Session));
196+
Logger.LogRequest([$"Exceeded resource limit when calling {request.Url}.", "Request will be throttled"], MessageType.Failed, new LoggingContext(e.Session));
195197
if (_configuration.WhenLimitExceeded == RateLimitResponseWhenLimitExceeded.Throttle)
196198
{
197199
if (!e.GlobalData.ContainsKey(RetryAfterPlugin.ThrottledRequestsKey))
@@ -250,7 +252,7 @@ _urlsToWatch is null ||
250252
}
251253
else
252254
{
253-
_logger?.LogRequest([$"Custom behavior not set. {_configuration.CustomResponseFile} not found."], MessageType.Failed, new LoggingContext(e.Session));
255+
Logger.LogRequest([$"Custom behavior not set. {_configuration.CustomResponseFile} not found."], MessageType.Failed, new LoggingContext(e.Session));
254256
}
255257
}
256258
}

0 commit comments

Comments
 (0)