Skip to content

Commit bf7cf65

Browse files
committed
Update Redis backend
1 parent 86b526e commit bf7cf65

File tree

2 files changed

+51
-38
lines changed

2 files changed

+51
-38
lines changed

lib/graphql/tracing/perfetto_sampler/redis_backend.rb

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,58 +7,59 @@ class RedisBackend
77
KEY_PREFIX = "gql:trace:"
88
def initialize(redis:)
99
@redis = redis
10+
@key = KEY_PREFIX + "traces"
1011
end
1112

12-
def traces
13-
keys = @redis.scan_each(match: "#{KEY_PREFIX}*").to_a
14-
keys.sort!
15-
keys.map do |k|
16-
h = @redis.hgetall(k)
17-
StoredTrace.new(
18-
id: k.sub(KEY_PREFIX, ""),
19-
operation_name: h["operation_name"],
20-
duration_ms: h["duration_ms"].to_f,
21-
timestamp: Time.at(h["timestamp"].to_i),
22-
trace_data: h["trace_data"],
23-
)
13+
def traces(last:, before:)
14+
before = case before
15+
when Numeric
16+
"(#{before}"
17+
when nil
18+
"+inf"
19+
end
20+
str_pairs = @redis.zrange(@key, before, 0, byscore: true, rev: true, limit: [0, last || 100], withscores: true)
21+
str_pairs.map do |(str_data, score)|
22+
entry_to_trace(score, str_data)
2423
end
2524
end
2625

2726
def delete_trace(id)
28-
@redis.del("#{KEY_PREFIX}#{id}")
27+
@redis.zremrangebyscore(@key, id, id)
2928
nil
3029
end
3130

3231
def delete_all_traces
33-
keys = @redis.scan_each(match: "#{KEY_PREFIX}*")
34-
@redis.del(*keys)
32+
@redis.del(@key)
3533
end
3634

3735
def find_trace(id)
38-
redis_h = @redis.hgetall("#{KEY_PREFIX}#{id}")
39-
if redis_h.empty?
36+
str_data = @redis.zrange(@key, id, id, byscore: true).first
37+
if str_data.nil?
4038
nil
4139
else
42-
StoredTrace.new(
43-
id: id,
44-
operation_name: redis_h["operation_name"],
45-
duration_ms: redis_h["duration_ms"].to_f,
46-
timestamp: Time.at(redis_h["timestamp"].to_i),
47-
trace_data: redis_h["trace_data"],
48-
)
40+
entry_to_trace(id, str_data)
4941
end
5042
end
5143

52-
def save_trace(operation_name, duration_ms, timestamp, trace_data)
53-
id = (timestamp.to_i * 1000) + rand(1000)
54-
@redis.hmset("#{KEY_PREFIX}#{id}",
55-
"operation_name", operation_name,
56-
"duration_ms", duration_ms,
57-
"timestamp", timestamp.to_i,
58-
"trace_data", trace_data,
59-
)
44+
def save_trace(operation_name, duration_ms, begin_ms, trace_data)
45+
id = begin_ms
46+
data = JSON.dump({ "o" => operation_name, "d" => duration_ms, "b" => begin_ms, "t" => Base64.encode64(trace_data) })
47+
@redis.zadd(@key, id, data)
6048
id
6149
end
50+
51+
private
52+
53+
def entry_to_trace(id, json_str)
54+
data = JSON.parse(json_str)
55+
StoredTrace.new(
56+
id: id,
57+
operation_name: data["o"],
58+
duration_ms: data["d"].to_f,
59+
timestamp: data["b"].to_i,
60+
trace_data: Base64.decode64(data["t"]),
61+
)
62+
end
6263
end
6364
end
6465
end

spec/graphql/tracing/perfetto_sampler/backend_assertions.rb

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,33 +13,45 @@ def self.included(child_class)
1313
trace_id = @backend.save_trace(
1414
"GetStuff",
1515
100.56,
16-
Time.utc(2024, 01, 01, 04, 44, 33, 695),
16+
(Time.utc(2024, 01, 01, 04, 44, 33, 695000).to_f * 1000).round,
1717
data
1818
)
1919

2020
trace = @backend.find_trace(trace_id)
2121
assert_kind_of GraphQL::Tracing::PerfettoSampler::StoredTrace, trace
22+
assert_equal trace_id, trace.id
2223
assert_equal "GetStuff", trace.operation_name
2324
assert_equal 100.56, trace.duration_ms
24-
assert_equal "2024-01-01 04:44:33.000", trace.timestamp.utc.strftime("%Y-%m-%d %H:%M:%S.%L")
25+
assert_equal "2024-01-01 04:44:33.694", Time.at(trace.timestamp / 1000.0).utc.strftime("%Y-%m-%d %H:%M:%S.%L")
2526
assert_equal data, trace.trace_data
2627

2728

2829
@backend.save_trace(
2930
"GetOtherStuff",
3031
200.16,
31-
Time.utc(2024, 01, 03, 04, 44, 33, 695),
32+
(Time.utc(2024, 01, 03, 04, 44, 33, 695000).to_f * 1000).round,
3233
data
3334
)
3435

35-
assert_equal ["GetStuff", "GetOtherStuff"], @backend.traces.map(&:operation_name)
36+
@backend.save_trace(
37+
"GetMoreOtherStuff",
38+
200.16,
39+
(Time.utc(2024, 01, 03, 04, 44, 33, 795000).to_f * 1000).round,
40+
data
41+
)
42+
43+
assert_equal ["GetMoreOtherStuff", "GetOtherStuff", "GetStuff" ], @backend.traces(last: 20, before: nil).map(&:operation_name)
44+
45+
assert_equal ["GetMoreOtherStuff"], @backend.traces(last: 1, before: nil).map(&:operation_name)
46+
assert_equal ["GetOtherStuff", "GetStuff"], @backend.traces(last: 2, before: Time.utc(2024, 01, 03, 04, 44, 33, 795000).to_f * 1000).map(&:operation_name)
47+
3648

3749
@backend.delete_trace(trace_id)
3850

39-
assert_equal ["GetOtherStuff"], @backend.traces.map(&:operation_name)
51+
assert_equal ["GetMoreOtherStuff", "GetOtherStuff"], @backend.traces(last: 20, before: nil).map(&:operation_name)
4052

4153
@backend.delete_all_traces
42-
assert_equal [], @backend.traces
54+
assert_equal [], @backend.traces(last: 20, before: nil)
4355
end
4456

4557
it "returns nil for nonexistent IDs" do

0 commit comments

Comments
 (0)