prometheus-client-mmap 0.20.0 → 0.20.2
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/ext/fast_mmaped_file_rs/Cargo.lock +10 -2
- data/ext/fast_mmaped_file_rs/Cargo.toml +1 -1
- data/ext/fast_mmaped_file_rs/extconf.rb +3 -1
- data/ext/fast_mmaped_file_rs/src/file_entry.rs +48 -13
- data/ext/fast_mmaped_file_rs/src/map.rs +49 -15
- data/lib/prometheus/client/version.rb +1 -1
- metadata +3 -4
- data/ext/fast_mmaped_file_rs/.tool-versions +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f91fbb3a1899d0093d51d92ab8dceec80981c6160b3a09d35d90117f29e6c3d0
|
4
|
+
data.tar.gz: fea591800d5a3a2344082fd38df75f35aea8b5bf5394bcd7e20bf80d14dd48fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6e98dda485f79a83fe614a21c52444fad33a69b208c4a6d637516c0390f79c9c54216dda50f7b151483d3e69fe4e7739ed0076984cb7497c59110f0f941b664
|
7
|
+
data.tar.gz: 30bc5288dd7247222128b99a4cf88bdde9ca8625682b0d013dc5ea9cd6ce12aa5285be4b3a875f9a933dcc23e943c4b2cccc9ad9c53e273754a4dac46ddee1ed
|
@@ -9,7 +9,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
9
|
checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
|
10
10
|
dependencies = [
|
11
11
|
"cfg-if",
|
12
|
-
"getrandom",
|
13
12
|
"once_cell",
|
14
13
|
"version_check",
|
15
14
|
]
|
@@ -161,8 +160,8 @@ dependencies = [
|
|
161
160
|
name = "fast_mmaped_file_rs"
|
162
161
|
version = "0.1.0"
|
163
162
|
dependencies = [
|
164
|
-
"ahash",
|
165
163
|
"bstr",
|
164
|
+
"hashbrown",
|
166
165
|
"indoc",
|
167
166
|
"libc",
|
168
167
|
"magnus",
|
@@ -212,6 +211,15 @@ version = "0.3.1"
|
|
212
211
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
213
212
|
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
214
213
|
|
214
|
+
[[package]]
|
215
|
+
name = "hashbrown"
|
216
|
+
version = "0.13.2"
|
217
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
218
|
+
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
|
219
|
+
dependencies = [
|
220
|
+
"ahash",
|
221
|
+
]
|
222
|
+
|
215
223
|
[[package]]
|
216
224
|
name = "hermit-abi"
|
217
225
|
version = "0.3.1"
|
@@ -6,7 +6,7 @@ edition = "2021"
|
|
6
6
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
7
7
|
|
8
8
|
[dependencies]
|
9
|
-
|
9
|
+
hashbrown = "0.13"
|
10
10
|
libc = "0.2"
|
11
11
|
magnus = { git = "https://github.com/matsadler/magnus", branch = "main", features = ["rb-sys"] }
|
12
12
|
memmap2 = "0.5"
|
@@ -1,7 +1,9 @@
|
|
1
1
|
require "mkmf"
|
2
2
|
require "rb_sys/mkmf"
|
3
3
|
|
4
|
-
create_rust_makefile("
|
4
|
+
create_rust_makefile("fast_mmaped_file_rs") do |r|
|
5
|
+
r.auto_install_rust_toolchain = false
|
6
|
+
|
5
7
|
if enable_config('fail-on-warning')
|
6
8
|
r.extra_rustflags = ["-Dwarnings"]
|
7
9
|
end
|
@@ -1,4 +1,6 @@
|
|
1
1
|
use magnus::{StaticSymbol, Symbol};
|
2
|
+
use std::fmt::Write;
|
3
|
+
use std::str;
|
2
4
|
|
3
5
|
use crate::error::{MmapError, RubyError};
|
4
6
|
use crate::file_info::FileInfo;
|
@@ -22,27 +24,55 @@ pub struct EntryData {
|
|
22
24
|
pub pid: Option<String>,
|
23
25
|
}
|
24
26
|
|
25
|
-
impl EntryData {
|
26
|
-
|
27
|
-
|
27
|
+
impl<'a> PartialEq<BorrowedData<'a>> for EntryData {
|
28
|
+
fn eq(&self, other: &BorrowedData) -> bool {
|
29
|
+
self.pid.as_deref() == other.pid && self.json == other.json
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
impl<'a> TryFrom<BorrowedData<'a>> for EntryData {
|
34
|
+
type Error = MmapError;
|
28
35
|
|
29
|
-
|
30
|
-
|
36
|
+
fn try_from(borrowed: BorrowedData) -> Result<Self> {
|
37
|
+
let mut json = String::new();
|
38
|
+
if json.try_reserve_exact(borrowed.json.len()).is_err() {
|
39
|
+
return Err(MmapError::OutOfMemory(borrowed.json.len()));
|
31
40
|
}
|
41
|
+
json.push_str(borrowed.json);
|
32
42
|
|
33
|
-
|
34
|
-
|
43
|
+
Ok(Self {
|
44
|
+
json,
|
45
|
+
// Don't bother checking for allocation failure, typically ~10 bytes
|
46
|
+
pid: borrowed.pid.map(|p| p.to_string()),
|
47
|
+
})
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
/// A borrowed copy of the JSON string and pid for a `FileEntry`. We use this
|
52
|
+
/// to check if a given string/pid combination is present in the `EntryMap`,
|
53
|
+
/// copying them to owned values only when needed.
|
54
|
+
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
|
55
|
+
pub struct BorrowedData<'a> {
|
56
|
+
pub json: &'a str,
|
57
|
+
pub pid: Option<&'a str>,
|
58
|
+
}
|
35
59
|
|
36
|
-
|
60
|
+
impl<'a> BorrowedData<'a> {
|
61
|
+
pub fn new(
|
62
|
+
raw_entry: &'a RawEntry,
|
63
|
+
file_info: &'a FileInfo,
|
64
|
+
pid_significant: bool,
|
65
|
+
) -> Result<Self> {
|
66
|
+
let json = str::from_utf8(raw_entry.json())
|
37
67
|
.map_err(|e| MmapError::Encoding(format!("invalid UTF-8 in entry JSON: {e}")))?;
|
38
68
|
|
39
69
|
let pid = if pid_significant {
|
40
|
-
Some(file_info.pid.
|
70
|
+
Some(file_info.pid.as_str())
|
41
71
|
} else {
|
42
72
|
None
|
43
73
|
};
|
44
74
|
|
45
|
-
Ok(
|
75
|
+
Ok(Self { json, pid })
|
46
76
|
}
|
47
77
|
}
|
48
78
|
|
@@ -121,7 +151,8 @@ impl FileEntry {
|
|
121
151
|
|
122
152
|
entry.append_entry(metrics_data, &mut out)?;
|
123
153
|
|
124
|
-
|
154
|
+
writeln!(&mut out, " {}", entry.meta.value)
|
155
|
+
.map_err(|e| MmapError::Other(format!("Failed to append to output: {e}")))?;
|
125
156
|
|
126
157
|
processed_count += 1;
|
127
158
|
}
|
@@ -419,7 +450,9 @@ mod test {
|
|
419
450
|
.zip(file_infos)
|
420
451
|
.map(|(entry, info)| {
|
421
452
|
let meta = EntryMetadata::new(&entry, &info).unwrap();
|
422
|
-
let
|
453
|
+
let borrowed =
|
454
|
+
BorrowedData::new(&entry, &info, meta.is_pid_significant()).unwrap();
|
455
|
+
let data = EntryData::try_from(borrowed).unwrap();
|
423
456
|
FileEntry { data, meta }
|
424
457
|
})
|
425
458
|
.collect();
|
@@ -526,7 +559,9 @@ mod test {
|
|
526
559
|
.map(|s| RawEntry::from_slice(s).unwrap())
|
527
560
|
.map(|entry| {
|
528
561
|
let meta = EntryMetadata::new(&entry, &info).unwrap();
|
529
|
-
let
|
562
|
+
let borrowed =
|
563
|
+
BorrowedData::new(&entry, &info, meta.is_pid_significant()).unwrap();
|
564
|
+
let data = EntryData::try_from(borrowed).unwrap();
|
530
565
|
FileEntry { data, meta }
|
531
566
|
})
|
532
567
|
.collect();
|
@@ -1,9 +1,11 @@
|
|
1
|
-
use
|
1
|
+
use hashbrown::hash_map::RawEntryMut;
|
2
|
+
use hashbrown::HashMap;
|
2
3
|
use magnus::{exception::*, Error, RArray};
|
4
|
+
use std::hash::{BuildHasher, Hash, Hasher};
|
3
5
|
use std::mem::size_of;
|
4
6
|
|
5
7
|
use crate::error::MmapError;
|
6
|
-
use crate::file_entry::{EntryData, EntryMetadata, FileEntry};
|
8
|
+
use crate::file_entry::{BorrowedData, EntryData, EntryMetadata, FileEntry};
|
7
9
|
use crate::file_info::FileInfo;
|
8
10
|
use crate::raw_entry::RawEntry;
|
9
11
|
use crate::util::read_u32;
|
@@ -17,12 +19,12 @@ use crate::{err, HEADER_SIZE};
|
|
17
19
|
/// allows us to have multiple entries on the map for multiple pids using the
|
18
20
|
/// same string.
|
19
21
|
#[derive(Default, Debug)]
|
20
|
-
pub struct EntryMap(
|
22
|
+
pub struct EntryMap(HashMap<EntryData, EntryMetadata>);
|
21
23
|
|
22
24
|
impl EntryMap {
|
23
25
|
/// Construct a new EntryMap.
|
24
26
|
pub fn new() -> Self {
|
25
|
-
Self(
|
27
|
+
Self(HashMap::new())
|
26
28
|
}
|
27
29
|
|
28
30
|
/// Given a list of files, read each one into memory and parse the metrics it contains.
|
@@ -95,12 +97,28 @@ impl EntryMap {
|
|
95
97
|
/// Check if the `EntryMap` already contains the JSON string.
|
96
98
|
/// If yes, update the associated value, if not insert the
|
97
99
|
/// entry into the map.
|
98
|
-
pub fn merge_or_store(&mut self, data:
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
100
|
+
pub fn merge_or_store(&mut self, data: BorrowedData, meta: EntryMetadata) -> Result<()> {
|
101
|
+
// Manually hash the `BorrowedData` and perform an equality check on the
|
102
|
+
// key. This allows us to perform the comparison without allocating a
|
103
|
+
// new `EntryData` that may not be needed.
|
104
|
+
let mut state = self.0.hasher().build_hasher();
|
105
|
+
data.hash(&mut state);
|
106
|
+
let hash = state.finish();
|
107
|
+
|
108
|
+
match self.0.raw_entry_mut().from_hash(hash, |k| k == &data) {
|
109
|
+
RawEntryMut::Vacant(entry) => {
|
110
|
+
// Allocate a new `EntryData` as the JSON/pid combination is
|
111
|
+
// not present in the map.
|
112
|
+
let owned = EntryData::try_from(data)?;
|
113
|
+
entry.insert(owned, meta);
|
114
|
+
}
|
115
|
+
RawEntryMut::Occupied(mut entry) => {
|
116
|
+
let existing = entry.get_mut();
|
117
|
+
existing.merge(&meta);
|
118
|
+
}
|
103
119
|
}
|
120
|
+
|
121
|
+
Ok(())
|
104
122
|
}
|
105
123
|
|
106
124
|
/// Parse metrics data from a `.db` file and store in the `EntryMap`.
|
@@ -135,9 +153,9 @@ impl EntryMap {
|
|
135
153
|
}
|
136
154
|
|
137
155
|
let meta = EntryMetadata::new(&raw_entry, &file_info)?;
|
138
|
-
let data =
|
156
|
+
let data = BorrowedData::new(&raw_entry, &file_info, meta.is_pid_significant())?;
|
139
157
|
|
140
|
-
self.merge_or_store(data, meta)
|
158
|
+
self.merge_or_store(data, meta)?;
|
141
159
|
|
142
160
|
pos += raw_entry.total_len();
|
143
161
|
}
|
@@ -155,6 +173,16 @@ mod test {
|
|
155
173
|
use crate::file_entry::FileEntry;
|
156
174
|
use crate::testhelper::{self, TestFile};
|
157
175
|
|
176
|
+
impl EntryData {
|
177
|
+
/// A helper function for tests to convert owned data to references.
|
178
|
+
fn as_borrowed(&self) -> BorrowedData {
|
179
|
+
BorrowedData {
|
180
|
+
json: &self.json,
|
181
|
+
pid: self.pid.as_deref(),
|
182
|
+
}
|
183
|
+
}
|
184
|
+
}
|
185
|
+
|
158
186
|
#[test]
|
159
187
|
fn test_into_sorted() {
|
160
188
|
let _cleanup = unsafe { magnus::embed::init() };
|
@@ -311,7 +339,9 @@ mod test {
|
|
311
339
|
map.0
|
312
340
|
.insert(starting_entry.data.clone(), starting_entry.meta.clone());
|
313
341
|
|
314
|
-
|
342
|
+
let matching_borrowed = matching_entry.data.as_borrowed();
|
343
|
+
map.merge_or_store(matching_borrowed, matching_entry.meta)
|
344
|
+
.unwrap();
|
315
345
|
|
316
346
|
assert_eq!(
|
317
347
|
5.0,
|
@@ -320,10 +350,12 @@ mod test {
|
|
320
350
|
);
|
321
351
|
assert_eq!(1, map.0.len(), "no entry added");
|
322
352
|
|
353
|
+
let same_key_different_worker_borrowed = same_key_different_worker.data.as_borrowed();
|
323
354
|
map.merge_or_store(
|
324
|
-
|
355
|
+
same_key_different_worker_borrowed,
|
325
356
|
same_key_different_worker.meta,
|
326
|
-
)
|
357
|
+
)
|
358
|
+
.unwrap();
|
327
359
|
|
328
360
|
assert_eq!(
|
329
361
|
5.0,
|
@@ -333,7 +365,9 @@ mod test {
|
|
333
365
|
|
334
366
|
assert_eq!(2, map.0.len(), "additional entry added");
|
335
367
|
|
336
|
-
|
368
|
+
let unmatched_entry_borrowed = unmatched_entry.data.as_borrowed();
|
369
|
+
map.merge_or_store(unmatched_entry_borrowed, unmatched_entry.meta)
|
370
|
+
.unwrap();
|
337
371
|
|
338
372
|
assert_eq!(
|
339
373
|
5.0,
|
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.20.
|
4
|
+
version: 0.20.2
|
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: 2023-04-
|
12
|
+
date: 2023-04-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rb_sys
|
@@ -130,7 +130,6 @@ files:
|
|
130
130
|
- ext/fast_mmaped_file/value_access.c
|
131
131
|
- ext/fast_mmaped_file/value_access.h
|
132
132
|
- ext/fast_mmaped_file_rs/.cargo/config.toml
|
133
|
-
- ext/fast_mmaped_file_rs/.tool-versions
|
134
133
|
- ext/fast_mmaped_file_rs/Cargo.lock
|
135
134
|
- ext/fast_mmaped_file_rs/Cargo.toml
|
136
135
|
- ext/fast_mmaped_file_rs/README.md
|
@@ -213,7 +212,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
213
212
|
- !ruby/object:Gem::Version
|
214
213
|
version: '0'
|
215
214
|
requirements: []
|
216
|
-
rubygems_version: 3.4.
|
215
|
+
rubygems_version: 3.4.12
|
217
216
|
signing_key:
|
218
217
|
specification_version: 4
|
219
218
|
summary: A suite of instrumentation metric primitivesthat can be exposed through a
|
@@ -1 +0,0 @@
|
|
1
|
-
rust 1.65.0
|