prometheus_enumerated_store 0.0.1.183933
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +19 -0
- data/README.md +97 -0
- data/lib/prometheus/enumerated-store.rb +1 -0
- data/lib/prometheus/enumerated_store/pid_enumerator.rb +95 -0
- data/lib/prometheus/enumerated_store/store.rb +35 -0
- data/lib/prometheus/enumerated_store/version.rb +8 -0
- data/lib/prometheus/enumerated_store.rb +11 -0
- data/lib/prometheus-enumerated-store.rb +1 -0
- data/lib/prometheus_enumerated_store.rb +5 -0
- metadata +156 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 514c84eb0f23127b7ecf237e33f32a5e4b33c7b63437feecde65e44bf4a085ec
|
4
|
+
data.tar.gz: 1ae0fc91c573feb22cdfe1110f176ddd408ed7feed9ec9aed8cf9115a67bfe4e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a6093fada7f4b37ba58bc68ce5a92a9a87437c9c6249dfb8c2e16431db13f7aa755aa992a7dd917acd7177ee462175367b3248f6fe7db5cb7bec4f63ac20f5b9
|
7
|
+
data.tar.gz: abefba09ff32857c324cf36953cce55c72a71a91cdcb6d435b2d0fc47673bdd17dd2dede0e213a84e1d8be9b2cc66ac3f5e17c39ac4fe1c1d6ad37f6465fcb6d
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2014-2023 Рнд Софт
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
# Enumerated File Store
|
2
|
+
|
3
|
+
<div align="center">
|
4
|
+
|
5
|
+
[![Gem Version](https://badge.fury.io/rb/prometheus_enumerated_store.svg)](https://rubygems.org/gems/prometheus_enumerated_store)
|
6
|
+
[![Gem](https://img.shields.io/gem/dt/prometheus_enumerated_store.svg)](https://rubygems.org/gems/prometheus_enumerated_store/versions)
|
7
|
+
[![YARD](https://badgen.net/badge/YARD/doc/blue)](http://www.rubydoc.info/gems/prometheus_enumerated_store)
|
8
|
+
|
9
|
+
|
10
|
+
[![coverage](https://lysander.rnds.pro/api/v1/badges/enumerated_coverage.svg)](https://lysander.rnds.pro/api/v1/badges/enumerated_coverage.html)
|
11
|
+
[![quality](https://lysander.rnds.pro/api/v1/badges/enumerated_quality.svg)](https://lysander.rnds.pro/api/v1/badges/enumerated_quality.html)
|
12
|
+
[![outdated](https://lysander.rnds.pro/api/v1/badges/enumerated_outdated.svg)](https://lysander.rnds.pro/api/v1/badges/enumerated_outdated.html)
|
13
|
+
[![vulnerable](https://lysander.rnds.pro/api/v1/badges/enumerated_vulnerable.svg)](https://lysander.rnds.pro/api/v1/badges/enumerated_vulnerable.html)
|
14
|
+
|
15
|
+
</div>
|
16
|
+
|
17
|
+
`Enumerated File Store` - это гем для реализации [специального Data Store](https://github.com/prometheus/client_ruby#data-stores) для библиотеки [prometheus-client](https://github.com/prometheus/client_ruby).
|
18
|
+
|
19
|
+
Данная библиотека решает [проблему огромного числа файлов-метрик](https://github.com/prometheus/client_ruby/issues/143) при использовании стандартного [DirectFileStore](https://github.com/prometheus/client_ruby#directfilestore-caveats-and-things-to-keep-in-mind)
|
20
|
+
|
21
|
+
---
|
22
|
+
|
23
|
+
`Enumerated File Store` provides [custom Data Store](https://github.com/prometheus/client_ruby#data-stores) for [prometheus-client](https://github.com/prometheus/client_ruby) library.
|
24
|
+
|
25
|
+
It fixes issue with [too many files for long running applications](https://github.com/prometheus/client_ruby/issues/143) when using [DirectFileStore](https://github.com/prometheus/client_ruby#directfilestore-caveats-and-things-to-keep-in-mind).
|
26
|
+
|
27
|
+
<div align="left">
|
28
|
+
<a href="https://rnds.pro/" >
|
29
|
+
<img src="https://library.rnds.pro/repository/public-blob/logo/RNDS.svg" alt="Supported by RNDSOFT" height="60">
|
30
|
+
</a>
|
31
|
+
</div>
|
32
|
+
|
33
|
+
## Возможности / Features
|
34
|
+
|
35
|
+
Библиоетка использует последовательное присвоение номеров файлам метри вместо использования PID / It uses sequential numbering for metric filenames instead of PID-stamps.
|
36
|
+
|
37
|
+
|
38
|
+
## Начало работы / Getting started
|
39
|
+
|
40
|
+
```sh
|
41
|
+
gem install prometheus-enumerated-store
|
42
|
+
```
|
43
|
+
|
44
|
+
При установке `prometheus_enumerated_store` через bundler добавьте следующую строку в `Gemfile`:
|
45
|
+
|
46
|
+
---
|
47
|
+
|
48
|
+
If you'd rather install `prometheus_enumerated_store` using bundler, add a line for it in your `Gemfile`:
|
49
|
+
|
50
|
+
```sh
|
51
|
+
gem 'prometheus_enumerated_store'
|
52
|
+
```
|
53
|
+
|
54
|
+
Затем выполните / Then run:
|
55
|
+
|
56
|
+
```sh
|
57
|
+
bundle install # для установки гема / gem installation
|
58
|
+
|
59
|
+
```
|
60
|
+
## Использование / Usage
|
61
|
+
|
62
|
+
Для использования необходимо в каком-нибудь файле `config/initializers/` настройить `Data Store` для библиотеки `prometheus-client`:
|
63
|
+
|
64
|
+
---
|
65
|
+
|
66
|
+
Now you need to set `Data Store` for `prometheus-client` gem somewhere in `config/initializers/`:
|
67
|
+
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
Prometheus::Client.config.data_store = Prometheus::Enumerated::Store.new(dir: Rails.root.join('tmp', 'prometheus_metrics'))
|
71
|
+
|
72
|
+
if defined?(PhusionPassenger)
|
73
|
+
PhusionPassenger.on_event(:starting_worker_process) do |_forked|
|
74
|
+
Prometheus::Client.config.data_store.reset
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
# Or somewhere in Pum config if any:
|
80
|
+
|
81
|
+
on_restart do
|
82
|
+
Prometheus::Client.config.data_store.reset
|
83
|
+
end
|
84
|
+
|
85
|
+
on_worker_boot do
|
86
|
+
Prometheus::Client.config.data_store.reset
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+
## Лицензия / License
|
91
|
+
|
92
|
+
Библиотека доступна с открытым исходным кодом в соответствии с условиями [лицензии MIT](./LICENSE).
|
93
|
+
|
94
|
+
---
|
95
|
+
|
96
|
+
The gem is available as open source under the terms of the [MIT License](./LICENSE).
|
97
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'enumerated_store'
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Prometheus
|
2
|
+
# Класс мапит текущий PID на минимальный "свободный" номер
|
3
|
+
# "свободность" определяется по принципу процесс с пидом есть? - значит занято
|
4
|
+
# реестр хранится в файле в виде {"22655":1,"22760":2,"22813":3,"22832":4}
|
5
|
+
# где слева PID, справа занятый им (когда-то) номер
|
6
|
+
# Информация актуализируется (удаляются несуществующие записи) при очередном выделении
|
7
|
+
# многопроцессность синхронизируется через механизм эксключзивных блокировок flock
|
8
|
+
module EnumeratedStore
|
9
|
+
class PidEnumerator
|
10
|
+
|
11
|
+
MAX_INSTANCES = 1000
|
12
|
+
|
13
|
+
attr_reader :dir, :instances_path, :lock_path
|
14
|
+
|
15
|
+
def initialize(dir:)
|
16
|
+
@dir = dir
|
17
|
+
|
18
|
+
@lock_path = File.join(@dir, 'enumetated_instances.lock')
|
19
|
+
@instances_path = File.join(@dir, 'enumetated_instances.json')
|
20
|
+
reset
|
21
|
+
end
|
22
|
+
|
23
|
+
def reset
|
24
|
+
@obtained = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def with_lock
|
28
|
+
File.open(lock_path, File::RDWR | File::CREAT, 0o644) do |file|
|
29
|
+
file.flock(File::LOCK_EX)
|
30
|
+
Dir.chdir(@dir) do
|
31
|
+
tmpfilename = ".tmp-#{$$}-#{rand(0x100000000).to_s(36)}.json"
|
32
|
+
yield(tmpfilename)
|
33
|
+
ensure
|
34
|
+
File.delete(tmpfilename) rescue nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def read_instances
|
40
|
+
raw = File.read(instances_path).strip
|
41
|
+
raw.empty? ? '{}' : raw
|
42
|
+
rescue Errno::ENOENT
|
43
|
+
# there is no file yet
|
44
|
+
'{}'
|
45
|
+
end
|
46
|
+
|
47
|
+
def obtained
|
48
|
+
@obtained ||= obtain_enumerated_number
|
49
|
+
end
|
50
|
+
|
51
|
+
def obtain_enumerated_number
|
52
|
+
with_lock do |tmpfilename|
|
53
|
+
break @obtained if @obtained # double check-lock
|
54
|
+
|
55
|
+
raw_data = read_instances
|
56
|
+
data = JSON.parse(raw_data) || {} # set {} if "null" in file
|
57
|
+
data = clean_dead_instances(data)
|
58
|
+
|
59
|
+
current = find_minimal_number(data)
|
60
|
+
File.write(tmpfilename, data.to_json) # We are inside tmpdir
|
61
|
+
File.rename(tmpfilename, instances_path)
|
62
|
+
current
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def find_minimal_number(data)
|
67
|
+
values = data.values
|
68
|
+
current = data[Process.pid.to_s] || (1..MAX_INSTANCES).find{|i| !values.include?(i) }
|
69
|
+
raise "Unable to find any number between 1 and #{MAX_INSTANCES}" unless current
|
70
|
+
|
71
|
+
data[Process.pid.to_s] = current
|
72
|
+
end
|
73
|
+
|
74
|
+
def clean_dead_instances(data)
|
75
|
+
data.select do |pid, num|
|
76
|
+
next nil if num.to_i <= 0 || num.to_i > MAX_INSTANCES
|
77
|
+
|
78
|
+
alive?(pid.to_i)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def alive?(pid)
|
83
|
+
return nil if pid <= 1
|
84
|
+
|
85
|
+
Process.getpgid(pid)
|
86
|
+
true
|
87
|
+
rescue Errno::ESRCH
|
88
|
+
false
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'prometheus/client/data_stores/direct_file_store'
|
2
|
+
|
3
|
+
module Prometheus
|
4
|
+
module EnumeratedStore
|
5
|
+
class Store < Prometheus::Client::DataStores::DirectFileStore
|
6
|
+
|
7
|
+
attr_reader :pid_enumerator
|
8
|
+
|
9
|
+
def initialize(*_args, dir:, **_kwargs)
|
10
|
+
super
|
11
|
+
@pid_enumerator = PidEnumerator.new(dir: dir)
|
12
|
+
# pass enumerator through store_settings to every MetricStore
|
13
|
+
@store_settings[:pid_enumerator] = @pid_enumerator
|
14
|
+
end
|
15
|
+
|
16
|
+
def reset
|
17
|
+
@pid_enumerator.reset
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.metric_store_class
|
21
|
+
MetricStore
|
22
|
+
end
|
23
|
+
|
24
|
+
MetricStore.class_eval do
|
25
|
+
# Monkeypatch! there is no normal method to overload filename generation
|
26
|
+
# https://github.com/prometheus/client_ruby/blob/e144d6225d3c346e9a4dd0a11f41f8acde386dd8/lib/prometheus/client/data_stores/direct_file_store.rb#L190
|
27
|
+
def process_id
|
28
|
+
@store_settings[:pid_enumerator].obtained
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'prometheus_enumerated_store'
|
metadata
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: prometheus_enumerated_store
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1.183933
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Samoilenko Yuri
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-09-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: prometheus-client
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 2.0.1
|
37
|
+
type: :development
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - "~>"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '2.0'
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 2.0.1
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rake
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: rspec
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: rspec_junit_formatter
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: simplecov
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: simplecov-console
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
description: Enchanced File Store for ruby Prometheus library
|
118
|
+
email:
|
119
|
+
- kinnalru@gmail.com
|
120
|
+
executables: []
|
121
|
+
extensions: []
|
122
|
+
extra_rdoc_files: []
|
123
|
+
files:
|
124
|
+
- LICENSE
|
125
|
+
- README.md
|
126
|
+
- lib/prometheus-enumerated-store.rb
|
127
|
+
- lib/prometheus/enumerated-store.rb
|
128
|
+
- lib/prometheus/enumerated_store.rb
|
129
|
+
- lib/prometheus/enumerated_store/pid_enumerator.rb
|
130
|
+
- lib/prometheus/enumerated_store/store.rb
|
131
|
+
- lib/prometheus/enumerated_store/version.rb
|
132
|
+
- lib/prometheus_enumerated_store.rb
|
133
|
+
homepage: https://github.com/RnD-Soft/prometheus_enumerated_store
|
134
|
+
licenses:
|
135
|
+
- MIT
|
136
|
+
metadata: {}
|
137
|
+
post_install_message:
|
138
|
+
rdoc_options: []
|
139
|
+
require_paths:
|
140
|
+
- lib
|
141
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
147
|
+
requirements:
|
148
|
+
- - ">="
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '0'
|
151
|
+
requirements: []
|
152
|
+
rubygems_version: 3.4.10
|
153
|
+
signing_key:
|
154
|
+
specification_version: 4
|
155
|
+
summary: Enchanced File Store for ruby Prometheus library
|
156
|
+
test_files: []
|