Class: Gitlab::Usage::MetricDefinition

Inherits:
Object
  • Object
show all
Defined in:
lib/gitlab/usage/metric_definition.rb

Constant Summary collapse

METRIC_SCHEMA_PATH =
Rails.root.join('config', 'metrics', 'schema.json')
AVAILABLE_STATUSES =
%w[active broken].to_set.freeze
VALID_SERVICE_PING_STATUSES =
%w[active broken].to_set.freeze
InvalidError =
Class.new(RuntimeError)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path, opts = {}) ⇒ MetricDefinition

Returns a new instance of MetricDefinition.



15
16
17
18
# File 'lib/gitlab/usage/metric_definition.rb', line 15

def initialize(path, opts = {})
  @path = path
  @attributes = opts
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args) ⇒ Object (private)



170
171
172
# File 'lib/gitlab/usage/metric_definition.rb', line 170

def method_missing(method, *args)
  attributes[method] || super
end

Instance Attribute Details

#attributesObject (readonly)

Returns the value of attribute attributes.



13
14
15
# File 'lib/gitlab/usage/metric_definition.rb', line 13

def attributes
  @attributes
end

#pathObject (readonly)

Returns the value of attribute path.



12
13
14
# File 'lib/gitlab/usage/metric_definition.rb', line 12

def path
  @path
end

Class Method Details

.allObject



100
101
102
# File 'lib/gitlab/usage/metric_definition.rb', line 100

def all
  @all ||= definitions.map { |_key_path, definition| definition }
end

.context_for(key_path) ⇒ Object



112
113
114
# File 'lib/gitlab/usage/metric_definition.rb', line 112

def context_for(key_path)
  definitions[key_path].to_context
end

.definitions(skip_validation: false) ⇒ Object



95
96
97
98
# File 'lib/gitlab/usage/metric_definition.rb', line 95

def definitions(skip_validation: false)
  @skip_validation = skip_validation
  @definitions ||= load_all!
end

.dump_metrics_yamlObject



120
121
122
# File 'lib/gitlab/usage/metric_definition.rb', line 120

def dump_metrics_yaml
  @metrics_yaml ||= definitions.values.map(&:to_h).map(&:deep_stringify_keys).to_yaml
end

.metric_definitions_changed?Boolean

Returns:

  • (Boolean)


124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/gitlab/usage/metric_definition.rb', line 124

def metric_definitions_changed?
  return false unless Rails.env.development?

  return false if @last_change_check && @last_change_check > 3.seconds.ago

  @last_change_check = Time.current

  last_change = Dir.glob(paths).map { |f| File.mtime(f) }.max
  did_change = @last_metric_update != last_change
  @last_metric_update = last_change
  did_change
end

.not_removedObject



104
105
106
# File 'lib/gitlab/usage/metric_definition.rb', line 104

def not_removed
  all.select { |definition| definition.attributes[:status] != 'removed' }.index_by(&:key_path)
end

.pathsObject



91
92
93
# File 'lib/gitlab/usage/metric_definition.rb', line 91

def paths
  @paths ||= [Rails.root.join('config', 'metrics', '[^agg]*', '*.yml')]
end

.schemerObject



116
117
118
# File 'lib/gitlab/usage/metric_definition.rb', line 116

def schemer
  @schemer ||= ::JSONSchemer.schema(Pathname.new(METRIC_SCHEMA_PATH))
end

.with_instrumentation_classObject



108
109
110
# File 'lib/gitlab/usage/metric_definition.rb', line 108

def with_instrumentation_class
  all.select { |definition| definition.attributes[:instrumentation_class].present? && definition.available? }
end

Instance Method Details

#available?Boolean

Returns:

  • (Boolean)


80
81
82
# File 'lib/gitlab/usage/metric_definition.rb', line 80

def available?
  AVAILABLE_STATUSES.include?(attributes[:status])
end

#category_to_lowercaseObject



76
77
78
# File 'lib/gitlab/usage/metric_definition.rb', line 76

def category_to_lowercase
  attributes[:data_category]&.downcase!
end

#eventsObject



24
25
26
# File 'lib/gitlab/usage/metric_definition.rb', line 24

def events
  events_from_new_structure || events_from_old_structure || {}
end

#has_json_schema?Boolean

Returns:

  • (Boolean)


56
57
58
# File 'lib/gitlab/usage/metric_definition.rb', line 56

def has_json_schema?
  attributes[:value_type] == 'object' && attributes[:value_json_schema].present?
end

#json_schemaObject



44
45
46
47
48
# File 'lib/gitlab/usage/metric_definition.rb', line 44

def json_schema
  return unless has_json_schema?

  @json_schema ||= Gitlab::Json.parse(File.read(json_schema_path))
end

#json_schema_pathObject



50
51
52
53
54
# File 'lib/gitlab/usage/metric_definition.rb', line 50

def json_schema_path
  return '' unless has_json_schema?

  Rails.root.join(attributes[:value_json_schema])
end

#keyObject



20
21
22
# File 'lib/gitlab/usage/metric_definition.rb', line 20

def key
  key_path
end

#to_contextObject



28
29
30
31
32
33
34
35
36
37
38
# File 'lib/gitlab/usage/metric_definition.rb', line 28

def to_context
  return unless %w[redis redis_hll].include?(data_source)

  event_name = if data_source == 'redis_hll'
                 options[:events].first
               elsif data_source == 'redis'
                 Gitlab::Usage::Metrics::Instrumentations::RedisMetric.new(attributes).redis_key
               end

  Gitlab::Tracking::ServicePingContext.new(data_source: data_source, event: event_name)
end

#to_hObject Also known as: to_dictionary



40
41
42
# File 'lib/gitlab/usage/metric_definition.rb', line 40

def to_h
  attributes
end

#valid_service_ping_status?Boolean

Returns:

  • (Boolean)


84
85
86
# File 'lib/gitlab/usage/metric_definition.rb', line 84

def valid_service_ping_status?
  VALID_SERVICE_PING_STATUSES.include?(attributes[:status])
end

#validate!Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/gitlab/usage/metric_definition.rb', line 60

def validate!
  unless skip_validation?
    self.class.schemer.validate(attributes.deep_stringify_keys).each do |error|
      error_message = <<~ERROR_MSG
        Error type: #{error['type']}
        Data: #{error['data']}
        Path: #{error['data_pointer']}
        Details: #{error['details']}
        Metric file: #{path}
      ERROR_MSG

      Gitlab::ErrorTracking.track_and_raise_for_dev_exception(InvalidError.new(error_message))
    end
  end
end