prometheus-client-mmap 0.9.10 → 0.13.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ea7b6fe48f2d5019181dcc236a5a8d187ea5aeb7e7d8e2acc8d31bfb6bc62207
4
- data.tar.gz: 6231f6c5e44fc07b7084d4f9e816c9eb97916bb00235829349b9903af4c9621b
3
+ metadata.gz: 77dda8e211c5981651a160500f0332b886e124935e969136abe4fd234ae311e1
4
+ data.tar.gz: 4ba3176b93611a3bcf63b0aed029408a5f22f33ca16635d05c9c244e33b0bfaa
5
5
  SHA512:
6
- metadata.gz: 48cc3fa10e0879d90340349ccc118dbd4b3eca40ee8e513f5600f58354f089c4ac7e8598ede6a696b24aafca51f75baeb8e2f4b1967a42b32dcacb2d408c83bb
7
- data.tar.gz: 2a01473c292535c2931efdbb1b5e958389d71521cb55f25edddef6f097eddec7d5cac08e0e4bab3b85ee5757626f67930312fefce99f24d7184541a1ab07b559
6
+ metadata.gz: 75cbb10eed65af805c4cccda2e91783ec0ce0987150881ecc763d8de07ea3af150eb20bc41fbaf414dc66d4341141d163cf83514f7f4c913aaf1fdb0efc99dad
7
+ data.tar.gz: d4b2e4e7a3a78a315cb490a5d07125eaeb2782c6e7c0cb1cbfa0ff302d44ca343b752a29912d3f46b2acc7a6999d84ffe5ee3903d2004a501c2d4dac62f93846
@@ -1,20 +1,17 @@
1
1
  #include <errno.h>
2
+ #include <hashmap.h>
3
+ #include <jsmn.h>
2
4
  #include <ruby.h>
3
5
  #include <ruby/intern.h>
4
-
5
6
  #include <sys/mman.h>
6
7
 
7
- #include <hashmap.h>
8
- #include <jsmn.h>
9
-
10
- #include "globals.h"
11
- #include "utils.h"
12
- #include "value_access.h"
13
-
14
8
  #include "file_parsing.h"
15
9
  #include "file_reading.h"
10
+ #include "globals.h"
16
11
  #include "mmap.h"
17
12
  #include "rendering.h"
13
+ #include "utils.h"
14
+ #include "value_access.h"
18
15
 
19
16
  VALUE MMAPED_FILE = Qnil;
20
17
 
@@ -1,9 +1,9 @@
1
+ #include "file_parsing.h"
2
+
1
3
  #include <hashmap.h>
2
4
  #include <jsmn.h>
3
- #include <ruby.h>
4
5
 
5
6
  #include "file_format.h"
6
- #include "file_parsing.h"
7
7
  #include "globals.h"
8
8
  #include "utils.h"
9
9
 
@@ -2,6 +2,7 @@
2
2
  #define FILE_PARSING_H
3
3
  #include <file_reading.h>
4
4
  #include <hashmap.h>
5
+ #include <ruby.h>
5
6
 
