Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ internal AuthenticationEventMetadataAttribute() { }
}
public partial class AuthenticationEventResponseHandler : Microsoft.Azure.WebJobs.Host.Bindings.IValueBinder, Microsoft.Azure.WebJobs.Host.Bindings.IValueProvider
{
public AuthenticationEventResponseHandler() { }
internal AuthenticationEventResponseHandler() { }
public Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.Framework.AuthenticationEventRequestBase Request { get { throw null; } }
public Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.Framework.AuthenticationEventResponse Response { get { throw null; } }
public System.Type Type { get { throw null; } }
Expand All @@ -34,10 +34,15 @@ public enum EventDefinition
[Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.AuthenticationEventMetadataAttribute(typeof(Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.TokenIssuanceStart.TokenIssuanceStartRequest), "microsoft.graph.authenticationEvent.TokenIssuanceStart", "TokenIssuanceStart", "CloudEventActionableTemplate.json")]
TokenIssuanceStart = 0,
}
public static partial class EventTriggerMetrics
public sealed partial class EventTriggerMetrics
{
public static string MetricsHeader;
public static string ProductName;
internal EventTriggerMetrics() { }
public const string MetricsHeader = "User-Agent";
public const string ProductName = "AuthenticationEvents";
public static string Framework { get { throw null; } }
public static Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.EventTriggerMetrics Instance { get { throw null; } }
public static string Platform { get { throw null; } }
public static string ProductVersion { get { throw null; } }
}
public enum EventType
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ private static IReadOnlyDictionary<string, Type> GetBindingDataContract(Paramete
public async Task<ITriggerData> BindAsync(object value, ValueBindingContext context)
{
var request = (HttpRequestMessage)value;
AuthenticationEventResponseHandler eventResponseHandler = (AuthenticationEventResponseHandler)request.Properties[AuthenticationEventResponseHandler.EventResponseProperty];
AuthenticationEventResponseHandler eventResponseHandler =
(AuthenticationEventResponseHandler)request.Properties[AuthenticationEventResponseHandler.EventResponseProperty];
try
{
if (request == null)
Expand All @@ -98,7 +99,15 @@ public async Task<ITriggerData> BindAsync(object value, ValueBindingContext cont
AuthenticationEventMetadata eventMetadata = GetEventAndValidateSchema(payload);

eventResponseHandler.Request = GetRequestForEvent(request, payload, eventMetadata, Claims);
return new TriggerData(new AuthenticationEventValueBinder(eventResponseHandler.Request, _authEventTriggerAttr), GetBindingData(context, value, eventResponseHandler))

return new TriggerData(
new AuthenticationEventValueBinder(
eventResponseHandler.Request,
_authEventTriggerAttr),
GetBindingData(
context,
value,
eventResponseHandler))
{
ReturnValueProvider = eventResponseHandler
};
Expand All @@ -119,7 +128,12 @@ public async Task<ITriggerData> BindAsync(object value, ValueBindingContext cont
/// <returns>A TriggerData Object with the failed event request based on the event. With the related request status set.</returns>
/// <seealso cref="TriggerData" />
/// <seealso cref="AuthenticationEventResponseHandler" />
private TriggerData GetFaultyRequest(ValueBindingContext context, object value, HttpRequestMessage request, AuthenticationEventResponseHandler eventResponseHandler, Exception ex)
private TriggerData GetFaultyRequest(
ValueBindingContext context,
object value,
HttpRequestMessage request,
AuthenticationEventResponseHandler eventResponseHandler,
Exception ex)
{
eventResponseHandler.Request = _parameterInfo.ParameterType == typeof(string) ? new EmptyRequest(request) : AuthenticationEventMetadata.CreateEventRequest(request, _parameterInfo.ParameterType, null);
eventResponseHandler.Request.StatusMessage = ex.Message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,20 @@ public class AuthenticationEventResponseHandler : IValueBinder
public AuthenticationEventResponse Response
{
get => _response;
internal set
private set
{
if (value != null)
{
_response = value;

// Set metrics on the headers for the response
EventTriggerMetrics.SetMetricHeaders(_response);
EventTriggerMetrics.Instance.SetMetricHeaders(_response);
}
}
}

internal AuthenticationEventResponseHandler() { }

/// <summary>Gets the type.</summary>
/// <value>The type.</value>
public Type Type => typeof(AuthenticationEventResponse).MakeByRefType();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,62 +1,85 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;

namespace Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents
{
/// <summary>
/// Static class to set the metric headers for each event trigger.
/// </summary>
public static class EventTriggerMetrics
public sealed class EventTriggerMetrics
{
/// <summary>
/// The client library's product name
/// Default constructor for eventmetrics
/// </summary>
private EventTriggerMetrics()
{
var assembly = AssemblyName.GetAssemblyName("Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.dll");

ProductVersion = assembly.Version.ToString();
Framework = RuntimeInformation.FrameworkDescription;
Platform = RuntimeInformation.OSDescription ?? "unknown";
}

/// <summary>
/// Lazy immplementation to make sure that only one instance is created and returned, while delaying the creation till needed.
/// </summary>
public static string ProductName = "AuthenticationEvents";
private static readonly Lazy<EventTriggerMetrics> lazyEventTrigger = new Lazy<EventTriggerMetrics>(() => new EventTriggerMetrics());

/// <summary>
/// Current executing assembly
/// The singleton instance for event trigger metrics
/// </summary>
public static EventTriggerMetrics Instance
{
get
{
return lazyEventTrigger.Value;
}
}

/// <summary>
/// The client library's product name
/// </summary>
private static readonly Assembly assembly = typeof(EventTriggerMetrics).Assembly;
public const string ProductName = "AuthenticationEvents";

/// <summary>
/// Get the platform of the event trigger based on the OS.
/// </summary>
/// <returns>OS Name</returns>
private static string Platform => RuntimeInformation.OSDescription ?? "unknown";
public static string Platform { get; private set; }

/// <summary>
/// Product version of the event trigger. Example: 1.0.0-beta, 1.0.0, 2.0.0
/// </summary>
private static string ProductVersion => assembly.GetCustomAttribute<AssemblyFileVersionAttribute>()?.Version;
public static string ProductVersion { get; private set; }

/// <summary>
/// Runtime of the event trigger. Example: .NET, JS, TS, PY
/// Framework of the event trigger. Example: .NET, JS, TS, PY
/// </summary>
private static string Framework => assembly.GetCustomAttribute<TargetFrameworkAttribute>()?.FrameworkName;
public static string Framework { get; private set; }

/// <summary>
/// Header key to add the metrics to.
/// User-Agent is the standard header to add metrics to recommended by Azure sdk guidelines.
/// </summary>
public static string MetricsHeader = "User-Agent";
public const string MetricsHeader = "User-Agent";

/// <summary>
/// Set the metrics on the response message.
/// </summary>
/// <param name="message">The reponse message</param>
internal static void SetMetricHeaders(HttpResponseMessage message)
internal void SetMetricHeaders(HttpResponseMessage message)
{
if (message != null)
{
var headers = message.Headers;
headers.AddOrReplaceToHeader(GetHeaderValue(Platform, ProductVersion, Framework));
AddOrReplaceToHeader(headers, GetHeaderValueFormatted(Platform, ProductVersion, Framework));
}
}

Expand All @@ -65,7 +88,7 @@ internal static void SetMetricHeaders(HttpResponseMessage message)
/// </summary>
/// <param name="headers"><see cref="HttpHeaders"/> to add the key and value to</param>
/// <param name="value">Header value to add</param>
private static void AddOrReplaceToHeader(this HttpHeaders headers, string value)
private static void AddOrReplaceToHeader(HttpHeaders headers, string value)
{
if (headers.Contains(MetricsHeader))
{
Expand All @@ -76,9 +99,9 @@ private static void AddOrReplaceToHeader(this HttpHeaders headers, string value)
headers.Add(MetricsHeader, value);
}

private static string GetHeaderValue(string platform, string version, string runtime)
private static string GetHeaderValueFormatted(string platform, string version, string runtime)
{
return $"azsdk-net-{ProductName}/{version} ({runtime}; {platform})";
return $"azsdk-net-{ProductName}/{version} ({runtime}; {platform.Trim()})";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ internal static HttpResponseMessage HttpErrorResponse(Exception ex)
};

// Set the metrics on header
EventTriggerMetrics.SetMetricHeaders(response);
EventTriggerMetrics.Instance.SetMetricHeaders(response);

return response;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Diagnostics.Eventing.Reader;
using System.Linq;
using System.Net.Http;

Expand All @@ -16,7 +17,7 @@ public class EventTriggerMetricsTests
public void TestSetMetricHeadersNull()
{
HttpResponseMessage message = null;
Assert.DoesNotThrow(() => EventTriggerMetrics.SetMetricHeaders(message));
Assert.DoesNotThrow(() => EventTriggerMetrics.Instance.SetMetricHeaders(message));
Assert.IsNull(
anObject: message,
message: "Verify AuthenticationEventRequestBase is not set to anything when null.");
Expand All @@ -27,13 +28,32 @@ public void TestSetMetricHeadersNull()
public void TestSetMetricHeaders()
{
HttpResponseMessage message = new() { };
EventTriggerMetrics.SetMetricHeaders(message);
EventTriggerMetrics.Instance.SetMetricHeaders(message);

Assert.IsNotEmpty(EventTriggerMetrics.Framework, "Framework should note be empty");
Assert.IsNotEmpty(EventTriggerMetrics.ProductVersion, "ProductVersion should not be empty");
Assert.IsNotEmpty(EventTriggerMetrics.Platform, "Platform should not be empty");

var headers = message.Headers;
Assert.IsTrue(headers.Contains(EventTriggerMetrics.MetricsHeader));

string headerValue = headers.GetValues(EventTriggerMetrics.MetricsHeader).First();
Assert.AreEqual(GetTestHeaderValue(), headerValue, "Verify default header values match");
Assert.IsNotEmpty(headerValue, "Header value should not be empty or null");
}

[Test]
[Description("Verify if sets the headers is in the correct format")]
public void TestSetMetricFormat()
{
HttpResponseMessage message = new() { };
EventTriggerMetrics.Instance.SetMetricHeaders(message);

var headers = message.Headers;
Assert.IsTrue(headers.Contains(EventTriggerMetrics.MetricsHeader));

string headerValue = headers.GetValues(EventTriggerMetrics.MetricsHeader).First();

Assert.AreEqual(GetTestHeaderValue(), headerValue, "Verify format of header values matches");
}

[Test]
Expand All @@ -43,7 +63,7 @@ public void TestAppendMetricHeaders()
HttpResponseMessage message = new() { };
message.Headers.Add(EventTriggerMetrics.MetricsHeader, "test");

EventTriggerMetrics.SetMetricHeaders(message);
EventTriggerMetrics.Instance.SetMetricHeaders(message);

var headers = message.Headers;
Assert.IsTrue(headers.Contains(EventTriggerMetrics.MetricsHeader));
Expand All @@ -53,11 +73,15 @@ public void TestAppendMetricHeaders()
}

private static string GetTestHeaderValue(
string framework = ".NETStandard,Version=v2.0",
string version = "1.0.0.0",
string platform = "Microsoft Windows 10.0.22621")
string framework = null,
string version = null,
string platform = null)
{
return $"azsdk-net-{EventTriggerMetrics.ProductName}/{version} ({framework}; {platform})";
framework ??= EventTriggerMetrics.Framework;
version ??= EventTriggerMetrics.ProductVersion;
platform ??= EventTriggerMetrics.Platform;

return $"azsdk-net-{EventTriggerMetrics.ProductName}/{version} ({framework}; {platform.Trim()})";
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;
using static Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.Tests.TestHelper;
Expand Down Expand Up @@ -34,7 +34,7 @@ public async Task PostConfigProviderTests(string url, HttpStatusCode httpStatusC
{
AuthenticationEventResponseHandler eventsResponseHandler = GetAuthenticationEventResponseHandler(mockedRequest);

eventsResponseHandler.Response = GetContentForHttpStatus(httpStatusCode);
eventsResponseHandler.SetValueAsync(GetContentForHttpStatus(httpStatusCode), CancellationToken.None);
}
});

Expand Down