fast-prometheus 0.1.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.
Files changed (35) hide show
  1. checksums.yaml +7 -0
  2. data/AGENTS.md +38 -0
  3. data/CHANGELOG.md +59 -0
  4. data/README.md +109 -0
  5. data/lib/fast/prometheus/counter.rb +22 -0
  6. data/lib/fast/prometheus/errors.rb +11 -0
  7. data/lib/fast/prometheus/exposition.rb +46 -0
  8. data/lib/fast/prometheus/formats/metrics_pb.rb +33 -0
  9. data/lib/fast/prometheus/formats/protobuf.rb +154 -0
  10. data/lib/fast/prometheus/formats/text.rb +90 -0
  11. data/lib/fast/prometheus/gauge.rb +37 -0
  12. data/lib/fast/prometheus/histogram.rb +112 -0
  13. data/lib/fast/prometheus/metric.rb +144 -0
  14. data/lib/fast/prometheus/middleware/exporter.rb +39 -0
  15. data/lib/fast/prometheus/middleware/instrumentation.rb +34 -0
  16. data/lib/fast/prometheus/native_histogram.rb +145 -0
  17. data/lib/fast/prometheus/otlp/grpc_exporter.rb +39 -0
  18. data/lib/fast/prometheus/otlp/http_exporter.rb +43 -0
  19. data/lib/fast/prometheus/otlp/mapper.rb +207 -0
  20. data/lib/fast/prometheus/otlp/pb/opentelemetry/proto/collector/metrics/v1/metrics_service_pb.rb +27 -0
  21. data/lib/fast/prometheus/otlp/pb/opentelemetry/proto/common/v1/common_pb.rb +26 -0
  22. data/lib/fast/prometheus/otlp/pb/opentelemetry/proto/metrics/v1/metrics_pb.rb +41 -0
  23. data/lib/fast/prometheus/otlp/pb/opentelemetry/proto/resource/v1/resource_pb.rb +23 -0
  24. data/lib/fast/prometheus/otlp/push.rb +39 -0
  25. data/lib/fast/prometheus/otlp/service_interface.rb +18 -0
  26. data/lib/fast/prometheus/rack/exporter.rb +32 -0
  27. data/lib/fast/prometheus/rack/instrumentation.rb +33 -0
  28. data/lib/fast/prometheus/registry.rb +111 -0
  29. data/lib/fast/prometheus/request_metrics.rb +45 -0
  30. data/lib/fast/prometheus/snapshot.rb +78 -0
  31. data/lib/fast/prometheus/store.rb +37 -0
  32. data/lib/fast/prometheus/summary.rb +50 -0
  33. data/lib/fast/prometheus/version.rb +7 -0
  34. data/lib/fast/prometheus.rb +17 -0
  35. metadata +158 -0
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fast
4
+ module Prometheus
5
+ # Immutable value types for snapshots. Deep-frozen Data types.
6
+
7
+ HistogramValue = Data.define(:sum, :count, :cumulative_buckets)
8
+
9
+ NativeHistogramValue = Data.define(:schema, :zero_threshold, :zero_count, :sum, :count,
10
+ :positive_buckets, :negative_buckets)
11
+
12
+ Series = Data.define(:labels, :value)
13
+
14
+ SummaryValue = Data.define(:sum, :count)
15
+
16
+ MetricSnapshot = Data.define(:name, :docstring, :type, :label_names, :series) do
17
+ # Build a MetricSnapshot from a live metric. Reads only public readers
18
+ # and copies all mutable structures. The whole build runs under the
19
+ # metric's lock so no series is observed mid-mutation and no writer
20
+ # interleaves between series.
21
+ def self.of(metric)
22
+ metric.synchronize do
23
+ new(
24
+ metric.name,
25
+ metric.docstring,
26
+ metric.type,
27
+ metric.label_names.dup.freeze,
28
+ build_series(metric).freeze
29
+ )
30
+ end
31
+ end
32
+
33
+ def self.build_series(metric)
34
+ metric.values.map do |labels, value|
35
+ Series.new(
36
+ labels: labels.dup.freeze,
37
+ value: build_value(metric.type, value)
38
+ )
39
+ end
40
+ end
41
+
42
+ private_class_method def self.build_value(type, value)
43
+ case type
44
+ when :counter, :gauge
45
+ value
46
+ when :histogram
47
+ HistogramValue.new(
48
+ sum: value.sum,
49
+ count: value.count,
50
+ cumulative_buckets: value.cumulative_buckets.map { |pair| pair.dup.freeze }.freeze
51
+ )
52
+ when :summary
53
+ SummaryValue.new(sum: value.sum, count: value.count)
54
+ when :native_histogram
55
+ NativeHistogramValue.new(
56
+ schema: value.schema,
57
+ zero_threshold: value.zero_threshold,
58
+ zero_count: value.zero_count,
59
+ sum: value.sum,
60
+ count: value.count,
61
+ positive_buckets: value.positive_buckets.map { |pair| pair.dup.freeze }.freeze,
62
+ negative_buckets: value.negative_buckets.map { |pair| pair.dup.freeze }.freeze
63
+ )
64
+ end
65
+ end
66
+ end
67
+
68
+ Snapshot = Data.define(:metrics, :taken_at) do
69
+ # Build a Snapshot from an array of live metrics.
70
+ def self.of(metrics)
71
+ new(
72
+ metrics.map { |metric| MetricSnapshot.of(metric) }.freeze,
73
+ Time.now
74
+ )
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "monitor"
4
+
5
+ module Fast
6
+ module Prometheus
7
+ # Store holds one metric's per-series data plus the lock guarding it.
8
+ # Metrics produced by Metric#with_labels share their parent's Store (and
9
+ # therefore its lock) via the store: keyword.
10
+ #
11
+ # Monitor is reentrant: a thread already inside #synchronize (e.g. a
12
+ # derived reader delegating to another locked method, or Metric#synchronize
13
+ # driving MetricSnapshot.of) can re-enter without deadlocking itself.
14
+ class Store
15
+ def initialize
16
+ @data = {}
17
+ @monitor = Monitor.new
18
+ end
19
+
20
+ def synchronize(&block)
21
+ @monitor.synchronize(&block)
22
+ end
23
+
24
+ def [](key)
25
+ @data[key]
26
+ end
27
+
28
+ def []=(key, value)
29
+ @data[key] = value
30
+ end
31
+
32
+ def to_h
33
+ @data.dup
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "metric"
4
+
5
+ module Fast
6
+ module Prometheus
7
+ # Summary accumulates observations as sum + count per label set.
8
+ # Unlike the histogram, it provides no quantile computation.
9
+ class Summary < Metric
10
+ # Value holds the accumulated sum and count for a single label set.
11
+ class Value
12
+ attr_accessor :sum, :count
13
+
14
+ def initialize
15
+ @sum = 0.0
16
+ @count = 0
17
+ end
18
+ end
19
+
20
+ def type
21
+ :summary
22
+ end
23
+
24
+ def observe(value, labels: {})
25
+ key = resolve(labels)
26
+ store.synchronize do
27
+ slot = store[key] ||= Value.new
28
+ slot.sum += value
29
+ slot.count += 1
30
+ end
31
+ end
32
+
33
+ def get(labels: {})
34
+ key = resolve(labels)
35
+ store.synchronize { store[key] }
36
+ end
37
+
38
+ protected
39
+
40
+ def validate_label_names(labels)
41
+ labels.each do |label|
42
+ name = label.to_s
43
+ raise InvalidLabelName, "reserved label name: :quantile" if name == "quantile"
44
+ end
45
+
46
+ super
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fast
4
+ module Prometheus
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "prometheus/version"
4
+ require_relative "prometheus/errors"
5
+ require_relative "prometheus/metric"
6
+ require_relative "prometheus/counter"
7
+ require_relative "prometheus/gauge"
8
+ require_relative "prometheus/histogram"
9
+ require_relative "prometheus/summary"
10
+ require_relative "prometheus/native_histogram"
11
+ require_relative "prometheus/registry"
12
+ require_relative "prometheus/snapshot"
13
+
14
+ module Fast
15
+ module Prometheus
16
+ end
17
+ end
metadata ADDED
@@ -0,0 +1,158 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fast-prometheus
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Eric Jacobs
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: async
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '2.38'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '2.38'
26
+ - !ruby/object:Gem::Dependency
27
+ name: protocol-http
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '0.60'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.60'
40
+ - !ruby/object:Gem::Dependency
41
+ name: async-http
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '0.95'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0.95'
54
+ - !ruby/object:Gem::Dependency
55
+ name: async-grpc
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '0.7'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '0.7'
68
+ - !ruby/object:Gem::Dependency
69
+ name: google-protobuf
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '4.35'
75
+ type: :runtime
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '4.35'
82
+ - !ruby/object:Gem::Dependency
83
+ name: console
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '1.37'
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '1.37'
96
+ executables: []
97
+ extensions: []
98
+ extra_rdoc_files: []
99
+ files:
100
+ - AGENTS.md
101
+ - CHANGELOG.md
102
+ - README.md
103
+ - lib/fast/prometheus.rb
104
+ - lib/fast/prometheus/counter.rb
105
+ - lib/fast/prometheus/errors.rb
106
+ - lib/fast/prometheus/exposition.rb
107
+ - lib/fast/prometheus/formats/metrics_pb.rb
108
+ - lib/fast/prometheus/formats/protobuf.rb
109
+ - lib/fast/prometheus/formats/text.rb
110
+ - lib/fast/prometheus/gauge.rb
111
+ - lib/fast/prometheus/histogram.rb
112
+ - lib/fast/prometheus/metric.rb
113
+ - lib/fast/prometheus/middleware/exporter.rb
114
+ - lib/fast/prometheus/middleware/instrumentation.rb
115
+ - lib/fast/prometheus/native_histogram.rb
116
+ - lib/fast/prometheus/otlp/grpc_exporter.rb
117
+ - lib/fast/prometheus/otlp/http_exporter.rb
118
+ - lib/fast/prometheus/otlp/mapper.rb
119
+ - lib/fast/prometheus/otlp/pb/opentelemetry/proto/collector/metrics/v1/metrics_service_pb.rb
120
+ - lib/fast/prometheus/otlp/pb/opentelemetry/proto/common/v1/common_pb.rb
121
+ - lib/fast/prometheus/otlp/pb/opentelemetry/proto/metrics/v1/metrics_pb.rb
122
+ - lib/fast/prometheus/otlp/pb/opentelemetry/proto/resource/v1/resource_pb.rb
123
+ - lib/fast/prometheus/otlp/push.rb
124
+ - lib/fast/prometheus/otlp/service_interface.rb
125
+ - lib/fast/prometheus/rack/exporter.rb
126
+ - lib/fast/prometheus/rack/instrumentation.rb
127
+ - lib/fast/prometheus/registry.rb
128
+ - lib/fast/prometheus/request_metrics.rb
129
+ - lib/fast/prometheus/snapshot.rb
130
+ - lib/fast/prometheus/store.rb
131
+ - lib/fast/prometheus/summary.rb
132
+ - lib/fast/prometheus/version.rb
133
+ homepage: https://github.com/jetpks/fast-prometheus
134
+ licenses:
135
+ - MIT
136
+ metadata:
137
+ homepage_uri: https://github.com/jetpks/fast-prometheus
138
+ source_code_uri: https://github.com/jetpks/fast-prometheus
139
+ changelog_uri: https://github.com/jetpks/fast-prometheus/blob/main/CHANGELOG.md
140
+ rubygems_mfa_required: 'true'
141
+ rdoc_options: []
142
+ require_paths:
143
+ - lib
144
+ required_ruby_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ version: '3.3'
149
+ required_rubygems_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ requirements: []
155
+ rubygems_version: 4.0.10
156
+ specification_version: 4
157
+ summary: A fiber-native Prometheus client for modern Ruby.
158
+ test_files: []