diff options
author | Stan Hu <stanhu@gmail.com> | 2019-06-28 11:34:08 -0700 |
---|---|---|
committer | Stan Hu <stanhu@gmail.com> | 2019-07-02 21:55:34 -0700 |
commit | dac8e99ee7580df80faf72954912185f63e5f2a2 (patch) | |
tree | 8c388be1165842066dde162ed1273a907260e9d6 /lib/peek | |
parent | c1d250c2844991f51489d769dd6fca0f4ebdda19 (diff) | |
download | gitlab-ce-dac8e99ee7580df80faf72954912185f63e5f2a2.tar.gz |
Add Redis call details in Peek performance barsh-improve-redis-peek
Since Redis timings appear to be increasing in production, this change
makes it easier to see what exactly which queries are being called and
where.
This is done by prepending modules in peek-redis to store the call
details.
This commit redact values for all SET commands (e.g. HMSET, GETSET,
etc.).
Diffstat (limited to 'lib/peek')
-rw-r--r-- | lib/peek/views/redis.rb | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/lib/peek/views/redis.rb b/lib/peek/views/redis.rb new file mode 100644 index 00000000000..ad3c3c9fe01 --- /dev/null +++ b/lib/peek/views/redis.rb @@ -0,0 +1,82 @@ +# frozen_string_literal: true + +require 'redis' +require 'peek-redis' + +module Gitlab + module Peek + module RedisInstrumented + def call(*args, &block) + start = Time.now + super(*args, &block) + ensure + duration = (Time.now - start) + add_call_details(duration, args) + end + + private + + def add_call_details(duration, args) + # redis-rb passes an array (e.g. [:get, key]) + return unless args.length == 1 + + detail_store << { + cmd: args.first, + duration: duration, + backtrace: Gitlab::Profiler.clean_backtrace(caller) + } + end + + def detail_store + ::Gitlab::SafeRequestStore['redis_call_details'] ||= [] + end + end + end +end + +module Peek + module Views + module RedisDetailed + def results + super.merge(details: details) + end + + def details + detail_store + .sort { |a, b| b[:duration] <=> a[:duration] } + .map(&method(:format_call_details)) + end + + def detail_store + ::Gitlab::SafeRequestStore['redis_call_details'] ||= [] + end + + def format_call_details(call) + call.merge(cmd: format_command(call[:cmd]), + duration: (call[:duration] * 1000).round(3)) + end + + def format_command(cmd) + # Scrub out the value of the SET calls to avoid binary + # data or large data from spilling into the view + if cmd.length >= 2 && cmd.first =~ /set/i + cmd[-1] = "<redacted>" + end + + cmd.join(' ') + end + end + end +end + +class Redis::Client + prepend Gitlab::Peek::RedisInstrumented +end + +module Peek + module Views + class Redis < View + prepend Peek::Views::RedisDetailed + end + end +end |