@@ -79,39 +79,48 @@ public override IList<Metric> Parse()
7979 }
8080 ]
8181 */
82- foreach ( var metricObj in token . Children < JObject > ( ) )
82+ var metricList = JsonConvert . DeserializeObject < List < CustomMetric > > ( this . RawText ) ;
83+
84+ foreach ( var customMetric in metricList )
8385 {
84- string metricName = metricObj . Value < string > ( "metricName" ) ;
85- JToken metricValueToken = metricObj [ "metricValue" ] ;
86- if ( string . IsNullOrWhiteSpace ( metricName ) )
86+ if ( string . IsNullOrWhiteSpace ( customMetric . Name ) )
8787 {
8888 throw new WorkloadResultsException (
8989 $ "Invalid JSON metrics content formatting. 'metricName' is a required property.",
9090 ErrorReason . InvalidResults ) ;
9191 }
9292
93- if ( metricValueToken == null || ! double . TryParse ( metricValueToken . ToString ( ) , out double metricValue ) )
93+ if ( customMetric . Value == null || ! double . TryParse ( customMetric . Value . ToString ( ) , out double metricValue ) )
9494 {
9595 throw new WorkloadResultsException (
96- $ "Invalid JSON metrics content formatting. 'metricValue' for '{ metricName } ' is not a valid numeric data type. Provided metric value is '{ metricValueToken } '",
96+ $ "Invalid JSON metrics content formatting. 'metricValue' for '{ customMetric . Name } ' is not a valid numeric data type. Provided metric value is '{ customMetric . Value } '",
9797 ErrorReason . InvalidResults ) ;
9898 }
9999
100- string metricUnit = metricObj . Value < string > ( "metricUnit" ) ;
100+ // Robustly handle metricMetadata
101101 IDictionary < string , IConvertible > metricMetadata = null ;
102- if ( metricObj . TryGetValue ( "metricMetadata" , out JToken metadataToken ) && metadataToken . Type == JTokenType . Object )
102+ if ( customMetric . MetadataRaw != null && customMetric . MetadataRaw . Type != JTokenType . Null )
103103 {
104- metricMetadata = metadataToken
105- . Children < JProperty > ( )
106- . ToDictionary (
107- prop => prop . Name ,
108- prop => ( IConvertible ) Convert . ChangeType ( prop . Value . ToString ( ) , typeof ( string ) ) ) ;
104+ if ( customMetric . MetadataRaw . Type == JTokenType . Object )
105+ {
106+ metricMetadata = new Dictionary < string , IConvertible > ( StringComparer . OrdinalIgnoreCase ) ;
107+ foreach ( var prop in customMetric . MetadataRaw . Children < JProperty > ( ) )
108+ {
109+ metricMetadata [ prop . Name ] = prop . Value . ToString ( ) ;
110+ }
111+ }
112+ else
113+ {
114+ throw new WorkloadResultsException (
115+ $ "Invalid JSON metrics content formatting. 'metricMetadata' for '{ customMetric . Name } ' must be a JSON object.",
116+ ErrorReason . InvalidResults ) ;
117+ }
109118 }
110119
111120 metrics . Add (
112- metricUnit != null
113- ? new Metric ( metricName , metricValue , metricUnit , MetricRelativity . Undefined , tags : null , description : null , metadata : metricMetadata )
114- : new Metric ( metricName , metricValue , MetricRelativity . Undefined , tags : null , description : null , metadata : metricMetadata ) ) ;
121+ customMetric . Unit != null
122+ ? new Metric ( customMetric . Name , metricValue , customMetric . Unit , MetricRelativity . Undefined , tags : null , description : null , metadata : metricMetadata )
123+ : new Metric ( customMetric . Name , metricValue , MetricRelativity . Undefined , tags : null , description : null , metadata : metricMetadata ) ) ;
115124 }
116125 }
117126 else
@@ -136,5 +145,21 @@ public override IList<Metric> Parse()
136145
137146 return metrics ;
138147 }
148+
149+ internal class CustomMetric
150+ {
151+ [ JsonProperty ( "metricName" ) ]
152+ public string Name { get ; set ; }
153+
154+ [ JsonProperty ( "metricValue" ) ]
155+ public object Value { get ; set ; }
156+
157+ [ JsonProperty ( "metricUnit" ) ]
158+ public string Unit { get ; set ; }
159+
160+ // Use JToken to allow robust handling
161+ [ JsonProperty ( "metricMetadata" ) ]
162+ public JToken MetadataRaw { get ; set ; }
163+ }
139164 }
140165}
0 commit comments