Skip to content

Commit 713af29

Browse files
Moves rate as a configuration option for Graph- and GenericRandomError plugins. Closes #971 (#994)
Co-authored-by: Garry Trinder <garry@trinder365.co.uk>
1 parent cc40464 commit 713af29

File tree

12 files changed

+87
-48
lines changed

12 files changed

+87
-48
lines changed

dev-proxy-abstractions/IProxyConfiguration.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ public interface IProxyConfiguration
1717
LogLevel LogLevel { get; }
1818
bool NoFirstRun { get; }
1919
int Port { get; }
20-
int Rate { get; }
2120
bool Record { get; }
2221
IEnumerable<int> WatchPids { get; }
2322
IEnumerable<string> WatchProcessNames { get; }

dev-proxy-plugins/RandomErrors/GenericRandomErrorPlugin.cs

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
using DevProxy.Plugins.Behavior;
1313
using Microsoft.Extensions.Logging;
1414
using System.Text.RegularExpressions;
15+
using System.CommandLine.Invocation;
16+
using System.CommandLine;
1517

1618
namespace DevProxy.Plugins.RandomErrors;
1719
internal enum GenericRandomErrorFailMode
@@ -24,12 +26,15 @@ internal enum GenericRandomErrorFailMode
2426
public class GenericRandomErrorConfiguration
2527
{
2628
public string? ErrorsFile { get; set; }
29+
public int Rate { get; set; } = 50;
2730
public int RetryAfterInSeconds { get; set; } = 5;
2831
public IEnumerable<GenericErrorResponse> Errors { get; set; } = [];
2932
}
3033

