decision_agent 0.2.0 → 1.0.1

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 (126) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +313 -8
  3. data/bin/decision_agent +104 -0
  4. data/lib/decision_agent/agent.rb +72 -1
  5. data/lib/decision_agent/context.rb +1 -0
  6. data/lib/decision_agent/data_enrichment/cache/memory_adapter.rb +86 -0
  7. data/lib/decision_agent/data_enrichment/cache_adapter.rb +49 -0
  8. data/lib/decision_agent/data_enrichment/circuit_breaker.rb +135 -0
  9. data/lib/decision_agent/data_enrichment/client.rb +220 -0
  10. data/lib/decision_agent/data_enrichment/config.rb +78 -0
  11. data/lib/decision_agent/data_enrichment/errors.rb +36 -0
  12. data/lib/decision_agent/decision.rb +102 -2
  13. data/lib/decision_agent/dmn/adapter.rb +135 -0
  14. data/lib/decision_agent/dmn/cache.rb +306 -0
  15. data/lib/decision_agent/dmn/decision_graph.rb +327 -0
  16. data/lib/decision_agent/dmn/decision_tree.rb +192 -0
  17. data/lib/decision_agent/dmn/errors.rb +30 -0
  18. data/lib/decision_agent/dmn/exporter.rb +217 -0
  19. data/lib/decision_agent/dmn/feel/evaluator.rb +819 -0
  20. data/lib/decision_agent/dmn/feel/functions.rb +420 -0
  21. data/lib/decision_agent/dmn/feel/parser.rb +349 -0
  22. data/lib/decision_agent/dmn/feel/simple_parser.rb +276 -0
  23. data/lib/decision_agent/dmn/feel/transformer.rb +372 -0
  24. data/lib/decision_agent/dmn/feel/types.rb +276 -0
  25. data/lib/decision_agent/dmn/importer.rb +77 -0
  26. data/lib/decision_agent/dmn/model.rb +197 -0
  27. data/lib/decision_agent/dmn/parser.rb +191 -0
  28. data/lib/decision_agent/dmn/testing.rb +333 -0
  29. data/lib/decision_agent/dmn/validator.rb +315 -0
  30. data/lib/decision_agent/dmn/versioning.rb +229 -0
  31. data/lib/decision_agent/dmn/visualizer.rb +513 -0
  32. data/lib/decision_agent/dsl/condition_evaluator.rb +984 -838
  33. data/lib/decision_agent/dsl/schema_validator.rb +53 -14
  34. data/lib/decision_agent/evaluators/dmn_evaluator.rb +308 -0
  35. data/lib/decision_agent/evaluators/json_rule_evaluator.rb +69 -9
  36. data/lib/decision_agent/explainability/condition_trace.rb +83 -0
  37. data/lib/decision_agent/explainability/explainability_result.rb +52 -0
  38. data/lib/decision_agent/explainability/rule_trace.rb +39 -0
  39. data/lib/decision_agent/explainability/trace_collector.rb +24 -0
  40. data/lib/decision_agent/monitoring/alert_manager.rb +5 -1
  41. data/lib/decision_agent/simulation/errors.rb +18 -0
  42. data/lib/decision_agent/simulation/impact_analyzer.rb +498 -0
  43. data/lib/decision_agent/simulation/monte_carlo_simulator.rb +635 -0
  44. data/lib/decision_agent/simulation/replay_engine.rb +486 -0
  45. data/lib/decision_agent/simulation/scenario_engine.rb +318 -0
  46. data/lib/decision_agent/simulation/scenario_library.rb +163 -0
  47. data/lib/decision_agent/simulation/shadow_test_engine.rb +287 -0
  48. data/lib/decision_agent/simulation/what_if_analyzer.rb +1002 -0
  49. data/lib/decision_agent/simulation.rb +17 -0
  50. data/lib/decision_agent/version.rb +1 -1
  51. data/lib/decision_agent/versioning/activerecord_adapter.rb +23 -8
  52. data/lib/decision_agent/web/dmn_editor.rb +426 -0
  53. data/lib/decision_agent/web/public/app.js +119 -0
  54. data/lib/decision_agent/web/public/dmn-editor.css +596 -0
  55. data/lib/decision_agent/web/public/dmn-editor.html +250 -0
  56. data/lib/decision_agent/web/public/dmn-editor.js +553 -0
  57. data/lib/decision_agent/web/public/index.html +52 -0
  58. data/lib/decision_agent/web/public/simulation.html +130 -0
  59. data/lib/decision_agent/web/public/simulation_impact.html +478 -0
  60. data/lib/decision_agent/web/public/simulation_replay.html +551 -0
  61. data/lib/decision_agent/web/public/simulation_shadow.html +546 -0
  62. data/lib/decision_agent/web/public/simulation_whatif.html +532 -0
  63. data/lib/decision_agent/web/public/styles.css +86 -0
  64. data/lib/decision_agent/web/server.rb +1059 -23
  65. data/lib/decision_agent.rb +60 -2
  66. metadata +105 -61
  67. data/spec/ab_testing/ab_test_assignment_spec.rb +0 -253
  68. data/spec/ab_testing/ab_test_manager_spec.rb +0 -612
  69. data/spec/ab_testing/ab_test_spec.rb +0 -270
  70. data/spec/ab_testing/ab_testing_agent_spec.rb +0 -481
  71. data/spec/ab_testing/storage/adapter_spec.rb +0 -64
  72. data/spec/ab_testing/storage/memory_adapter_spec.rb +0 -485
  73. data/spec/activerecord_thread_safety_spec.rb +0 -553
  74. data/spec/advanced_operators_spec.rb +0 -3150
  75. data/spec/agent_spec.rb +0 -289
  76. data/spec/api_contract_spec.rb +0 -430
  77. data/spec/audit_adapters_spec.rb +0 -92
  78. data/spec/auth/access_audit_logger_spec.rb +0 -394
  79. data/spec/auth/authenticator_spec.rb +0 -112
  80. data/spec/auth/password_reset_spec.rb +0 -294
  81. data/spec/auth/permission_checker_spec.rb +0 -207
  82. data/spec/auth/permission_spec.rb +0 -73
  83. data/spec/auth/rbac_adapter_spec.rb +0 -550
  84. data/spec/auth/rbac_config_spec.rb +0 -82
  85. data/spec/auth/role_spec.rb +0 -51
  86. data/spec/auth/session_manager_spec.rb +0 -172
  87. data/spec/auth/session_spec.rb +0 -112
  88. data/spec/auth/user_spec.rb +0 -130
  89. data/spec/comprehensive_edge_cases_spec.rb +0 -1777
  90. data/spec/context_spec.rb +0 -127
  91. data/spec/decision_agent_spec.rb +0 -96
  92. data/spec/decision_spec.rb +0 -423
  93. data/spec/dsl/condition_evaluator_spec.rb +0 -774
  94. data/spec/dsl_validation_spec.rb +0 -648
  95. data/spec/edge_cases_spec.rb +0 -353
  96. data/spec/evaluation_spec.rb +0 -364
  97. data/spec/evaluation_validator_spec.rb +0 -165
  98. data/spec/examples/feedback_aware_evaluator_spec.rb +0 -460
  99. data/spec/examples.txt +0 -1633
  100. data/spec/issue_verification_spec.rb +0 -759
  101. data/spec/json_rule_evaluator_spec.rb +0 -587
  102. data/spec/monitoring/alert_manager_spec.rb +0 -378
  103. data/spec/monitoring/metrics_collector_spec.rb +0 -499
  104. data/spec/monitoring/monitored_agent_spec.rb +0 -222
  105. data/spec/monitoring/prometheus_exporter_spec.rb +0 -242
  106. data/spec/monitoring/storage/activerecord_adapter_spec.rb +0 -498
  107. data/spec/monitoring/storage/base_adapter_spec.rb +0 -61
  108. data/spec/monitoring/storage/memory_adapter_spec.rb +0 -247
  109. data/spec/performance_optimizations_spec.rb +0 -486
  110. data/spec/replay_edge_cases_spec.rb +0 -699
  111. data/spec/replay_spec.rb +0 -210
  112. data/spec/rfc8785_canonicalization_spec.rb +0 -215
  113. data/spec/scoring_spec.rb +0 -225
  114. data/spec/spec_helper.rb +0 -60
  115. data/spec/testing/batch_test_importer_spec.rb +0 -693
  116. data/spec/testing/batch_test_runner_spec.rb +0 -307
  117. data/spec/testing/test_coverage_analyzer_spec.rb +0 -292
  118. data/spec/testing/test_result_comparator_spec.rb +0 -392
  119. data/spec/testing/test_scenario_spec.rb +0 -113
  120. data/spec/thread_safety_spec.rb +0 -482
  121. data/spec/thread_safety_spec.rb.broken +0 -878
  122. data/spec/versioning/adapter_spec.rb +0 -156
  123. data/spec/versioning_spec.rb +0 -1030
  124. data/spec/web/middleware/auth_middleware_spec.rb +0 -133
  125. data/spec/web/middleware/permission_middleware_spec.rb +0 -247
  126. data/spec/web_ui_rack_spec.rb +0 -1840
