Class: Grafana::AbstractDatasource

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

Overview

This abstract class defines the base functionalities for the common datasource implementations. Additionally it provides a factory method to build a real datasource from a given specification.

Constant Summary collapse

@@subclasses =
[]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model) ⇒ AbstractDatasource

Returns a new instance of AbstractDatasource.


41
42
43
# File 'lib/grafana/abstract_datasource.rb', line 41

def initialize(model)
  @model = model
end

Instance Attribute Details

#modelObject (readonly)

Returns the value of attribute model.


7
8
9
# File 'lib/grafana/abstract_datasource.rb', line 7

def model
  @model
end

Class Method Details

.build_instance(ds_model) ⇒ AbstractDatasource

Factory method to build a datasource from a given datasource Hash description.

Parameters:

  • ds_model (Hash)

    grafana specification of a single datasource

Returns:

Raises:


29
30
31
32
33
34
35
36
37
38
39
# File 'lib/grafana/abstract_datasource.rb', line 29

def self.build_instance(ds_model)
  raise InvalidDatasourceQueryProvidedError, ds_model unless ds_model.is_a?(Hash)

  raise InvalidDatasourceQueryProvidedError, ds_model unless ds_model['meta'].is_a?(Hash)

  @@subclasses.each do |datasource_class|
    return datasource_class.new(ds_model) if datasource_class.handles?(ds_model)
  end

  UnsupportedDatasource.new(ds_model)
end

.handles?(model) ⇒ Boolean

Overwrite this method, to specify if the current datasource implementation handles the given model. This method is called by build_instance to determine, if the current datasource implementation can handle the given grafana model. By default this method returns false.

Parameters:

  • model (Hash)

    grafana specification of the datasource to check

Returns:

  • (Boolean)

    True if fits, false otherwise


22
23
24
# File 'lib/grafana/abstract_datasource.rb', line 22

def self.handles?(model)
  false
end

.inherited(subclass) ⇒ Object

Registers the subclass as datasource.

Parameters:

  • subclass (Class)

    class inheriting from this abstract class


13
14
15
# File 'lib/grafana/abstract_datasource.rb', line 13

def self.inherited(subclass)
  @@subclasses << subclass
end

Instance Method Details

#categoryString

Returns category of the datasource, e.g. tsdb or sql.

Returns:

  • (String)

    category of the datasource, e.g. tsdb or sql


46
47
48
# File 'lib/grafana/abstract_datasource.rb', line 46

def category
  @model['meta']['category']
end

#default_variable_formatString

This method is abstract.

Overwrite in subclass, to specify the default variable format during replacement of variables.

Returns:

Raises:

  • (NotImplementedError)

113
114
115
# File 'lib/grafana/abstract_datasource.rb', line 113

def default_variable_format
  raise NotImplementedError
end

#idInteger

Returns ID of the datasource.

Returns:

  • (Integer)

    ID of the datasource


66
67
68
# File 'lib/grafana/abstract_datasource.rb', line 66

def id
  @model['id'].to_i
end

#nameString

Returns name of the datasource.

Returns:

  • (String)

    name of the datasource


56
57
58
# File 'lib/grafana/abstract_datasource.rb', line 56

def name
  @model['name']
end

#raw_query_from_panel_model(panel_query_target) ⇒ String

This method is abstract.

The different datasources supported by grafana use different ways to store the query in the panel's JSON model. This method extracts a query from that description, that can be used by the Grafana::AbstractDatasource implementation of the datasource.

Parameters:

  • panel_query_target (Hash)

    grafana panel target, which contains the query description

Returns:

  • (String)

    query string, which can be used as raw_query in a #request

Raises:

  • (NotImplementedError)

105
106
107
# File 'lib/grafana/abstract_datasource.rb', line 105

def raw_query_from_panel_model(panel_query_target)
  raise NotImplementedError
end

#replace_variables(string, variables, overwrite_default_format = nil) ⇒ String

Replaces the grafana variables in the given string with their replacement value.

Parameters:

  • string (String)

    string in which the variables shall be replaced

  • variables (Hash<String,Variable>)

    Hash containing the variables, which shall be replaced in the given string

  • overwrite_default_format (String) (defaults to: nil)

    Variable#value_formatted value, if a custom default format should be used, otherwise #default_variable_format is used as default, which may be overwritten

Returns:

  • (String)

    string in which all variables are properly replaced


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
# File 'lib/grafana/abstract_datasource.rb', line 124

def replace_variables(string, variables, overwrite_default_format = nil)
  res = string
  repeat = true
  repeat_count = 0

  # TODO: find a proper way to replace variables recursively instead of over and over again
  # TODO: add tests for recursive replacement of variable
  while repeat && (repeat_count < 3)
    repeat = false
    repeat_count += 1

    variables.each do |name, variable|
      # do not replace with non grafana variables
      next unless name =~ /^var-/

      # only set ticks if value is string
      var_name = name.gsub(/^var-/, '')
      next unless var_name =~ /^\w+$/

      res = res.gsub(/(?:\$\{#{var_name}(?::(?<format>\w+))?\}|\$#{var_name}(?!\w))/) do
        format = overwrite_default_format
        format = default_variable_format if overwrite_default_format.nil?
        if $LAST_MATCH_INFO
          format = $LAST_MATCH_INFO[:format] if $LAST_MATCH_INFO[:format]
        end
        variable.value_formatted(format)
      end
    end
    repeat = true if res.include?('$')
  end

  res
end

#request(query_description) ⇒ Hash

This method is abstract.

Executes a request for the current database with the given options.

Used format of the response will always be the following:

{
  :header => [column_title_1, column_title_2],
  :content => [
                [row_1_column_1, row_1_column_2],
                [row_2_column_1, row_2_column_2]
              ]
}

Parameters:

  • query_description (Hash)

    query description, which will requested:

Options Hash (query_description):

  • :grafana_version (String)

    grafana version, for which the request is to be prepared

  • :from (String)

    from timestamp

  • :to (String)

    to timestamp

  • :timeout (Integer)

    expected timeout for the request

  • :prepared_request (WebRequest)

    prepared web request for relevant Grafana instance, if this is needed by datasource

  • :raw_query (String)

    raw query, which shall be executed. May include variables, which will be replaced before execution

  • :variables (Hash<Variable>)

    hash of variables, which can potentially be replaced in the given :raw_query

Returns:

  • (Hash)

    sql result formatted as stated above

Raises:

  • (NotImplementedError)

93
94
95
# File 'lib/grafana/abstract_datasource.rb', line 93

def request(query_description)
  raise NotImplementedError
end

#typeString

Returns type of the datasource, e.g. mysql.

Returns:

  • (String)

    type of the datasource, e.g. mysql


51
52
53
# File 'lib/grafana/abstract_datasource.rb', line 51

def type
  @model['type'] || @model['meta']['id']
end

#uidString

Returns unique ID of the datasource.

Returns:

  • (String)

    unique ID of the datasource


61
62
63
# File 'lib/grafana/abstract_datasource.rb', line 61

def uid
  @model['uid']
end