Class: PrometheusExporter::Middleware

Inherits:
Object
  • Object
show all
Defined in:
lib/prometheus_exporter/middleware.rb

Defined Under Namespace

Modules: RedisInstrumenter

Constant Summary collapse

MethodProfiler =
PrometheusExporter::Instrumentation::MethodProfiler

Instance Method Summary collapse

Constructor Details

#initialize(app, config = { instrument: :alias_method, client: nil }) ⇒ Middleware

Returns a new instance of Middleware.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/prometheus_exporter/middleware.rb', line 9

def initialize(app, config = { instrument: :alias_method, client: nil })
  @app = app
  @client = config[:client] || PrometheusExporter::Client.default

  if config[:instrument]
    apply_redis_client_middleware! if defined?(RedisClient)

    if defined?(Redis::VERSION) && (Gem::Version.new(Redis::VERSION) >= Gem::Version.new("5.0.0"))
      # redis 5 support handled via RedisClient
    elsif defined?(Redis::Client)
      MethodProfiler.patch(
        Redis::Client,
        %i[call call_pipeline],
        :redis,
        instrument: config[:instrument],
      )
    end

    if defined?(PG::Connection)
      MethodProfiler.patch(
        PG::Connection,
        %i[exec async_exec exec_prepared exec_params send_query_prepared query],
        :sql,
        instrument: config[:instrument],
      )
    end

    if defined?(Mysql2::Client)
      MethodProfiler.patch(Mysql2::Client, [:query], :sql, instrument: config[:instrument])
      MethodProfiler.patch(Mysql2::Statement, [:execute], :sql, instrument: config[:instrument])
      MethodProfiler.patch(Mysql2::Result, [:each], :sql, instrument: config[:instrument])
    end

    if defined?(Dalli::Client)
      MethodProfiler.patch(
        Dalli::Client,
        %i[delete fetch get add set],
        :memcache,
        instrument: config[:instrument],
      )
    end
  end
end

Instance Method Details

#call(env) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/prometheus_exporter/middleware.rb', line 53

def call(env)
  queue_time = measure_queue_time(env)

  MethodProfiler.start
  result = @app.call(env)
  info = MethodProfiler.stop

  result
ensure
  status = (result && result[0]) || -1
  obj = {
    type: "web",
    timings: info,
    queue_time: queue_time,
    status: status,
    default_labels: default_labels(env, result),
  }
  labels = custom_labels(env)
  obj = obj.merge(custom_labels: labels) if labels

  @client.send_json(obj)
end

#custom_labels(env) ⇒ Object

allows subclasses to add custom labels based on env



93
94
95
# File 'lib/prometheus_exporter/middleware.rb', line 93

def custom_labels(env)
  nil
end

#default_labels(env, result) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/prometheus_exporter/middleware.rb', line 76

def default_labels(env, result)
  controller_instance = env["action_controller.instance"]
  action = controller = nil
  if controller_instance
    action = controller_instance.action_name
    controller = controller_instance.controller_name
  elsif (cors = env["rack.cors"]) && cors.respond_to?(:preflight?) && cors.preflight?
    # if the Rack CORS Middleware identifies the request as a preflight request,
    # the stack doesn't get to the point where controllers/actions are defined
    action = "preflight"
    controller = "preflight"
  end

  { action: action || "other", controller: controller || "other" }
end