prometheus-client-mmap 0.19.1 → 0.20.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,121 @@
1
+ use nix::errno::Errno;
2
+ use nix::libc::c_long;
3
+ use std::fmt::Display;
4
+ use std::io;
5
+ use std::mem::size_of;
6
+
7
+ use crate::error::MmapError;
8
+ use crate::Result;
9
+
10
+ /// Wrapper around `checked_add()` that converts failures
11
+ /// to `MmapError::Overflow`.
12
+ pub trait CheckedOps: Sized {
13
+ fn add_chk(self, rhs: Self) -> Result<Self>;
14
+ fn mul_chk(self, rhs: Self) -> Result<Self>;
15
+ }
16
+
17
+ impl CheckedOps for usize {
18
+ fn add_chk(self, rhs: Self) -> Result<Self> {
19
+ self.checked_add(rhs)
20
+ .ok_or_else(|| MmapError::overflowed(self, rhs, "adding"))
21
+ }
22
+
23
+ fn mul_chk(self, rhs: Self) -> Result<Self> {
24
+ self.checked_mul(rhs)
25
+ .ok_or_else(|| MmapError::overflowed(self, rhs, "multiplying"))
26
+ }
27
+ }
28
+
29
+ impl CheckedOps for c_long {
30
+ fn add_chk(self, rhs: Self) -> Result<Self> {
31
+ self.checked_add(rhs)
32
+ .ok_or_else(|| MmapError::overflowed(self, rhs, "adding"))
33
+ }
34
+
35
+ fn mul_chk(self, rhs: Self) -> Result<Self> {
36
+ self.checked_mul(rhs)
37
+ .ok_or_else(|| MmapError::overflowed(self, rhs, "multiplying"))
38
+ }
39
+ }
40
+
41
+ /// A wrapper around `TryFrom`, returning `MmapError::FailedCast` on error.
42
+ pub fn cast_chk<T, U>(val: T, name: &str) -> Result<U>
43
+ where
44
+ T: Copy + Display,
45
+ U: std::convert::TryFrom<T>,
46
+ {
47
+ U::try_from(val).map_err(|_| MmapError::failed_cast::<T, U>(val, name))
48
+ }
49
+
50
+ /// Retrieve errno(3).
51
+ pub fn errno() -> i32 {
52
+ // UNWRAP: This will always return `Some` when called from `last_os_error()`.
53
+ io::Error::last_os_error().raw_os_error().unwrap()
54
+ }
55
+
56
+ /// Get the error string associated with errno(3).
57
+ /// Equivalent to strerror(3).
58
+ pub fn strerror(errno: i32) -> &'static str {
59
+ Errno::from_i32(errno).desc()
60
+ }
61
+
62
+ /// Read a `u32` value from a byte slice starting from `offset`.
63
+ #[inline]
64
+ pub fn read_u32(buf: &[u8], offset: usize) -> Result<u32> {
65
+ if let Some(slice) = buf.get(offset..offset + size_of::<u32>()) {
66
+ // UNWRAP: We can safely unwrap the conversion from slice to array as we
67
+ // the source and targets are constructed here with the same length.
68
+ let out: &[u8; size_of::<u32>()] = slice.try_into().unwrap();
69
+
70
+ return Ok(u32::from_ne_bytes(*out));
71
+ }
72
+ Err(MmapError::out_of_bounds(offset, buf.len()))
73
+ }
74
+
75
+ /// Read an `f64` value from a byte slice starting from `offset`.
76
+ #[inline]
77
+ pub fn read_f64(buf: &[u8], offset: usize) -> Result<f64> {
78
+ if let Some(slice) = buf.get(offset..offset + size_of::<f64>()) {
79
+ // UNWRAP: We can safely unwrap the conversion from slice to array as we
80
+ // can be sure the target array has same length as the source slice.
81
+ let out: &[u8; size_of::<f64>()] = slice.try_into().unwrap();
82
+
83
+ return Ok(f64::from_ne_bytes(*out));
84
+ }
85
+ Err(MmapError::out_of_bounds(
86
+ offset + size_of::<f64>(),
87
+ buf.len(),
88
+ ))
89
+ }
90
+
91
+ #[cfg(test)]
92
+ mod test {
93
+ use super::*;
94
+
95
+ #[test]
96
+ fn test_read_u32() {
97
+ let buf = 1u32.to_ne_bytes();
98
+
99
+ assert!(matches!(read_u32(&buf, 0), Ok(1)), "index ok");
100
+ assert!(read_u32(&buf, 10).is_err(), "index out of range");
101
+ assert!(
102
+ read_u32(&buf, 1).is_err(),
103
+ "index in range but end out of range"
104
+ );
105
+ }
106
+
107
+ #[test]
108
+ fn test_read_f64() {
109
+ let buf = 1.00f64.to_ne_bytes();
110
+
111
+ let ok = read_f64(&buf, 0);
112
+ assert!(ok.is_ok());
113
+ assert_eq!(ok.unwrap(), 1.00);
114
+
115
+ assert!(read_f64(&buf, 10).is_err(), "index out of range");
116
+ assert!(
117
+ read_f64(&buf, 1).is_err(),
118
+ "index in range but end out of range"
119
+ );
120
+ }
121
+ }
@@ -1,5 +1,6 @@
1
1
  require 'prometheus/client/registry'
