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
# 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]
    if defined?(RedisClient)
      apply_redis_client_middleware!
    end
    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, [
        :call, :call_pipeline
      ], :redis, instrument: config[:instrument])
    end
    if defined? PG::Connection
      MethodProfiler.patch(PG::Connection, [
        :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
  end
end

Instance Method Details

#call(env) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/prometheus_exporter/middleware.rb', line 37

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)
  if labels
    obj = obj.merge(custom_labels: labels)
  end

  @client.send_json(obj)
end

#custom_labels(env) ⇒ Object

allows subclasses to add custom labels based on env



82
83
84
# File 'lib/prometheus_exporter/middleware.rb', line 82

def custom_labels(env)
  nil
end

#default_labels(env, result) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/prometheus_exporter/middleware.rb', line 62

def default_labels(env, result)
  params = env["action_dispatch.request.parameters"]
  action = controller = nil
  if params
    action = params["action"]
    controller = params["controller"]
  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