Class: Gitlab::Metrics::Transaction

Inherits:
Object
  • Object
show all
Includes:
Methods
Defined in:
lib/gitlab/metrics/transaction.rb

Overview

Class for storing metrics information of a single transaction.

Direct Known Subclasses

BackgroundTransaction, WebTransaction

Constant Summary collapse

BASE_LABEL_KEYS =

base label keys shared among all transactions

%i(controller action feature_category).freeze
FILTERED_LABEL_KEYS =

labels that potentially contain sensitive information and will be filtered

%i(branch path).freeze
THREAD_KEY =
:_gitlab_metrics_transaction
SMALL_BUCKETS =
[0.1, 0.25, 0.5, 1.0, 2.5, 5.0].freeze
EVENT_SERIES =

The series to store events (e.g. Git pushes) in.

'events'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeTransaction

Returns a new instance of Transaction.


40
41
42
43
44
45
# File 'lib/gitlab/metrics/transaction.rb', line 40

def initialize
  @methods = {}

  @started_at = nil
  @finished_at = nil
end

Instance Attribute Details

#methodObject (readonly)

Returns the value of attribute method


21
22
23
# File 'lib/gitlab/metrics/transaction.rb', line 21

def method
  @method
end

Class Method Details

.currentObject


24
25
26
# File 'lib/gitlab/metrics/transaction.rb', line 24

def current
  Thread.current[THREAD_KEY]
end

.prometheus_metric(name, type, &block) ⇒ Object


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

def prometheus_metric(name, type, &block)
  fetch_metric(type, name) do
    # set default metric options
    docstring "#{name.to_s.humanize} #{type}"

    evaluate(&block)
    # always filter sensitive labels and merge with base ones
    label_keys BASE_LABEL_KEYS | (label_keys - FILTERED_LABEL_KEYS)
  end
end

Instance Method Details

#add_event(event_name, tags = {}) ⇒ Object

Tracks a business level event

Business level events including events such as Git pushes, Emails being sent, etc.

event_name - The name of the event (e.g. “git_push”). tags - A set of tags to attach to the event.


82
83
84
85
86
87
88
89
# File 'lib/gitlab/metrics/transaction.rb', line 82

def add_event(event_name, tags = {})
  event_name = "gitlab_transaction_event_#{event_name}_total".to_sym
  metric = self.class.prometheus_metric(event_name, :counter) do
    label_keys tags.keys
  end

  metric.increment(filter_labels(tags))
end

#durationObject


47
48
49
# File 'lib/gitlab/metrics/transaction.rb', line 47

def duration
  @finished_at ? (@finished_at - @started_at) : 0.0
end

#filter_labels(labels) ⇒ Object


162
163
164
# File 'lib/gitlab/metrics/transaction.rb', line 162

def filter_labels(labels)
  labels.empty? ? self.labels : labels.without(*FILTERED_LABEL_KEYS).merge(self.labels)
end

#increment(name, value = 1, labels = {}, &block) ⇒ Object

Increment counter metric

It will initialize the metric if metric is not found

block - if provided can be used to initialize metric with custom options (docstring, labels, with_feature)

Example: “` transaction.increment(:mestric_name, 1, { docstring: 'Custom title', base_labels: 'yes' } ) do

transaction.increment(:mestric_name, 1) do

docstring 'Custom title'
label_keys %i(sane)

end “`


115
116
117
118
119
# File 'lib/gitlab/metrics/transaction.rb', line 115

def increment(name, value = 1, labels = {}, &block)
  counter = self.class.prometheus_metric(name, :counter, &block)

  counter.increment(filter_labels(labels), value)
end

#labelsObject


158
159
160
# File 'lib/gitlab/metrics/transaction.rb', line 158

def labels
  BASE_LABEL_KEYS.product([nil]).to_h
end

#method_call_for(name, module_name, method_name) ⇒ Object

Returns a MethodCall object for the given name.


92
93
94
95
96
97
98
# File 'lib/gitlab/metrics/transaction.rb', line 92

def method_call_for(name, module_name, method_name)
  unless method = @methods[name]
    @methods[name] = method = MethodCall.new(name, module_name, method_name, self)
  end

  method
end

#observe(name, value, labels = {}, &block) ⇒ Object

Observe histogram metric

It will initialize the metric if metric is not found

block - if provided, it can be used to initialize metric with custom options (docstring, labels, with_feature, buckets)

Example: “` transaction.observe(:mestric_name, 1) do

buckets [100, 1000, 10000, 100000, 1000000, 10000000]

end “`


152
153
154
155
156
# File 'lib/gitlab/metrics/transaction.rb', line 152

def observe(name, value, labels = {}, &block)
  histogram = self.class.prometheus_metric(name, :histogram, &block)

  histogram.observe(filter_labels(labels), value)
end

#runObject


55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/gitlab/metrics/transaction.rb', line 55

def run
  Thread.current[THREAD_KEY] = self

  @started_at = System.monotonic_time
  @thread_cputime_start = System.thread_cpu_time

  yield
ensure
  @finished_at = System.monotonic_time

  observe(:gitlab_transaction_cputime_seconds, thread_cpu_duration) do
    buckets SMALL_BUCKETS
  end
  observe(:gitlab_transaction_duration_seconds, duration) do
    buckets SMALL_BUCKETS
  end

  Thread.current[THREAD_KEY] = nil
end

#set(name, value, labels = {}, &block) ⇒ Object

Set gauge metric

It will initialize the metric if metric is not found

block - if provided, it can be used to initialize metric with custom options (docstring, labels, with_feature, multiprocess_mode)

  • multiprocess_mode is :all by default

Example: “` transaction.set(:mestric_name, 1) do

multiprocess_mode :livesum

end “`


134
135
136
137
138
# File 'lib/gitlab/metrics/transaction.rb', line 134

def set(name, value, labels = {}, &block)
  gauge = self.class.prometheus_metric(name, :gauge, &block)

  gauge.set(filter_labels(labels), value)
end

#thread_cpu_durationObject


51
52
53
# File 'lib/gitlab/metrics/transaction.rb', line 51

def thread_cpu_duration
  System.thread_cpu_duration(@thread_cputime_start)
end