Skip to content

Commit 1ef9d3b

Browse files
author
Timothy Mothra
authored
fix additional AOT errors (Azure#49665)
1 parent 95646c9 commit 1ef9d3b

File tree

7 files changed

+71
-15
lines changed

7 files changed

+71
-15
lines changed

sdk/monitor/Azure.Monitor.OpenTelemetry.LiveMetrics/src/Customizations/Models/DocumentIngress.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4+
using System.Diagnostics.CodeAnalysis;
5+
46
namespace Azure.Monitor.OpenTelemetry.LiveMetrics.Models
57
{
68
/// <summary> Additional properties used to calculate metrics. </summary>
9+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
710
internal partial class DocumentIngress
811
{
912
public bool Extension_IsSuccess { get; set; }

sdk/monitor/Azure.Monitor.OpenTelemetry.LiveMetrics/src/Internals/Filtering/CollectionConfiguration.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,16 +118,17 @@ private void UpdateAllErrorsWithKeyValue(CollectionConfigurationError[] errors,
118118

119119
public string ETag => info.ETag;
120120

121-
private static void AddMetric<DocumentIngress>(
121+
private static void AddMetric<TTelemetry>(
122122
DerivedMetricInfo metricInfo,
123-
List<DerivedMetric<DocumentIngress>> metrics,
123+
List<DerivedMetric<TTelemetry>> metrics,
124124
out CollectionConfigurationError[] errors)
125+
where TTelemetry : DocumentIngress
125126
{
126127
errors = Array.Empty<CollectionConfigurationError>();
127128

128129
try
129130
{
130-
metrics.Add(new DerivedMetric<DocumentIngress>(metricInfo, out errors));
131+
metrics.Add(new DerivedMetric<TTelemetry>(metricInfo, out errors));
131132
}
132133
catch (System.Exception e)
133134
{

sdk/monitor/Azure.Monitor.OpenTelemetry.LiveMetrics/src/Internals/Filtering/DerivedMetric.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ namespace Azure.Monitor.OpenTelemetry.LiveMetrics.Internals.Filtering
1616
/// which defines which field to use as a value, and an aggregation which dictates the algorithm of arriving at
1717
/// a single reportable value within a second.
1818
/// </summary>
19-
internal class DerivedMetric<TTelemetry>
19+
internal class DerivedMetric<TTelemetry> where TTelemetry : DocumentIngress
2020
{
2121
private const string ProjectionCount = "Count()";
2222

sdk/monitor/Azure.Monitor.OpenTelemetry.LiveMetrics/src/Internals/Filtering/DocumentStream.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ private static bool CheckFilters<TTelemetry>(
9292
List<FilterConjunctionGroup<TTelemetry>> filterGroups,
9393
TTelemetry document,
9494
out CollectionConfigurationError[] errors)
95+
where TTelemetry : DocumentIngress
9596
{
9697
var errorList = new List<CollectionConfigurationError>();
9798
bool leastOneConjunctionGroupPassed = false;
@@ -121,6 +122,7 @@ private static bool CheckFilters<TTelemetry>(
121122
}
122123

123124
private static bool CheckFiltersGeneric<TTelemetry>(TTelemetry document, FilterConjunctionGroup<TTelemetry> filterGroup, List<CollectionConfigurationError> errorList)
125+
where TTelemetry : DocumentIngress
124126
{
125127
bool filterPassed = false;
126128

sdk/monitor/Azure.Monitor.OpenTelemetry.LiveMetrics/src/Internals/Filtering/Filter.cs

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ namespace Azure.Monitor.OpenTelemetry.LiveMetrics.Internals.Filtering
1919
/// The filter's configuration (condition) is specified in a <see cref="FilterInfo"/> DTO.
2020
/// </summary>
2121
/// <typeparam name="TTelemetry">Type of telemetry documents.</typeparam>
22-
internal class Filter<TTelemetry>
22+
internal class Filter<TTelemetry> where TTelemetry : DocumentIngress
2323
{
2424
private const string FieldNameCustomDimensionsPrefix = "CustomDimensions.";
2525

@@ -56,15 +56,15 @@ internal class Filter<TTelemetry>
5656
new[] { typeof(string), typeof(NumberStyles), typeof(IFormatProvider), typeof(double).MakeByRefType() });
5757

5858
private static readonly MethodInfo ListStringTryGetValueMethodInfo =
59-
GetMethodInfo<IList<KeyValuePairString>, string, string>((list, key) => Filter<int>.TryGetString(list, key));
59+
GetMethodInfo<IList<KeyValuePairString>, string, string>((list, key) => TryGetString(list, key));
6060

6161
private static readonly MethodInfo DictionaryStringDoubleTryGetValueMethodInfo = typeof(IDictionary<string, double>).GetMethod("TryGetValue");
6262

6363
private static readonly MethodInfo ListKeyValuePairStringScanMethodInfo =
64-
GetMethodInfo<IList<KeyValuePairString>, string, bool>((list, searchValue) => Filter<int>.ScanList(list, searchValue));
64+
GetMethodInfo<IList<KeyValuePairString>, string, bool>((list, searchValue) => ScanList(list, searchValue));
6565

6666
private static readonly MethodInfo DictionaryStringDoubleScanMethodInfo =
67-
GetMethodInfo<IDictionary<string, double>, string, bool>((dict, searchValue) => Filter<int>.ScanDictionary(dict, searchValue));
67+
GetMethodInfo<IDictionary<string, double>, string, bool>((dict, searchValue) => ScanDictionary(dict, searchValue));
6868

6969
private static readonly ConstantExpression DoubleDefaultNumberStyles = Expression.Constant(NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite | NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands | NumberStyles.AllowExponent);
7070
private static readonly ConstantExpression InvariantCulture = Expression.Constant(CultureInfo.InvariantCulture);
@@ -218,12 +218,35 @@ public override string ToString()
218218
return info?.ToString() ?? string.Empty;
219219
}
220220

221-
internal static Expression ProduceFieldExpression(ParameterExpression documentExpression, string fieldName, FieldNameType fieldNameType)
221+
[UnconditionalSuppressMessage("AOT", "IL2075", Justification = "The DocumentIngress class and its derived classes have DynamicallyAccessedMembers attribute applied to preserve public properties.")]
222+
internal static Expression ProduceFieldExpression(
223+
ParameterExpression documentExpression,
224+
string fieldName,
225+
FieldNameType fieldNameType)
222226
{
223227
switch (fieldNameType)
224228
{
225229
case FieldNameType.FieldName:
226-
return fieldName.Split(FieldNameTrainSeparator).Aggregate<string, Expression>(documentExpression, Expression.Property);
230+
Expression current = documentExpression;
231+
string[] propertyNames = fieldName.Split(FieldNameTrainSeparator);
232+
233+
foreach (string propertyName in propertyNames)
234+
{
235+
Type currentType = current.Type;
236+
PropertyInfo propertyInfo = currentType.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public);
237+
238+
if (propertyInfo == null)
239+
{
240+
throw new ArgumentOutOfRangeException(
241+
nameof(fieldName),
242+
$"Property '{propertyName}' not found on type '{currentType.FullName}'");
243+
}
244+
245+
current = Expression.Property(current, propertyInfo);
246+
}
247+
248+
return current;
249+
227250
case FieldNameType.CustomMetricName:
228251
string customMetricName = fieldName.Substring(
229252
FieldNameCustomMetricsPrefix.Length,
@@ -276,21 +299,47 @@ internal static Type GetFieldType(string fieldName, out FieldNameType fieldNameT
276299
return GetPropertyTypeFromFieldName(fieldName);
277300
}
278301

279-
private static Expression CreateListAccessExpression(ParameterExpression documentExpression, string listName, MethodInfo tryGetValueMethodInfo, Type valueType, string keyValue)
302+
[UnconditionalSuppressMessage("AOT", "IL2075", Justification = "The DocumentIngress class and its derived classes have DynamicallyAccessedMembers attribute applied to preserve public properties.")]
303+
private static Expression CreateListAccessExpression(
304+
ParameterExpression documentExpression,
305+
string listName,
306+
MethodInfo tryGetValueMethodInfo,
307+
Type valueType,
308+
string keyValue)
280309
{
310+
// Get the PropertyInfo directly to avoid string-based property access
311+
PropertyInfo listProperty = documentExpression.Type.GetProperty(listName, BindingFlags.Instance | BindingFlags.Public);
312+
if (listProperty == null)
313+
{
314+
throw new ArgumentException($"Property '{listName}' not found on type '{documentExpression.Type.FullName}'", nameof(listName));
315+
}
316+
281317
// return Filter<int>.TryGetString(document.listName, keyValue)
282-
MemberExpression properties = Expression.Property(documentExpression, listName);
318+
MemberExpression properties = Expression.Property(documentExpression, listProperty);
283319
return Expression.Call(tryGetValueMethodInfo, properties, Expression.Constant(keyValue));
284320
}
285321

286-
private static Expression CreateDictionaryAccessExpression(ParameterExpression documentExpression, string dictionaryName, MethodInfo tryGetValueMethodInfo, Type valueType, string keyValue)
322+
[UnconditionalSuppressMessage("AOT", "IL2075", Justification = "The DocumentIngress class and its derived classes have DynamicallyAccessedMembers attribute applied to preserve public properties.")]
323+
private static Expression CreateDictionaryAccessExpression(
324+
ParameterExpression documentExpression,
325+
string dictionaryName,
326+
MethodInfo tryGetValueMethodInfo,
327+
Type valueType,
328+
string keyValue)
287329
{
330+
// Get the PropertyInfo directly to avoid string-based property access
331+
PropertyInfo dictionaryProperty = documentExpression.Type.GetProperty(dictionaryName, BindingFlags.Instance | BindingFlags.Public);
332+
if (dictionaryProperty == null)
333+
{
334+
throw new ArgumentException($"Property '{dictionaryName}' not found on type '{documentExpression.Type.FullName}'", nameof(dictionaryName));
335+
}
336+
288337
// valueType value;
289338
// document.dictionaryName.TryGetValue(keyValue, out value)
290339
// return value;
291340
ParameterExpression valueVariable = Expression.Variable(valueType);
292341

293-
MemberExpression properties = Expression.Property(documentExpression, dictionaryName);
342+
MemberExpression properties = Expression.Property(documentExpression, dictionaryProperty);
294343
MethodCallExpression tryGetValueCall = Expression.Call(properties, tryGetValueMethodInfo, Expression.Constant(keyValue), valueVariable);
295344

296345
// a block will "return" its last expression

sdk/monitor/Azure.Monitor.OpenTelemetry.LiveMetrics/src/Internals/Filtering/FilterConjunctionGroup.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace Azure.Monitor.OpenTelemetry.LiveMetrics.Internals.Filtering
1111
/// <summary>
1212
/// Defines an AND group of filters.
1313
/// </summary>
14-
internal class FilterConjunctionGroup<TTelemetry>
14+
internal class FilterConjunctionGroup<TTelemetry> where TTelemetry : DocumentIngress
1515
{
1616
private readonly FilterConjunctionGroupInfo info;
1717

sdk/monitor/Azure.Monitor.OpenTelemetry.LiveMetrics/src/Internals/LiveMetricsClientManager.MetricsCollection.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ private void ApplyFilters<TTelemetry>(
225225
TTelemetry telemetry,
226226
out CollectionConfigurationError[] filteringErrors,
227227
ref string projectionError)
228+
where TTelemetry : DocumentIngress
228229
{
229230
filteringErrors = Array.Empty<CollectionConfigurationError>();
230231

0 commit comments

Comments
 (0)