Method: GrafanaReporter::AbstractQuery#replace_values

Defined in:
lib/grafana_reporter/abstract_query.rb

#replace_values(result, configs) ⇒ Hash

Used to replace values in a query result according given configurations.

The given variables will be applied to an appropriate column, depending on the naming of the variable. The variable name ending specifies the column, e.g. a variable named replace_values_2 will be applied to the second column.

The Grafana::Variable#text needs to contain the replace specification. Multiple replacements can be specified by separating them with ,. If a literal comma is needed, it can be escaped with a backslash: \,.

The rule will be separated from the replacement text with a colon :. If a literal colon is wanted, it can be escaped with a backslash: :.

Examples:

  • Basic string replacement

    MyTest:ThisValue
    

will replace all occurences of the text ‘MyTest’ with ‘ThisValue’.

  • Number comparison

    <=10:OK
    

will replace all values smaller or equal to 10 with ‘OK’.

  • Regular expression

    ^[^ ]\\+ (\d+)$:\1 is the answer
    

will replace all values matching the pattern, e.g. ‘answerToAllQuestions 42’ to ‘42 is the answer’. Important to know: the regular expressions always have to start with ^ and end with $, i.e. the expression itself always has to match the whole content in one field.

Parameters:

Returns:

  • (Hash)

    query result with replaced values



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
# File 'lib/grafana_reporter/abstract_query.rb', line 241

def replace_values(result, configs)
  return result if configs.empty?

  configs.each do |key, formats|
    cols = key.split('_')[2..-1].map(&:to_i)

    formats.text.split(/(?<!\\),/).each_index do |j|
      format = formats.text.split(/(?<!\\),/)[j]

      arr = format.split(/(?<!\\):/)
      raise MalformedReplaceValuesStatementError, format if arr.length != 2

      k = arr[0]
      v = arr[1]

      # allow keys and values to contain escaped colons or commas
      k = k.gsub(/\\([:,])/, '\1')
      v = v.gsub(/\\([:,])/, '\1')

      result[:content].map do |row|
        (row.length - 1).downto 0 do |i|
          if cols.include?(i + 1) || cols.empty?

            # handle regular expressions
            if k.start_with?('^') && k.end_with?('$')
              begin
                row[i] = row[i].to_s.gsub(/#{k}/, v) if row[i].to_s =~ /#{k}/
              rescue StandardError => e
                @logger.error(e.message)
                row[i] = e.message
              end

            # handle value comparisons
            elsif (match = k.match(/^ *(?<operator>[<>]=?|<>|=) *(?<number>[+-]?\d+(?:\.\d+)?)$/))
              skip = false
              begin
                val = Float(row[i])
              rescue StandardError
                # value cannot be converted to number, simply ignore it as the comparison does not fit here
                skip = true
              end

              unless skip
                begin
                  op = match[:operator].gsub(/^=$/, '==').gsub(/^<>$/, '!=')
                  if val.public_send(op.to_sym, Float(match[:number]))
                    row[i] = if v.include?('\\1')
                               v.gsub(/\\1/, row[i].to_s)
                             else
                               v
                             end
                  end
                rescue StandardError => e
                  @logger.error(e.message)
                  row[i] = e.message
                end
              end

            # handle as normal comparison
            elsif row[i].to_s == k
              row[i] = v
            end
          end
        end
      end
    end
  end

  result
end