prometheus-client-mmap 0.7.0.beta34 → 0.7.0.beta35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +18 -1
- data/ext/fast_mmaped_file/fast_mmaped_file.c +57 -24
- data/ext/fast_mmaped_file/mmap.h +2 -3
- data/lib/fast_mmaped_file.bundle +0 -0
- data/lib/prometheus/client/gauge.rb +4 -0
- data/lib/prometheus/client/helper/entry_parser.rb +14 -8
- data/lib/prometheus/client/helper/mmaped_file.rb +2 -5
- data/lib/prometheus/client/helper/plain_file.rb +1 -0
- data/lib/prometheus/client/mmaped_value.rb +50 -29
- data/lib/prometheus/client/simple_value.rb +1 -1
- data/lib/prometheus/client/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d8a992632af121ceb8b2b8049f293e69822afbce
|
4
|
+
data.tar.gz: 99c14fe2ced8279e6f02e9ca13fef3293bf55090
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 712cdf6271eb5660c4d13852be75a70a9aab6c736a9e8f77588e18ccb0ce82c22001e146273ee2ae4fa95270ea4bd3fe562541b5d25ed9e3bd49033724cc1dea
|
7
|
+
data.tar.gz: f49a4b52b8d5dcc2c629c52ab010dc979d8401c928632d51a0d82f211fadd9870503c9e4a7aa5cea5d6aab93fad76d6fa934eba76eb6f5d6b2072809be656444
|
data/README.md
CHANGED
@@ -10,7 +10,7 @@ through a HTTP interface. Intended to be used together with a
|
|
10
10
|
|
11
11
|
[![Gem Version][4]](http://badge.fury.io/rb/prometheus-client-mmap)
|
12
12
|
[![Build Status][3]](https://gitlab.com/gitlab-org/prometheus-client-mmap/commits/master)
|
13
|
-
[![Dependency Status][5]](https://gemnasium.com/prometheus/
|
13
|
+
[![Dependency Status][5]](https://gemnasium.com/prometheus/prometheus-client-mmap)
|
14
14
|
|
15
15
|
## Usage
|
16
16
|
|
@@ -185,6 +185,23 @@ To use it add this line to your `configure` block:
|
|
185
185
|
config.pid_provider = Prometheus::Client::Support::Unicorn.method(:worker_pid_provider)
|
186
186
|
```
|
187
187
|
|
188
|
+
## Tools
|
189
|
+
|
190
|
+
###`bin/parse`
|
191
|
+
|
192
|
+
This command can be used to parse metric files located on the filesystem just like a metric exporter would.
|
193
|
+
It outputs either `json` formatted raw data or digested data in prometheus `text` format.
|
194
|
+
|
195
|
+
#### Usage:
|
196
|
+
|
197
|
+
```bash
|
198
|
+
$ ./bin/parse -h
|
199
|
+
Usage: parse [options] files...
|
200
|
+
-t, --to-prometheus-text format output using Prometheus text formatter
|
201
|
+
-p, --profile enable profiling
|
202
|
+
-h, --help Show this message
|
203
|
+
```
|
204
|
+
|
188
205
|
## Tests
|
189
206
|
|
190
207
|
Install necessary development gems with `bundle install` and run tests with
|
@@ -12,33 +12,48 @@ VALUE MMAPED_FILE = Qnil;
|
|
12
12
|
#define START_POSITION 8
|
13
13
|
#define INITIAL_SIZE (2 * sizeof(int32_t))
|
14
14
|
|
15
|
-
|
15
|
+
int open_and_extend_file(mm_ipc *i_mm, size_t len) {
|
16
16
|
int fd;
|
17
|
-
|
18
|
-
rb_raise(rb_eArgError, "munmap failed");
|
19
|
-
}
|
17
|
+
|
20
18
|
if ((fd = open(i_mm->t->path, i_mm->t->smode)) == -1) {
|
21
19
|
rb_raise(rb_eArgError, "Can't open %s", i_mm->t->path);
|
22
20
|
}
|
23
21
|
|
24
|
-
if (len < i_mm->t->len) {
|
25
|
-
rb_raise(rb_eArgError, "Can't reduce the size of mmap");
|
26
|
-
}
|
27
|
-
|
28
22
|
if (lseek(fd, len - i_mm->t->len - 1, SEEK_END) == -1) {
|
23
|
+
close(fd);
|
29
24
|
rb_raise(rb_eIOError, "Can't lseek %lu", len - i_mm->t->len - 1);
|
30
25
|
}
|
26
|
+
|
31
27
|
if (write(fd, "\000", 1) != 1) {
|
28
|
+
close(fd);
|
32
29
|
rb_raise(rb_eIOError, "Can't extend %s", i_mm->t->path);
|
33
30
|
}
|
34
31
|
|
32
|
+
return fd;
|
33
|
+
}
|
34
|
+
|
35
|
+
void expand(mm_ipc *i_mm, size_t len) {
|
36
|
+
if (len < i_mm->t->len) {
|
37
|
+
rb_raise(rb_eArgError, "Can't reduce the size of mmap");
|
38
|
+
}
|
39
|
+
|
40
|
+
if (munmap(i_mm->t->addr, i_mm->t->len)) {
|
41
|
+
rb_raise(rb_eArgError, "munmap failed");
|
42
|
+
}
|
43
|
+
|
44
|
+
int fd = open_and_extend_file(i_mm, len);
|
45
|
+
|
35
46
|
i_mm->t->addr = mmap(0, len, i_mm->t->pmode, i_mm->t->vscope, fd, i_mm->t->offset);
|
36
|
-
close(fd);
|
37
47
|
|
38
48
|
if (i_mm->t->addr == MAP_FAILED) {
|
49
|
+
close(fd);
|
39
50
|
rb_raise(rb_eArgError, "mmap failed");
|
40
51
|
}
|
41
52
|
|
53
|
+
if (close(fd) == -1){
|
54
|
+
rb_raise(rb_eArgError, "Can't close %s", i_mm->t->path);
|
55
|
+
}
|
56
|
+
|
42
57
|
if ((i_mm->t->flag & MM_LOCK) && mlock(i_mm->t->addr, len) == -1) {
|
43
58
|
rb_raise(rb_eArgError, "mlock(%d)", errno);
|
44
59
|
}
|
@@ -46,8 +61,8 @@ void expand(mm_ipc *i_mm, size_t len){
|
|
46
61
|
i_mm->t->real = len;
|
47
62
|
}
|
48
63
|
|
49
|
-
inline uint32_t padding_length(uint32_t key_length){
|
50
|
-
return 8 - (
|
64
|
+
inline uint32_t padding_length(uint32_t key_length) {
|
65
|
+
return 8 - (sizeof(uint32_t) + key_length) % 8; // padding | 8 byte aligned
|
51
66
|
}
|
52
67
|
|
53
68
|
void save_entry(mm_ipc *i_mm, uint32_t offset, VALUE key, VALUE value){
|
@@ -68,9 +83,8 @@ void save_entry(mm_ipc *i_mm, uint32_t offset, VALUE key, VALUE value){
|
|
68
83
|
memcpy(pos, &val, sizeof(double));
|
69
84
|
}
|
70
85
|
|
71
|
-
inline uint32_t load_used(mm_ipc *i_mm){
|
72
|
-
uint32_t used =
|
73
|
-
memcpy(&used, (char *)i_mm->t->addr, sizeof(uint32_t));
|
86
|
+
inline uint32_t load_used(mm_ipc *i_mm) {
|
87
|
+
uint32_t used = *((uint32_t *)i_mm->t->addr);
|
74
88
|
|
75
89
|
if (used == 0){
|
76
90
|
used = START_POSITION;
|
@@ -78,8 +92,29 @@ inline uint32_t load_used(mm_ipc *i_mm){
|
|
78
92
|
return used;
|
79
93
|
}
|
80
94
|
|
81
|
-
inline void save_used(mm_ipc *i_mm, uint32_t used){
|
82
|
-
|
95
|
+
inline void save_used(mm_ipc *i_mm, uint32_t used) {
|
96
|
+
*((uint32_t *)i_mm->t->addr) = used;
|
97
|
+
}
|
98
|
+
|
99
|
+
VALUE method_load_used(VALUE self) {
|
100
|
+
mm_ipc *i_mm;
|
101
|
+
|
102
|
+
GET_MMAP(self, i_mm, MM_MODIFY);
|
103
|
+
return UINT2NUM(load_used(i_mm));
|
104
|
+
}
|
105
|
+
|
106
|
+
VALUE method_save_used(VALUE self, VALUE value) {
|
107
|
+
Check_Type(value, T_FIXNUM);
|
108
|
+
mm_ipc *i_mm;
|
109
|
+
|
110
|
+
GET_MMAP(self, i_mm, MM_MODIFY);
|
111
|
+
|
112
|
+
if (i_mm->t->len < INITIAL_SIZE) {
|
113
|
+
expand(i_mm, INITIAL_SIZE);
|
114
|
+
}
|
115
|
+
|
116
|
+
save_used(i_mm, NUM2UINT(value));
|
117
|
+
return value;
|
83
118
|
}
|
84
119
|
|
85
120
|
VALUE method_add_entry(VALUE self, VALUE positions, VALUE key, VALUE value) {
|
@@ -92,17 +127,13 @@ VALUE method_add_entry(VALUE self, VALUE positions, VALUE key, VALUE value) {
|
|
92
127
|
}
|
93
128
|
|
94
129
|
mm_ipc *i_mm;
|
95
|
-
|
96
|
-
|
97
|
-
if ((i_mm->t->len) < INITIAL_SIZE) {
|
98
|
-
expand(i_mm, INITIAL_SIZE);
|
99
|
-
}
|
130
|
+
GET_MMAP(self, i_mm, MM_MODIFY);
|
100
131
|
|
101
|
-
if (i_mm->t->flag & MM_FROZEN){
|
132
|
+
if (i_mm->t->flag & MM_FROZEN) {
|
102
133
|
rb_error_frozen("mmap");
|
103
134
|
}
|
104
135
|
|
105
|
-
if (RSTRING_LEN(key) > UINT32_MAX){
|
136
|
+
if (RSTRING_LEN(key) > UINT32_MAX) {
|
106
137
|
rb_raise(rb_eArgError, "string length gt %u", UINT32_MAX);
|
107
138
|
}
|
108
139
|
|
@@ -122,7 +153,7 @@ VALUE method_add_entry(VALUE self, VALUE positions, VALUE key, VALUE value) {
|
|
122
153
|
|
123
154
|
VALUE method_get_double(VALUE self, VALUE index) {
|
124
155
|
mm_ipc *i_mm;
|
125
|
-
|
156
|
+
GET_MMAP(self, i_mm, MM_MODIFY);
|
126
157
|
|
127
158
|
Check_Type(index, T_FIXNUM);
|
128
159
|
size_t idx = NUM2UINT(index);
|
@@ -140,5 +171,7 @@ VALUE method_get_double(VALUE self, VALUE index) {
|
|
140
171
|
void Init_fast_mmaped_file() {
|
141
172
|
MMAPED_FILE = rb_define_module("FastMmapedFile");
|
142
173
|
rb_define_method(MMAPED_FILE, "get_double", method_get_double, 1);
|
174
|
+
rb_define_method(MMAPED_FILE, "used", method_load_used, 0);
|
175
|
+
rb_define_method(MMAPED_FILE, "used=", method_save_used, 1);
|
143
176
|
rb_define_method(MMAPED_FILE, "add_entry", method_add_entry, 3);
|
144
177
|
}
|
data/ext/fast_mmaped_file/mmap.h
CHANGED
@@ -45,7 +45,7 @@ typedef struct {
|
|
45
45
|
} mm_ipc;
|
46
46
|
|
47
47
|
|
48
|
-
#define
|
48
|
+
#define GET_MMAP(obj, i_mm, t_modify) \
|
49
49
|
Data_Get_Struct(obj, mm_ipc, i_mm); \
|
50
50
|
if (!i_mm->t->path) { \
|
51
51
|
rb_raise(rb_eIOError, "unmapped file"); \
|
@@ -54,5 +54,4 @@ typedef struct {
|
|
54
54
|
rb_error_frozen("mmap"); \
|
55
55
|
}
|
56
56
|
|
57
|
-
|
58
|
-
#endif
|
57
|
+
#endif
|
data/lib/fast_mmaped_file.bundle
CHANGED
Binary file
|
@@ -6,8 +6,11 @@ module Prometheus
|
|
6
6
|
module EntryParser
|
7
7
|
class ParsingError < RuntimeError;
|
8
8
|
end
|
9
|
+
|
9
10
|
MINIMUM_SIZE = 8
|
10
11
|
START_POSITION = 8
|
12
|
+
VALUE_BYTES = 8
|
13
|
+
ENCODED_LENGTH_BYTES = 4
|
11
14
|
|
12
15
|
def used
|
13
16
|
slice(0..3).unpack('l')[0]
|
@@ -57,16 +60,18 @@ module Prometheus
|
|
57
60
|
next
|
58
61
|
end
|
59
62
|
|
60
|
-
|
61
|
-
|
63
|
+
entry_len = ENCODED_LENGTH_BYTES + encoded_len
|
64
|
+
padding_len = 8 - entry_len % 8
|
65
|
+
|
66
|
+
value_offset = entry_len + padding_len # align to 8 bytes
|
62
67
|
pos += value_offset
|
63
68
|
|
64
|
-
if value_offset > 0 && (pos +
|
69
|
+
if value_offset > 0 && (pos + VALUE_BYTES) < size # if positions are safe
|
65
70
|
yielder.yield data, encoded_len, value_offset, pos
|
66
71
|
else
|
67
72
|
raise ParsingError, "data slice is nil at pos #{pos}" unless ignore_errors
|
68
73
|
end
|
69
|
-
pos +=
|
74
|
+
pos += VALUE_BYTES
|
70
75
|
end
|
71
76
|
end
|
72
77
|
end
|
@@ -82,7 +87,7 @@ module Prometheus
|
|
82
87
|
end
|
83
88
|
end
|
84
89
|
|
85
|
-
|
90
|
+
metrics.reject!(&:nil?) if ignore_errors
|
86
91
|
result
|
87
92
|
end
|
88
93
|
|
@@ -90,8 +95,9 @@ module Prometheus
|
|
90
95
|
parsed_entries(ignore_errors).each do |key, value|
|
91
96
|
begin
|
92
97
|
metric_name, name, labelnames, labelvalues = JsonParser.load(key)
|
93
|
-
labelnames
|
94
|
-
labelvalues
|
98
|
+
labelnames ||= []
|
99
|
+
labelvalues ||= []
|
100
|
+
|
95
101
|
metric = metrics.fetch(metric_name,
|
96
102
|
metric_name: metric_name,
|
97
103
|
help: 'Multiprocess metric',
|
@@ -111,7 +117,7 @@ module Prometheus
|
|
111
117
|
end
|
112
118
|
end
|
113
119
|
|
114
|
-
metrics.reject
|
120
|
+
metrics.reject!(&:nil?) if ignore_errors
|
115
121
|
metrics
|
116
122
|
end
|
117
123
|
|
@@ -7,8 +7,9 @@ module Prometheus
|
|
7
7
|
module Client
|
8
8
|
module Helper
|
9
9
|
class MmapedFile < Mmap
|
10
|
-
include FastMmapedFile
|
11
10
|
include EntryParser
|
11
|
+
include FastMmapedFile
|
12
|
+
|
12
13
|
attr_reader :filepath, :size
|
13
14
|
|
14
15
|
def initialize(filepath, mode = 'r', protection = Mmap::MAP_SHARED, options = {})
|
@@ -22,10 +23,6 @@ module Prometheus
|
|
22
23
|
super(filepath, mode, protection, options)
|
23
24
|
end
|
24
25
|
|
25
|
-
def used=(value)
|
26
|
-
self[0..3] = [value].pack('l')
|
27
|
-
end
|
28
|
-
|
29
26
|
def close
|
30
27
|
munmap
|
31
28
|
end
|
@@ -6,8 +6,9 @@ module Prometheus
|
|
6
6
|
module Client
|
7
7
|
# A float protected by a mutex backed by a per-process mmaped file.
|
8
8
|
class MmapedValue
|
9
|
-
@@files = {}
|
10
9
|
VALUE_LOCK = Mutex.new
|
10
|
+
|
11
|
+
@@files = {}
|
11
12
|
@@pid = -1
|
12
13
|
|
13
14
|
def initialize(type, metric_name, name, labels, multiprocess_mode = '')
|
@@ -25,7 +26,7 @@ module Prometheus
|
|
25
26
|
initialize_file
|
26
27
|
end
|
27
28
|
|
28
|
-
def increment(amount=1)
|
29
|
+
def increment(amount = 1)
|
29
30
|
@mutex.synchronize do
|
30
31
|
initialize_file if pid_changed?
|
31
32
|
|
@@ -56,35 +57,19 @@ module Prometheus
|
|
56
57
|
@pid != Process.pid
|
57
58
|
end
|
58
59
|
|
59
|
-
|
60
|
-
|
60
|
+
# method needs to be run in VALUE_LOCK mutex
|
61
|
+
def unsafe_reinitialize_file(check_pid = true)
|
62
|
+
unsafe_initialize_file if !check_pid || pid_changed?
|
61
63
|
end
|
62
64
|
|
63
|
-
def
|
65
|
+
def self.reset_and_reinitialize
|
64
66
|
VALUE_LOCK.synchronize do
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
@pid = Process.pid
|
69
|
-
unless @@files.has_key?(@file_prefix)
|
70
|
-
unless @file.nil?
|
71
|
-
@file.close
|
72
|
-
end
|
73
|
-
mmaped_file = Helper::MmapedFile.open_exclusive_file(@file_prefix)
|
74
|
-
|
75
|
-
@@files[@file_prefix] = MmapedDict.new(mmaped_file)
|
76
|
-
end
|
67
|
+
@@pid = Process.pid
|
68
|
+
@@files = {}
|
77
69
|
|
78
|
-
|
79
|
-
|
80
|
-
labelvalues = []
|
81
|
-
@labels.each do |k, v|
|
82
|
-
labelnames << k
|
83
|
-
labelvalues << v
|
70
|
+
ObjectSpace.each_object(MmapedValue).each do |v|
|
71
|
+
v.unsafe_reinitialize_file(false)
|
84
72
|
end
|
85
|
-
|
86
|
-
@key = [@metric_name, @name, labelnames, labelvalues].to_json
|
87
|
-
@value = read_value(@key)
|
88
73
|
end
|
89
74
|
end
|
90
75
|
|
@@ -98,9 +83,9 @@ module Prometheus
|
|
98
83
|
def self.reinitialize_on_pid_change
|
99
84
|
VALUE_LOCK.synchronize do
|
100
85
|
reset_on_pid_change
|
101
|
-
end
|
102
86
|
|
103
|
-
|
87
|
+
ObjectSpace.each_object(MmapedValue, &:unsafe_reinitialize_file)
|
88
|
+
end
|
104
89
|
end
|
105
90
|
|
106
91
|
def self.pid_changed?
|
@@ -113,9 +98,45 @@ module Prometheus
|
|
113
98
|
|
114
99
|
private
|
115
100
|
|
101
|
+
def initialize_file
|
102
|
+
VALUE_LOCK.synchronize do
|
103
|
+
unsafe_initialize_file
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def unsafe_initialize_file
|
108
|
+
self.class.reset_on_pid_change
|
109
|
+
|
110
|
+
@pid = Process.pid
|
111
|
+
unless @@files.has_key?(@file_prefix)
|
112
|
+
unless @file.nil?
|
113
|
+
@file.close
|
114
|
+
end
|
115
|
+
mmaped_file = Helper::MmapedFile.open_exclusive_file(@file_prefix)
|
116
|
+
|
117
|
+
@@files[@file_prefix] = MmapedDict.new(mmaped_file)
|
118
|
+
end
|
119
|
+
|
120
|
+
@file = @@files[@file_prefix]
|
121
|
+
@key = rebuild_key
|
122
|
+
|
123
|
+
@value = read_value(@key)
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
def rebuild_key
|
128
|
+
labelnames = []
|
129
|
+
labelvalues = []
|
130
|
+
@labels.each do |k, v|
|
131
|
+
labelnames << k
|
132
|
+
labelvalues << v
|
133
|
+
end
|
134
|
+
|
135
|
+
[@metric_name, @name, labelnames, labelvalues].to_json
|
136
|
+
end
|
137
|
+
|
116
138
|
def write_value(key, val)
|
117
139
|
@file.write_value(key, val)
|
118
|
-
|
119
140
|
rescue StandardError => e
|
120
141
|
Prometheus::Client.logger.warn("writing value to #{@file.path} failed with #{e}")
|
121
142
|
Prometheus::Client.logger.debug(e.backtrace.join("\n"))
|