History

GrafanaAdapters: Added meta-data substitution parameters for Label function when series values map directly to point tags.

J. Ritchie Carroll committed 9 years ago

Commit da0dc1b1 parent 0063ff64 files · +54 −4Browse files

Unified · Split

4 files
  1. Source/Documentation/GrafanaFunctions.md +1 −1
  2. Source/Libraries/Adapters/GrafanaAdapters/AnnotationExtensions.cs +17 −1
  3. Source/Libraries/Adapters/GrafanaAdapters/DataSourceValueGroup.cs +5 −0
  4. Source/Libraries/Adapters/GrafanaAdapters/GrafanaDataSourceBase.cs +31 −2
Source/Documentation/GrafanaFunctions.md+1−1
@@ -417,7 +417,7 @@ Returns a series of values that represent an adjusted set of angles that are wra · 416 unmodified lines
417417
418418 ## Label
419419
420−Renames a series with the specified label value. If multiple series are targeted, labels will be indexed starting at one, e.g., if there are three series in the target expression with a label value of "Max", series would be labeled as "Max 1", "Max 2" and "Max 3". Group operations on this function will be ignored.
420+Renames a series with the specified label value. If multiple series are targeted, labels will be indexed starting at one, e.g., if there are three series in the target expression with a label value of "Max", series would be labeled as "Max 1", "Max 2" and "Max 3". Group operations on this function will be ignored. The label parameter also supports substitutions when root target metadata can be resolved. For series values that directly map to a point tag, one of the following metadata value substitutions can be used in the label value: {ID}, {SignalID}, {PointTag}, {AlternateTag}, {SignalReference}, {Device} or {SignalType} - where applicable, these substitutions can be used in any combination.
421421
422422 * Signature: `Label(value, expression)`
423423 * Returns: Series of values
Source/Libraries/Adapters/GrafanaAdapters/AnnotationExtensions.cs+17−1
@@ -340,7 +340,7 @@ namespace GrafanaAdapters · 339 unmodified lines
340340 /// </remarks>
341341 internal static MeasurementKey KeyFromTag(this string pointTag, DataSet source)
342342 {
343− DataRow record = GetMetaData(source, "ActiveMeasurements", $"PointTag = '{pointTag}'");
343+ DataRow record = pointTag.MetadataRecordFromTag(source);
344344
345345 if ((object)record == null)
346346 return MeasurementKey.Undefined;
@@ -355,6 +355,22 @@ namespace GrafanaAdapters · 8 unmodified lines
355355 }
356356 }
357357
358+ /// <summary>
359+ /// Looks up metadata record from point tag.
360+ /// </summary>
361+ /// <param name="pointTag">Point tag to lookup.</param>
362+ /// <param name="source">Source metadata.</param>
363+ /// <returns>Metadata record from source metadata for provided point tag.</returns>
364+ /// <remarks>
365+ /// This function uses the <see cref="DataTable.Select(string)"/> function which uses a linear
366+ /// search algorithm that can be slow for large data sets, it is recommended that any results
367+ /// for calls to this function be cached to improve performance.
368+ /// </remarks>
369+ internal static DataRow MetadataRecordFromTag(this string pointTag, DataSet source)
370+ {
371+ return GetMetaData(source, "ActiveMeasurements", $"PointTag = '{pointTag}'");
372+ }
373+
358374 private static DataRow GetMetaData(DataSet source, string table, string expression)
359375 {
360376 try
Source/Libraries/Adapters/GrafanaAdapters/DataSourceValueGroup.cs+5−0
@@ -38,6 +38,11 @@ namespace GrafanaAdapters · 37 unmodified lines
3838 /// </summary>
3939 public string Target;
4040
41+ /// <summary>
42+ /// Defines the root target expression, without any referenced series functions.
43+ /// </summary>
44+ public string RootTarget;
45+
4146 /// <summary>
4247 /// Data source values enumerable.
4348 /// </summary>
Source/Libraries/Adapters/GrafanaAdapters/GrafanaDataSourceBase.cs+31−2
@@ -459,7 +459,9 @@ namespace GrafanaAdapters · 458 unmodified lines
459459 /// <summary>
460460 /// Renames a series with the specified label value. If multiple series are targeted, labels will be indexed starting at one, e.g., if there are three
461461 /// series in the target expression with a label value of "Max", series would be labeled as "Max 1", "Max 2" and "Max 3". Group operations on this
462− /// function will be ignored.
462+ /// function will be ignored. The label parameter also supports substitutions when root target metadata can be resolved. For series values that directly
463+ /// map to a point tag, one of the following metadata value substitutions can be used in the label value: {ID}, {SignalID}, {PointTag}, {AlternateTag},
464+ /// {SignalReference}, {Device} or {SignalType} - where applicable, these substitutions can be used in any combination.
463465 /// </summary>
464466 /// <remarks>
465467 /// Signature: <c>Label(value, expression)</c><br/>
@@ -797,6 +799,7 @@ namespace GrafanaAdapters · 331 unmodified lines
797799 yield return new DataSourceValueGroup
798800 {
799801 Target = target.Value,
802+ RootTarget = target.Value,
800803 Source = dataValues.Where(dataValue => dataValue.Target.Equals(target.Value))
801804 };
802805 }
@@ -898,9 +901,29 @@ namespace GrafanaAdapters · 95 unmodified lines
898901
899902 for (int i = 0; i < groups.Length; i++)
900903 {
904+ string target = groups[i].RootTarget;
905+
906+ string seriesLabel = TargetCache<string>.GetOrAdd($"{label}@{target}", () =>
907+ {
908+ string derivedLabel = label;
909+ DataRow record = target.MetadataRecordFromTag(Metadata);
910+
911+ if ((object)record != null)
912+ {
913+ foreach (string fieldName in s_metadataRecordFields)
914+ derivedLabel = derivedLabel.ReplaceCaseInsensitive($"{{{fieldName}}}", record[fieldName].ToString());
915+ }
916+
917+ if (derivedLabel.Equals(label, StringComparison.Ordinal))
918+ derivedLabel = $"{label}{(groups.Length > 1 ? $" {i + 1}" : "")}";
919+
920+ return derivedLabel;
921+ });
922+
901923 yield return new DataSourceValueGroup
902924 {
903− Target = $"{label}{(groups.Length > 1 ? $" {i + 1}" : "")}",
925+ Target = seriesLabel,
926+ RootTarget = target,
904927 Source = groups[i].Source
905928 };
906929 }
@@ -914,6 +937,7 @@ namespace GrafanaAdapters · 7 unmodified lines
914937 DataSourceValueGroup result = new DataSourceValueGroup
915938 {
916939 Target = $"Set{seriesFunction}({string.Join(", ", parameters)}{(parameters.Length > 0 ? ", " : "")}{targetExpression})",
940+ RootTarget = targetExpression,
917941 Source = ExecuteSeriesFunctionOverSource(dataset.AsParallel().WithCancellation(cancellationToken).SelectMany(source => source.Source), seriesFunction, parameters)
918942 };
919943
@@ -922,6 +946,7 @@ namespace GrafanaAdapters · 2 unmodified lines
922946 {
923947 DataSourceValue dataValue = result.Source.First();
924948 result.Target = $"Set{seriesFunction} = {dataValue.Target}";
949+ result.RootTarget = dataValue.Target;
925950 }
926951
927952 yield return result;
@@ -935,6 +960,7 @@ namespace GrafanaAdapters · 7 unmodified lines
935960 yield return new DataSourceValueGroup
936961 {
937962 Target = $"Slice{seriesFunction}({string.Join(", ", parameters)}{(parameters.Length > 0 ? ", " : "")}{targetExpression})",
963+ RootTarget = targetExpression,
938964 Source = ExecuteSeriesFunctionOverTimeSlices(scanner, seriesFunction, parameters)
939965 };
940966
@@ -944,6 +970,7 @@ namespace GrafanaAdapters · 3 unmodified lines
944970 yield return new DataSourceValueGroup
945971 {
946972 Target = $"{seriesFunction}({string.Join(", ", parameters)}{(parameters.Length > 0 ? ", " : "")}{dataValues.Target})",
973+ RootTarget = dataValues.Target,
947974 Source = ExecuteSeriesFunctionOverSource(dataValues.Source, seriesFunction, parameters)
948975 };
949976
@@ -995,6 +1022,7 @@ namespace GrafanaAdapters · 45 unmodified lines
9951022 private static readonly Dictionary<SeriesFunction, int> s_requiredParameters;
9961023 private static readonly Dictionary<SeriesFunction, int> s_optionalParameters;
9971024 private static readonly string[] s_groupOperationNames;
1025+ private static readonly string[] s_metadataRecordFields;
9981026
9991027 // Static Constructor
10001028 static GrafanaDataSourceBase()
@@ -1004,6 +1032,7 @@ namespace GrafanaAdapters · 3 unmodified lines
10041032 // RegEx instance to find all series functions
10051033 s_groupOperationNames = Enum.GetNames(typeof(GroupOperation));
10061034 s_seriesFunctions = new Regex($@"({string.Join("|", s_groupOperationNames)})?\w+\s*(?<!\s+IN\s+)\((([^\(\)]|(?<counter>\()|(?<-counter>\)))*(?(counter)(?!)))\)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
1035+ s_metadataRecordFields = new[] { "ID", "SignalID", "PointTag", "AlternateTag", "SignalReference", "Device", "SignalType" };
10071036
10081037 // RegEx instances to identify specific functions and extract internal expressions
10091038 s_averageExpression = new Regex(string.Format(GetExpression, "(Average|Avg|Mean)"), RegexOptions.Compiled | RegexOptions.IgnoreCase);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t