Class: Grafana::Variable

Inherits:
Object
  • Object
show all
Defined in:
lib/grafana/variable.rb

Overview

This class contains a representation of grafana variables, aka grafana templates.

The main need therefore rises in order to replace variables properly in different texts, e.g. SQL statements or results.

Constant Summary collapse

DATE_MATCHES =

Translation table to support /.

{ 'M' => '%-m', 'MM' => '%m', 'MMM' => '%b',  'MMMM' => '%B',
'D' => '%-d', 'DD' => '%d', 'DDD' => '%-j', 'DDDD' => '%j',
'd' => '%w',                'ddd' => '%a',  'dddd' => '%A',
'YY' => '%y', 'YYYY' => '%Y',
'h' => '%-I', 'hh' => '%I',
'H' => '%-H', 'HH' => '%H',
'm' => '%-M', 'mm' => '%M',
's' => '%-S', 'ss' => '%S',
'w' => '%-U', 'ww' => '%U',
'W' => '%-V', 'WW' => '%V',
'a' => '%P',
'A' => '%p',
'e' => '%w',
'E' => '%u',
'X' => '%s' }.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config_or_value, dashboard = nil) ⇒ Variable

Returns a new instance of Variable.

Parameters:

  • config_or_value (Hash, Object)

    configuration hash of a variable out of an Dashboard instance or a value of any kind.

  • dashboard (Dashboard) (defaults to: nil)

    parent dashboard, if applicable; especially needed for query variable evaluation.



34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/grafana/variable.rb', line 34

def initialize(config_or_value, dashboard = nil)
  if config_or_value.is_a? Hash
    @dashboard = dashboard
    @config = config_or_value
    @name = @config['name']
    init_values
  else
    @config = {}
    @raw_value = config_or_value
    @text = config_or_value.to_s
  end
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



11
12
13
# File 'lib/grafana/variable.rb', line 11

def name
  @name
end

#raw_valueObject

Returns the value of attribute raw_value.



11
12
13
# File 'lib/grafana/variable.rb', line 11

def raw_value
  @raw_value
end

#textObject (readonly)

Returns the value of attribute text.



11
12
13
# File 'lib/grafana/variable.rb', line 11

def text
  @text
end

Class Method Details

.format_as_date(value, format) ⇒ String

Parameters:

  • value (String)

    time as milliseconds to be formatted

  • format (String)

    format string in which the time value shall be returned

Returns:

  • (String)

    time converted to the specified time format



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/grafana/variable.rb', line 203

