vinted-prometheus-client-mmap 1.5.0-x86_64-linux

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +5 -0
  3. data/ext/fast_mmaped_file_rs/Cargo.toml +40 -0
  4. data/ext/fast_mmaped_file_rs/README.md +52 -0
  5. data/ext/fast_mmaped_file_rs/build.rs +7 -0
  6. data/ext/fast_mmaped_file_rs/extconf.rb +28 -0
  7. data/ext/fast_mmaped_file_rs/src/error.rs +174 -0
  8. data/ext/fast_mmaped_file_rs/src/exemplars.rs +25 -0
  9. data/ext/fast_mmaped_file_rs/src/file_entry.rs +1252 -0
  10. data/ext/fast_mmaped_file_rs/src/file_info.rs +240 -0
  11. data/ext/fast_mmaped_file_rs/src/lib.rs +89 -0
  12. data/ext/fast_mmaped_file_rs/src/macros.rs +14 -0
  13. data/ext/fast_mmaped_file_rs/src/map.rs +519 -0
  14. data/ext/fast_mmaped_file_rs/src/metrics.proto +153 -0
  15. data/ext/fast_mmaped_file_rs/src/mmap/inner.rs +775 -0
  16. data/ext/fast_mmaped_file_rs/src/mmap.rs +977 -0
  17. data/ext/fast_mmaped_file_rs/src/raw_entry.rs +547 -0
  18. data/ext/fast_mmaped_file_rs/src/testhelper.rs +222 -0
  19. data/ext/fast_mmaped_file_rs/src/util.rs +140 -0
  20. data/lib/.DS_Store +0 -0
  21. data/lib/2.7/fast_mmaped_file_rs.so +0 -0
  22. data/lib/3.0/fast_mmaped_file_rs.so +0 -0
  23. data/lib/3.1/fast_mmaped_file_rs.so +0 -0
  24. data/lib/3.2/fast_mmaped_file_rs.so +0 -0
  25. data/lib/3.3/fast_mmaped_file_rs.so +0 -0
  26. data/lib/prometheus/.DS_Store +0 -0
  27. data/lib/prometheus/client/configuration.rb +24 -0
  28. data/lib/prometheus/client/counter.rb +27 -0
  29. data/lib/prometheus/client/formats/protobuf.rb +93 -0
  30. data/lib/prometheus/client/formats/text.rb +85 -0
  31. data/lib/prometheus/client/gauge.rb +40 -0
  32. data/lib/prometheus/client/helper/entry_parser.rb +132 -0
  33. data/lib/prometheus/client/helper/file_locker.rb +50 -0
  34. data/lib/prometheus/client/helper/json_parser.rb +23 -0
  35. data/lib/prometheus/client/helper/metrics_processing.rb +45 -0
  36. data/lib/prometheus/client/helper/metrics_representation.rb +51 -0
  37. data/lib/prometheus/client/helper/mmaped_file.rb +64 -0
  38. data/lib/prometheus/client/helper/plain_file.rb +29 -0
  39. data/lib/prometheus/client/histogram.rb +80 -0
  40. data/lib/prometheus/client/label_set_validator.rb +85 -0
  41. data/lib/prometheus/client/metric.rb +80 -0
  42. data/lib/prometheus/client/mmaped_dict.rb +83 -0
  43. data/lib/prometheus/client/mmaped_value.rb +164 -0
  44. data/lib/prometheus/client/page_size.rb +17 -0
  45. data/lib/prometheus/client/push.rb +203 -0
  46. data/lib/prometheus/client/rack/collector.rb +88 -0
  47. data/lib/prometheus/client/rack/exporter.rb +102 -0
  48. data/lib/prometheus/client/registry.rb +65 -0
  49. data/lib/prometheus/client/simple_value.rb +31 -0
  50. data/lib/prometheus/client/summary.rb +69 -0
  51. data/lib/prometheus/client/support/puma.rb +44 -0
  52. data/lib/prometheus/client/support/unicorn.rb +35 -0
  53. data/lib/prometheus/client/uses_value_type.rb +20 -0
  54. data/lib/prometheus/client/version.rb +5 -0
  55. data/lib/prometheus/client.rb +58 -0
  56. data/lib/prometheus.rb +3 -0
  57. metadata +210 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e813eec5d2233337d34cd3f19c79e68a9b38b63e45607b3dd0929fbcf84e353f
