Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LiveMetricsExporter] Add Filtering Support part 7 - Sync Model change for Duration #43080

Merged
merged 3 commits into from
Apr 5, 2024
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 @@ -192,6 +192,11 @@ private void CreateProjection()
// special case - for TimeSpan values ToString() will not result in a value convertable to double, so we must take care of that ourselves
if (fieldType == typeof(TimeSpan))
{
if (fieldExpression.Type == typeof(string))
{
MethodInfo? parseMethod = typeof(TimeSpan).GetMethod("Parse", new[] { typeof(string) });
fieldExpression = Expression.Call(parseMethod!, fieldExpression);
}
fieldExpression = Expression.Property(fieldExpression, "TotalMilliseconds");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,11 @@ private static Type GetPropertyTypeFromFieldName(string fieldName)
typeof(TTelemetry),
(type, propertyName) => type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public).PropertyType);

if (fieldName == "Duration")
{
propertyType = typeof(TimeSpan);
}

if (propertyType == null)
{
string propertyNotFoundMessage = string.Format(
Expand Down Expand Up @@ -555,6 +560,11 @@ private Expression ProduceComparatorExpressionForSingleFieldCondition(Expression
if (fieldType == typeof(TimeSpan))
{
this.ThrowOnInvalidFilter(fieldType, !this.comparandTimeSpan.HasValue);
if (fieldExpression.Type == typeof(string))
{
MethodInfo parseMethod = typeof(TimeSpan).GetMethod("Parse", new[] { typeof(string) });
fieldExpression = Expression.Call(parseMethod, fieldExpression);
}

switch (this.predicate)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public bool CheckFilters(TTelemetry document, out CollectionConfigurationError[]
////errorList.Add(
//// CollectionConfigurationError.CreateError(
//// CollectionConfigurationErrorType.FilterFailureToRun,
//// string.Format(CultureInfo.InvariantCulture, "Failter failed to run: {0}.", filter),
//// string.Format(CultureInfo.InvariantCulture, "Filter failed to run: {0}.", filter),
//// e));
filterPassed = false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,32 @@ public void DerivedMetricProjectsCorrectlyWhenTimeSpan()
Assert.Equal(120, projection);
}

[Fact]
public void DerivedMetricProjectsCorrectlyWhenDurationIsString()
{
// ARRANGE
var metricInfo = new DerivedMetricInfo(
id: "Metric1",
telemetryType: TelemetryType.Request,
filterGroups: new FilterConjunctionGroupInfo[0],
projection: "Duration",
aggregation: DerivedMetricInfoAggregation.Avg
);

var durationString = TimeSpan.FromMilliseconds(120).ToString();
var telemetry = new DocumentMockWithStringDuration(durationString);

// ACT
CollectionConfigurationError[] errors;
var metric = new DerivedMetric<DocumentMockWithStringDuration>(metricInfo, out errors);
double projection = metric.Project(telemetry);

// ASSERT
Assert.Equal(DerivedMetricInfoAggregation.Avg, metric.AggregationType);
Assert.Empty(errors);
Assert.Equal(120, projection);
}

[Fact(Skip = "Unknown failure.")]
public void DerivedMetricReportsErrorsForInvalidFilters()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

namespace Azure.Monitor.OpenTelemetry.LiveMetrics.Internals.Filtering.Tests
{
using Azure.Monitor.OpenTelemetry.LiveMetrics.Models;

internal class DocumentMockWithStringDuration : DocumentIngress
{
internal DocumentMockWithStringDuration(string duration)
{
Duration = duration;
}

public string Duration { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -912,6 +912,20 @@ public void FilterTimeSpanGarbageComparand()
Assert.Throws<ArgumentOutOfRangeException>(() => new Filter<DocumentMock>(equalsValue));
}

[Fact]
public void FilterDurationAsString()
{
// ARRANGE
var equalsValue = new FilterInfo("Duration", FilterInfoPredicate.Equal, "123");

// ACT
bool result1 = new Filter<DocumentMockWithStringDuration>(equalsValue).Check(new DocumentMockWithStringDuration(TimeSpan.Parse("123", CultureInfo.InvariantCulture).ToString()));
bool result2 = new Filter<DocumentMockWithStringDuration>(equalsValue).Check(new DocumentMockWithStringDuration(TimeSpan.Parse("124", CultureInfo.InvariantCulture).ToString()));

// ASSERT
Assert.True(result1);
Assert.False(result2);
}
#endregion

#region String
Expand Down
Loading