2
2
  require 'prometheus/client/mmaped_value'
3
+ require 'prometheus/client/page_size'
3
4
  require 'logger'
4
5
  require 'tmpdir'
5
6
 
@@ -10,7 +11,7 @@ module Prometheus
10
11
 
11
12
  def initialize
12
13
  @value_class = ::Prometheus::Client::MmapedValue
13
- @initial_mmap_file_size = 4 * 1024
14
+ @initial_mmap_file_size = ::Prometheus::Client::PageSize.page_size(fallback_page_size: 4096)
14
15
  @logger = Logger.new($stdout)
15
16
  @pid_provider = Process.method(:pid)
16
17
  @multiprocess_files_dir = ENV.fetch('prometheus_multiproc_dir') do
@@ -26,16 +26,40 @@ module Prometheus
26
26
  Helper::MetricsRepresentation.to_text(metrics)
27
27
  end
28
28
 
29
- def marshal_multiprocess(path = Prometheus::Client.configuration.multiprocess_files_dir)
29
+ def marshal_multiprocess(path = Prometheus::Client.configuration.multiprocess_files_dir, use_rust: false)
30
30
  file_list = Dir.glob(File.join(path, '*.db')).sort
31
31
  .map {|f| Helper::PlainFile.new(f) }
32
32
  .map {|f| [f.filepath, f.multiprocess_mode.to_sym, f.type.to_sym, f.pid] }
33
33
 
34
- FastMmapedFile.to_metrics(file_list.to_a)
34
+ if use_rust && rust_impl_available?
35
+ FastMmapedFileRs.to_metrics(file_list.to_a)
36
+ else
37
+ FastMmapedFile.to_metrics(file_list.to_a)
38
+ end
39
+ end
40
+
41
+ def rust_impl_available?
42
+ return @rust_available unless @rust_available.nil?
43
+
44
+ check_for_rust
35
45
  end
36
46
 
37
47
  private
38
48
 
49
+ def check_for_rust
50
+ # This will be evaluated on each invocation even with `||=` if
51
+ # `@rust_available` if false. Running a `require` statement is slow,
52
+ # so the `rust_impl_available?` method memoizes the result, external
53
+ # callers can only trigger this method a single time.
54
+ @rust_available = begin
55
+ require 'fast_mmaped_file_rs'
56
+ true
57
+ rescue LoadError
58
+ Prometheus::Client.logger.info('FastMmapedFileRs unavailable')
59
+ false
60
+ end
61
+ end
62
+
39
63
  def load_metrics(path)
40
64
  metrics = {}
41
65
  Dir.glob(File.join(path, '*.db')).sort.each do |f|
@@ -0,0 +1,17 @@
1
+ require 'open3'
2
+
3
+ module Prometheus
4
+ module Client
5
+ module PageSize
6
+ def self.page_size(fallback_page_size: 4096)
7
+ stdout, status = Open3.capture2('getconf PAGESIZE')
8
+ return fallback_page_size if status.nil? || !status.success?
9
+
10
+ page_size = stdout.chomp.to_i
11
+ return fallback_page_size if page_size <= 0
12
+
13
+ page_size
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,5 +1,5 @@
1
1
  module Prometheus
2
2
  module Client
3
- VERSION = '0.19.1'.freeze
3
+ VERSION = '0.20.1'.freeze
4
4
  end
5
5
  end