6
7
  typedef struct {
7
8
  char *json;
@@ -1,8 +1,8 @@
1
+ #include "file_reading.h"
2
+
1
3
  #include <errno.h>
2
4
  #include <fcntl.h>
3
- #include <ruby.h>
4
5
 
5
- #include "file_reading.h"
6
6
  #include "utils.h"
7
7
 
8
8
  static int file_open(file_t *source, const char *filepath) {
@@ -1,11 +1,11 @@
1
+ #include "mmap.h"
2
+
1
3
  #include <errno.h>
2
4
  #include <fcntl.h>
3
- #include <ruby.h>
4
5
  #include <ruby/util.h>
5
6
  #include <sys/mman.h>
6
7
 
7
8
  #include "file_format.h"
8
- #include "mmap.h"
9
9
  #include "utils.h"
10
10
 
11
11
  #if 0
@@ -42,7 +42,6 @@ static VALUE mm_str(VALUE obj, int modify) {
42
42
  GET_MMAP(obj, i_mm, modify & ~MM_ORIGIN);
43
43
  if (modify & MM_MODIFY) {
44
44
  if (i_mm->t->flag & MM_FROZEN) rb_error_frozen("mmap");
45
- if (!OBJ_TAINTED(ret) && rb_safe_level() >= 4) rb_raise(rb_eSecurityError, "Insecure: can't modify mmap");
46
45
  }
47
46
  ret = rb_obj_alloc(rb_cString);
48
47
  if (rb_obj_tainted(obj)) {
@@ -170,6 +169,35 @@ VALUE mm_s_alloc(VALUE obj) {
170
169
  return res;
171
170
  }
172
171
 
172
+ size_t next_page_boundary(size_t value) {
173
+ size_t page_size = sysconf(_SC_PAGESIZE);
174
+
175
+ while (page_size < value) {
176
+ page_size *= 2;
177
+ }
178
+
179
+ return page_size;
180
+ }
181
+
182
+ /* Reference implementations:
183
+ * mozilla: https://hg.mozilla.org/mozilla-central/file/3d846420a907/xpcom/glue/FileUtils.cpp#l71
184
+ * glibc: https://github.com/lattera/glibc/blob/master/sysdeps/posix/posix_fallocate.c
185
+ */
186
+ int reserve_mmap_file_bytes(int fd, size_t size) {
187
+ #if __linux__
188
+ /* From https://stackoverflow.com/a/22820221: The difference with
189
+ * ftruncate(2) is that (on file systems supporting it, e.g. Ext4)
190
+ * disk space is indeed reserved by posix_fallocate but ftruncate
191
+ * extends the file by adding holes (and without reserving disk
192
+ * space). */
193
+ return posix_fallocate(fd, 0, size);
194
+ #else
195
+ /* We simplify the reference implemnetations since we generally
196
+ * don't need to reserve more than a page size. */
197
+ return ftruncate(fd, size);
198
+ #endif
199
+ }
200
+
173
201
  VALUE mm_init(VALUE obj, VALUE fname) {
174
202
  struct stat st;
175
203
  int fd, smode = 0, pmode = 0, vscope, perm, init;
@@ -187,13 +215,6 @@ VALUE mm_init(VALUE obj, VALUE fname) {
187
215
  SafeStringValue(fname);
188
216
  path = StringValuePtr(fname);
189
217
 
190
- {
191
- if (rb_safe_level() > 0 && OBJ_TAINTED(fname)) {
192
- rb_raise(rb_eSecurityError, "Insecure operation");
193
- }
194
- rb_secure(1);
195
- }
196
-
197
218
  vscope = MAP_SHARED;
198
219
  size = 0;
199
220
  perm = 0666;
@@ -206,6 +227,7 @@ VALUE mm_init(VALUE obj, VALUE fname) {
206
227
  }
207
228
 
208
229
  if (fstat(fd, &st) == -1) {
230
+ close(fd);
209
231
  rb_raise(rb_eArgError, "Can't stat %s", path);
210
232
  }
211
233
  size = st.st_size;
@@ -215,17 +237,21 @@ VALUE mm_init(VALUE obj, VALUE fname) {
215
237
  offset = 0;
216
238
  init = 0;
217
239
 
218
- if (size == 0 && (smode & O_RDWR)) {
219
- if (lseek(fd, INITIAL_SIZE - 1, SEEK_END) == -1) {
220
- rb_raise(rb_eIOError, "Can't lseek %zu", INITIAL_SIZE - 1);
221
- }
222
- if (write(fd, "\000", 1) != 1) {
223
- rb_raise(rb_eIOError, "Can't extend %s", path);
224
- }
240
+ if (size == 0) {
225
241
  init = 1;
226
242
  size = INITIAL_SIZE;
227
243
  }
228
244
 
245
+ /* We need to ensure the underlying file descriptor is at least a page size.
246
+ * Otherwise, we could get a SIGBUS error if mmap() attempts to read or write
247
+ * past the file. */
248
+ size_t reserve_size = next_page_boundary(size);
249
+
250
+ if (reserve_mmap_file_bytes(fd, reserve_size) != 0) {
251
+ close(fd);
252
+ rb_raise(rb_eIOError, "Can't reserve %zu bytes for memory-mapped file in %s", reserve_size, path);
253
+ }
254
+
229
255
  addr = mmap(0, size, pmode, vscope, fd, offset);
230
256
 
231
257
  if (addr == MAP_FAILED || !addr) {
@@ -1,9 +1,10 @@
1
+ #include "rendering.h"
2
+
1
3
  #include <float.h>
2
4
  #include <jsmn.h>
3
5
 
4
6
  #include "file_parsing.h"
5
7
  #include "globals.h"
6
- #include "rendering.h"
7
8
  #include "utils.h"
8
9
 
9
10
  #ifndef DBL_DECIMAL_DIG
@@ -1,8 +1,7 @@
1
- #include <errno.h>
2
- #include <ruby.h>
3
-
4
1
  #include "utils.h"
5
2
 
3
+ #include <errno.h>
4
+
6
5
  static void rb_save_exception(VALUE exception, VALUE message) {
7
6
  VALUE current_thread = rb_thread_current();
8
7
 
@@ -1,5 +1,6 @@
1
1
  #ifndef UNUSED_H
2
2
  #define UNUSED_H
3
+ #include <ruby.h>
3
4
 
4
5
  #ifdef UNUSED
5
6
  #elif defined(__GNUC__)
@@ -1,15 +1,13 @@
1
- #include <ruby.h>
2
- #include <ruby/intern.h>
1
+ #include "value_access.h"
3
2
 
4
3
  #include <errno.h>
5
4
  #include <fcntl.h>
5
+ #include <ruby/intern.h>
6
6
  #include <sys/mman.h>
7
7
  #include <unistd.h>
8
8
 
9
9
  #include "file_format.h"
10
10
  #include "mmap.h"
11
- #include "value_access.h"
12
-
13
11
  #include "utils.h"
14
12
 
15
13
  static void close_file(mm_ipc *i_mm) {
@@ -1,5 +1,6 @@
1
1
  #ifndef VALUE_ACCESS_H
2
2
  #define VALUE_ACCESS_H
3
+ #include <ruby.h>
3
4
 
4
5
  VALUE method_load_used(VALUE self);
5
6
 
Binary file
@@ -31,6 +31,10 @@ module Prometheus
31
31
  def increment(labels, value)
32
32
  @values[label_set_for(labels)].increment(value)
33
33
  end
34
+
35
+ def decrement(labels, value)
36
+ @values[label_set_for(labels)].decrement(value)
37
+ end
34
38
  end
35
39
  end
36
40
  end
@@ -57,6 +57,10 @@ module Prometheus
57
57
  Prometheus::Client.logger.warn("munmap raised error #{e}")
58
58
  end
59
59
 
60
+ def inspect
61
+ "#<#{self.class}:0x#{(object_id << 1).to_s(16)}>"
62
+ end
63
+
60
64
  private
61
65
 
62
66
  def init_value(key)
@@ -36,6 +36,10 @@ module Prometheus
36
36
  end
37
37
  end
38
38
 
39
+ def decrement(amount = 1)
40
+ increment(-amount)
41
+ end
42
+
39
43
  def set(value)
40
44
  @mutex.synchronize do
41
45
  initialize_file if pid_changed?
@@ -1,7 +1,9 @@
1
1
  # encoding: UTF-8
2
2
 
3
+ require 'thread'
3
4
  require 'net/http'
4
5
  require 'uri'
6
+ require 'erb'
5
7
 
6
8
  require 'prometheus/client'
7
9
  require 'prometheus/client/formats/text'
@@ -13,31 +15,45 @@ module Prometheus
13
15
  # Pushgateway.
14
16
  class Push
15
17
  DEFAULT_GATEWAY = 'http://localhost:9091'.freeze
16
- PATH = '/metrics/jobs/%s'.freeze
17
- INSTANCE_PATH = '/metrics/jobs/%s/instances/%s'.freeze
18
- HEADER = { 'Content-Type' => Formats::Text::CONTENT_TYPE }.freeze
18
+ PATH = '/metrics/job/%s'.freeze
19
+ INSTANCE_PATH = '/metrics/job/%s/instance/%s'.freeze
20
+ SUPPORTED_SCHEMES = %w(http https).freeze
19
21
 
20
22
  attr_reader :job, :instance, :gateway, :path
21
23
 
22
- def initialize(job, instance = nil, gateway = nil)
24
+ def initialize(job:, instance: nil, gateway: DEFAULT_GATEWAY, **kwargs)
25
+ raise ArgumentError, "job cannot be nil" if job.nil?
26
+ raise ArgumentError, "job cannot be empty" if job.empty?
27
+
28
+ @mutex = Mutex.new
23
29
  @job = job
24
30
  @instance = instance
25
31
  @gateway = gateway || DEFAULT_GATEWAY
26
- @uri = parse(@gateway)
27
32
  @path = build_path(job, instance)
33
+ @uri = parse("#{@gateway}#{@path}")
34
+
28
35
  @http = Net::HTTP.new(@uri.host, @uri.port)
36
+ @http.use_ssl = (@uri.scheme == 'https')
37
+ @http.open_timeout = kwargs[:open_timeout] if kwargs[:open_timeout]
38
+ @http.read_timeout = kwargs[:read_timeout] if kwargs[:read_timeout]
29
39
  end
30
40
 
31
41
  def add(registry)
32
- request('POST', registry)
42
+ synchronize do
43
+ request(Net::HTTP::Post, registry)
44
+ end
33
45
  end
34
46
 
35
47
  def replace(registry)
36
- request('PUT', registry)
48
+ synchronize do
49
+ request(Net::HTTP::Put, registry)
50
+ end
37
51
  end
38
52
 
39
53
  def delete
40
- @http.send_request('DELETE', path)
54
+ synchronize do
55
+ request(Net::HTTP::Delete)
56
+ end
41
57
  end
42
58
 
43
59
  private
@@ -45,27 +61,34 @@ module Prometheus
45
61
  def parse(url)
46
62
  uri = URI.parse(url)
47
63
 
48
- if uri.scheme == 'http'
49
- uri
50
- else
64
+ unless SUPPORTED_SCHEMES.include?(uri.scheme)
51
65
  raise ArgumentError, 'only HTTP gateway URLs are supported currently.'
52
66
  end
67
+
68
+ uri
53
69
  rescue URI::InvalidURIError => e
54
70
  raise ArgumentError, "#{url} is not a valid URL: #{e}"
55
71
  end
56
72
 
57
73
  def build_path(job, instance)
58
- if instance
59
- format(INSTANCE_PATH, URI.escape(job), URI.escape(instance))
74
+ if instance && !instance.empty?
75
+ format(INSTANCE_PATH, ERB::Util::url_encode(job), ERB::Util::url_encode(instance))
60
76
  else
61
- format(PATH, URI.escape(job))
77
+ format(PATH, ERB::Util::url_encode(job))
62
78
  end
63
79
  end
64
80
 
65
- def request(method, registry)
66
- data = Formats::Text.marshal(registry)
81
+ def request(req_class, registry = nil)
82
+ req = req_class.new(@uri)
83
+ req.content_type = Formats::Text::CONTENT_TYPE
84
+ req.basic_auth(@uri.user, @uri.password) if @uri.user
85
+ req.body = Formats::Text.marshal(registry) if registry
86
+
87
+ @http.request(req)
88
+ end
67
89
 
68
- @http.send_request(method, path, data, HEADER)
90
+ def synchronize
91
+ @mutex.synchronize { yield }
69
92
  end
70
93
  end
71
94
  end
@@ -15,6 +15,10 @@ module Prometheus
15
15
  @value += by
16
16
  end
17
17
 
18
+ def decrement(by = 1)
19
+ @value -= by
20
+ end
21
+
18
22
  def get
19
23
  @value
20
24
  end
@@ -1,5 +1,5 @@
1
1
  module Prometheus
2
2
  module Client
3
- VERSION = '0.9.10'.freeze
3
+ VERSION = '0.13.0'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prometheus-client-mmap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.10
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Schmidt
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-09-16 00:00:00.000000000 Z
12
+ date: 2021-07-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fuzzbert
@@ -181,7 +181,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
181
181
  - !ruby/object:Gem::Version
182
182
  version: '0'
183
183
  requirements: []
184
- rubygems_version: 3.0.3
184
+ rubygems_version: 3.1.4
185
185
  signing_key:
186
186
  specification_version: 4
187
187
  summary: A suite of instrumentation metric primitivesthat can be exposed through a