fractor 0.1.4 → 0.1.7
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/.rubocop-https---raw-githubusercontent-com-riboseinc-oss-guides-main-ci-rubocop-yml +552 -0
- data/.rubocop.yml +14 -8
- data/.rubocop_todo.yml +284 -43
- data/README.adoc +111 -950
- data/docs/.lycheeignore +16 -0
- data/docs/Gemfile +24 -0
- data/docs/README.md +157 -0
- data/docs/_config.yml +151 -0
- data/docs/_features/error-handling.adoc +1192 -0
- data/docs/_features/index.adoc +80 -0
- data/docs/_features/monitoring.adoc +589 -0
- data/docs/_features/signal-handling.adoc +202 -0
- data/docs/_features/workflows.adoc +1235 -0
- data/docs/_guides/continuous-mode.adoc +736 -0
- data/docs/_guides/cookbook.adoc +1133 -0
- data/docs/_guides/index.adoc +55 -0
- data/docs/_guides/pipeline-mode.adoc +730 -0
- data/docs/_guides/troubleshooting.adoc +358 -0
- data/docs/_pages/architecture.adoc +1390 -0
- data/docs/_pages/core-concepts.adoc +1392 -0
- data/docs/_pages/design-principles.adoc +862 -0
- data/docs/_pages/getting-started.adoc +290 -0
- data/docs/_pages/installation.adoc +143 -0
- data/docs/_reference/api.adoc +1080 -0
- data/docs/_reference/error-reporting.adoc +670 -0
- data/docs/_reference/examples.adoc +181 -0
- data/docs/_reference/index.adoc +96 -0
- data/docs/_reference/troubleshooting.adoc +862 -0
- data/docs/_tutorials/complex-workflows.adoc +1022 -0
- data/docs/_tutorials/data-processing-pipeline.adoc +740 -0
- data/docs/_tutorials/first-application.adoc +384 -0
- data/docs/_tutorials/index.adoc +48 -0
- data/docs/_tutorials/long-running-services.adoc +931 -0
- data/docs/assets/images/favicon-16.png +0 -0
- data/docs/assets/images/favicon-32.png +0 -0
- data/docs/assets/images/favicon-48.png +0 -0
- data/docs/assets/images/favicon.ico +0 -0
- data/docs/assets/images/favicon.png +0 -0
- data/docs/assets/images/favicon.svg +45 -0
- data/docs/assets/images/fractor-icon.svg +49 -0
- data/docs/assets/images/fractor-logo.svg +61 -0
- data/docs/index.adoc +131 -0
- data/docs/lychee.toml +39 -0
- data/examples/api_aggregator/README.adoc +627 -0
- data/examples/api_aggregator/api_aggregator.rb +376 -0
- data/examples/auto_detection/README.adoc +407 -29
- data/examples/auto_detection/auto_detection.rb +9 -9
- data/examples/continuous_chat_common/message_protocol.rb +53 -0
- data/examples/continuous_chat_fractor/README.adoc +217 -0
- data/examples/continuous_chat_fractor/chat_client.rb +303 -0
- data/examples/continuous_chat_fractor/chat_common.rb +83 -0
- data/examples/continuous_chat_fractor/chat_server.rb +167 -0
- data/examples/continuous_chat_fractor/simulate.rb +345 -0
- data/examples/continuous_chat_server/README.adoc +135 -0
- data/examples/continuous_chat_server/chat_client.rb +303 -0
- data/examples/continuous_chat_server/chat_server.rb +359 -0
- data/examples/continuous_chat_server/simulate.rb +343 -0
- data/examples/error_reporting.rb +207 -0
- data/examples/file_processor/README.adoc +170 -0
- data/examples/file_processor/file_processor.rb +615 -0
- data/examples/file_processor/sample_files/invalid.csv +1 -0
- data/examples/file_processor/sample_files/orders.xml +24 -0
- data/examples/file_processor/sample_files/products.json +23 -0
- data/examples/file_processor/sample_files/users.csv +6 -0
- data/examples/hierarchical_hasher/README.adoc +629 -41
- data/examples/hierarchical_hasher/hierarchical_hasher.rb +12 -8
- data/examples/image_processor/README.adoc +610 -0
- data/examples/image_processor/image_processor.rb +349 -0
- data/examples/image_processor/processed_images/sample_10_processed.jpg.json +12 -0
- data/examples/image_processor/processed_images/sample_1_processed.jpg.json +12 -0
- data/examples/image_processor/processed_images/sample_2_processed.jpg.json +12 -0
- data/examples/image_processor/processed_images/sample_3_processed.jpg.json +12 -0
- data/examples/image_processor/processed_images/sample_4_processed.jpg.json +12 -0
- data/examples/image_processor/processed_images/sample_5_processed.jpg.json +12 -0
- data/examples/image_processor/processed_images/sample_6_processed.jpg.json +12 -0
- data/examples/image_processor/processed_images/sample_7_processed.jpg.json +12 -0
- data/examples/image_processor/processed_images/sample_8_processed.jpg.json +12 -0
- data/examples/image_processor/processed_images/sample_9_processed.jpg.json +12 -0
- data/examples/image_processor/test_images/sample_1.png +1 -0
- data/examples/image_processor/test_images/sample_10.png +1 -0
- data/examples/image_processor/test_images/sample_2.png +1 -0
- data/examples/image_processor/test_images/sample_3.png +1 -0
- data/examples/image_processor/test_images/sample_4.png +1 -0
- data/examples/image_processor/test_images/sample_5.png +1 -0
- data/examples/image_processor/test_images/sample_6.png +1 -0
- data/examples/image_processor/test_images/sample_7.png +1 -0
- data/examples/image_processor/test_images/sample_8.png +1 -0
- data/examples/image_processor/test_images/sample_9.png +1 -0
- data/examples/log_analyzer/README.adoc +662 -0
- data/examples/log_analyzer/log_analyzer.rb +579 -0
- data/examples/log_analyzer/sample_logs/apache.log +20 -0
- data/examples/log_analyzer/sample_logs/json.log +15 -0
- data/examples/log_analyzer/sample_logs/nginx.log +15 -0
- data/examples/log_analyzer/sample_logs/rails.log +29 -0
- data/examples/multi_work_type/README.adoc +576 -26
- data/examples/multi_work_type/multi_work_type.rb +30 -29
- data/examples/performance_monitoring.rb +120 -0
- data/examples/pipeline_processing/README.adoc +740 -26
- data/examples/pipeline_processing/pipeline_processing.rb +16 -16
- data/examples/priority_work_example.rb +155 -0
- data/examples/producer_subscriber/README.adoc +889 -46
- data/examples/producer_subscriber/producer_subscriber.rb +20 -16
- data/examples/scatter_gather/README.adoc +829 -27
- data/examples/scatter_gather/scatter_gather.rb +29 -28
- data/examples/simple/README.adoc +347 -0
- data/examples/simple/sample.rb +5 -5
- data/examples/specialized_workers/README.adoc +622 -26
- data/examples/specialized_workers/specialized_workers.rb +88 -45
- data/examples/stream_processor/README.adoc +206 -0
- data/examples/stream_processor/stream_processor.rb +284 -0
- data/examples/web_scraper/README.adoc +625 -0
- data/examples/web_scraper/web_scraper.rb +285 -0
- data/examples/workflow/README.adoc +406 -0
- data/examples/workflow/circuit_breaker/README.adoc +360 -0
- data/examples/workflow/circuit_breaker/circuit_breaker_workflow.rb +225 -0
- data/examples/workflow/conditional/README.adoc +483 -0
- data/examples/workflow/conditional/conditional_workflow.rb +215 -0
- data/examples/workflow/dead_letter_queue/README.adoc +374 -0
- data/examples/workflow/dead_letter_queue/dead_letter_queue_workflow.rb +217 -0
- data/examples/workflow/fan_out/README.adoc +381 -0
- data/examples/workflow/fan_out/fan_out_workflow.rb +202 -0
- data/examples/workflow/retry/README.adoc +248 -0
- data/examples/workflow/retry/retry_workflow.rb +195 -0
- data/examples/workflow/simple_linear/README.adoc +267 -0
- data/examples/workflow/simple_linear/simple_linear_workflow.rb +175 -0
- data/examples/workflow/simplified/README.adoc +329 -0
- data/examples/workflow/simplified/simplified_workflow.rb +222 -0
- data/exe/fractor +10 -0
- data/lib/fractor/cli.rb +288 -0
- data/lib/fractor/configuration.rb +307 -0
- data/lib/fractor/continuous_server.rb +183 -0
- data/lib/fractor/error_formatter.rb +72 -0
- data/lib/fractor/error_report_generator.rb +152 -0
- data/lib/fractor/error_reporter.rb +244 -0
- data/lib/fractor/error_statistics.rb +147 -0
- data/lib/fractor/execution_tracer.rb +162 -0
- data/lib/fractor/logger.rb +230 -0
- data/lib/fractor/main_loop_handler.rb +406 -0
- data/lib/fractor/main_loop_handler3.rb +135 -0
- data/lib/fractor/main_loop_handler4.rb +299 -0
- data/lib/fractor/performance_metrics_collector.rb +181 -0
- data/lib/fractor/performance_monitor.rb +215 -0
- data/lib/fractor/performance_report_generator.rb +202 -0
- data/lib/fractor/priority_work.rb +93 -0
- data/lib/fractor/priority_work_queue.rb +189 -0
- data/lib/fractor/result_aggregator.rb +33 -1
- data/lib/fractor/shutdown_handler.rb +168 -0
- data/lib/fractor/signal_handler.rb +80 -0
- data/lib/fractor/supervisor.rb +430 -144
- data/lib/fractor/supervisor_logger.rb +88 -0
- data/lib/fractor/version.rb +1 -1
- data/lib/fractor/work.rb +12 -0
- data/lib/fractor/work_distribution_manager.rb +151 -0
- data/lib/fractor/work_queue.rb +88 -0
- data/lib/fractor/work_result.rb +181 -9
- data/lib/fractor/worker.rb +75 -1
- data/lib/fractor/workflow/builder.rb +210 -0
- data/lib/fractor/workflow/chain_builder.rb +169 -0
- data/lib/fractor/workflow/circuit_breaker.rb +183 -0
- data/lib/fractor/workflow/circuit_breaker_orchestrator.rb +208 -0
- data/lib/fractor/workflow/circuit_breaker_registry.rb +112 -0
- data/lib/fractor/workflow/dead_letter_queue.rb +334 -0
- data/lib/fractor/workflow/execution_hooks.rb +39 -0
- data/lib/fractor/workflow/execution_strategy.rb +225 -0
- data/lib/fractor/workflow/execution_trace.rb +134 -0
- data/lib/fractor/workflow/helpers.rb +191 -0
- data/lib/fractor/workflow/job.rb +290 -0
- data/lib/fractor/workflow/job_dependency_validator.rb +120 -0
- data/lib/fractor/workflow/logger.rb +110 -0
- data/lib/fractor/workflow/pre_execution_context.rb +193 -0
- data/lib/fractor/workflow/retry_config.rb +156 -0
- data/lib/fractor/workflow/retry_orchestrator.rb +184 -0
- data/lib/fractor/workflow/retry_strategy.rb +93 -0
- data/lib/fractor/workflow/structured_logger.rb +30 -0
- data/lib/fractor/workflow/type_compatibility_validator.rb +222 -0
- data/lib/fractor/workflow/visualizer.rb +211 -0
- data/lib/fractor/workflow/workflow_context.rb +132 -0
- data/lib/fractor/workflow/workflow_executor.rb +669 -0
- data/lib/fractor/workflow/workflow_result.rb +55 -0
- data/lib/fractor/workflow/workflow_validator.rb +295 -0
- data/lib/fractor/workflow.rb +333 -0
- data/lib/fractor/wrapped_ractor.rb +66 -91
- data/lib/fractor/wrapped_ractor3.rb +161 -0
- data/lib/fractor/wrapped_ractor4.rb +242 -0
- data/lib/fractor.rb +93 -3
- metadata +192 -6
- data/tests/sample.rb.bak +0 -309
- data/tests/sample_working.rb.bak +0 -209
|
@@ -45,7 +45,7 @@ module MultiWorkType
|
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
def to_s
|
|
48
|
-
"ImageWork: dimensions=#{dimensions.join(
|
|
48
|
+
"ImageWork: dimensions=#{dimensions.join('x')}, format=#{format}"
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
51
|
|
|
@@ -62,7 +62,7 @@ module MultiWorkType
|
|
|
62
62
|
error = TypeError.new("Unsupported work type: #{work.class}")
|
|
63
63
|
Fractor::WorkResult.new(
|
|
64
64
|
error: error,
|
|
65
|
-
work: work
|
|
65
|
+
work: work,
|
|
66
66
|
)
|
|
67
67
|
end
|
|
68
68
|
end
|
|
@@ -74,7 +74,8 @@ module MultiWorkType
|
|
|
74
74
|
sleep(rand(0.01..0.05)) # Simulate processing time
|
|
75
75
|
|
|
76
76
|
processed_text = case work.format
|
|
77
|
-
when :markdown then process_markdown(work.data,
|
|
77
|
+
when :markdown then process_markdown(work.data,
|
|
78
|
+
work.options)
|
|
78
79
|
when :html then process_html(work.data, work.options)
|
|
79
80
|
when :json then process_json(work.data, work.options)
|
|
80
81
|
else work.data.upcase # Simple transformation for plain text
|
|
@@ -87,10 +88,10 @@ module MultiWorkType
|
|
|
87
88
|
transformed_data: processed_text,
|
|
88
89
|
metadata: {
|
|
89
90
|
word_count: processed_text.split(/\s+/).size,
|
|
90
|
-
char_count: processed_text.length
|
|
91
|
-
}
|
|
91
|
+
char_count: processed_text.length,
|
|
92
|
+
},
|
|
92
93
|
},
|
|
93
|
-
work: work
|
|
94
|
+
work: work,
|
|
94
95
|
)
|
|
95
96
|
end
|
|
96
97
|
|
|
@@ -110,13 +111,13 @@ module MultiWorkType
|
|
|
110
111
|
applied_filters: %i[sharpen contrast],
|
|
111
112
|
processing_metadata: {
|
|
112
113
|
original_size: input_size,
|
|
113
|
-
processed_size: (input_size * 0.8).to_i # Simulate compression
|
|
114
|
-
}
|
|
114
|
+
processed_size: (input_size * 0.8).to_i, # Simulate compression
|
|
115
|
+
},
|
|
115
116
|
}
|
|
116
117
|
|
|
117
118
|
Fractor::WorkResult.new(
|
|
118
119
|
result: simulated_result,
|
|
119
|
-
work: work
|
|
120
|
+
work: work,
|
|
120
121
|
)
|
|
121
122
|
end
|
|
122
123
|
|
|
@@ -127,7 +128,7 @@ module MultiWorkType
|
|
|
127
128
|
links = text.scan(/\[(.+?)\]\((.+?)\)/)
|
|
128
129
|
|
|
129
130
|
"Processed Markdown: #{text.length} chars, #{headers.size} headers, #{links.size} links\n" \
|
|
130
|
-
"Headers: #{headers.join(
|
|
131
|
+
"Headers: #{headers.join(', ')}\n" \
|
|
131
132
|
"#{text.gsub(/^#+\s+(.+)$/, '💫 \1 💫')}"
|
|
132
133
|
end
|
|
133
134
|
|
|
@@ -136,7 +137,7 @@ module MultiWorkType
|
|
|
136
137
|
tags = text.scan(/<(\w+)[^>]*>/).flatten
|
|
137
138
|
|
|
138
139
|
"Processed HTML: #{text.length} chars, #{tags.size} tags\n" \
|
|
139
|
-
"Tags: #{tags.uniq.join(
|
|
140
|
+
"Tags: #{tags.uniq.join(', ')}\n" \
|
|
140
141
|
"#{text.gsub(%r{<(\w+)[^>]*>(.+?)</\1>}, '✨\2✨')}"
|
|
141
142
|
end
|
|
142
143
|
|
|
@@ -147,7 +148,7 @@ module MultiWorkType
|
|
|
147
148
|
keys = data.keys
|
|
148
149
|
|
|
149
150
|
"Processed JSON: #{keys.size} top-level keys\n" \
|
|
150
|
-
"Keys: #{keys.join(
|
|
151
|
+
"Keys: #{keys.join(', ')}\n" \
|
|
151
152
|
"Pretty-printed: #{data}"
|
|
152
153
|
rescue StandardError => e
|
|
153
154
|
"Invalid JSON: #{e.message}"
|
|
@@ -162,14 +163,14 @@ module MultiWorkType
|
|
|
162
163
|
# Create supervisor with a MultiFormatWorker pool
|
|
163
164
|
@supervisor = Fractor::Supervisor.new(
|
|
164
165
|
worker_pools: [
|
|
165
|
-
{ worker_class: MultiFormatWorker, num_workers: worker_count }
|
|
166
|
-
]
|
|
166
|
+
{ worker_class: MultiFormatWorker, num_workers: worker_count },
|
|
167
|
+
],
|
|
167
168
|
)
|
|
168
169
|
|
|
169
170
|
@results = {
|
|
170
171
|
text: [],
|
|
171
172
|
image: [],
|
|
172
|
-
errors: []
|
|
173
|
+
errors: [],
|
|
173
174
|
}
|
|
174
175
|
end
|
|
175
176
|
|
|
@@ -197,10 +198,10 @@ module MultiWorkType
|
|
|
197
198
|
total_items: text_items.size + image_items.size,
|
|
198
199
|
processed: {
|
|
199
200
|
text: @results[:text].size,
|
|
200
|
-
image: @results[:image].size
|
|
201
|
+
image: @results[:image].size,
|
|
201
202
|
},
|
|
202
203
|
errors: @results[:errors].size,
|
|
203
|
-
results: @results
|
|
204
|
+
results: @results,
|
|
204
205
|
}
|
|
205
206
|
end
|
|
206
207
|
|
|
@@ -220,7 +221,7 @@ module MultiWorkType
|
|
|
220
221
|
results_aggregator.errors.each do |error_result|
|
|
221
222
|
@results[:errors] << {
|
|
222
223
|
error: error_result.error,
|
|
223
|
-
work_type: error_result.work.class.name
|
|
224
|
+
work_type: error_result.work.class.name,
|
|
224
225
|
}
|
|
225
226
|
end
|
|
226
227
|
|
|
@@ -244,21 +245,21 @@ if __FILE__ == $PROGRAM_NAME
|
|
|
244
245
|
text_items = [
|
|
245
246
|
{
|
|
246
247
|
data: "This is a plain text document. It has no special formatting.",
|
|
247
|
-
format: :plain
|
|
248
|
+
format: :plain,
|
|
248
249
|
},
|
|
249
250
|
{
|
|
250
251
|
data: "# Markdown Document\n\nThis is a **bold** statement. Here's a [link](https://example.com).",
|
|
251
|
-
format: :markdown
|
|
252
|
+
format: :markdown,
|
|
252
253
|
},
|
|
253
254
|
{
|
|
254
255
|
data: "<html><body><h1>HTML Document</h1><p>This is a paragraph.</p></body></html>",
|
|
255
|
-
format: :html
|
|
256
|
+
format: :html,
|
|
256
257
|
},
|
|
257
258
|
{
|
|
258
259
|
data: "{name: 'Product', price: 29.99, tags: ['electronics', 'gadget']}",
|
|
259
260
|
format: :json,
|
|
260
|
-
options: { pretty: true }
|
|
261
|
-
}
|
|
261
|
+
options: { pretty: true },
|
|
262
|
+
},
|
|
262
263
|
]
|
|
263
264
|
|
|
264
265
|
# Sample image items (simulated)
|
|
@@ -266,18 +267,18 @@ if __FILE__ == $PROGRAM_NAME
|
|
|
266
267
|
{
|
|
267
268
|
data: "simulated_jpeg_data_1",
|
|
268
269
|
dimensions: [800, 600],
|
|
269
|
-
format: :jpeg
|
|
270
|
+
format: :jpeg,
|
|
270
271
|
},
|
|
271
272
|
{
|
|
272
273
|
data: "simulated_png_data_1",
|
|
273
274
|
dimensions: [1024, 768],
|
|
274
|
-
format: :png
|
|
275
|
+
format: :png,
|
|
275
276
|
},
|
|
276
277
|
{
|
|
277
278
|
data: "simulated_gif_data_1",
|
|
278
279
|
dimensions: [320, 240],
|
|
279
|
-
format: :gif
|
|
280
|
-
}
|
|
280
|
+
format: :gif,
|
|
281
|
+
},
|
|
281
282
|
]
|
|
282
283
|
|
|
283
284
|
worker_count = 4
|
|
@@ -309,8 +310,8 @@ if __FILE__ == $PROGRAM_NAME
|
|
|
309
310
|
puts "Image Processing Results:"
|
|
310
311
|
result[:results][:image].each_with_index do |image_result, index|
|
|
311
312
|
puts "Image Item #{index + 1} (#{image_result[:format]}):"
|
|
312
|
-
puts " Dimensions: #{image_result[:dimensions].join(
|
|
313
|
-
puts " Applied filters: #{image_result[:applied_filters].join(
|
|
313
|
+
puts " Dimensions: #{image_result[:dimensions].join('x')}"
|
|
314
|
+
puts " Applied filters: #{image_result[:applied_filters].join(', ')}"
|
|
314
315
|
puts " Compression: #{(1 - image_result[:processing_metadata][:processed_size].to_f / image_result[:processing_metadata][:original_size]).round(2) * 100}%"
|
|
315
316
|
puts
|
|
316
317
|
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../lib/fractor"
|
|
4
|
+
require_relative "../lib/fractor/performance_monitor"
|
|
5
|
+
|
|
6
|
+
# Example worker that simulates varying processing times
|
|
7
|
+
class VariableLatencyWorker
|
|
8
|
+
def self.perform(work)
|
|
9
|
+
# Simulate variable work latency
|
|
10
|
+
sleep(rand * 0.1) # 0-100ms
|
|
11
|
+
|
|
12
|
+
result = work.payload[:value] * 2
|
|
13
|
+
Fractor::WorkResult.new(result: result, work: work)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Example: Basic Performance Monitoring
|
|
18
|
+
puts "=" * 80
|
|
19
|
+
puts "Performance Monitoring Example"
|
|
20
|
+
puts "=" * 80
|
|
21
|
+
|
|
22
|
+
# Create supervisor with multiple workers
|
|
23
|
+
supervisor = Fractor::Supervisor.new(
|
|
24
|
+
worker_pools: [
|
|
25
|
+
{ worker_class: VariableLatencyWorker, num_workers: 4 },
|
|
26
|
+
],
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
# Create and start performance monitor
|
|
30
|
+
monitor = Fractor::PerformanceMonitor.new(supervisor, sample_interval: 0.5)
|
|
31
|
+
monitor.start
|
|
32
|
+
|
|
33
|
+
puts "\nProcessing 100 work items..."
|
|
34
|
+
puts "Monitor started, sampling every 0.5 seconds"
|
|
35
|
+
|
|
36
|
+
# Add work items
|
|
37
|
+
100.times do |i|
|
|
38
|
+
supervisor.add_work_item(Fractor::Work.new({ value: i }))
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Run the supervisor
|
|
42
|
+
supervisor_thread = Thread.new { supervisor.run }
|
|
43
|
+
|
|
44
|
+
# Wait for completion
|
|
45
|
+
sleep 0.5 while supervisor.work_queue.size > 0 || supervisor.results.results.size < 100
|
|
46
|
+
|
|
47
|
+
# Stop monitoring
|
|
48
|
+
monitor.stop
|
|
49
|
+
supervisor.stop
|
|
50
|
+
supervisor_thread.join
|
|
51
|
+
|
|
52
|
+
puts "\n" + "=" * 80
|
|
53
|
+
puts "Human-Readable Report"
|
|
54
|
+
puts "=" * 80
|
|
55
|
+
puts monitor.report
|
|
56
|
+
|
|
57
|
+
puts "\n" + "=" * 80
|
|
58
|
+
puts "JSON Export"
|
|
59
|
+
puts "=" * 80
|
|
60
|
+
puts JSON.pretty_generate(JSON.parse(monitor.to_json))
|
|
61
|
+
|
|
62
|
+
puts "\n" + "=" * 80
|
|
63
|
+
puts "Prometheus Metrics"
|
|
64
|
+
puts "=" * 80
|
|
65
|
+
puts monitor.to_prometheus
|
|
66
|
+
|
|
67
|
+
puts "\n" + "=" * 80
|
|
68
|
+
puts "Example: Real-time Monitoring with Manual Recording"
|
|
69
|
+
puts "=" * 80
|
|
70
|
+
|
|
71
|
+
# Create a new monitor
|
|
72
|
+
supervisor2 = Fractor::Supervisor.new(
|
|
73
|
+
worker_pools: [
|
|
74
|
+
{ worker_class: VariableLatencyWorker, num_workers: 2 },
|
|
75
|
+
],
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
monitor2 = Fractor::PerformanceMonitor.new(supervisor2)
|
|
79
|
+
monitor2.start
|
|
80
|
+
|
|
81
|
+
puts "\nManually recording job completions..."
|
|
82
|
+
|
|
83
|
+
# Simulate job execution and manually record metrics
|
|
84
|
+
10.times do |i|
|
|
85
|
+
start_time = Time.now
|
|
86
|
+
|
|
87
|
+
# Simulate work
|
|
88
|
+
sleep(rand * 0.05)
|
|
89
|
+
|
|
90
|
+
# Record the job
|
|
91
|
+
latency = Time.now - start_time
|
|
92
|
+
success = rand > 0.1 # 90% success rate
|
|
93
|
+
|
|
94
|
+
monitor2.record_job(latency, success: success)
|
|
95
|
+
|
|
96
|
+
print "." if i % 10 == 0
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
monitor2.stop
|
|
100
|
+
|
|
101
|
+
puts "\n\nFinal Metrics:"
|
|
102
|
+
snapshot = monitor2.snapshot
|
|
103
|
+
puts " Jobs Processed: #{snapshot[:jobs_processed]}"
|
|
104
|
+
puts " Success Rate: #{(snapshot[:jobs_succeeded].to_f / snapshot[:jobs_processed] * 100).round(2)}%"
|
|
105
|
+
puts " Average Latency: #{(snapshot[:average_latency] * 1000).round(2)}ms"
|
|
106
|
+
puts " P95 Latency: #{(snapshot[:p95_latency] * 1000).round(2)}ms"
|
|
107
|
+
puts " Throughput: #{snapshot[:throughput].round(2)} jobs/sec"
|
|
108
|
+
|
|
109
|
+
puts "\n" + "=" * 80
|
|
110
|
+
puts "Example Complete"
|
|
111
|
+
puts "=" * 80
|
|
112
|
+
puts "\nPerformance monitoring provides:"
|
|
113
|
+
puts " ✓ Jobs processed counter"
|
|
114
|
+
puts " ✓ Latency tracking (average, p50, p95, p99)"
|
|
115
|
+
puts " ✓ Throughput calculation (jobs/second)"
|
|
116
|
+
puts " ✓ Worker utilization tracking"
|
|
117
|
+
puts " ✓ Queue depth monitoring"
|
|
118
|
+
puts " ✓ Memory usage tracking"
|
|
119
|
+
puts " ✓ JSON export"
|
|
120
|
+
puts " ✓ Prometheus metrics export"
|