@@ -1,222 +0,0 @@
1
- require "spec_helper"
2
- require "decision_agent/monitoring/metrics_collector"
3
- require "decision_agent/monitoring/monitored_agent"
4
-
5
- RSpec.describe DecisionAgent::Monitoring::MonitoredAgent do
6
- let(:collector) { DecisionAgent::Monitoring::MetricsCollector.new(storage: :memory) }
7
- let(:evaluator) do
8
- double(
9
- "Evaluator",
10
- evaluate: DecisionAgent::Evaluation.new(
11
- decision: "approve",
12
- weight: 0.9,
13
- reason: "Test reason",
14
- evaluator_name: "test_evaluator"
15
- )
16
- )
17
- end
18
- let(:agent) { DecisionAgent::Agent.new(evaluators: [evaluator]) }
19
- let(:monitored_agent) { described_class.new(agent: agent, metrics_collector: collector) }
20
-
21
- describe "#initialize" do
22
- it "wraps an agent with metrics collection" do
23
- expect(monitored_agent.agent).to eq(agent)
24
- expect(monitored_agent.metrics_collector).to eq(collector)
25
- end
26
- end
27
-
28
- describe "#decide" do
29
- let(:context) { { amount: 1000 } }
30
-
31
- it "makes a decision and records metrics" do
32
- result = monitored_agent.decide(context: context)
33
-
34
- expect(result).to be_a(DecisionAgent::Decision)
35
- expect(result.decision).to eq("approve")
36
- expect(collector.metrics_count[:decisions]).to eq(1)
37
- expect(collector.metrics_count[:evaluations]).to eq(1)
38
- expect(collector.metrics_count[:performance]).to eq(1)
39
- end
40
-
41
- it "records decision metrics with duration" do
42
- monitored_agent.decide(context: context)
43
-
44
- stats = collector.statistics
45
- expect(stats[:decisions][:total]).to eq(1)
46
- expect(stats[:decisions][:avg_duration_ms]).to be > 0
47
- end
48
-
49
- it "records evaluation metrics" do
50
- monitored_agent.decide(context: context)
51
-
52
- stats = collector.statistics
53
- expect(stats[:evaluations][:total]).to eq(1)
54
- expect(stats[:evaluations][:evaluator_distribution]["test_evaluator"]).to eq(1)
55
- end
56
-
57
- it "records performance metrics as successful" do
58
- monitored_agent.decide(context: context)
59
-
60
- stats = collector.statistics
61
- expect(stats[:performance][:total_operations]).to eq(1)
62
- expect(stats[:performance][:successful]).to eq(1)
63
- expect(stats[:performance][:success_rate]).to eq(1.0)
64
- end
65
-
66
- it "includes metadata in performance metrics" do
67
- monitored_agent.decide(context: context)
68
-
69
- collector.statistics
70
- perf_metric = collector.instance_variable_get(:@metrics)[:performance].first
71
-
72
- expect(perf_metric[:metadata][:evaluators_count]).to eq(1)
73
- expect(perf_metric[:metadata][:decision]).to eq("approve")
74
- expect(perf_metric[:metadata][:confidence]).to be_a(Float)
75
- end
76
-
77
- context "when decision fails" do
78
- before do
79
- allow(agent).to receive(:decide).and_raise(StandardError.new("Test error"))
80
- end
81
-
82
- it "records error metrics" do
83
- expect do
84
- monitored_agent.decide(context: context)
85
- end.to raise_error(StandardError, "Test error")
86
-
87
- expect(collector.metrics_count[:errors]).to eq(1)
88
- end
89
-
90
- it "records failed performance metrics" do
91
- expect do
92
- monitored_agent.decide(context: context)
93
- end.to raise_error(StandardError)
94
-
95
- stats = collector.statistics
96
- expect(stats[:performance][:total_operations]).to eq(1)
97
- expect(stats[:performance][:failed]).to eq(1)
98
- expect(stats[:performance][:success_rate]).to eq(0.0)
99
- end
100
-
101
- it "includes error details in metrics" do
102
- expect do
103
- monitored_agent.decide(context: context)
104
- end.to raise_error(StandardError)
105
-
106
- error_metric = collector.instance_variable_get(:@metrics)[:errors].first
107
- expect(error_metric[:error_class]).to eq("StandardError")
108
- expect(error_metric[:error_message]).to eq("Test error")
109
- expect(error_metric[:context]).to eq(context)
110
- end
111
-
112
- it "re-raises the error" do
113
- expect do
114
- monitored_agent.decide(context: context)
115
- end.to raise_error(StandardError, "Test error")
116
- end
117
- end
118
-
119
- it "handles Context objects" do
120
- ctx = DecisionAgent::Context.new(context)
121
- result = monitored_agent.decide(context: ctx)
122
-
123
- expect(result).to be_a(DecisionAgent::Decision)
124
- expect(collector.metrics_count[:decisions]).to eq(1)
125
- end
126
-
127
- it "handles hash contexts" do
128
- result = monitored_agent.decide(context: context)
129
-
130
- expect(result).to be_a(DecisionAgent::Decision)
131
- expect(collector.metrics_count[:decisions]).to eq(1)
132
- end
133
-
134
- it "measures decision duration accurately" do
135
- # Mock agent to introduce delay
136
- allow(agent).to receive(:decide) do |*args|
137
- sleep 0.01 # 10ms delay
138
- evaluator.evaluate(args.first)
139
- DecisionAgent::Decision.new(
140
- decision: "approve",
141
- confidence: 0.9,
142
- explanations: ["Test"],
143
- evaluations: [evaluator.evaluate(args.first)],
144
- audit_payload: {}
145
- )
146
- end
147
-
148
- monitored_agent.decide(context: context)
149
-
150
- stats = collector.statistics
151
- expect(stats[:decisions][:avg_duration_ms]).to be >= 10
152
- end
153
- end
154
-
155
- describe "method delegation" do
156
- it "delegates methods to wrapped agent" do
157
- expect(monitored_agent.evaluators).to eq(agent.evaluators)
158
- expect(monitored_agent.scoring_strategy).to eq(agent.scoring_strategy)
159
- expect(monitored_agent.audit_adapter).to eq(agent.audit_adapter)
160
- end
161
-
162
- it "responds to agent methods" do
163
- expect(monitored_agent).to respond_to(:evaluators)
164
- expect(monitored_agent).to respond_to(:scoring_strategy)
165
- expect(monitored_agent).to respond_to(:audit_adapter)
166
- end
167
- end
168
-
169
- describe "thread safety" do
170
- it "handles concurrent decisions safely" do
171
- # Materialize let variables before creating threads
172
- test_context = { amount: 1000 }
173
- test_monitored_agent = monitored_agent
174
- test_collector = collector
175
-
176
- threads = 10.times.map do
177
- Thread.new do
178
- 10.times do
179
- test_monitored_agent.decide(context: test_context)
180
- end
181
- end
182
- end
183
-
184
- threads.each(&:join)
185
-
186
- expect(test_collector.metrics_count[:decisions]).to eq(100)
187
- expect(test_collector.metrics_count[:evaluations]).to eq(100)
188
- expect(test_collector.metrics_count[:performance]).to eq(100)
189
- end
190
- end
191
-
192
- describe "integration test" do
193
- it "provides comprehensive metrics for multiple decisions" do
194
- contexts = [
195
- { amount: 500 },
196
- { amount: 1500 },
197
- { amount: 2000 }
198
- ]
199
-
200
- contexts.each do |ctx|
201
- monitored_agent.decide(context: ctx)
202
- end
203
-
204
- stats = collector.statistics
205
-
206
- # Summary
207
- expect(stats[:summary][:total_decisions]).to eq(3)
208
- expect(stats[:summary][:total_evaluations]).to eq(3)
209
- expect(stats[:summary][:total_errors]).to eq(0)
210
-
211
- # Decision stats
212
- expect(stats[:decisions][:total]).to eq(3)
213
- expect(stats[:decisions][:avg_confidence]).to be > 0
214
- expect(stats[:decisions][:decision_distribution]["approve"]).to eq(3)
215
-
216
- # Performance stats
217
- expect(stats[:performance][:total_operations]).to eq(3)
218
- expect(stats[:performance][:success_rate]).to eq(1.0)
219
- expect(stats[:performance][:avg_duration_ms]).to be > 0
220
- end
221
- end
222
- end
@@ -1,242 +0,0 @@
1
- require "spec_helper"
2
- require "decision_agent/monitoring/metrics_collector"
3
- require "decision_agent/monitoring/prometheus_exporter"
4
-
5
- RSpec.describe DecisionAgent::Monitoring::PrometheusExporter do
6
- let(:collector) { DecisionAgent::Monitoring::MetricsCollector.new(storage: :memory) }
7
- let(:exporter) { described_class.new(metrics_collector: collector, namespace: "test") }
8
-
9
- let(:decision) do
10
- double(
11
- "Decision",
12
- decision: "approve",
13
- confidence: 0.85,
14
- evaluations: [double("Evaluation", evaluator_name: "test_evaluator")]
15
- )
16
- end
17
- let(:context) { double("Context", to_h: { user: "test" }) }
18
-
19
- describe "#initialize" do
20
- it "initializes with metrics collector" do
21
- expect(exporter).to be_a(described_class)
22
- end
23
-
24
- it "uses default namespace" do
25
- exporter = described_class.new(metrics_collector: collector)
26
- output = exporter.export
27
- expect(output).to include("decision_agent_")
28
- end
29
-
30
- it "uses custom namespace" do
31
- output = exporter.export
32
- expect(output).to include("test_")
33
- end
34
- end
35
-
36
- describe "#export" do
37
- before do
38
- # Record some metrics
39
- 3.times { collector.record_decision(decision, context, duration_ms: 10.0) }
40
- collector.record_performance(operation: "decide", duration_ms: 15.0, success: true)
41
- collector.record_error(StandardError.new("Test error"))
42
- end
43
-
44
- it "exports in Prometheus text format" do
45
- output = exporter.export
46
-
47
- expect(output).to be_a(String)
48
- expect(output).to include("# DecisionAgent Metrics Export")
49
- end
50
-
51
- it "includes decision metrics" do
52
- output = exporter.export
53
-
54
- expect(output).to include("# HELP test_decisions_total")
55
- expect(output).to include("# TYPE test_decisions_total counter")
56
- expect(output).to include("test_decisions_total 3")
57
- end
58
-
59
- it "includes confidence metrics" do
60
- output = exporter.export
61
-
62
- expect(output).to include("# HELP test_decision_confidence_avg")
63
- expect(output).to include("# TYPE test_decision_confidence_avg gauge")
64
- expect(output).to include("test_decision_confidence_avg 0.85")
65
- end
66
-
67
- it "includes performance metrics" do
68
- output = exporter.export
69
-
70
- expect(output).to include("# HELP test_success_rate")
71
- expect(output).to include("# TYPE test_success_rate gauge")
72
- end
73
-
74
- it "includes error metrics" do
75
- output = exporter.export
76
-
77
- expect(output).to include("# HELP test_errors_total")
78
- expect(output).to include("# TYPE test_errors_total counter")
79
- expect(output).to include("test_errors_total 1")
80
- end
81
-
82
- it "includes system info" do
83
- output = exporter.export
84
-
85
- expect(output).to include("# HELP test_info")
86
- expect(output).to include("# TYPE test_info gauge")
87
- expect(output).to include("version=\"#{DecisionAgent::VERSION}\"")
88
- end
89
-
90
- it "includes decision distribution" do
91
- output = exporter.export
92
-
93
- expect(output).to include("# HELP test_decisions_by_type")
94
- expect(output).to include("test_decisions_by_type{decision=\"approve\"} 3")
95
- end
96
-
97
- it "includes error distribution by type" do
98
- output = exporter.export
99
-
100
- expect(output).to include("# HELP test_errors_by_type")
101
- expect(output).to include("test_errors_by_type{error=\"StandardError\"} 1")
102
- end
103
-
104
- it "includes metrics count" do
105
- output = exporter.export
106
-
107
- expect(output).to include("# HELP test_metrics_stored")
108
- expect(output).to include("test_metrics_stored{type=\"decisions\"} 3")
109
- expect(output).to include("test_metrics_stored{type=\"errors\"} 1")
110
- end
111
- end
112
-
113
- describe "#register_kpi" do
114
- it "registers a custom KPI" do
115
- exporter.register_kpi(
116
- name: "custom_metric",
117
- value: 42.5,
118
- help: "A custom metric"
119
- )
120
-
121
- output = exporter.export
122
- expect(output).to include("# HELP test_custom_metric A custom metric")
123
- expect(output).to include("# TYPE test_custom_metric gauge")
124
- expect(output).to include("test_custom_metric 42.5")
125
- end
126
-
127
- it "registers KPI with labels" do
128
- exporter.register_kpi(
129
- name: "requests",
130
- value: 100,
131
- labels: { endpoint: "/api/v1", method: "GET" }
132
- )
133
-
134
- output = exporter.export
135
- expect(output).to include("test_requests{endpoint=\"/api/v1\",method=\"GET\"} 100")
136
- end
137
-
138
- it "sanitizes metric names" do
139
- exporter.register_kpi(name: "my-custom.metric!", value: 10)
140
-
141
- output = exporter.export
142
- expect(output).to include("test_my_custom_metric_")
143
- end
144
-
145
- it "escapes label values" do
146
- exporter.register_kpi(
147
- name: "metric",
148
- value: 1,
149
- labels: { message: 'Contains "quotes"' }
150
- )
151
-
152
- output = exporter.export
153
- expect(output).to include('message="Contains \"quotes\""')
154
- end
155
- end
156
-
157
- describe "#metrics_hash" do
158
- before do
159
- collector.record_decision(decision, context, duration_ms: 10.0)
160
- end
161
-
162
- it "returns metrics as hash" do
163
- metrics = exporter.metrics_hash
164
-
165
- expect(metrics).to be_a(Hash)
166
- expect(metrics).to have_key(:decisions)
167
- expect(metrics).to have_key(:performance)
168
- expect(metrics).to have_key(:errors)
169
- expect(metrics).to have_key(:system)
170
- end
171
-
172
- it "includes metric types" do
173
- metrics = exporter.metrics_hash
174
-
175
- expect(metrics[:decisions][:total][:type]).to eq("counter")
176
- expect(metrics[:decisions][:avg_confidence][:type]).to eq("gauge")
177
- end
178
-
179
- it "includes metric values" do
180
- metrics = exporter.metrics_hash
181
-
182
- expect(metrics[:decisions][:total][:value]).to eq(1)
183
- expect(metrics[:decisions][:avg_confidence][:value]).to eq(0.85)
184
- end
185
- end
186
-
187
- describe "thread safety" do
188
- it "handles concurrent KPI registration" do
189
- threads = 10.times.map do |i|
190
- Thread.new do
191
- 10.times do |j|
192
- exporter.register_kpi(
193
- name: "metric_#{i}_#{j}",
194
- value: (i * 10) + j
195
- )
196
- end
197
- end
198
- end
199
-
200
- expect { threads.each(&:join) }.not_to raise_error
201
- end
202
-
203
- it "handles concurrent exports" do
204
- threads = 5.times.map do
205
- Thread.new do
206
- 10.times { exporter.export }
207
- end
208
- end
209
-
210
- expect { threads.each(&:join) }.not_to raise_error
211
- end
212
- end
213
-
214
- describe "performance metrics export" do
215
- before do
216
- 5.times do |i|
217
- collector.record_performance(
218
- operation: "decide",
219
- duration_ms: (i + 1) * 10.0,
220
- success: true
221
- )
222
- end
223
- end
224
-
225
- it "exports summary metrics" do
226
- output = exporter.export
227
-
228
- expect(output).to include("# TYPE test_operation_duration_ms summary")
229
- expect(output).to include("test_operation_duration_ms{quantile=\"0.5\"}")
230
- expect(output).to include("test_operation_duration_ms{quantile=\"0.95\"}")
231
- expect(output).to include("test_operation_duration_ms{quantile=\"0.99\"}")
232
- expect(output).to include("test_operation_duration_ms_sum")
233
- expect(output).to include("test_operation_duration_ms_count")
234
- end
235
- end
236
-
237
- describe "content type" do
238
- it "defines Prometheus content type" do
239
- expect(described_class::CONTENT_TYPE).to eq("text/plain; version=0.0.4")
240
- end
241
- end
242
- end