Skip to content

Commit

Permalink
Reporters (dotnet#714)
Browse files Browse the repository at this point in the history
  • Loading branch information
waldekmastykarz authored May 22, 2024
1 parent 5f76f8b commit aa2de7a
Show file tree
Hide file tree
Showing 17 changed files with 1,084 additions and 304 deletions.
17 changes: 17 additions & 0 deletions dev-proxy-abstractions/BaseReportingPlugin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

namespace Microsoft.DevProxy.Abstractions;

public abstract class BaseReportingPlugin : BaseProxyPlugin
{
protected virtual void StoreReport(object report, ProxyEventArgsBase e)
{
if (report is null)
{
return;
}

((Dictionary<string, object>)e.GlobalData[ProxyUtils.ReportsKey])[Name] = report;
}
}
2 changes: 2 additions & 0 deletions dev-proxy-abstractions/ProxyUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public static class ProxyUtils
// doesn't end with a path separator
public static string? AppFolder => Path.GetDirectoryName(AppContext.BaseDirectory);

public static readonly string ReportsKey = "Reports";

public static bool IsGraphRequest(Request request) => IsGraphUrl(request.RequestUri);

public static bool IsGraphUrl(Uri uri) =>
Expand Down
2 changes: 1 addition & 1 deletion dev-proxy-plugins/MinimalPermissions/PermissionsType.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace Microsoft.DevProxy.Plugins.RequestLogs.MinimalPermissions;

internal enum PermissionsType
public enum PermissionsType
{
Application,
Delegated
Expand Down
2 changes: 1 addition & 1 deletion dev-proxy-plugins/MinimalPermissions/RequestInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Microsoft.DevProxy.Plugins.RequestLogs.MinimalPermissions;

internal class RequestInfo
public class RequestInfo
{
[JsonPropertyName("requestUrl")]
public string Url { get; set; } = string.Empty;
Expand Down
63 changes: 63 additions & 0 deletions dev-proxy-plugins/Reporters/BaseReporter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using Microsoft.DevProxy.Abstractions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

namespace Microsoft.DevProxy.Plugins.Reporters;

public abstract class BaseReporter : BaseProxyPlugin
{
public virtual string FileExtension => throw new NotImplementedException();

public override void Register(IPluginEvents pluginEvents,
IProxyContext context,
ISet<UrlToWatch> urlsToWatch,
IConfigurationSection? configSection = null)
{
base.Register(pluginEvents, context, urlsToWatch, configSection);

pluginEvents.AfterRecordingStop += AfterRecordingStop;
}

protected abstract string? GetReport(KeyValuePair<string, object> report);

protected virtual Task AfterRecordingStop(object sender, RecordingArgs e)
{
if (!e.GlobalData.ContainsKey(ProxyUtils.ReportsKey) ||
e.GlobalData[ProxyUtils.ReportsKey] is not Dictionary<string, object> reports ||
!reports.Any())
{
_logger?.LogDebug("No reports found");
return Task.CompletedTask;
}

foreach (var report in reports)
{
_logger?.LogDebug("Transforming report {reportKey}...", report.Key);

var reportContents = GetReport(report);

if (string.IsNullOrEmpty(reportContents))
{
_logger?.LogDebug("Report {reportKey} is empty, ignore", report.Key);
continue;
}

var fileName = $"{report.Key}_{Name}{FileExtension}";
_logger?.LogDebug("File name for report {report}: {fileName}", report.Key, fileName);

if (File.Exists(fileName))
{
_logger?.LogDebug("File {fileName} already exists, appending timestamp", fileName);
fileName = $"{report.Key}_{Name}_{DateTime.Now:yyyyMMddHHmmss}{FileExtension}";
}

_logger?.LogDebug("Writing report {reportKey} to {fileName}...", report.Key, fileName);
File.WriteAllText(fileName, reportContents);
}

return Task.CompletedTask;
}
}
64 changes: 64 additions & 0 deletions dev-proxy-plugins/Reporters/JsonReporter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.Text.Json;
using Microsoft.DevProxy.Abstractions;
using Microsoft.DevProxy.Plugins.RequestLogs;
using Microsoft.Extensions.Logging;

namespace Microsoft.DevProxy.Plugins.Reporters;

public class JsonReporter : BaseReporter
{
public override string Name => nameof(JsonReporter);
public override string FileExtension => ".json";

private readonly Dictionary<Type, Func<object, object>> _transformers = new()
{
{ typeof(ExecutionSummaryPluginReportByUrl), TransformExecutionSummary },
{ typeof(ExecutionSummaryPluginReportByMessageType), TransformExecutionSummary },
};

protected override string GetReport(KeyValuePair<string, object> report)
{
_logger?.LogDebug("Serializing report {reportKey}...", report.Key);

var reportData = report.Value;
var reportType = reportData.GetType();

if (_transformers.TryGetValue(reportType, out var transform))
{
_logger?.LogDebug("Transforming {reportType} using {transform}...", reportType.Name, transform.Method.Name);
reportData = transform(reportData);
}
else
{
_logger?.LogDebug("No transformer found for {reportType}", reportType.Name);
}

if (reportData is string strVal)
{
_logger?.LogDebug("{reportKey} is a string. Checking if it's JSON...", report.Key);

try
{
JsonSerializer.Deserialize<object>(strVal);
_logger?.LogDebug("{reportKey} is already JSON, ignore", report.Key);
// already JSON, ignore
return strVal;
}
catch
{
_logger?.LogDebug("{reportKey} is not JSON, serializing...", report.Key);
}
}

return JsonSerializer.Serialize(reportData, ProxyUtils.JsonSerializerOptions);
}

private static object TransformExecutionSummary(object report)
{
var executionSummaryReport = (ExecutionSummaryPluginReportBase)report;
return executionSummaryReport.Data;
}
}
Loading

0 comments on commit aa2de7a

Please sign in to comment.