3134
public class GenericRandomErrorPlugin(IPluginEvents pluginEvents, IProxyContext context, ILogger logger, ISet<UrlToWatch> urlsToWatch, IConfigurationSection? configSection = null) : BaseProxyPlugin(pluginEvents, context, logger, urlsToWatch, configSection)
3235
{
36+
private static readonly string _rateOptionName = "--failure-rate";
37+
3338
private readonly GenericRandomErrorConfiguration _configuration = new();
3439
private GenericErrorResponsesLoader? _loader = null;
3540

@@ -38,7 +43,7 @@ public class GenericRandomErrorPlugin(IPluginEvents pluginEvents, IProxyContext
3843
private readonly Random _random = new();
3944

4045
// uses config to determine if a request should be failed
41-
private GenericRandomErrorFailMode ShouldFail() => _random.Next(1, 100) <= Context.Configuration.Rate ? GenericRandomErrorFailMode.Random : GenericRandomErrorFailMode.PassThru;
46+
private GenericRandomErrorFailMode ShouldFail() => _random.Next(1, 100) <= _configuration.Rate ? GenericRandomErrorFailMode.Random : GenericRandomErrorFailMode.PassThru;
4247

4348
private void FailResponse(ProxyRequestArgs e)
4449
{
@@ -192,9 +197,43 @@ public override async Task RegisterAsync()
192197
_loader = new GenericErrorResponsesLoader(Logger, _configuration);
193198

194199
PluginEvents.Init += OnInit;
200+
PluginEvents.OptionsLoaded += OnOptionsLoaded;
195201
PluginEvents.BeforeRequest += OnRequestAsync;
196202
}
197203

204+
public override Option[] GetOptions()
205+
{
206+
var _rateOption = new Option<int?>(_rateOptionName, "The percentage of chance that a request will fail");
207+
_rateOption.AddAlias("-f");
208+
_rateOption.ArgumentHelpName = "failure rate";
209+
_rateOption.AddValidator((input) =>
210+
{
211+
try
212+
{
213+
int? value = input.GetValueForOption(_rateOption);
214+
if (value.HasValue && (value < 0 || value > 100))
215+
{
216+
input.ErrorMessage = $"{value} is not a valid failure rate. Specify a number between 0 and 100";
217+
}
218+
}
219+
catch (InvalidOperationException ex)
220+
{
221+
input.ErrorMessage = ex.Message;
222+
}
223+
});
224+
225+
return [_rateOption];
226+
}
227+
228+
private void OnOptionsLoaded(object? sender, OptionsLoadedArgs e)
229+
{
230+
InvocationContext context = e.Context;
231+
232+
var rate = context.ParseResult.GetValueForOption<int?>(_rateOptionName, e.Options);
233+
if (rate is not null)
234+
_configuration.Rate = rate.Value;
235+
}
236+
198237
private void OnInit(object? sender, InitArgs e)
199238
{
200239
_loader?.InitResponsesWatcher();
@@ -216,7 +255,7 @@ private Task OnRequestAsync(object? sender, ProxyRequestArgs e)
216255

217256
var failMode = ShouldFail();
218257

219-
if (failMode == GenericRandomErrorFailMode.PassThru && Context.Configuration?.Rate != 100)
258+
if (failMode == GenericRandomErrorFailMode.PassThru && _configuration.Rate != 100)
220259
{
221260
Logger.LogRequest("Pass through", MessageType.Skipped, new LoggingContext(e.Session));
222261
return Task.CompletedTask;

dev-proxy-plugins/RandomErrors/GraphRandomErrorPlugin.cs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,15 @@ internal enum GraphRandomErrorFailMode
2525
public class GraphRandomErrorConfiguration
2626
{
2727
public List<int> AllowedErrors { get; set; } = [];
28+
public int Rate { get; set; } = 50;
2829
public int RetryAfterInSeconds { get; set; } = 5;
2930
}
3031

3132
public class GraphRandomErrorPlugin(IPluginEvents pluginEvents, IProxyContext context, ILogger logger, ISet<UrlToWatch> urlsToWatch, IConfigurationSection? configSection = null) : BaseProxyPlugin(pluginEvents, context, logger, urlsToWatch, configSection)
3233
{
3334
private static readonly string _allowedErrorsOptionName = "--allowed-errors";
35+
private static readonly string _rateOptionName = "--failure-rate";
36+
3437
private readonly GraphRandomErrorConfiguration _configuration = new();
3538

3639
public override string Name => nameof(GraphRandomErrorPlugin);
@@ -89,7 +92,7 @@ public class GraphRandomErrorPlugin(IPluginEvents pluginEvents, IProxyContext co
8992
private readonly Random _random = new();
9093

9194
// uses config to determine if a request should be failed
92-
private GraphRandomErrorFailMode ShouldFail(ProxyRequestArgs e) => _random.Next(1, 100) <= Context.Configuration.Rate ? GraphRandomErrorFailMode.Random : GraphRandomErrorFailMode.PassThru;
95+
private GraphRandomErrorFailMode ShouldFail(ProxyRequestArgs e) => _random.Next(1, 100) <= _configuration.Rate ? GraphRandomErrorFailMode.Random : GraphRandomErrorFailMode.PassThru;
9396

9497
private void FailResponse(ProxyRequestArgs e)
9598
{
@@ -222,7 +225,26 @@ public override Option[] GetOptions()
222225
};
223226
_allowedErrors.AddAlias("-a");
224227

225-
return [_allowedErrors];
228+
var _rateOption = new Option<int?>(_rateOptionName, "The percentage of chance that a request will fail");
229+
_rateOption.AddAlias("-f");
230+
_rateOption.ArgumentHelpName = "failure rate";
231+
_rateOption.AddValidator((input) =>
232+
{
233+
try
234+
{
235+
int? value = input.GetValueForOption(_rateOption);
236+
if (value.HasValue && (value < 0 || value > 100))
237+
{
238+
input.ErrorMessage = $"{value} is not a valid failure rate. Specify a number between 0 and 100";
239+
}
240+
}
241+
catch (InvalidOperationException ex)
242+
{
243+
input.ErrorMessage = ex.Message;
244+
}
245+
});
246+
247+
return [_allowedErrors, _rateOption];
226248
}
227249

228250
public override async Task RegisterAsync()
@@ -250,6 +272,10 @@ private void OnOptionsLoaded(object? sender, OptionsLoadedArgs e)
250272
_methodStatusCode[k] = _methodStatusCode[k].Where(e => _configuration.AllowedErrors.Any(a => (int)e == a)).ToArray();
251273
}
252274
}
275+
276+
var rate = context.ParseResult.GetValueForOption<int?>(_rateOptionName, e.Options);
277+
if (rate is not null)
278+
_configuration.Rate = rate.Value;
253279
}
254280

255281
private Task OnRequestAsync(object? sender, ProxyRequestArgs e)
@@ -267,9 +293,8 @@ private Task OnRequestAsync(object? sender, ProxyRequestArgs e)
267293
return Task.CompletedTask;
268294
}
269295

270-
271296
var failMode = ShouldFail(e);
272-
if (failMode == GraphRandomErrorFailMode.PassThru && Context.Configuration.Rate != 100)
297+
if (failMode == GraphRandomErrorFailMode.PassThru && _configuration.Rate != 100)
273298
{
274299
Logger.LogRequest("Pass through", MessageType.Skipped, new LoggingContext(e.Session));
275300
return Task.CompletedTask;

dev-proxy/CommandHandlers/ProxyCommandHandler.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,6 @@ private void ParseOptions(InvocationContext context)
120120
{
121121
Configuration.WatchProcessNames = watchProcessNames;
122122
}
123-
var rate = context.ParseResult.GetValueForOption<int?>(ProxyHost.RateOptionName, _options);
124-
if (rate is not null)
125-
{
126-
Configuration.Rate = rate.Value;
127-
}
128123
var noFirstRun = context.ParseResult.GetValueForOption<bool?>(ProxyHost.NoFirstRunOptionName, _options);
129124
if (noFirstRun is not null)
130125
{

dev-proxy/ProxyConfiguration.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ public class ProxyConfiguration : IProxyConfiguration
2828
public LogLevel LogLevel { get; set; } = LogLevel.Information;
2929
public IEnumerable<int> WatchPids { get; set; } = new List<int>();
3030
public IEnumerable<string> WatchProcessNames { get; set; } = [];
31-
public int Rate { get; set; } = 50;
3231
public bool NoFirstRun { get; set; } = false;
3332
public bool AsSystemProxy { get; set; } = true;
3433
public bool InstallCert { get; set; } = true;

dev-proxy/ProxyHost.cs

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ internal class ProxyHost
2727
private readonly Option<IEnumerable<string>?> _watchProcessNamesOption;
2828
internal static readonly string ConfigFileOptionName = "--config-file";
2929
private static Option<string?>? _configFileOption;
30-
internal static readonly string RateOptionName = "--failure-rate";
31-
private readonly Option<int?> _rateOption;
3230
internal static readonly string NoFirstRunOptionName = "--no-first-run";
3331
private readonly Option<bool?> _noFirstRunOption;
3432
internal static readonly string AsSystemProxyOptionName = "--as-system-proxy";
@@ -230,25 +228,6 @@ public ProxyHost()
230228
AllowMultipleArgumentsPerToken = true
231229
};
232230

233-
_rateOption = new Option<int?>(RateOptionName, "The percentage of chance that a request will fail");
234-
_rateOption.AddAlias("-f");
235-
_rateOption.ArgumentHelpName = "failure rate";
236-
_rateOption.AddValidator((input) =>
237-
{
238-
try
239-
{
240-
int? value = input.GetValueForOption(_rateOption);
241-
if (value.HasValue && (value < 0 || value > 100))
242-
{
243-
input.ErrorMessage = $"{value} is not a valid failure rate. Specify a number between 0 and 100";
244-
}
245-
}
246-
catch (InvalidOperationException ex)
247-
{
248-
input.ErrorMessage = ex.Message;
249-
}
250-
});
251-
252231
_noFirstRunOption = new Option<bool?>(NoFirstRunOptionName, "Skip the first run experience");
253232

254233
_asSystemProxyOption = new Option<bool?>(AsSystemProxyOptionName, "Set Dev Proxy as the system proxy");
@@ -304,7 +283,6 @@ public RootCommand GetRootCommand(ILogger logger)
304283
_recordOption,
305284
_watchPidsOption,
306285
_watchProcessNamesOption,
307-
_rateOption,
308286
// _configFileOption is set during the call to load
309287
// `ProxyCommandHandler.Configuration`. As such, it's always set here
310288
_configFileOption!,
@@ -466,7 +444,6 @@ public RootCommand GetRootCommand(ILogger logger)
466444
_recordOption,
467445
_watchPidsOption,
468446
_watchProcessNamesOption,
469-
_rateOption,
470447
_noFirstRunOption,
471448
_asSystemProxyOption,
472449
_installCertOption,

dev-proxy/config/m365.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,8 @@
185185
503,
186186
504,
187187
507
188-
]
188+
],
189+
"rate": 50
189190
},
190191
"executionSummaryPlugin": {
191192
"$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v0.25.0/executionsummaryplugin.schema.json",
@@ -214,7 +215,6 @@
214215
"rateLimit": 120,
215216
"retryAfterSeconds": 5
216217
},
217-
"rate": 50,
218218
"labelMode": "text",
219219
"logLevel": "information"
220-
}
220+
}

dev-proxy/config/microsoft-graph.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,13 @@
7575
503,
7676
504,
7777
507
78-
]
78+
],
79+
"rate": 50
7980
},
8081
"executionSummaryPlugin": {
8182
"$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v0.25.0/executionsummaryplugin.schema.json",
8283
"groupBy": "url"
8384
},
84-
"rate": 50,
8585
"labelMode": "text",
8686
"logLevel": "information"
8787
}

dev-proxy/devproxyrc.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
],
1919
"genericRandomErrorPlugin": {
2020
"$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v0.25.0/genericrandomerrorplugin.schema.json",
21-
"errorsFile": "devproxy-errors.json"
21+
"errorsFile": "devproxy-errors.json",
22+
"rate": 50
2223
},
23-
"rate": 50,
2424
"logLevel": "information",
2525
"newVersionNotification": "stable",
2626
"showSkipMessages": true,

schemas/v0.25.0/genericrandomerrorplugin.schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
"errorsFile": {
1010
"type": "string"
1111
},
12+
"rate": {
13+
"type": "number",
14+
"minimum": 0,
15+
"maximum": 100
16+
},
1217
"retryAfterInSeconds": {
1318
"type": "integer",
1419
"minimum": 1

0 commit comments

Comments
 (0)