def self.format_as_date(value, format)
  return (Float(value) / 1000).to_i.to_s if format == 'seconds'
  return Time.at((Float(value) / 1000).to_i).utc.iso8601(3) if !format || (format == 'iso')

  # build array of known matches
  matches = []
  work_string = format
  until work_string.empty?
    tmp = work_string.scan(/^(?:M{1,4}|D{1,4}|d{1,4}|e|E|w{1,2}|W{1,2}|Y{4}|Y{2}|A|a|H{1,2}|
                                h{1,2}|k{1,2}|m{1,2}|s{1,2}|S+|X)/x)

    if tmp.empty?
      matches << work_string[0]
      work_string = work_string.sub(/^#{work_string[0]}/, '')
    else
      matches << tmp[0]
      work_string = work_string.sub(/^#{tmp[0]}/, '')
    end
  end

  format_string = ''.dup
  matches.each do |match|
    replacement = DATE_MATCHES[match]
    format_string << (replacement || match)
  end

  Time.at((Float(value) / 1000).to_i).strftime(format_string)
end

Instance Method Details

#multi?Boolean

Returns true, if the value can contain multiple selections, i.e. can contain an Array or does contain all.

Returns:

  • (Boolean)

    true, if the value can contain multiple selections, i.e. can contain an Array or does contain all



178
179
180
181
182
183
# File 'lib/grafana/variable.rb', line 178

def multi?
  return true if @raw_value == '$__all'
  return @config['multi'] unless @config['multi'].nil?

  @raw_value.is_a? Array
end

#value_formatted(format = '') ⇒ String

Returns the stored value formatted according the given format.

Supported formats are: csv, distributed, doublequote, json, percentencode, pipe, raw, regex, singlequote, sqlstring, lucene, date or glob (default)

For details see Grafana Advanced variable format options.

For details of date format, see Grafana global variables $__from and $__to. Please note that input for date format is unixtime in milliseconds.

Parameters:

  • format (String) (defaults to: '')

    desired format

Returns:

  • (String)

    value of stored variable according the specified format



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/grafana/variable.rb', line 62

def value_formatted(format = '')
  value = @raw_value

  # if 'All' is selected for this template variable, capture all values properly
  # (from grafana config or query) and format the results afterwards accordingly
  if value == '$__all'
    if !@config['options'].empty?
      # this query contains predefined values, so capture them and format the values accordingly
      # this happens either for type='custom' or type 'query', if it is never updated
      value = @config['options'].reject { |item| item['value'] == '$__all' }.map { |item| item['value'] }

    elsif @config['type'] == 'query' && !@config['query'].empty?
      # variables in this configuration are not stored in grafana, i.e. if all is selected here,
      # the values have to be fetched from the datasource
      query = ::GrafanaReporter::QueryValueQuery.new(@dashboard)
      query.datasource = @dashboard.grafana.datasource_by_name(@config['datasource'])
      query.variables['result_type'] = Variable.new('object')
      query.raw_query = @config['query']
      result = query.execute

      value = result[:content].map { |item| item[0].to_s }

    else
      # TODO: add support for variable type: 'datasource' and 'adhoc'
    end
  end

  case format
  when 'csv'
    return value.join(',').to_s if multi? && value.is_a?(Array)

    value.to_s

  when 'distributed'
    return value.join(",#{name}=") if multi? && value.is_a?(Array)

    value
  when 'doublequote'
    if multi? && value.is_a?(Array)
      value = value.map { |item| "\"#{item.gsub(/\\/, '\\\\').gsub(/"/, '\\"')}\"" }
      return value.join(',')
    end
    "\"#{value.gsub(/"/, '\\"')}\""

  when 'json'
    if multi? && value.is_a?(Array)
      value = value.map { |item| "\"#{item.gsub(/["\\]/, '\\\\\0')}\"" }
      return "[#{value.join(',')}]"
    end
    "\"#{value.gsub(/"/, '\\"')}\""

  when 'percentencode'
    value = "{#{value.join(',')}}" if multi? && value.is_a?(Array)
    ERB::Util.url_encode(value)

  when 'pipe'
    return value.join('|') if multi? && value.is_a?(Array)

    value

  when 'raw'
    return "{#{value.join(',')}}" if multi? && value.is_a?(Array)

    value

  when 'regex'
    if multi? && value.is_a?(Array)
      value = value.map { |item| item.gsub(%r{[/$.|\\]}, '\\\\\0') }
      return "(#{value.join('|')})"
    end
    value.gsub(%r{[/$.|\\]}, '\\\\\0')

  when 'singlequote'
    if multi? && value.is_a?(Array)
      value = value.map { |item| "'#{item.gsub(/'/, '\\\\\0')}'" }
      return value.join(',')
    end
    "'#{value.gsub(/'/, '\\\\\0')}'"

  when 'sqlstring'
    if multi? && value.is_a?(Array)
      value = value.map { |item| "'#{item.gsub(/'/, "''")}'" }
      return value.join(',')
    end
    "'#{value.gsub(/'/, "''")}'"

  when 'lucene'
    if multi? && value.is_a?(Array)
      value = value.map { |item| "\"#{item.gsub(%r{[" |=/\\]}, '\\\\\0')}\"" }
      return "(#{value.join(' OR ')})"
    end
    value.gsub(%r{[" |=/\\]}, '\\\\\0')

  when /^date(?::(?<format>.*))?$/
    if multi? && value.is_a?(Array)
      raise GrafanaError, "Date format cannot be specified for a variable containing an array of values"
    end
    Variable.format_as_date(value, Regexp.last_match(1))

  when ''
    # default
    if multi? && value.is_a?(Array)
      value = value.map { |item| "'#{item.gsub(/'/, "''")}'" }
      return value.join(',')
    end
    value.gsub(/'/, "''")

  else
    # glob and all unknown
    return "{#{value.join(',')}}" if multi? && value.is_a?(Array)

    value
  end
end