bugsnag-maze-runner 9.32.4 → 9.33.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.
- checksums.yaml +4 -4
- data/bin/benchmarks-to-datadog +186 -0
- data/lib/maze.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 36d5614273840b3532dae2fc1c515389dec6e36c99b348bd1cc6a91b3d3da656
|
4
|
+
data.tar.gz: 6c0ee4526be46ba9b322f625701e00e00ec8af6001d3d8f12fa7fa32e4005dc3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ccaff84971397feaca6de27dd8db438a3e51de38b002956c1076e1e85aa496b99d059e67dfaa4491cc22248c5e337348eb80fe112b480d8e413deee12498db3
|
7
|
+
data.tar.gz: e2b77ff39efc000d8f6db1d910d414a3f8428cf0f21b2e2b62c592b5879ca7e746cb681e963215c37cf5e3b3e23215527f528cbd217a2bae85fd76573ac5b3f6
|
@@ -0,0 +1,186 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'csv'
|
5
|
+
require 'time'
|
6
|
+
require 'optimist'
|
7
|
+
require 'datadog_api_client'
|
8
|
+
|
9
|
+
require_relative '../lib/maze'
|
10
|
+
require_relative '../lib/maze/loggers/logger'
|
11
|
+
|
12
|
+
class DatadogMetricsIngester
|
13
|
+
def initialize(api_key:, app_key:, host: 'platforms-benchmark')
|
14
|
+
configuration = DatadogAPIClient::Configuration.new
|
15
|
+
configuration.api_key['apiKeyAuth'] = api_key
|
16
|
+
configuration.api_key['appKeyAuth'] = app_key
|
17
|
+
|
18
|
+
api_client = DatadogAPIClient::APIClient.new(configuration)
|
19
|
+
@api = DatadogAPIClient::V2::MetricsAPI.new(api_client)
|
20
|
+
@host = host
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.run(args)
|
24
|
+
parser = Optimist::Parser.new do
|
25
|
+
text 'Ingest CSV metrics into Datadog'
|
26
|
+
opt :csv_file, 'Path to the CSV file containing metrics', type: :string, required: true
|
27
|
+
opt :api_key, 'Datadog API key', type: :string
|
28
|
+
opt :app_key, 'Datadog App key', type: :string
|
29
|
+
end
|
30
|
+
|
31
|
+
opts = Optimist::with_standard_exception_handling(parser) do
|
32
|
+
raise Optimist::HelpNeeded if args.empty?
|
33
|
+
parser.parse(args)
|
34
|
+
end
|
35
|
+
|
36
|
+
csv_file = opts[:csv_file]
|
37
|
+
api_key = opts[:api_key] || ENV['DATADOG_API_KEY']
|
38
|
+
app_key = opts[:app_key] || ENV['DATADOG_APP_KEY']
|
39
|
+
|
40
|
+
abort_with_help(parser, "CSV file is missing") if csv_file.to_s.empty?
|
41
|
+
abort_with_help(parser, "API key is missing") if api_key.to_s.empty?
|
42
|
+
abort_with_help(parser, "App key is missing") if app_key.to_s.empty?
|
43
|
+
|
44
|
+
new(api_key: api_key, app_key: app_key).ingest_csv(csv_file)
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.abort_with_help(parser, message)
|
48
|
+
$logger.warn message
|
49
|
+
Optimist::with_standard_exception_handling(parser) { raise Optimist::HelpNeeded }
|
50
|
+
end
|
51
|
+
|
52
|
+
def ingest_csv(file_path)
|
53
|
+
total_rows = 0
|
54
|
+
|
55
|
+
CSV.foreach(file_path, headers: true) do |row|
|
56
|
+
next unless valid_benchmark_row?(row)
|
57
|
+
|
58
|
+
total_rows += 1
|
59
|
+
benchmark_name = row['benchmark']
|
60
|
+
tags = build_tags(row)
|
61
|
+
timestamp = parse_timestamp(row['timestamp'])
|
62
|
+
|
63
|
+
$logger.info "Processing row #{total_rows}: #{benchmark_name} at #{row['timestamp']}"
|
64
|
+
|
65
|
+
process_cpu_metrics(row, tags, timestamp)
|
66
|
+
process_run_metrics(row, tags, timestamp)
|
67
|
+
process_total_metrics(row, tags, timestamp)
|
68
|
+
|
69
|
+
$logger.info "Completed processing #{benchmark_name}"
|
70
|
+
$logger.info '-' * 60
|
71
|
+
|
72
|
+
# Sleep briefly to avoid overwhelming the Datadog API
|
73
|
+
sleep(0.1)
|
74
|
+
end
|
75
|
+
|
76
|
+
$logger.info "Ingestion Summary:"
|
77
|
+
$logger.info "Total rows processed: #{total_rows}"
|
78
|
+
end
|
79
|
+
|
80
|
+
def valid_benchmark_row?(row)
|
81
|
+
row['benchmark'] && !row['benchmark'].strip.empty?
|
82
|
+
end
|
83
|
+
|
84
|
+
def parse_timestamp(timestamp_str)
|
85
|
+
Time.strptime(timestamp_str, "%a %b %d %H:%M:%S GMT %Y").to_i
|
86
|
+
rescue ArgumentError
|
87
|
+
Time.now.to_i
|
88
|
+
end
|
89
|
+
|
90
|
+
def build_tags(row)
|
91
|
+
tags = ["env:platforms-testing", "benchmark:#{row['benchmark']}"]
|
92
|
+
tags << "cpu_intensive:true" if row['cpu'] == 'true'
|
93
|
+
tags << "memory_intensive:true" if row['memory'] == 'true'
|
94
|
+
tags << "rendering_enabled:true" if row['rendering'] == 'true'
|
95
|
+
tags
|
96
|
+
end
|
97
|
+
|
98
|
+
def send_metric(name, value, tags, type = DatadogAPIClient::V2::MetricIntakeType::GAUGE, timestamp = Time.now.to_i)
|
99
|
+
metric_series = DatadogAPIClient::V2::MetricSeries.new(
|
100
|
+
metric: name,
|
101
|
+
type: type,
|
102
|
+
points: [
|
103
|
+
DatadogAPIClient::V2::MetricPoint.new(timestamp: timestamp, value: value)
|
104
|
+
],
|
105
|
+
tags: tags,
|
106
|
+
resources: [
|
107
|
+
DatadogAPIClient::V2::MetricResource.new(name: @host, type: "host")
|
108
|
+
]
|
109
|
+
)
|
110
|
+
|
111
|
+
payload = DatadogAPIClient::V2::MetricPayload.new(series: [metric_series])
|
112
|
+
|
113
|
+
begin
|
114
|
+
@api.submit_metrics(payload)
|
115
|
+
rescue DatadogAPIClient::APIError => e
|
116
|
+
$logger.error "Failed to send metric #{name}: #{e.message}"
|
117
|
+
$logger.error "HTTP status code: #{e.code}"
|
118
|
+
$logger.error "Response body: #{e.response_body}"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def process_cpu_metrics(row, tags, timestamp)
|
123
|
+
# Select all headers matching cpuUse.<number> pattern and extract their float values
|
124
|
+
cpu_values = row.headers.grep(/^cpuUse\.\d+$/).map { |key|
|
125
|
+
val = row[key]
|
126
|
+
val&.empty? ? nil : val.to_f
|
127
|
+
}.compact
|
128
|
+
|
129
|
+
return if cpu_values.empty?
|
130
|
+
|
131
|
+
avg_cpu = cpu_values.sum / cpu_values.size
|
132
|
+
send_metric('benchmark.cpu_usage_percent', avg_cpu, tags, timestamp)
|
133
|
+
end
|
134
|
+
|
135
|
+
def process_run_metrics(row, base_tags, timestamp)
|
136
|
+
# Extract unique run indices from headers like measuredTime.1, iterations.2, etc.
|
137
|
+
run_indices = row.headers
|
138
|
+
.grep(/^(measuredTime|iterations|timeTaken|excludedTime)\.(\d+)$/)
|
139
|
+
.map { |key| key.split('.').last.to_i } # Extract the run index number
|
140
|
+
.uniq
|
141
|
+
.sort
|
142
|
+
|
143
|
+
run_indices.each do |i|
|
144
|
+
run_tags = base_tags + ["run:#{i}"]
|
145
|
+
|
146
|
+
{
|
147
|
+
'benchmark.measured_time_ns' => row["measuredTime.#{i}"],
|
148
|
+
'benchmark.iterations' => row["iterations.#{i}"],
|
149
|
+
'benchmark.time_taken_ns' => row["timeTaken.#{i}"],
|
150
|
+
'benchmark.excluded_time_ns' => row["excludedTime.#{i}"]
|
151
|
+
}.each do |metric, value|
|
152
|
+
send_if_valid(metric, value, run_tags, timestamp)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def process_total_metrics(row, tags, timestamp)
|
158
|
+
totals = {
|
159
|
+
'benchmark.total_measured_time_ns' => row['totalMeasuredTime'],
|
160
|
+
'benchmark.total_iterations' => row['totalIterations'],
|
161
|
+
'benchmark.total_time_taken_ns' => row['totalTimeTaken'],
|
162
|
+
'benchmark.total_excluded_time_ns' => row['totalExcludedTime']
|
163
|
+
}
|
164
|
+
|
165
|
+
totals.each { |metric, value| send_if_valid(metric, value, tags, timestamp) }
|
166
|
+
|
167
|
+
if valid_value?(row['totalMeasuredTime']) && valid_value?(row['totalIterations'])
|
168
|
+
total_time = row['totalMeasuredTime'].to_f
|
169
|
+
total_iters = row['totalIterations'].to_f
|
170
|
+
if total_iters > 0
|
171
|
+
avg = total_time / total_iters
|
172
|
+
send_metric('benchmark.avg_time_per_iteration_ns', avg, tags, timestamp)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def valid_value?(value)
|
178
|
+
value && !value.empty? && value.to_f > 0
|
179
|
+
end
|
180
|
+
|
181
|
+
def send_if_valid(metric, value, tags, timestamp)
|
182
|
+
send_metric(metric, value.to_f, tags, timestamp) if valid_value?(value)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
DatadogMetricsIngester.run(ARGV)
|
data/lib/maze.rb
CHANGED
@@ -8,7 +8,7 @@ require_relative 'maze/timers'
|
|
8
8
|
# providing an alternative to the proliferation of global variables or singletons.
|
9
9
|
module Maze
|
10
10
|
|
11
|
-
VERSION = '9.
|
11
|
+
VERSION = '9.33.0'
|
12
12
|
|
13
13
|
class << self
|
14
14
|
attr_accessor :check, :driver, :internal_hooks, :mode, :start_time, :dynamic_retry, :public_address,
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bugsnag-maze-runner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 9.
|
4
|
+
version: 9.33.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steve Kirkland
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-08-
|
11
|
+
date: 2025-08-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cucumber
|
@@ -379,6 +379,7 @@ email:
|
|
379
379
|
- steve@bugsnag.com
|
380
380
|
executables:
|
381
381
|
- bb-failed-sessions
|
382
|
+
- benchmarks-to-datadog
|
382
383
|
- bugsnag-print-load-paths
|
383
384
|
- download-logs
|
384
385
|
- maze-runner
|
@@ -388,6 +389,7 @@ extensions: []
|
|
388
389
|
extra_rdoc_files: []
|
389
390
|
files:
|
390
391
|
- bin/bb-failed-sessions
|
392
|
+
- bin/benchmarks-to-datadog
|
391
393
|
- bin/bugsnag-print-load-paths
|
392
394
|
- bin/download-logs
|
393
395
|
- bin/maze-runner
|