prometheus-client-mmap 0.19.1 → 0.21.0

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,49 @@ 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 load_rust_extension
50
+ begin
51
+ ruby_version = /(\d+\.\d+)/.match(RUBY_VERSION)
52
+ require_relative "../../../#{ruby_version}/fast_mmaped_file_rs"
53
+ rescue LoadError
54
+ require 'fast_mmaped_file_rs'
55
+ end
56
+ end
57
+
58
+ def check_for_rust
59
+ # This will be evaluated on each invocation even with `||=` if
60
+ # `@rust_available` if false. Running a `require` statement is slow,
61
+ # so the `rust_impl_available?` method memoizes the result, external
62
+ # callers can only trigger this method a single time.
63
+ @rust_available = begin
64
+ load_rust_extension
65
+ true
66
+ rescue LoadError
67
+ Prometheus::Client.logger.info('FastMmapedFileRs unavailable')
68
+ false
69
+ end
70
+ end
71
+
39
72
  def load_metrics(path)
40
73
  metrics = {}
41
74
  Dir.glob(File.join(path, '*.db')).sort.each do |f|
@@ -1,6 +1,13 @@
1
1
  require 'prometheus/client/helper/entry_parser'
2
2
  require 'prometheus/client/helper/file_locker'
3
- require 'fast_mmaped_file'
3
+
4
+ # load precompiled extension if available
5
+ begin
6
+ ruby_version = /(\d+\.\d+)/.match(RUBY_VERSION)
7
+ require_relative "../../../#{ruby_version}/fast_mmaped_file"
8
+ rescue LoadError
9
+ require 'fast_mmaped_file'
10
+ end
4
11
 
5
12
  module Prometheus
6
13
  module Client
@@ -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.21.0'.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,16 +1,30 @@
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.21.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Schmidt
8
8
  - Paweł Chojnacki
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-03-17 00:00:00.000000000 Z
12
+ date: 2023-04-21 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
@@ -65,14 +79,28 @@ dependencies:
65
79
  requirements:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
- version: '1'
82
+ version: 1.2.1
69
83
  type: :development
70
84
  prerelease: false
71
85
  version_requirements: !ruby/object:Gem::Requirement
72
86
  requirements:
73
87
  - - "~>"
74
88
  - !ruby/object:Gem::Version
75
- version: '1'
89
+ version: 1.2.1
90
+ - !ruby/object:Gem::Dependency
91
+ name: rake-compiler-dock
92
+ requirement: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 1.3.0
97
+ type: :development
98
+ prerelease: false
99
+ version_requirements: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 1.3.0
76
104
  - !ruby/object:Gem::Dependency
77
105
  name: ruby-prof
78
106
  requirement: !ruby/object:Gem::Requirement
@@ -87,13 +115,14 @@ dependencies:
87
115
  - - "~>"
88
116
  - !ruby/object:Gem::Version
89
117
  version: 0.16.2
90
- description:
118
+ description:
91
119
  email:
92
120
  - ts@soundcloud.com
93
121
  - pawel@gitlab.com
94
122
  executables: []
95
123
  extensions:
96
124
  - ext/fast_mmaped_file/extconf.rb
125
+ - ext/fast_mmaped_file_rs/extconf.rb
97
126
  extra_rdoc_files: []
98
127
  files:
99
128
  - README.md
@@ -114,6 +143,22 @@ files:
114
143
  - ext/fast_mmaped_file/utils.h
115
144
  - ext/fast_mmaped_file/value_access.c
116
145
  - ext/fast_mmaped_file/value_access.h
146
+ - ext/fast_mmaped_file_rs/.cargo/config.toml
147
+ - ext/fast_mmaped_file_rs/Cargo.lock
148
+ - ext/fast_mmaped_file_rs/Cargo.toml
149
+ - ext/fast_mmaped_file_rs/README.md
150
+ - ext/fast_mmaped_file_rs/extconf.rb
151
+ - ext/fast_mmaped_file_rs/src/error.rs
152
+ - ext/fast_mmaped_file_rs/src/file_entry.rs
153
+ - ext/fast_mmaped_file_rs/src/file_info.rs
154
+ - ext/fast_mmaped_file_rs/src/lib.rs
155
+ - ext/fast_mmaped_file_rs/src/macros.rs
156
+ - ext/fast_mmaped_file_rs/src/map.rs
157
+ - ext/fast_mmaped_file_rs/src/mmap.rs
158
+ - ext/fast_mmaped_file_rs/src/parser.rs
159
+ - ext/fast_mmaped_file_rs/src/raw_entry.rs
160
+ - ext/fast_mmaped_file_rs/src/testhelper.rs
161
+ - ext/fast_mmaped_file_rs/src/util.rs
117
162
  - lib/prometheus.rb
118
163
  - lib/prometheus/client.rb
119
164
  - lib/prometheus/client/configuration.rb
@@ -132,6 +177,7 @@ files:
132
177
  - lib/prometheus/client/metric.rb
133
178
  - lib/prometheus/client/mmaped_dict.rb
134
179
  - lib/prometheus/client/mmaped_value.rb
180
+ - lib/prometheus/client/page_size.rb
135
181
  - lib/prometheus/client/push.rb
136
182
  - lib/prometheus/client/rack/collector.rb
137
183
  - lib/prometheus/client/rack/exporter.rb
@@ -141,6 +187,7 @@ files:
141
187
  - lib/prometheus/client/support/unicorn.rb
142
188
  - lib/prometheus/client/uses_value_type.rb
143
189
  - lib/prometheus/client/version.rb
190
+ - vendor/c/hashmap/.gitignore
144
191
  - vendor/c/hashmap/LICENSE
145
192
  - vendor/c/hashmap/README.md
146
193
  - vendor/c/hashmap/_config.yml
@@ -148,6 +195,7 @@ files:
148
195
  - vendor/c/hashmap/src/hashmap.h
149
196
  - vendor/c/hashmap/test/Makefile
150
197
  - vendor/c/hashmap/test/hashmap_test.c
198
+ - vendor/c/jsmn/.travis.yml
151
199
  - vendor/c/jsmn/LICENSE
152
200
  - vendor/c/jsmn/Makefile
153
201
  - vendor/c/jsmn/README.md
@@ -163,7 +211,7 @@ homepage: https://gitlab.com/gitlab-org/prometheus-client-mmap
163
211
  licenses:
164
212
  - Apache-2.0
165
213
  metadata: {}
166
- post_install_message:
214
+ post_install_message:
167
215
  rdoc_options: []
168
216
  require_paths:
169
217
  - lib
@@ -176,10 +224,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
176
224
  requirements:
177
225
  - - ">="
178
226
  - !ruby/object:Gem::Version
179
- version: '0'
227
+ version: 3.3.22
180
228
  requirements: []
181
- rubygems_version: 3.4.8
182
- signing_key:
229
+ rubygems_version: 3.3.26
230
+ signing_key:
183
231
  specification_version: 4
184
232
  summary: A suite of instrumentation metric primitivesthat can be exposed through a
185
233
  web services interface.