Skip to content

Commit d8b247b

Browse files
author
Daniel Magliola
committed
WIP: Allow having all metrics in one file, #143
This was a quick experiment on having all metrics for each process on the same file, because it seemed like it would be easy. (just do these things in this commit) However, even though tests pass, this doesn't actually work. See next commit on why. If the change were just this, i'd say we should do this. However, as you'll see in the next commit, it's more involved than that, and i'm not sure it's worth doing, at least not with this approach... I'm just pushing this up so it doesn't get lost.
1 parent af29066 commit d8b247b

File tree

3 files changed

+85
-4
lines changed

3 files changed

+85
-4
lines changed

lib/prometheus/client/data_stores/direct_file_store.rb

+23-4
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ class InvalidStoreSettingsError < StandardError; end
2929
DEFAULT_METRIC_SETTINGS = { aggregation: SUM }
3030
DEFAULT_GAUGE_SETTINGS = { aggregation: ALL }
3131

32-
def initialize(dir:)
33-
@store_settings = { dir: dir }
32+
def initialize(dir:, separate_files_per_metric: true)
33+
@store_settings = { dir: dir,
34+
separate_files_per_metric: separate_files_per_metric }
3435
FileUtils.mkdir_p(dir)
3536
end
3637

@@ -125,6 +126,12 @@ def all_values
125126
[k.to_sym, vs.first]
126127
end.to_h
127128

129+
unless @store_settings[:separate_files_per_metric]
130+
# All metrics are in the same file. Ignore entries for other metrics
131+
next unless label_set[:__metric_name] == metric_name.to_s
132+
label_set.delete(:__metric_name)
133+
end
134+
128135
stores_data[label_set] << v
129136
end
130137
ensure
@@ -149,6 +156,9 @@ def store_key(labels)
149156
if @values_aggregation_mode == ALL
150157
labels[:pid] = process_id
151158
end
159+
unless @store_settings[:separate_files_per_metric]
160+
labels[:__metric_name] = metric_name.to_s
161+
end
152162

153163
labels.map{|k,v| "#{CGI::escape(k.to_s)}=#{CGI::escape(v.to_s)}"}.join('&')
154164
end
@@ -164,12 +174,21 @@ def internal_store
164174

165175
# Filename for this metric's PStore (one per process)
166176
def filemap_filename
167-
filename = "metric_#{ metric_name }___#{ process_id }.bin"
177+
filename = if @store_settings[:separate_files_per_metric]
178+
"metric_#{ metric_name }___#{ process_id }.bin"
179+
else
180+
"metric___all_metrics___#{ process_id }.bin"
181+
end
168182
File.join(@store_settings[:dir], filename)
169183
end
170184

171185
def stores_for_metric
172-
Dir.glob(File.join(@store_settings[:dir], "metric_#{ metric_name }___*"))
186+
base_filename = if @store_settings[:separate_files_per_metric]
187+
"metric_#{ metric_name }___*"
188+
else
189+
"metric___all_metrics___*"
190+
end
191+
Dir.glob(File.join(@store_settings[:dir], base_filename))
173192
end
174193

175194
def process_id

spec/benchmarks/data_stores.rb

+6
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ def all_values; {}; end
8181
{
8282
store: Prometheus::Client::DataStores::DirectFileStore.new(dir: TMP_DIR),
8383
before: -> () { cleanup_dir(TMP_DIR) },
84+
},
85+
{
86+
store: Prometheus::Client::DataStores::DirectFileStore.new(dir: TMP_DIR,
87+
separate_files_per_metric: false),
88+
before: -> () { cleanup_dir(TMP_DIR) },
89+
name: "DirectFileStore Single File"
8490
}
8591
]
8692

spec/prometheus/client/data_stores/direct_file_store_spec.rb

+56
Original file line numberDiff line numberDiff line change
@@ -250,4 +250,60 @@
250250

251251
expect(truncate_calls_count).to be >= 3
252252
end
253+
254+
context "with all metrics in one single file" do
255+
subject { described_class.new(dir: "/tmp/prometheus_test", separate_files_per_metric: false) }
256+
257+
let(:metric_store1) { subject.for_metric(:metric_name, metric_type: :counter) }
258+
let(:metric_store2) { subject.for_metric(:metric_name2, metric_type: :counter) }
259+
260+
it "stores all metrics into one file" do
261+
metric_store1.increment(labels: {a: "x", b: "x"}, by: 1)
262+
metric_store1.increment(labels: {a: "x", b: "zzz"}, by: 2)
263+
metric_store2.increment(labels: {a: "x", b: "x"}, by: 3)
264+
265+
expect(Dir.glob('/tmp/prometheus_test/*').length).to eq(1)
266+
end
267+
268+
it "exports values correctly" do
269+
metric_store1.increment(labels: {a: "x", b: "x"}, by: 1)
270+
metric_store1.increment(labels: {a: "x", b: "zzz"}, by: 2)
271+
metric_store2.increment(labels: {a: "x", b: "x"}, by: 3)
272+
273+
expect(metric_store1.all_values).to eq(
274+
{a: "x", b: "x"} => 1.0,
275+
{a: "x", b: "zzz"} => 2.0,
276+
)
277+
278+
expect(metric_store2.all_values).to eq(
279+
{a: "x", b: "x"} => 3.0,
280+
)
281+
end
282+
283+
it "exports values correctly from multiple processes" do
284+
metric_store1.increment(labels: {a: "x", b: "x"}, by: 1)
285+
metric_store1.increment(labels: {a: "x", b: "zzz"}, by: 2)
286+
metric_store2.increment(labels: {a: "x", b: "x"}, by: 3)
287+
288+
# 2nd process
289+
allow(Process).to receive(:pid).and_return(23456)
290+
metric_store1.increment(labels: {a: "x", b: "x"}, by: 4)
291+
metric_store1.increment(labels: {a: "x", b: "yyy"}, by: 5)
292+
metric_store2.increment(labels: {a: "x", b: "x"}, by: 6)
293+
294+
# Make sure we actually have 2 files to sup together
295+
expect(Dir.glob('/tmp/prometheus_test/metric___all_metrics___*').length).to eq(2)
296+
297+
expect(metric_store1.all_values).to eq(
298+
{a: "x", b: "x"} => 5.0,
299+
{a: "x", b: "zzz"} => 2.0,
300+
{a: "x", b: "yyy"} => 5.0,
301+
)
302+
303+
expect(metric_store2.all_values).to eq(
304+
{a: "x", b: "x"} => 9.0,
305+
)
306+
end
307+
308+
end
253309
end

0 commit comments

Comments
 (0)