Skip to content

Commit 5b371e9

Browse files
authored
[Feature][DevTools] Logging of HTTP Exchange operations (#217) +semver: 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
1 parent c26cddb commit 5b371e9

File tree

16 files changed

+620
-15
lines changed

16 files changed

+620
-15
lines changed

Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.csproj

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
<None Remove="Resources\JavaScripts\SetAttribute.js" />
2929
<None Remove="Resources\Localization\be.json" />
3030
<None Remove="Resources\Localization\en.json" />
31+
<None Remove="Resources\Localization\pl.json" />
3132
<None Remove="Resources\Localization\ru.json" />
33+
<None Remove="Resources\Localization\uk.json" />
3234
<None Remove="Resources\settings.json" />
3335
<None Include="..\..\..\LICENSE">
3436
<Pack>True</Pack>
@@ -65,14 +67,16 @@
6567
<EmbeddedResource Include="Resources\JavaScripts\OpenNewTab.js" />
6668
<EmbeddedResource Include="Resources\JavaScripts\SetAttribute.js" />
6769
<EmbeddedResource Include="Resources\JavaScripts\SetValue.js" />
70+
<EmbeddedResource Include="Resources\Localization\pl.json" />
71+
<EmbeddedResource Include="Resources\Localization\uk.json" />
6872
<EmbeddedResource Include="Resources\Localization\be.json" />
6973
<EmbeddedResource Include="Resources\Localization\en.json" />
7074
<EmbeddedResource Include="Resources\Localization\ru.json" />
7175
<EmbeddedResource Include="Resources\settings.json" />
7276
</ItemGroup>
7377

7478
<ItemGroup>
75-
<PackageReference Include="Aquality.Selenium.Core" Version="2.0.1" />
79+
<PackageReference Include="Aquality.Selenium.Core" Version="2.0.2" />
7680
<PackageReference Include="WebDriverManager" Version="2.12.3" />
7781
</ItemGroup>
7882

Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.xml

Lines changed: 85 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserNetworkExtensions.cs

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
using OpenQA.Selenium;
1+
using Aquality.Selenium.Logging;
2+
using OpenQA.Selenium;
3+
using System;
4+
using System.Linq;
25
using System.Threading.Tasks;
36

47
namespace Aquality.Selenium.Browsers
@@ -35,5 +38,89 @@ public static async Task RegisterBasicAuthenticationAndStartMonitoring(this Brow
3538
networkHandling.AddAuthenticationHandler(handler);
3639
await networkHandling.StartMonitoring();
3740
}
41+
42+
/// <summary>
43+
/// Enables HTTP Request/Response logging, and starts network monitoring.
44+
/// </summary>
45+
/// <param name="browser">Browser instance.</param>
46+
/// <param name="loggingOptions">Logging preferences.</param>
47+
/// <returns>A task to be awaited.</returns>
48+
public static async Task EnableHttpExchangeLoggingAndStartMonitoring(this Browser browser, HttpExchangeLoggingOptions loggingOptions = null)
49+
{
50+
browser.EnableHttpExchangeLogging(loggingOptions);
51+
await browser.Network.StartMonitoring();
52+
}
53+
54+
/// <summary>
55+
/// Enables HTTP Request/Response logging.
56+
/// </summary>
57+
/// <param name="browser">Browser instance.</param>
58+
/// <param name="loggingOptions">Logging preferences.</param>
59+
public static void EnableHttpExchangeLogging(this Browser browser, HttpExchangeLoggingOptions loggingOptions = null)
60+
{
61+
if (loggingOptions == null)
62+
{
63+
loggingOptions = new HttpExchangeLoggingOptions();
64+
}
65+
browser.Network.NetworkRequestSent += GetRequestEventHandler(loggingOptions);
66+
browser.Network.NetworkResponseReceived += GetResponseEventHandler(loggingOptions);
67+
}
68+
69+
private static EventHandler<NetworkResponseReceivedEventArgs> GetResponseEventHandler(HttpExchangeLoggingOptions loggingOptions)
70+
{
71+
return (object sender, NetworkResponseReceivedEventArgs args) =>
72+
{
73+
if (loggingOptions.ResponseInfo.Enabled)
74+
{
75+
AqualityServices.LocalizedLogger.LogByLevel(
76+
loggingOptions.ResponseInfo.LogLevel,
77+
"loc.browser.network.event.responsereceived.log.info",
78+
args.ResponseStatusCode, args.ResponseUrl, args.ResponseResourceType, args.RequestId);
79+
}
80+
if (loggingOptions.ResponseHeaders.Enabled && args.ResponseHeaders.Any())
81+
{
82+
AqualityServices.LocalizedLogger.LogByLevel(
83+
loggingOptions.ResponseHeaders.LogLevel,
84+
"loc.browser.network.event.responsereceived.log.headers",
85+
string.Join(",", args.ResponseHeaders.Select(header => $"{Environment.NewLine}\t{header.Key}: {header.Value}")));
86+
}
87+
if (loggingOptions.ResponseBody.Enabled && !string.IsNullOrEmpty(args.ResponseBody))
88+
{
89+
AqualityServices.LocalizedLogger.LogByLevel(
90+
loggingOptions.ResponseBody.LogLevel,
91+
"loc.browser.network.event.responsereceived.log.body",
92+
args.ResponseBody);
93+
}
94+
};
95+
}
96+
97+
private static EventHandler<NetworkRequestSentEventArgs> GetRequestEventHandler(HttpExchangeLoggingOptions loggingOptions)
98+
{
99+
return (object sender, NetworkRequestSentEventArgs args) =>
100+
{
101+
if (loggingOptions.RequestInfo.Enabled)
102+
{
103+
AqualityServices.LocalizedLogger.LogByLevel(
104+
loggingOptions.RequestInfo.LogLevel,
105+
"loc.browser.network.event.requestsent.log.info",
106+
args.RequestMethod, args.RequestUrl, args.RequestId);
107+
108+
}
109+
if (loggingOptions.RequestHeaders.Enabled && args.RequestHeaders.Any())
110+
{
111+
AqualityServices.LocalizedLogger.LogByLevel(
112+
loggingOptions.RequestHeaders.LogLevel,
113+
"loc.browser.network.event.requestsent.log.headers",
114+
string.Join(",", args.RequestHeaders.Select(header => $"{Environment.NewLine}\t{header.Key}: {header.Value}")));
115+
}
116+
if (loggingOptions.RequestPostData.Enabled && !string.IsNullOrEmpty(args.RequestPostData))
117+
{
118+
AqualityServices.LocalizedLogger.LogByLevel(
119+
loggingOptions.RequestPostData.LogLevel,
120+
"loc.browser.network.event.requestsent.log.data",
121+
args.RequestPostData);
122+
}
123+
};
124+
}
38125
}
39126
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
namespace Aquality.Selenium.Logging
2+
{
3+
/// <summary>
4+
/// HTTP Request/Response logging options.
5+
/// </summary>
6+
public class HttpExchangeLoggingOptions
7+
{
8+
/// <summary>
9+
/// Controls logging of general request info: Method, URL, Request ID.
10+
/// </summary>
11+
public LoggingParameters RequestInfo { get; set; } = new LoggingParameters { Enabled = true, LogLevel = LogLevel.Info };
12+
13+
/// <summary>
14+
/// Controls logging of request headers.
15+
/// </summary>
16+
public LoggingParameters RequestHeaders { get; set; } = new LoggingParameters { Enabled = true, LogLevel = LogLevel.Debug };
17+
18+
/// <summary>
19+
/// Controls logging of request POST data.
20+
/// </summary>
21+
public LoggingParameters RequestPostData { get; set; } = new LoggingParameters { Enabled = false, LogLevel = LogLevel.Debug };
22+
23+
/// <summary>
24+
/// Controls logging of general response info: Status code, URL, Resource type, Request ID.
25+
/// </summary>
26+
public LoggingParameters ResponseInfo { get; set; } = new LoggingParameters { Enabled = true, LogLevel = LogLevel.Info };
27+
28+
/// <summary>
29+
/// Controls logging of response headers.
30+
/// </summary>
31+
public LoggingParameters ResponseHeaders { get; set; } = new LoggingParameters { Enabled = true, LogLevel = LogLevel.Debug };
32+
33+
/// <summary>
34+
/// Controls logging of response body.
35+
/// </summary>
36+
public LoggingParameters ResponseBody { get; set; } = new LoggingParameters { Enabled = false, LogLevel = LogLevel.Debug };
37+
}
38+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using Aquality.Selenium.Core.Localization;
2+
using System;
3+
4+
namespace Aquality.Selenium.Logging
5+
{
6+
/// <summary>
7+
/// Extensions for localized logger.
8+
/// </summary>
9+
public static class LocalizedLoggerExtensions
10+
{
11+
/// <summary>
12+
/// Logging of localized messages with a specific log level.
13+
/// </summary>
14+
/// <param name="logger">Current instance of logger.</param>
15+
/// <param name="logLevel">Logging level.</param>
16+
/// <param name="messageKey">Localized message key.</param>
17+
/// <param name="args">Arguments for the localized message.</param>
18+
/// <exception cref="NotSupportedException">Thrown when specified log level is not supported.</exception>
19+
public static void LogByLevel(this ILocalizedLogger logger, LogLevel logLevel, string messageKey, params object[] args)
20+
{
21+
switch (logLevel)
22+
{
23+
case LogLevel.Debug:
24+
logger.Debug(messageKey, args: args);
25+
break;
26+
case LogLevel.Info:
27+
logger.Info(messageKey, args);
28+
break;
29+
case LogLevel.Warn:
30+
logger.Warn(messageKey, args);
31+
break;
32+
case LogLevel.Error:
33+
logger.Error(messageKey, args);
34+
break;
35+
case LogLevel.Fatal:
36+
logger.Fatal(messageKey, args: args);
37+
break;
38+
default:
39+
throw new NotSupportedException($"Localized logging at level [{logLevel}] is not supported.");
40+
}
41+
}
42+
}
43+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
namespace Aquality.Selenium.Logging
2+
{
3+
/// <summary>
4+
/// Logging level for specific features, such as HTTP Exchange.
5+
/// </summary>
6+
public enum LogLevel
7+
{
8+
Debug,
9+
Info,
10+
Warn,
11+
Error,
12+
Fatal
13+
}
14+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace Aquality.Selenium.Logging
2+
{
3+
/// <summary>
4+
/// Logging parameters for specific features, such as HTTP Exchange.
5+
/// </summary>
6+
public struct LoggingParameters
7+
{
8+
/// <summary>
9+
/// Whether feature logging should be enabled or not.
10+
/// </summary>
11+
public bool Enabled { get; set; }
12+
13+
/// <summary>
14+
/// Logging level for the specific feature.
15+
/// </summary>
16+
public LogLevel LogLevel { get; set; }
17+
}
18+
}

Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/be.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"loc.browser.arguments": "Атрымалі стартавыя аргументы браўзэра з settings файла: {0}",
3-
"loc.browser.excludedArguments": "Выключэнне аргументаў браўзэра з settings файла: {0}",
3+
"loc.browser.excludedArguments": "Атрымалі выключаныя аргументы браўзэра з settings файла: {0}",
44
"loc.browser.back": "Вяртаемся да папярэдняй старонкі",
55
"loc.browser.forward": "Пераходзім да наступнай старонкі",
66
"loc.browser.capabilities": "Атрымалі capabilities браўзэра з settings файла: {0}",
@@ -86,6 +86,12 @@
8686
"loc.browser.devtools.command.execute.result": "Вынік DevTools каманды: [{0}]",
8787
"loc.browser.network.event.requestsent.add": "Падпісваемся на падзею адпраўкі сеткавага запыта",
8888
"loc.browser.network.event.requestsent.remove": "Адпісваемся ад падзеі адпраўкі сеткавага запыта",
89+
"loc.browser.network.event.requestsent.log.info": "Адпраўлены HTTP запыт:\r\nМетад: \t\t{0}, \r\nURL: \t\t\t{1}, \r\nID запыта: \t{2}",
90+
"loc.browser.network.event.requestsent.log.headers": "Загалоўкі запыта:\r\n{{{0}\r\n}}",
91+
"loc.browser.network.event.requestsent.log.data": "POST дадзеныя запыта:\r\n{0}",
92+
"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}",
93+
"loc.browser.network.event.responsereceived.log.headers": "Загалоўкі адказа:\r\n{{{0}\r\n}}",
94+
"loc.browser.network.event.responsereceived.log.body": "Цела адказа:\r\n{0}",
8995
"loc.browser.network.event.responsereceived.add": "Падпісваемся на падзею атрымання сеткавага адказа",
9096
"loc.browser.network.event.responsereceived.remove": "Адпісваемся ад падзеі атрымання сеткавага адказа",
9197
"loc.browser.network.handler.authentication.add": "Дадаем апрацоўшчык базавай аўтэнтыфікацыі",

Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/en.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"loc.browser.arguments": "Got browser start arguments from settings file: {0}",
3-
"loc.browser.excludedArguments": "Exclude browser arguments from settings file: {0}",
3+
"loc.browser.excludedArguments": "Got excluded browser arguments from settings file: {0}",
44
"loc.browser.back": "Return to previous page",
55
"loc.browser.forward": "Proceed to the next page",
66
"loc.browser.capabilities": "Got browser capabilities from settings file: {0}",
@@ -86,6 +86,12 @@
8686
"loc.browser.devtools.command.execute.result": "DevTools command result: [{0}]",
8787
"loc.browser.network.event.requestsent.add": "Subscribing to Network Request Sent event",
8888
"loc.browser.network.event.requestsent.remove": "Unsubscribing from Network Request Sent event",
89+
"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}",
90+
"loc.browser.network.event.requestsent.log.headers": "Request headers:\r\n{{{0}\r\n}}",
91+
"loc.browser.network.event.requestsent.log.data": "Request POST data:\r\n{0}",
92+
"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}",
93+
"loc.browser.network.event.responsereceived.log.headers": "Response headers:\r\n{{{0}\r\n}}",
94+
"loc.browser.network.event.responsereceived.log.body": "Response body:\r\n{0}",
8995
"loc.browser.network.event.responsereceived.add": "Subscribing to Network Response Received event",
9096
"loc.browser.network.event.responsereceived.remove": "Unsubscribing from Network Response Received event",
9197
"loc.browser.network.handler.authentication.add": "Adding Basic Authentication handler",

0 commit comments

Comments
 (0)