@@ -0,0 +1,52 @@
1
+ # Prerequisites
2
+ *.d
3
+
4
+ # Object files
5
+ *.o
6
+ *.ko
7
+ *.obj
8
+ *.elf
9
+
10
+ # Linker output
11
+ *.ilk
12
+ *.map
13
+ *.exp
14
+
15
+ # Precompiled Headers
16
+ *.gch
17
+ *.pch
18
+
19
+ # Libraries
20
+ *.lib
21
+ *.a
22
+ *.la
23
+ *.lo
24
+
25
+ # Shared objects (inc. Windows DLLs)
26
+ *.dll
27
+ *.so
28
+ *.so.*
29
+ *.dylib
30
+
31
+ # Executables
32
+ *.exe
33
+ *.out
34
+ *.app
35
+ *.i*86
36
+ *.x86_64
37
+ *.hex
38
+
39
+ # Debug files
40
+ *.dSYM/
41
+ *.su
42
+ *.idb
43
+ *.pdb
44
+
45
+ # Kernel Module Compile Results
46
+ *.mod*
47
+ *.cmd
48
+ .tmp_versions/
49
+ modules.order
50
+ Module.symvers
51
+ Mkfile.old
52
+ dkms.conf
@@ -0,0 +1,4 @@
1
+ language: c
2
+ sudo: false
3
+ script:
4
+ - make test
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.19.1
4
+ version: 0.20.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Schmidt
@@ -9,8 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-03-17 00:00:00.000000000 Z
12
+ date: 2023-04-15 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rb_sys
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '0.9'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '0.9'
14
28
  - !ruby/object:Gem::Dependency
15
29
  name: fuzzbert
16
30
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +108,7 @@ email:
94
108
  executables: []
95
109
  extensions:
96
110
  - ext/fast_mmaped_file/extconf.rb
111
+ - ext/fast_mmaped_file_rs/extconf.rb
97
112
  extra_rdoc_files: []
98
113
  files:
99
114
  - README.md
@@ -114,6 +129,22 @@ files:
114
129
  - ext/fast_mmaped_file/utils.h
115
130
  - ext/fast_mmaped_file/value_access.c
116
131
  - ext/fast_mmaped_file/value_access.h
132
+ - ext/fast_mmaped_file_rs/.cargo/config.toml
133
+ - ext/fast_mmaped_file_rs/Cargo.lock
134
+ - ext/fast_mmaped_file_rs/Cargo.toml
135
+ - ext/fast_mmaped_file_rs/README.md
136
+ - ext/fast_mmaped_file_rs/extconf.rb
137
+ - ext/fast_mmaped_file_rs/src/error.rs
138
+ - ext/fast_mmaped_file_rs/src/file_entry.rs
139
+ - ext/fast_mmaped_file_rs/src/file_info.rs
140
+ - ext/fast_mmaped_file_rs/src/lib.rs
141
+ - ext/fast_mmaped_file_rs/src/macros.rs
142
+ - ext/fast_mmaped_file_rs/src/map.rs
143
+ - ext/fast_mmaped_file_rs/src/mmap.rs
144
+ - ext/fast_mmaped_file_rs/src/parser.rs
145
+ - ext/fast_mmaped_file_rs/src/raw_entry.rs
146
+ - ext/fast_mmaped_file_rs/src/testhelper.rs
147
+ - ext/fast_mmaped_file_rs/src/util.rs
117
148
  - lib/prometheus.rb
118
149
  - lib/prometheus/client.rb
119
150
  - lib/prometheus/client/configuration.rb
@@ -132,6 +163,7 @@ files:
132
163
  - lib/prometheus/client/metric.rb
133
164
  - lib/prometheus/client/mmaped_dict.rb
134
165
  - lib/prometheus/client/mmaped_value.rb
166
+ - lib/prometheus/client/page_size.rb
135
167
  - lib/prometheus/client/push.rb
136
168
  - lib/prometheus/client/rack/collector.rb
137
169
  - lib/prometheus/client/rack/exporter.rb
@@ -141,6 +173,7 @@ files:
141
173
  - lib/prometheus/client/support/unicorn.rb
142
174
  - lib/prometheus/client/uses_value_type.rb
143
175
  - lib/prometheus/client/version.rb
176
+ - vendor/c/hashmap/.gitignore
144
177
  - vendor/c/hashmap/LICENSE
145
178
  - vendor/c/hashmap/README.md
146
179
  - vendor/c/hashmap/_config.yml
@@ -148,6 +181,7 @@ files:
148
181
  - vendor/c/hashmap/src/hashmap.h
149
182
  - vendor/c/hashmap/test/Makefile
150
183
  - vendor/c/hashmap/test/hashmap_test.c
184
+ - vendor/c/jsmn/.travis.yml
151
185
  - vendor/c/jsmn/LICENSE
152
186
  - vendor/c/jsmn/Makefile
153
187
  - vendor/c/jsmn/README.md
@@ -178,7 +212,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
178
212
  - !ruby/object:Gem::Version
179
213
  version: '0'
180
214
  requirements: []
181
- rubygems_version: 3.4.8
215
+ rubygems_version: 3.4.12
182
216
  signing_key:
183
217
  specification_version: 4
184
218
  summary: A suite of instrumentation metric primitivesthat can be exposed through a