4
+ data.tar.gz: 979ebaef61c83ecf0e6eeb85c85581e3869c269e7868d3194d6d6faab2c83bf4
5
+ SHA512:
6
+ metadata.gz: 1df8af4b3368826fde07874b89b14648a66f193a5c5a945bcda4fc6e9588500ddf800866ce2af04c573474b2c8aa5b1ee275674ba45dabc82539345b42f4ff10
7
+ data.tar.gz: 51c47ecccd1d1f0afb6c4543837c43657f203dc8b391b3ff4ed57a947499a6a7e98375be644eb5cd1033f2fc901f38cc4b663944ffb2a76c2ad8cbcd856bc27d
data/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # vinted-prometheus-client-mmap
2
+
3
+ ### ! This gem is part of the Engineering Hackathon, not to be used in production
4
+
5
+ Forked prometheus-client-mmap gem
@@ -0,0 +1,40 @@
1
+ [package]
2
+ name = "fast_mmaped_file_rs"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+
6
+ # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7
+
8
+ [dependencies]
9
+ prost = "0.12"
10
+ prost-types = "0.12"
11
+ hashbrown = "0.14"
12
+ varint-rs = "2.2.0"
13
+ itertools = "0.11.0"
14
+ libc = "0.2"
15
+ magnus = { version = "0.6", features = ["rb-sys"] }
16
+ memmap2 = "0.9"
17
+ # v0.26 cannot be built on CentOS 7 https://github.com/nix-rust/nix/issues/1972
18
+ nix = { version = "0.25", features = ["mman"] } # mman used for MsFlags
19
+ rb-sys = { version = "0.9", features = ["stable-api-compiled-fallback"] }
20
+ serde = { version = "1.0", features = ["derive"] }
21
+ serde_json = { version = "1.0", features = ["raw_value"] }
22
+ smallvec = { version = "1.10", features = ["serde"] }
23
+ thiserror = "1.0"
24
+
25
+ [dev-dependencies]
26
+ bstr = "1.9"
27
+ indoc = "2.0"
28
+ # We need the `embed` feature to run tests, but this triggers failures when building as a Gem.
29
+ magnus = { version = "0.6", features = ["rb-sys","embed"] }
30
+ rand = "0.8"
31
+ sha2 = "0.10"
32
+ tempfile = "3.9"
33
+
34
+ [build-dependencies]
35
+ rb-sys-env = "0.1"
36
+ prost-build = "0.12"
37
+
38
+ [lib]
39
+ # Integration tests won't work if crate is only `cdylib`.
40
+ crate-type = ["cdylib","lib"]
@@ -0,0 +1,52 @@
1
+ # Testing
2
+
3
+ ## Running Tests
4
+
5
+ Use [cargo nextest](https://nexte.st/) to execute the Rust unit tests.
6
+
7
+ ```sh
8
+ $ cargo nextest run
9
+ ```
10
+
11
+ ## Why not use 'cargo test'?
12
+
13
+ We need to embed Ruby into the test binary to access Ruby types. This requires
14
+ us to run `magnus::embed::init()` no more than once before calling Ruby.
15
+ See [the magnus docs](https://docs.rs/magnus/latest/magnus/embed/fn.init.html)
16
+ for more details.
17
+
18
+ If we try to create separate `#[test]` functions that call `init()` these will
19
+ conflict, as Cargo runs tests in parallel using a single process with separate
20
+ threads. Running `cargo test` will result in errors like:
21
+
22
+ ```
23
+ ---- file_info::test::with_ruby stdout ----
24
+ thread 'file_info::test::with_ruby' panicked at 'Ruby already initialized'
25
+ ```
26
+
27
+ The simplest workaround for this is to avoid using `cargo test` to run unit
28
+ tests. [nextest](https://nexte.st/) is an alternate test harness that runs each
29
+ test as its own process, enabling each test to intitialize Ruby without
30
+ conflict.
31
+
32
+ ## 'symbol not found' errors when running tests
33
+
34
+ If you see errors like the following when running tests:
35
+
36
+ ```
37
+ Caused by:
38
+ for `fast_mmaped_file_rs`, command `/Users/myuser/prometheus-client-mmap/ext/fast_mmaped_file_rs/target/debug/deps/fast_mmaped_file_rs-c81ccc96a6484e04 --list --format terse` exited with signal 6 (SIGABRT)
39
+ --- stdout:
40
+
41
+ --- stderr:
42
+ dyld[17861]: symbol not found in flat namespace '_rb_cArray'
43
+ ```
44
+
45
+ Clearing the build cache will resolve the problem.
46
+
47
+ ```sh
48
+ $ cargo clean
49
+ ```
50
+
51
+ This is probably due to separate features being used with `magnus` in
52
+ development builds.
@@ -0,0 +1,7 @@
1
+ fn main() -> Result<(), Box<dyn std::error::Error>> {
2
+ let _ = rb_sys_env::activate()?;
3
+ prost_build::compile_protos(&["src/metrics.proto"], &["src/"])
4
+ .expect("failed compile protobufs");
5
+
6
+ Ok(())
7
+ }
@@ -0,0 +1,28 @@
1
+ require "mkmf"
2
+ require "rb_sys/mkmf"
3
+
4
+ if find_executable('rustc')
5
+ create_rust_makefile("fast_mmaped_file_rs") do |r|
6
+ r.auto_install_rust_toolchain = false
7
+
8
+ if enable_config('fail-on-warning')
9
+ r.extra_rustflags = ["-Dwarnings"]
10
+ end
11
+
12
+ if enable_config('debug')
13
+ r.profile = :dev
14
+ end
15
+
16
+ if enable_config('address-sanitizer')
17
+ r.extra_rustflags = ["-Zsanitizer=address"]
18
+ end
19
+
20
+ # `rb_sys/mkmf` passes all arguments after `--` directly to `cargo rustc`.
21
+ # We use this awful hack to keep compatibility with existing flags used by
22
+ # the C implementation.
23
+ trimmed_argv = ARGV.take_while { |arg| arg != "--" }
24
+ ARGV = trimmed_argv
25
+ end
26
+ else
27
+ raise 'rustc not found. prometheus-client-mmap now requires Rust.'
28
+ end
@@ -0,0 +1,174 @@
1
+ use magnus::{exception, Ruby};
2
+ use std::any;
3
+ use std::fmt::Display;
4
+ use std::io;
5
+ use std::path::Path;
6
+ use thiserror::Error;
7
+
8
+ use crate::util;
9
+ use crate::PROM_EPARSING_ERROR;
10
+
11
+ /// A lightweight representation of Ruby ExceptionClasses.
12
+ #[derive(PartialEq, Eq, Clone, Copy, Debug)]
13
+ pub enum RubyError {
14
+ Arg,
15
+ Encoding,
16
+ Frozen,
17
+ Index,
18
+ Io,
19
+ NoMem,
20
+ PromParsing,
21
+ Runtime,
22
+ Type,
23
+ }
24
+
25
+ impl From<RubyError> for magnus::ExceptionClass {
26
+ fn from(err: RubyError) -> magnus::ExceptionClass {
27
+ match err {
28
+ RubyError::Arg => exception::arg_error(),
29
+ RubyError::Encoding => exception::encoding_error(),
30
+ RubyError::Frozen => exception::frozen_error(),
31
+ RubyError::Index => exception::index_error(),
32
+ RubyError::Io => exception::io_error(),
33
+ RubyError::NoMem => exception::no_mem_error(),
34
+ RubyError::Runtime => exception::runtime_error(),
35
+ RubyError::PromParsing => {
36
+ // UNWRAP: this will panic if called outside of a Ruby thread.
37
+ let ruby = Ruby::get().unwrap();
38
+ ruby.get_inner(&PROM_EPARSING_ERROR)
39
+ }
40
+ RubyError::Type => exception::type_error(),
41
+ }
42
+ }
43
+ }
44
+
45
+ /// Errors returned internally within the crate. Methods called directly by Ruby return
46
+ /// `magnus::error::Error` as do functions that interact heavily with Ruby. This can be
47
+ /// converted into a `magnus::error::Error` at the boundary between Rust and Ruby.
48
+ #[derive(PartialEq, Eq, Error, Debug)]
49
+ pub enum MmapError {
50
+ /// A read or write was made while another thread had mutable access to the mmap.
51
+ #[error("read/write operation attempted while mmap was being written to")]
52
+ ConcurrentAccess,
53
+ /// An error message used to exactly match the messages returned by the C
54
+ /// implementation.
55
+ #[error("{0}")]
56
+ Legacy(String, RubyError),
57
+ /// A String had invalid UTF-8 sequences.
58
+ #[error("{0}")]
59
+ Encoding(String),
60
+ /// A failed attempt to cast an integer from one type to another.
61
+ #[error("failed to cast {object_name} {value} from {from} to {to}")]
62
+ FailedCast {
63
+ from: &'static str,
64
+ to: &'static str,
65
+ value: String,
66
+ object_name: String,
67
+ },
68
+ /// The mmap was frozen when a mutable operation was attempted.
69
+ #[error("mmap")]
70
+ Frozen,
71
+ /// An io operation failed.
72
+ #[error("failed to {operation} path '{path}': {err}")]
73
+ Io {
74
+ operation: String,
75
+ path: String,
76
+ err: String,
77
+ },
78
+ #[error("string length gt {}", i32::MAX)]
79
+ KeyLength,
80
+ /// Failed to allocate memory.
81
+ #[error("Couldn't allocate for {0} memory")]
82
+ OutOfMemory(usize),
83
+ /// A memory operation fell outside of the containers bounds.
84
+ #[error("offset {index} out of bounds of len {len}")]
85
+ OutOfBounds { index: String, len: String },
86
+ /// A numeric operation overflowed.
87
+ #[error("overflow when {op} {value} and {added} of type {ty}")]
88
+ Overflow {
89
+ value: String,
90
+ added: String,
91
+ op: String,
92
+ ty: &'static str,
93
+ },
94
+ /// A miscellaneous error.
95
+ #[error("{0}")]
96
+ Other(String),
97
+ /// A failure when parsing a `.db` file containing Prometheus metrics.
98
+ #[error("{0}")]
99
+ PromParsing(String),
100
+ /// No mmap open.
101
+ #[error("unmapped file")]
102
+ UnmappedFile,
103
+ /// A custom error message with `strerror(3)` appended.
104
+ #[error("{0}")]
105
+ WithErrno(String),
106
+ }
107
+
108
+ impl MmapError {
109
+ pub fn legacy<T: Into<String>>(msg: T, ruby_err: RubyError) -> Self {
110
+ MmapError::Legacy(msg.into(), ruby_err)
111
+ }
112
+
113
+ pub fn failed_cast<T: Display, U>(value: T, object_name: &str) -> Self {
114
+ MmapError::FailedCast {
115
+ from: any::type_name::<T>(),
116
+ to: any::type_name::<U>(),
117
+ value: value.to_string(),
118
+ object_name: object_name.to_string(),
119
+ }
120
+ }
121
+ pub fn io(operation: &str, path: &Path, err: io::Error) -> Self {
122
+ MmapError::Io {
123
+ operation: operation.to_string(),
124
+ path: path.display().to_string(),
125
+ err: err.to_string(),
126
+ }
127
+ }
128
+
129
+ pub fn overflowed<T: Display>(value: T, added: T, op: &str) -> Self {
130
+ MmapError::Overflow {
131
+ value: value.to_string(),
132
+ added: added.to_string(),
133
+ op: op.to_string(),
134
+ ty: any::type_name::<T>(),
135
+ }
136
+ }
137
+
138
+ pub fn out_of_bounds<T: Display>(index: T, len: T) -> Self {
139
+ MmapError::OutOfBounds {
140
+ index: index.to_string(),
141
+ len: len.to_string(),
142
+ }
143
+ }
144
+
145
+ pub fn with_errno<T: Into<String>>(msg: T) -> Self {
146
+ let strerror = util::strerror(util::errno());
147
+ MmapError::WithErrno(format!("{}: ({strerror})", msg.into()))
148
+ }
149
+
150
+ pub fn ruby_err(&self) -> RubyError {
151
+ match self {
152
+ MmapError::ConcurrentAccess => RubyError::Arg,
153
+ MmapError::Legacy(_, e) => *e,
154
+ MmapError::Encoding(_) => RubyError::Encoding,
155
+ MmapError::Io { .. } => RubyError::Io,
156
+ MmapError::FailedCast { .. } => RubyError::Arg,
157
+ MmapError::Frozen => RubyError::Frozen,
158
+ MmapError::KeyLength => RubyError::Arg,
159
+ MmapError::Overflow { .. } => RubyError::Arg,
160
+ MmapError::OutOfBounds { .. } => RubyError::Index,
161
+ MmapError::OutOfMemory { .. } => RubyError::NoMem,
162
+ MmapError::Other(_) => RubyError::Arg,
163
+ MmapError::PromParsing(_) => RubyError::PromParsing,
164
+ MmapError::UnmappedFile => RubyError::Io,
165
+ MmapError::WithErrno(_) => RubyError::Io,
166
+ }
167
+ }
168
+ }
169
+
170
+ impl From<MmapError> for magnus::error::Error {
171
+ fn from(err: MmapError) -> magnus::error::Error {
172
+ magnus::error::Error::new(err.ruby_err().into(), err.to_string())
173
+ }
174
+ }
@@ -0,0 +1,25 @@
1
+ #[derive(Clone, Debug, Serialize, Deserialize)]
2
+ pub struct Exemplar {
3
+ // Labels (set of label names/values). Only 1 for now.
4
+ // Value -> f64.
5
+ // Timestamp -> uint64.
6
+ // We have to cap the maximum size of strings.
7
+ // From the spec:
8
+ // The combined length of the label names and values of an Exemplar's LabelSet MUST NOT exceed 128 UTF-8 character code points.
9
+ // 4 bytes max per code point.
10
+ // So, we need to allocate 128*4 = 512 bytes for the label names and values.
11
+ pub label_name: String,
12
+
13
+ pub label_value: String,
14
+ pub value: f64,
15
+ pub timestamp: u128,
16
+ }
17
+
18
+ use serde::{Deserialize, Serialize};
19
+
20
+ use crate::size_of;
21
+
22
+ pub const EXEMPLAR_ENTRY_MAX_SIZE_BYTES:usize = 512 + size_of::<f64>() + size_of::<u64>();
23
+
24
+ // Key -> use the old one.
25
+ // Value -> allocate EXEMPLAR_ENTRY_MAX_SIZE_BYTES. If it exceeds this, we need to return an error. Use JSON.