Skip to content

Commit

Permalink
[Feature][DevTools] Logging of HTTP Exchange operations (#217) +semve…
Browse files Browse the repository at this point in the history
…r: feature

* [Feature][DevTools] Logging of HTTP Exchange operations

* Update .NET version and NuGet package versions
Add pl and uk localizations

* Update pipeline to use .NET 6
  • Loading branch information
mialeska authored Mar 8, 2022
1 parent c26cddb commit 5b371e9
Show file tree
Hide file tree
Showing 16 changed files with 620 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
<None Remove="Resources\JavaScripts\SetAttribute.js" />
<None Remove="Resources\Localization\be.json" />
<None Remove="Resources\Localization\en.json" />
<None Remove="Resources\Localization\pl.json" />
<None Remove="Resources\Localization\ru.json" />
<None Remove="Resources\Localization\uk.json" />
<None Remove="Resources\settings.json" />
<None Include="..\..\..\LICENSE">
<Pack>True</Pack>
Expand Down Expand Up @@ -65,14 +67,16 @@
<EmbeddedResource Include="Resources\JavaScripts\OpenNewTab.js" />
<EmbeddedResource Include="Resources\JavaScripts\SetAttribute.js" />
<EmbeddedResource Include="Resources\JavaScripts\SetValue.js" />
<EmbeddedResource Include="Resources\Localization\pl.json" />
<EmbeddedResource Include="Resources\Localization\uk.json" />
<EmbeddedResource Include="Resources\Localization\be.json" />
<EmbeddedResource Include="Resources\Localization\en.json" />
<EmbeddedResource Include="Resources\Localization\ru.json" />
<EmbeddedResource Include="Resources\settings.json" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Aquality.Selenium.Core" Version="2.0.1" />
<PackageReference Include="Aquality.Selenium.Core" Version="2.0.2" />
<PackageReference Include="WebDriverManager" Version="2.12.3" />
</ItemGroup>

Expand Down
85 changes: 85 additions & 0 deletions Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using OpenQA.Selenium;
using Aquality.Selenium.Logging;
using OpenQA.Selenium;
using System;
using System.Linq;
using System.Threading.Tasks;

namespace Aquality.Selenium.Browsers
Expand Down Expand Up @@ -35,5 +38,89 @@ public static async Task RegisterBasicAuthenticationAndStartMonitoring(this Brow
networkHandling.AddAuthenticationHandler(handler);
await networkHandling.StartMonitoring();
}

/// <summary>
/// Enables HTTP Request/Response logging, and starts network monitoring.
/// </summary>
/// <param name="browser">Browser instance.</param>
/// <param name="loggingOptions">Logging preferences.</param>
/// <returns>A task to be awaited.</returns>
public static async Task EnableHttpExchangeLoggingAndStartMonitoring(this Browser browser, HttpExchangeLoggingOptions loggingOptions = null)
{
browser.EnableHttpExchangeLogging(loggingOptions);
await browser.Network.StartMonitoring();
}

/// <summary>
/// Enables HTTP Request/Response logging.
/// </summary>
/// <param name="browser">Browser instance.</param>
/// <param name="loggingOptions">Logging preferences.</param>
public static void EnableHttpExchangeLogging(this Browser browser, HttpExchangeLoggingOptions loggingOptions = null)
{
if (loggingOptions == null)
{
loggingOptions = new HttpExchangeLoggingOptions();
}
browser.Network.NetworkRequestSent += GetRequestEventHandler(loggingOptions);
browser.Network.NetworkResponseReceived += GetResponseEventHandler(loggingOptions);
}

private static EventHandler<NetworkResponseReceivedEventArgs> GetResponseEventHandler(HttpExchangeLoggingOptions loggingOptions)
{
return (object sender, NetworkResponseReceivedEventArgs args) =>
{
if (loggingOptions.ResponseInfo.Enabled)
{
AqualityServices.LocalizedLogger.LogByLevel(
loggingOptions.ResponseInfo.LogLevel,
"loc.browser.network.event.responsereceived.log.info",
args.ResponseStatusCode, args.ResponseUrl, args.ResponseResourceType, args.RequestId);
}
if (loggingOptions.ResponseHeaders.Enabled && args.ResponseHeaders.Any())
{
AqualityServices.LocalizedLogger.LogByLevel(
loggingOptions.ResponseHeaders.LogLevel,
"loc.browser.network.event.responsereceived.log.headers",
string.Join(",", args.ResponseHeaders.Select(header => $"{Environment.NewLine}\t{header.Key}: {header.Value}")));
}
if (loggingOptions.ResponseBody.Enabled && !string.IsNullOrEmpty(args.ResponseBody))
{
AqualityServices.LocalizedLogger.LogByLevel(
loggingOptions.ResponseBody.LogLevel,
"loc.browser.network.event.responsereceived.log.body",
args.ResponseBody);
}
};
}

private static EventHandler<NetworkRequestSentEventArgs> GetRequestEventHandler(HttpExchangeLoggingOptions loggingOptions)
{
return (object sender, NetworkRequestSentEventArgs args) =>
{
if (loggingOptions.RequestInfo.Enabled)
{
AqualityServices.LocalizedLogger.LogByLevel(
loggingOptions.RequestInfo.LogLevel,
"loc.browser.network.event.requestsent.log.info",
args.RequestMethod, args.RequestUrl, args.RequestId);

}
if (loggingOptions.RequestHeaders.Enabled && args.RequestHeaders.Any())
{
AqualityServices.LocalizedLogger.LogByLevel(
loggingOptions.RequestHeaders.LogLevel,
"loc.browser.network.event.requestsent.log.headers",
string.Join(",", args.RequestHeaders.Select(header => $"{Environment.NewLine}\t{header.Key}: {header.Value}")));
}
if (loggingOptions.RequestPostData.Enabled && !string.IsNullOrEmpty(args.RequestPostData))
{
AqualityServices.LocalizedLogger.LogByLevel(
loggingOptions.RequestPostData.LogLevel,
"loc.browser.network.event.requestsent.log.data",
args.RequestPostData);
}
};
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
namespace Aquality.Selenium.Logging
{
/// <summary>
/// HTTP Request/Response logging options.
/// </summary>
public class HttpExchangeLoggingOptions
{
/// <summary>
/// Controls logging of general request info: Method, URL, Request ID.
/// </summary>
public LoggingParameters RequestInfo { get; set; } = new LoggingParameters { Enabled = true, LogLevel = LogLevel.Info };

/// <summary>
/// Controls logging of request headers.
/// </summary>
public LoggingParameters RequestHeaders { get; set; } = new LoggingParameters { Enabled = true, LogLevel = LogLevel.Debug };

/// <summary>
/// Controls logging of request POST data.
/// </summary>
public LoggingParameters RequestPostData { get; set; } = new LoggingParameters { Enabled = false, LogLevel = LogLevel.Debug };

/// <summary>
/// Controls logging of general response info: Status code, URL, Resource type, Request ID.
/// </summary>
public LoggingParameters ResponseInfo { get; set; } = new LoggingParameters { Enabled = true, LogLevel = LogLevel.Info };

/// <summary>
/// Controls logging of response headers.
/// </summary>
public LoggingParameters ResponseHeaders { get; set; } = new LoggingParameters { Enabled = true, LogLevel = LogLevel.Debug };

/// <summary>
/// Controls logging of response body.
/// </summary>
public LoggingParameters ResponseBody { get; set; } = new LoggingParameters { Enabled = false, LogLevel = LogLevel.Debug };
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using Aquality.Selenium.Core.Localization;
using System;

namespace Aquality.Selenium.Logging
{
/// <summary>
/// Extensions for localized logger.
/// </summary>
public static class LocalizedLoggerExtensions
{
/// <summary>
/// Logging of localized messages with a specific log level.
/// </summary>
/// <param name="logger">Current instance of logger.</param>
/// <param name="logLevel">Logging level.</param>
/// <param name="messageKey">Localized message key.</param>
/// <param name="args">Arguments for the localized message.</param>
/// <exception cref="NotSupportedException">Thrown when specified log level is not supported.</exception>
public static void LogByLevel(this ILocalizedLogger logger, LogLevel logLevel, string messageKey, params object[] args)
{
switch (logLevel)
{
case LogLevel.Debug:
logger.Debug(messageKey, args: args);
break;
case LogLevel.Info:
logger.Info(messageKey, args);
break;
case LogLevel.Warn:
logger.Warn(messageKey, args);
break;
case LogLevel.Error:
logger.Error(messageKey, args);
break;
case LogLevel.Fatal:
logger.Fatal(messageKey, args: args);
break;
default:
throw new NotSupportedException($"Localized logging at level [{logLevel}] is not supported.");
}
}
}
}
14 changes: 14 additions & 0 deletions Aquality.Selenium/src/Aquality.Selenium/Logging/LogLevel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace Aquality.Selenium.Logging
{
/// <summary>
/// Logging level for specific features, such as HTTP Exchange.
/// </summary>
public enum LogLevel
{
Debug,
Info,
Warn,
Error,
Fatal
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace Aquality.Selenium.Logging
{
/// <summary>
/// Logging parameters for specific features, such as HTTP Exchange.
/// </summary>
public struct LoggingParameters
{
/// <summary>
/// Whether feature logging should be enabled or not.
/// </summary>
public bool Enabled { get; set; }

/// <summary>
/// Logging level for the specific feature.
/// </summary>
public LogLevel LogLevel { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"loc.browser.arguments": "Атрымалі стартавыя аргументы браўзэра з settings файла: {0}",
"loc.browser.excludedArguments": "Выключэнне аргументаў браўзэра з settings файла: {0}",
"loc.browser.excludedArguments": "Атрымалі выключаныя аргументы браўзэра з settings файла: {0}",
"loc.browser.back": "Вяртаемся да папярэдняй старонкі",
"loc.browser.forward": "Пераходзім да наступнай старонкі",
"loc.browser.capabilities": "Атрымалі capabilities браўзэра з settings файла: {0}",
Expand Down Expand Up @@ -86,6 +86,12 @@
"loc.browser.devtools.command.execute.result": "Вынік DevTools каманды: [{0}]",
"loc.browser.network.event.requestsent.add": "Падпісваемся на падзею адпраўкі сеткавага запыта",
"loc.browser.network.event.requestsent.remove": "Адпісваемся ад падзеі адпраўкі сеткавага запыта",
"loc.browser.network.event.requestsent.log.info": "Адпраўлены HTTP запыт:\r\nМетад: \t\t{0}, \r\nURL: \t\t\t{1}, \r\nID запыта: \t{2}",
"loc.browser.network.event.requestsent.log.headers": "Загалоўкі запыта:\r\n{{{0}\r\n}}",
"loc.browser.network.event.requestsent.log.data": "POST дадзеныя запыта:\r\n{0}",
"loc.browser.network.event.responsereceived.log.info": "Атрыманы HTTP адказ:\r\nСтатус-код: \t{0}, \r\nURL: \t\t\t{1}, \r\nТып рэсурса: \t{2}, \r\nID запыта: \t{3}",
"loc.browser.network.event.responsereceived.log.headers": "Загалоўкі адказа:\r\n{{{0}\r\n}}",
"loc.browser.network.event.responsereceived.log.body": "Цела адказа:\r\n{0}",
"loc.browser.network.event.responsereceived.add": "Падпісваемся на падзею атрымання сеткавага адказа",
"loc.browser.network.event.responsereceived.remove": "Адпісваемся ад падзеі атрымання сеткавага адказа",
"loc.browser.network.handler.authentication.add": "Дадаем апрацоўшчык базавай аўтэнтыфікацыі",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"loc.browser.arguments": "Got browser start arguments from settings file: {0}",
"loc.browser.excludedArguments": "Exclude browser arguments from settings file: {0}",
"loc.browser.excludedArguments": "Got excluded browser arguments from settings file: {0}",
"loc.browser.back": "Return to previous page",
"loc.browser.forward": "Proceed to the next page",
"loc.browser.capabilities": "Got browser capabilities from settings file: {0}",
Expand Down Expand Up @@ -86,6 +86,12 @@
"loc.browser.devtools.command.execute.result": "DevTools command result: [{0}]",
"loc.browser.network.event.requestsent.add": "Subscribing to Network Request Sent event",
"loc.browser.network.event.requestsent.remove": "Unsubscribing from Network Request Sent event",
"loc.browser.network.event.requestsent.log.info": "Send HTTP Request:\r\nMethod: \t\t{0}, \r\nURL: \t\t\t{1}, \r\nRequest ID: \t{2}",
"loc.browser.network.event.requestsent.log.headers": "Request headers:\r\n{{{0}\r\n}}",
"loc.browser.network.event.requestsent.log.data": "Request POST data:\r\n{0}",
"loc.browser.network.event.responsereceived.log.info": "Received HTTP Response:\r\nStatus code: \t{0}, \r\nURL: \t\t\t{1}, \r\nResource type: \t{2}, \r\nRequest ID: \t{3}",
"loc.browser.network.event.responsereceived.log.headers": "Response headers:\r\n{{{0}\r\n}}",
"loc.browser.network.event.responsereceived.log.body": "Response body:\r\n{0}",
"loc.browser.network.event.responsereceived.add": "Subscribing to Network Response Received event",
"loc.browser.network.event.responsereceived.remove": "Unsubscribing from Network Response Received event",
"loc.browser.network.handler.authentication.add": "Adding Basic Authentication handler",
Expand Down
Loading

0 comments on commit 5b371e9

Please sign in to comment.