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
417 417
418## Label418## Label
419 419
420Renames 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.420Renames 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.
421 421
422* Signature: `Label(value, expression)`422* Signature: `Label(value, expression)`
423* Returns: Series of values423* Returns: Series of values
Source/Libraries/Adapters/GrafanaAdapters/AnnotationExtensions.cs+17−1
@@ -340,7 +340,7 @@ namespace GrafanaAdapters · 339 unmodified lines
340 /// </remarks>340 /// </remarks>
341 internal static MeasurementKey KeyFromTag(this string pointTag, DataSet source)341 internal static MeasurementKey KeyFromTag(this string pointTag, DataSet source)
342 {342 {
343 DataRow record = GetMetaData(source, "ActiveMeasurements", $"PointTag = '{pointTag}'");343 DataRow record = pointTag.MetadataRecordFromTag(source);
344 344
345 if ((object)record == null)345 if ((object)record == null)
346 return MeasurementKey.Undefined;346 return MeasurementKey.Undefined;
@@ -355,6 +355,22 @@ namespace GrafanaAdapters · 8 unmodified lines
355 }355 }
356 }356 }
357 357
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
358 private static DataRow GetMetaData(DataSet source, string table, string expression)374 private static DataRow GetMetaData(DataSet source, string table, string expression)
359 {375 {
360 try376 try
Source/Libraries/Adapters/GrafanaAdapters/DataSourceValueGroup.cs+5−0
@@ -38,6 +38,11 @@ namespace GrafanaAdapters · 37 unmodified lines
38 /// </summary>38 /// </summary>
39 public string Target;39 public string Target;
40 40
41 /// <summary>
42 /// Defines the root target expression, without any referenced series functions.
43 /// </summary>
44 public string RootTarget;
45
41 /// <summary>46 /// <summary>
42 /// Data source values enumerable.47 /// Data source values enumerable.
43 /// </summary>48 /// </summary>
Source/Libraries/Adapters/GrafanaAdapters/GrafanaDataSourceBase.cs+31−2
@@ -459,7 +459,9 @@ namespace GrafanaAdapters · 458 unmodified lines
459 /// <summary>459 /// <summary>
460 /// 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 three460 /// 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
461 /// 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 this461 /// 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.
463 /// </summary>465 /// </summary>
464 /// <remarks>466 /// <remarks>
465 /// Signature: <c>Label(value, expression)</c><br/>467 /// Signature: <c>Label(value, expression)</c><br/>
@@ -797,6 +799,7 @@ namespace GrafanaAdapters · 331 unmodified lines
797 yield return new DataSourceValueGroup799 yield return new DataSourceValueGroup
798 {800 {
799 Target = target.Value,801 Target = target.Value,
802 RootTarget = target.Value,
800 Source = dataValues.Where(dataValue => dataValue.Target.Equals(target.Value))803 Source = dataValues.Where(dataValue => dataValue.Target.Equals(target.Value))
801 };804 };
802 }805 }
@@ -898,9 +901,29 @@ namespace GrafanaAdapters · 95 unmodified lines
898 901
899 for (int i = 0; i < groups.Length; i++)902 for (int i = 0; i < groups.Length; i++)
900 {903 {
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
901 yield return new DataSourceValueGroup923 yield return new DataSourceValueGroup
902 {924 {
903 Target = $"{label}{(groups.Length > 1 ? $" {i + 1}" : "")}",925 Target = seriesLabel,
926 RootTarget = target,
904 Source = groups[i].Source927 Source = groups[i].Source
905 };928 };
906 }929 }
@@ -914,6 +937,7 @@ namespace GrafanaAdapters · 7 unmodified lines
914 DataSourceValueGroup result = new DataSourceValueGroup937 DataSourceValueGroup result = new DataSourceValueGroup
915 {938 {
916 Target = $"Set{seriesFunction}({string.Join(", ", parameters)}{(parameters.Length > 0 ? ", " : "")}{targetExpression})",939 Target = $"Set{seriesFunction}({string.Join(", ", parameters)}{(parameters.Length > 0 ? ", " : "")}{targetExpression})",
940 RootTarget = targetExpression,
917 Source = ExecuteSeriesFunctionOverSource(dataset.AsParallel().WithCancellation(cancellationToken).SelectMany(source => source.Source), seriesFunction, parameters)941 Source = ExecuteSeriesFunctionOverSource(dataset.AsParallel().WithCancellation(cancellationToken).SelectMany(source => source.Source), seriesFunction, parameters)
918 };942 };
919 943
@@ -922,6 +946,7 @@ namespace GrafanaAdapters · 2 unmodified lines
922 {946 {
923 DataSourceValue dataValue = result.Source.First();947 DataSourceValue dataValue = result.Source.First();
924 result.Target = $"Set{seriesFunction} = {dataValue.Target}";948 result.Target = $"Set{seriesFunction} = {dataValue.Target}";
949 result.RootTarget = dataValue.Target;
925 }950 }
926 951
927 yield return result;952 yield return result;
@@ -935,6 +960,7 @@ namespace GrafanaAdapters · 7 unmodified lines
935 yield return new DataSourceValueGroup960 yield return new DataSourceValueGroup
936 {961 {
937 Target = $"Slice{seriesFunction}({string.Join(", ", parameters)}{(parameters.Length > 0 ? ", " : "")}{targetExpression})",962 Target = $"Slice{seriesFunction}({string.Join(", ", parameters)}{(parameters.Length > 0 ? ", " : "")}{targetExpression})",
963 RootTarget = targetExpression,
938 Source = ExecuteSeriesFunctionOverTimeSlices(scanner, seriesFunction, parameters)964 Source = ExecuteSeriesFunctionOverTimeSlices(scanner, seriesFunction, parameters)
939 };965 };
940 966
@@ -944,6 +970,7 @@ namespace GrafanaAdapters · 3 unmodified lines
944 yield return new DataSourceValueGroup970 yield return new DataSourceValueGroup
945 {971 {
946 Target = $"{seriesFunction}({string.Join(", ", parameters)}{(parameters.Length > 0 ? ", " : "")}{dataValues.Target})",972 Target = $"{seriesFunction}({string.Join(", ", parameters)}{(parameters.Length > 0 ? ", " : "")}{dataValues.Target})",
973 RootTarget = dataValues.Target,
947 Source = ExecuteSeriesFunctionOverSource(dataValues.Source, seriesFunction, parameters)974 Source = ExecuteSeriesFunctionOverSource(dataValues.Source, seriesFunction, parameters)
948 };975 };
949 976
@@ -995,6 +1022,7 @@ namespace GrafanaAdapters · 45 unmodified lines
995 private static readonly Dictionary<SeriesFunction, int> s_requiredParameters;1022 private static readonly Dictionary<SeriesFunction, int> s_requiredParameters;
996 private static readonly Dictionary<SeriesFunction, int> s_optionalParameters;1023 private static readonly Dictionary<SeriesFunction, int> s_optionalParameters;
997 private static readonly string[] s_groupOperationNames;1024 private static readonly string[] s_groupOperationNames;
1025 private static readonly string[] s_metadataRecordFields;
998 1026
999 // Static Constructor1027 // Static Constructor
1000 static GrafanaDataSourceBase()1028 static GrafanaDataSourceBase()
@@ -1004,6 +1032,7 @@ namespace GrafanaAdapters · 3 unmodified lines
1004 // RegEx instance to find all series functions1032 // RegEx instance to find all series functions
1005 s_groupOperationNames = Enum.GetNames(typeof(GroupOperation));1033 s_groupOperationNames = Enum.GetNames(typeof(GroupOperation));
1006 s_seriesFunctions = new Regex($@"({string.Join("|", s_groupOperationNames)})?\w+\s*(?<!\s+IN\s+)\((([^\(\)]|(?<counter>\()|(?<-counter>\)))*(?(counter)(?!)))\)", RegexOptions.Compiled | RegexOptions.IgnoreCase);1034 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" };
1007 1036
1008 // RegEx instances to identify specific functions and extract internal expressions1037 // RegEx instances to identify specific functions and extract internal expressions
1009 s_averageExpression = new Regex(string.Format(GetExpression, "(Average|Avg|Mean)"), RegexOptions.Compiled | RegexOptions.IgnoreCase);1038 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