diff --git a/lib/net9.0/Voucherify.deps.json b/lib/net9.0/Voucherify.deps.json
index f05ddd0c..2c1cb4e9 100644
--- a/lib/net9.0/Voucherify.deps.json
+++ b/lib/net9.0/Voucherify.deps.json
@@ -6,7 +6,7 @@
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v9.0": {
- "Voucherify/9.0.0": {
+ "Voucherify/9.0.1": {
"dependencies": {
"JsonSubTypes": "2.0.1",
"Microsoft.Extensions.DependencyInjection": "9.0.10",
@@ -478,7 +478,7 @@
}
},
"libraries": {
- "Voucherify/9.0.0": {
+ "Voucherify/9.0.1": {
"type": "project",
"serviceable": false,
"sha512": ""
diff --git a/lib/net9.0/Voucherify.dll b/lib/net9.0/Voucherify.dll
index f2cc01bd..8a205b19 100644
Binary files a/lib/net9.0/Voucherify.dll and b/lib/net9.0/Voucherify.dll differ
diff --git a/lib/net9.0/Voucherify.xml b/lib/net9.0/Voucherify.xml
index 872b8003..ec9aac18 100644
--- a/lib/net9.0/Voucherify.xml
+++ b/lib/net9.0/Voucherify.xml
@@ -26260,6 +26260,24 @@
RestSharp's HttpMethod instance.
+
+
+ Starts a stopwatch when debug timing is enabled.
+
+ Whether debug timing is enabled for the current request.
+ A started when enabled; otherwise null.
+
+
+
+ Stops timing and writes a debug log entry for a request stage.
+
+ Whether debug timing is enabled for the current request.
+ The stopwatch instance started for the stage.
+ The request stage label (for example: construction or execution).
+ HTTP method name.
+ Request resource path.
+ Optional response used to enrich debug metadata.
+
Provides all logic for constructing a new RestSharp .
@@ -26844,6 +26862,11 @@
Determine whether or not the "default credentials" (e.g. the user account under which the current process is running) will be sent along to the server. The default is false.
+
+
+ Determines whether request timing diagnostics are enabled.
+
+
Gets or sets the default header.
@@ -27053,6 +27076,12 @@
Api Key name.
Api Key value.
+
+
+ Checks whether debug mode is enabled via the DEBUG environment variable.
+
+ true when DEBUG equals "true" (case-insensitive); otherwise, false.
+
Merge configurations.
@@ -27341,6 +27370,11 @@
Determine whether or not the "default credentials" (e.g. the user account under which the current process is running) will be sent along to the server. The default is false.
+
+
+ Determines whether request timing diagnostics are enabled.
+
+
Get the servers associated with the operation.
diff --git a/lib/netstandard2.0/Voucherify.deps.json b/lib/netstandard2.0/Voucherify.deps.json
index 7ef79ffa..667abb3a 100644
--- a/lib/netstandard2.0/Voucherify.deps.json
+++ b/lib/netstandard2.0/Voucherify.deps.json
@@ -7,10 +7,9 @@
"targets": {
".NETStandard,Version=v2.0": {},
".NETStandard,Version=v2.0/": {
- "Voucherify/9.0.0": {
+ "Voucherify/9.0.1": {
"dependencies": {
"JsonSubTypes": "2.0.1",
- "NETStandard.Library": "2.0.3",
"Newtonsoft.Json": "13.0.3",
"Polly": "8.1.0",
"RestSharp": "112.0.0",
@@ -42,12 +41,6 @@
}
}
},
- "Microsoft.NETCore.Platforms/1.1.0": {},
- "NETStandard.Library/2.0.3": {
- "dependencies": {
- "Microsoft.NETCore.Platforms": "1.1.0"
- }
- },
"Newtonsoft.Json/13.0.3": {
"runtime": {
"lib/netstandard2.0/Newtonsoft.Json.dll": {
@@ -179,7 +172,7 @@
}
},
"libraries": {
- "Voucherify/9.0.0": {
+ "Voucherify/9.0.1": {
"type": "project",
"serviceable": false,
"sha512": ""
@@ -198,20 +191,6 @@
"path": "microsoft.bcl.asyncinterfaces/8.0.0",
"hashPath": "microsoft.bcl.asyncinterfaces.8.0.0.nupkg.sha512"
},
- "Microsoft.NETCore.Platforms/1.1.0": {
- "type": "package",
- "serviceable": true,
- "sha512": "sha512-kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==",
- "path": "microsoft.netcore.platforms/1.1.0",
- "hashPath": "microsoft.netcore.platforms.1.1.0.nupkg.sha512"
- },
- "NETStandard.Library/2.0.3": {
- "type": "package",
- "serviceable": true,
- "sha512": "sha512-st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==",
- "path": "netstandard.library/2.0.3",
- "hashPath": "netstandard.library.2.0.3.nupkg.sha512"
- },
"Newtonsoft.Json/13.0.3": {
"type": "package",
"serviceable": true,
diff --git a/lib/netstandard2.0/Voucherify.dll b/lib/netstandard2.0/Voucherify.dll
index 01a7deee..9f72bc5b 100644
Binary files a/lib/netstandard2.0/Voucherify.dll and b/lib/netstandard2.0/Voucherify.dll differ
diff --git a/lib/netstandard2.0/Voucherify.xml b/lib/netstandard2.0/Voucherify.xml
index 872b8003..ec9aac18 100644
--- a/lib/netstandard2.0/Voucherify.xml
+++ b/lib/netstandard2.0/Voucherify.xml
@@ -26260,6 +26260,24 @@
RestSharp's HttpMethod instance.
+
+
+ Starts a stopwatch when debug timing is enabled.
+
+ Whether debug timing is enabled for the current request.
+ A started when enabled; otherwise null.
+
+
+
+ Stops timing and writes a debug log entry for a request stage.
+
+ Whether debug timing is enabled for the current request.
+ The stopwatch instance started for the stage.
+ The request stage label (for example: construction or execution).
+ HTTP method name.
+ Request resource path.
+ Optional response used to enrich debug metadata.
+
Provides all logic for constructing a new RestSharp .
@@ -26844,6 +26862,11 @@
Determine whether or not the "default credentials" (e.g. the user account under which the current process is running) will be sent along to the server. The default is false.
+
+
+ Determines whether request timing diagnostics are enabled.
+
+
Gets or sets the default header.
@@ -27053,6 +27076,12 @@
Api Key name.
Api Key value.
+
+
+ Checks whether debug mode is enabled via the DEBUG environment variable.
+
+ true when DEBUG equals "true" (case-insensitive); otherwise, false.
+
Merge configurations.
@@ -27341,6 +27370,11 @@
Determine whether or not the "default credentials" (e.g. the user account under which the current process is running) will be sent along to the server. The default is false.
+
+
+ Determines whether request timing diagnostics are enabled.
+
+
Get the servers associated with the operation.
diff --git a/lib/netstandard2.1/Voucherify.deps.json b/lib/netstandard2.1/Voucherify.deps.json
index 1e39839c..bcbf3b82 100644
--- a/lib/netstandard2.1/Voucherify.deps.json
+++ b/lib/netstandard2.1/Voucherify.deps.json
@@ -7,7 +7,7 @@
"targets": {
".NETStandard,Version=v2.1": {},
".NETStandard,Version=v2.1/": {
- "Voucherify/9.0.0": {
+ "Voucherify/9.0.1": {
"dependencies": {
"JsonSubTypes": "2.0.1",
"Newtonsoft.Json": "13.0.3",
@@ -169,7 +169,7 @@
}
},
"libraries": {
- "Voucherify/9.0.0": {
+ "Voucherify/9.0.1": {
"type": "project",
"serviceable": false,
"sha512": ""
diff --git a/lib/netstandard2.1/Voucherify.dll b/lib/netstandard2.1/Voucherify.dll
index e7b835d3..7db207b1 100644
Binary files a/lib/netstandard2.1/Voucherify.dll and b/lib/netstandard2.1/Voucherify.dll differ
diff --git a/lib/netstandard2.1/Voucherify.xml b/lib/netstandard2.1/Voucherify.xml
index 872b8003..ec9aac18 100644
--- a/lib/netstandard2.1/Voucherify.xml
+++ b/lib/netstandard2.1/Voucherify.xml
@@ -26260,6 +26260,24 @@
RestSharp's HttpMethod instance.
+
+
+ Starts a stopwatch when debug timing is enabled.
+
+ Whether debug timing is enabled for the current request.
+ A started when enabled; otherwise null.
+
+
+
+ Stops timing and writes a debug log entry for a request stage.
+
+ Whether debug timing is enabled for the current request.
+ The stopwatch instance started for the stage.
+ The request stage label (for example: construction or execution).
+ HTTP method name.
+ Request resource path.
+ Optional response used to enrich debug metadata.
+
Provides all logic for constructing a new RestSharp .
@@ -26844,6 +26862,11 @@
Determine whether or not the "default credentials" (e.g. the user account under which the current process is running) will be sent along to the server. The default is false.
+
+
+ Determines whether request timing diagnostics are enabled.
+
+
Gets or sets the default header.
@@ -27053,6 +27076,12 @@
Api Key name.
Api Key value.
+
+
+ Checks whether debug mode is enabled via the DEBUG environment variable.
+
+ true when DEBUG equals "true" (case-insensitive); otherwise, false.
+
Merge configurations.
@@ -27341,6 +27370,11 @@
Determine whether or not the "default credentials" (e.g. the user account under which the current process is running) will be sent along to the server. The default is false.
+
+
+ Determines whether request timing diagnostics are enabled.
+
+
Get the servers associated with the operation.
diff --git a/readme.md b/readme.md
index 2c3298b2..b748ce53 100644
--- a/readme.md
+++ b/readme.md
@@ -90,6 +90,15 @@ webProxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
c.Proxy = webProxy;
```
+### ๐งช Request build timing (DEBUG)
+
+You can enable debug mode:
+
+- set `DEBUG=true` in environment variables (`.env`), or
+- set it directly in code with `config.DebugModeEnabled = true`.
+
+When enabled, the SDK prints request duration in milliseconds to console.
+
## ๐ Run code
Once installed, run:
@@ -163,7 +172,7 @@ This SDK is auto-generated (except for tests), so changes made here will be over
## ๐ท๏ธ Link tags
-[OpenAPI generated from tag](https://github.com/voucherifyio/voucherify-openapi/releases/tag/sdk-dotnet-9.0.0).
+[OpenAPI generated from tag](https://github.com/voucherifyio/voucherify-openapi/releases/tag/sdk-dotnet-9.0.1).
## ๐ Authorization
@@ -255,7 +264,8 @@ Authorization schemes defined for the API.
- `templates`: Gives access to all endpoints and methods starting with `/v1/templates`.
## ๐
Changelog
-
+- **2026-02-27** - `9.0.1`
+ - Added debug mode to measure request timings
- **2025-12-14** - `9.0.0`
- All POST requests now require a payload. As a result, the order of parameters in API method calls may have changed. If you encounter a build error, please check the documentation for the method you are calling.
- `OrdersImportCreateRequestBodyItem` no longer has `CreatedAt` property.
diff --git a/src/Voucherify.Test/.env.example b/src/Voucherify.Test/.env.example
index 4be0f31f..da8836b4 100644
--- a/src/Voucherify.Test/.env.example
+++ b/src/Voucherify.Test/.env.example
@@ -4,3 +4,4 @@ X_APP_TOKEN=
X_MANAGEMENT_ID=
X_MANAGEMENT_TOKEN=
PROJECT_ID=
+DEBUG=true
\ No newline at end of file
diff --git a/src/Voucherify/Client/ApiClient.cs b/src/Voucherify/Client/ApiClient.cs
index 31afe7f7..3e578966 100644
--- a/src/Voucherify/Client/ApiClient.cs
+++ b/src/Voucherify/Client/ApiClient.cs
@@ -12,6 +12,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
@@ -262,6 +263,46 @@ private RestSharpMethod Method(HttpMethod method)
return other;
}
+ ///
+ /// Starts a stopwatch when debug timing is enabled.
+ ///
+ /// Whether debug timing is enabled for the current request.
+ /// A started when enabled; otherwise null.
+ private static Stopwatch StartTiming(bool debugModeEnabled = false)
+ {
+ return debugModeEnabled ? Stopwatch.StartNew() : null;
+ }
+
+ ///
+ /// Stops timing and writes a debug log entry for a request stage.
+ ///
+ /// Whether debug timing is enabled for the current request.
+ /// The stopwatch instance started for the stage.
+ /// The request stage label (for example: construction or execution).
+ /// HTTP method name.
+ /// Request resource path.
+ /// Optional response used to enrich debug metadata.
+ private static void StopTiming(bool debugModeEnabled, Stopwatch stopwatch, string stage, string method, string resource, RestResponse response = null)
+ {
+ if (!debugModeEnabled || stopwatch == null)
+ {
+ return;
+ }
+
+ stopwatch.Stop();
+ double elapsedMilliseconds = stopwatch.Elapsed.TotalMilliseconds;
+
+ string responseMeta = string.Empty;
+ if (response != null)
+ {
+ int payloadSize = response.RawBytes?.Length ?? 0;
+
+ responseMeta = $" status={(int)response.StatusCode} response body size={payloadSize}B";
+ }
+
+ Console.WriteLine($"[Voucherify SDK][DEBUG][{DateTimeOffset.UtcNow:yyyy-MM-dd HH:mm:ss.fff} UTC] {stage} {method} {resource}{responseMeta} took {elapsedMilliseconds:F2}ms");
+ }
+
///
/// Provides all logic for constructing a new RestSharp .
/// At this point, all information for querying the service is known.
@@ -283,6 +324,9 @@ private RestRequest NewRequest(
if (path == null) throw new ArgumentNullException("path");
if (options == null) throw new ArgumentNullException("options");
if (configuration == null) throw new ArgumentNullException("configuration");
+
+ bool debugModeEnabled = configuration.DebugModeEnabled;
+ Stopwatch stopwatch = StartTiming(debugModeEnabled);
RestRequest request = new RestRequest(path, Method(method));
@@ -394,6 +438,8 @@ private RestRequest NewRequest(
}
}
+ StopTiming(debugModeEnabled, stopwatch, "Request construction", method.ToString(), path);
+
return request;
}
@@ -558,11 +604,17 @@ private async Task> ExecClientAsync(Func> DeserializeRestResponseFromPolicyAsync(RestClient client, RestRequest request, PolicyResult policyResult, CancellationToken cancellationToken = default)
+ private async Task> DeserializeRestResponseFromPolicyAsync(RestClient client, RestRequest request, PolicyResult policyResult, bool debugModeEnabled = false, CancellationToken cancellationToken = default)
{
if (policyResult.Outcome == OutcomeType.Successful)
{
- return await client.Deserialize(policyResult.Result, cancellationToken);
+ Stopwatch watch = StartTiming(debugModeEnabled);
+
+ var deserializeResult = await client.Deserialize(policyResult.Result, cancellationToken);
+
+ StopTiming(debugModeEnabled, watch, "Response parse", request.Method.ToString(), request.Resource, deserializeResult);
+
+ return deserializeResult;
}
else
{
@@ -572,7 +624,7 @@ private async Task> DeserializeRestResponseFromPolicyAsync(Re
};
}
}
-
+
private ApiResponse Exec(RestRequest request, RequestOptions options, IReadableConfiguration configuration)
{
Action setOptions = (clientOptions) =>
@@ -594,12 +646,23 @@ private ApiResponse Exec(RestRequest request, RequestOptions options, IRea
if (RetryConfiguration.RetryPolicy != null)
{
var policy = RetryConfiguration.RetryPolicy;
+
+ bool debugModeEnabled = configuration?.DebugModeEnabled ?? false;
+ Stopwatch watch = StartTiming(debugModeEnabled);
var policyResult = policy.ExecuteAndCapture(() => client.Execute(request));
- return DeserializeRestResponseFromPolicyAsync(client, request, policyResult);
+ StopTiming(debugModeEnabled, watch, "HTTP send", request.Method.ToString(), request.Resource, policyResult.Result);
+ return DeserializeRestResponseFromPolicyAsync(client, request, policyResult, debugModeEnabled);
}
else
{
- return Task.FromResult(client.Execute(request));
+ bool debugModeEnabled = configuration.DebugModeEnabled;
+ Stopwatch watch = StartTiming(debugModeEnabled);
+
+ var executeResult = client.Execute(request);
+
+ StopTiming(debugModeEnabled, watch, "HTTP end-to-end (send + parse)", request.Method.ToString(), request.Resource, executeResult);
+
+ return Task.FromResult(executeResult);
}
};
@@ -615,15 +678,23 @@ private ApiResponse Exec(RestRequest request, RequestOptions options, IRea
Func>> getResponse = async (client) =>
{
+ bool debugEnabled = configuration.DebugModeEnabled;
if (RetryConfiguration.AsyncRetryPolicy != null)
{
var policy = RetryConfiguration.AsyncRetryPolicy;
+ Stopwatch networkStopwatch = StartTiming(debugEnabled);
var policyResult = await policy.ExecuteAndCaptureAsync((ct) => client.ExecuteAsync(request, ct), cancellationToken).ConfigureAwait(false);
- return await DeserializeRestResponseFromPolicyAsync(client, request, policyResult, cancellationToken);
+ StopTiming(debugEnabled, networkStopwatch, "HTTP send", request.Method.ToString(), request.Resource, policyResult.Result);
+
+ return await DeserializeRestResponseFromPolicyAsync(client, request, policyResult, debugEnabled, cancellationToken);
}
else
{
- return await client.ExecuteAsync(request, cancellationToken).ConfigureAwait(false);
+ Stopwatch networkStopwatch = StartTiming(debugEnabled);
+ var rawResponse = await client.ExecuteAsync(request, cancellationToken).ConfigureAwait(false);
+ StopTiming(debugEnabled, networkStopwatch, "HTTP end-to-end (send + parse)", request.Method.ToString(), request.Resource, rawResponse);
+
+ return rawResponse;
}
};
diff --git a/src/Voucherify/Client/Configuration.cs b/src/Voucherify/Client/Configuration.cs
index 3ed8c379..a1f255e9 100644
--- a/src/Voucherify/Client/Configuration.cs
+++ b/src/Voucherify/Client/Configuration.cs
@@ -35,7 +35,7 @@ public class Configuration : IReadableConfiguration
/// Version of the package.
///
/// Version of the package.
- public const string Version = "9.0.0";
+ public const string Version = "9.0.1";
///
/// Identifier for ISO 8601 DateTime Format
@@ -114,7 +114,7 @@ public class Configuration : IReadableConfiguration
public Configuration()
{
Proxy = null;
- UserAgent = WebUtility.UrlEncode("DOTNET-SDK-9.0.0");
+ UserAgent = WebUtility.UrlEncode("DOTNET-SDK-9.0.1");
BasePath = "https://api.voucherify.io";
DefaultHeaders = new ConcurrentDictionary();
ApiKey = new ConcurrentDictionary();
@@ -151,6 +151,7 @@ public Configuration()
OperationServers = new Dictionary>>()
{
};
+ DebugModeEnabled = IsDebugModeEnabledInEnvironment();
// Setting Timeout has side effects (forces ApiClient creation).
Timeout = TimeSpan.FromSeconds(100);
@@ -215,6 +216,11 @@ public virtual bool UseDefaultCredentials
set { _useDefaultCredentials = value; }
}
+ ///
+ /// Determines whether request timing diagnostics are enabled.
+ ///
+ public virtual bool DebugModeEnabled { get; set; }
+
///
/// Gets or sets the default header.
///
@@ -587,7 +593,7 @@ public static string ToDebugReport()
report += " OS: " + System.Environment.OSVersion + "\n";
report += " .NET Framework Version: " + System.Environment.Version + "\n";
report += " Version of the API: v2018-08-01\n";
- report += " SDK Package Version: 9.0.0\n";
+ report += " SDK Package Version: 9.0.1\n";
return report;
}
@@ -613,6 +619,16 @@ public void AddApiKeyPrefix(string key, string value)
ApiKeyPrefix[key] = value;
}
+ ///
+ /// Checks whether debug mode is enabled via the DEBUG environment variable.
+ ///
+ /// true when DEBUG equals "true" (case-insensitive); otherwise, false.
+ private static bool IsDebugModeEnabledInEnvironment()
+ {
+ string debugValue = Environment.GetEnvironmentVariable("DEBUG");
+ return string.Equals(debugValue, "true", StringComparison.OrdinalIgnoreCase);
+ }
+
#endregion Methods
#region Static Members
@@ -655,6 +671,7 @@ public static IReadableConfiguration MergeConfigurations(IReadableConfiguration
DateTimeFormat = second.DateTimeFormat ?? first.DateTimeFormat,
ClientCertificates = second.ClientCertificates ?? first.ClientCertificates,
UseDefaultCredentials = second.UseDefaultCredentials,
+ DebugModeEnabled = second.DebugModeEnabled || first.DebugModeEnabled,
RemoteCertificateValidationCallback = second.RemoteCertificateValidationCallback ?? first.RemoteCertificateValidationCallback,
};
return config;
diff --git a/src/Voucherify/Client/IReadableConfiguration.cs b/src/Voucherify/Client/IReadableConfiguration.cs
index 5fca5e56..05d0473a 100644
--- a/src/Voucherify/Client/IReadableConfiguration.cs
+++ b/src/Voucherify/Client/IReadableConfiguration.cs
@@ -137,6 +137,11 @@ public interface IReadableConfiguration
///
bool UseDefaultCredentials { get; }
+ ///
+ /// Determines whether request timing diagnostics are enabled.
+ ///
+ bool DebugModeEnabled { get; }
+
///
/// Get the servers associated with the operation.
///
diff --git a/src/Voucherify/Voucherify.csproj b/src/Voucherify/Voucherify.csproj
index 9b4c7efb..707f82ee 100644
--- a/src/Voucherify/Voucherify.csproj
+++ b/src/Voucherify/Voucherify.csproj
@@ -12,7 +12,7 @@
A library generated from a OpenAPI doc
MIT
Voucherify
- 9.0.0
+ 9.0.1
bin\$(Configuration)\$(TargetFramework)\Voucherify.xml
https://github.com/voucherifyio/voucherify-dotNET-sdk
git
diff --git a/src/Voucherify/Voucherify.nuspec b/src/Voucherify/Voucherify.nuspec
index 76eb3c33..f3364b54 100644
--- a/src/Voucherify/Voucherify.nuspec
+++ b/src/Voucherify/Voucherify.nuspec
@@ -9,11 +9,13 @@
MIT
https://github.com/voucherifyio/voucherify-dotNET-sdk
false
- 9.0.0
+ 9.0.1
.Net SDK for Voucherify - coupons, vouchers, promo codes - http://www.voucherify.io
MIT
+ 2026-02-27: 9.0.1
+ - Added debug mode to measure request timings
2025-12-14: 9.0.0
- All POST requests now require a payload. As a result, the order of parameters in API method calls may have changed. If you encounter a build error, please check the documentation for the method you are calling.
โ `OrdersImportCreateRequestBodyItem` no longer has `CreatedAt` property.