flare 0.1.1 → 1.0.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.

Potentially problematic release.


This version of flare might be problematic. Click here for more details.

Files changed (56) hide show
  1. data/.document +5 -0
  2. data/.gitignore +22 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +18 -0
  5. data/Rakefile +55 -0
  6. data/VERSION +1 -0
  7. data/flare.gemspec +66 -0
  8. data/lib/flare/active_record.rb +102 -0
  9. data/lib/flare/collection.rb +47 -0
  10. data/lib/flare/configuration.rb +64 -109
  11. data/lib/flare/index_builder.rb +24 -0
  12. data/lib/flare/session.rb +142 -0
  13. data/lib/flare/tasks.rb +18 -0
  14. data/lib/flare.rb +19 -408
  15. data/test/helper.rb +10 -0
  16. data/test/test_flare.rb +7 -0
  17. metadata +89 -228
  18. checksums.yaml +0 -7
  19. data/CHANGELOG.md +0 -5
  20. data/LICENSE.txt +0 -21
  21. data/README.md +0 -148
  22. data/app/controllers/flare/application_controller.rb +0 -22
  23. data/app/controllers/flare/jobs_controller.rb +0 -55
  24. data/app/controllers/flare/requests_controller.rb +0 -73
  25. data/app/controllers/flare/spans_controller.rb +0 -101
  26. data/app/helpers/flare/application_helper.rb +0 -168
  27. data/app/views/flare/jobs/index.html.erb +0 -69
  28. data/app/views/flare/jobs/show.html.erb +0 -323
  29. data/app/views/flare/requests/index.html.erb +0 -120
  30. data/app/views/flare/requests/show.html.erb +0 -498
  31. data/app/views/flare/spans/index.html.erb +0 -112
  32. data/app/views/flare/spans/show.html.erb +0 -184
  33. data/app/views/layouts/flare/application.html.erb +0 -126
  34. data/config/routes.rb +0 -20
  35. data/exe/flare +0 -9
  36. data/lib/flare/backoff_policy.rb +0 -73
  37. data/lib/flare/cli/doctor_command.rb +0 -129
  38. data/lib/flare/cli/output.rb +0 -45
  39. data/lib/flare/cli/setup_command.rb +0 -404
  40. data/lib/flare/cli/status_command.rb +0 -47
  41. data/lib/flare/cli.rb +0 -50
  42. data/lib/flare/engine.rb +0 -43
  43. data/lib/flare/http_metrics_config.rb +0 -101
  44. data/lib/flare/metric_counter.rb +0 -45
  45. data/lib/flare/metric_flusher.rb +0 -124
  46. data/lib/flare/metric_key.rb +0 -42
  47. data/lib/flare/metric_span_processor.rb +0 -470
  48. data/lib/flare/metric_storage.rb +0 -42
  49. data/lib/flare/metric_submitter.rb +0 -221
  50. data/lib/flare/source_location.rb +0 -113
  51. data/lib/flare/sqlite_exporter.rb +0 -279
  52. data/lib/flare/storage/sqlite.rb +0 -789
  53. data/lib/flare/storage.rb +0 -54
  54. data/lib/flare/version.rb +0 -5
  55. data/public/flare-assets/flare.css +0 -1245
  56. data/public/flare-assets/images/flipper.png +0 -0
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Flare
4
- module CLI
5
- module Output
6
- private
7
-
8
- def color?
9
- $stdout.tty?
10
- end
11
-
12
- def green(text)
13
- color? ? "\e[32m#{text}\e[0m" : text
14
- end
15
-
16
- def yellow(text)
17
- color? ? "\e[33m#{text}\e[0m" : text
18
- end
19
-
20
- def red(text)
21
- color? ? "\e[31m#{text}\e[0m" : text
22
- end
23
-
24
- def bold(text)
25
- color? ? "\e[1m#{text}\e[0m" : text
26
- end
27
-
28
- def dim(text)
29
- color? ? "\e[2m#{text}\e[0m" : text
30
- end
31
-
32
- def checkmark
33
- green("✓")
34
- end
35
-
36
- def xmark
37
- red("✗")
38
- end
39
-
40
- def warn_mark
41
- yellow("!")
42
- end
43
- end
44
- end
45
- end
@@ -1,404 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "securerandom"
4
- require "digest"
5
- require "base64"
6
- require "socket"
7
- require "net/http"
8
- require "uri"
9
- require "json"
10
- require "fileutils"
11
- require_relative "output"
12
-
13
- module Flare
14
- class SetupCommand
15
- include CLI::Output
16
-
17
- DEFAULT_HOST = "https://flare.am"
18
- TIMEOUT_SECONDS = 300 # 5 minutes
19
-
20
- INITIALIZER_CONTENT = <<~RUBY
21
- # frozen_string_literal: true
22
-
23
- Flare.configure do |config|
24
- # ── Spans (local development dashboard) ────────────────────────────
25
- # Spans capture detailed trace data and are stored in a local SQLite
26
- # database. Enabled by default in development only. Visit /flare in
27
- # your browser to see the dashboard.
28
-
29
- # Enable or disable spans (default: true in development)
30
- # config.spans_enabled = true
31
-
32
- # How long to keep spans in hours (default: 24)
33
- # config.retention_hours = 24
34
-
35
- # Maximum number of spans to store (default: 10000)
36
- # config.max_spans = 10000
37
-
38
- # Path to the SQLite database (default: db/flare.sqlite3)
39
- # config.database_path = Rails.root.join("db", "flare.sqlite3").to_s
40
-
41
- # Ignore specific requests (receives a Rack::Request, return true to ignore)
42
- # config.ignore_request = ->(request) {
43
- # request.path.start_with?("/health")
44
- # }
45
-
46
- # ── Metrics (remote monitoring) ────────────────────────────────────
47
- # Metrics aggregate span data into counts, durations, and error rates.
48
- # Enabled by default in development and production (disabled in test).
49
- # Sent to flare.am when FLARE_KEY is configured.
50
-
51
- # Enable or disable metrics (default: true except in test)
52
- # config.metrics_enabled = true
53
-
54
- # How often to flush metrics in seconds (default: 60)
55
- # config.metrics_flush_interval = 60
56
-
57
- # ── Custom Instrumentation ─────────────────────────────────────────
58
- # Subscribe to additional notification prefixes (default: ["app."])
59
- # config.subscribe_patterns << "mycompany."
60
- end
61
-
62
- # ════════════════════════════════════════════════════════════════════════
63
- # Custom Instrumentation
64
- # ════════════════════════════════════════════════════════════════════════
65
- #
66
- # Use ActiveSupport::Notifications.instrument with an "app." prefix
67
- # anywhere in your code. Flare captures these in development and
68
- # displays them in the dashboard.
69
- #
70
- # ActiveSupport::Notifications.instrument("app.geocoding", address: address) do
71
- # geocoder.lookup(address)
72
- # end
73
- #
74
- # ActiveSupport::Notifications.instrument("app.stripe.charge", amount: 1000) do
75
- # Stripe::Charge.create(amount: 1000, currency: "usd")
76
- # end
77
- RUBY
78
-
79
- def initialize(force: false)
80
- @force = force
81
- end
82
-
83
- def run
84
- authenticate
85
- create_initializer
86
- add_gitignore_entries
87
-
88
- puts
89
- puts "#{green("Setup complete!")}"
90
- puts
91
- puts bold("What's next:")
92
- puts " 1. Start your Rails server (#{dim("bin/rails server")})"
93
- puts " 2. Make a few requests to your app"
94
- puts " 3. Visit #{bold("/flare")} to see the dashboard"
95
- puts
96
- puts dim(" The dashboard auto-mounts at /flare in development.")
97
- puts dim(" Metrics are sent to flare.am when FLARE_KEY is configured.")
98
- puts
99
- puts " Run #{bold("flare doctor")} to verify your setup."
100
- puts " Run #{bold("flare status")} to see your configuration."
101
- rescue Interrupt
102
- puts
103
- puts "Setup cancelled."
104
- exit 1
105
- end
106
-
107
- private
108
-
109
- # --- Auth ---
110
-
111
- def authenticate
112
- env_path = File.join(Dir.pwd, ".env")
113
-
114
- if !@force && File.exist?(env_path) && File.read(env_path).match?(/^FLARE_KEY=.+/)
115
- puts "#{checkmark} FLARE_KEY already set in .env, skipping auth."
116
- puts " Run with --force to re-authenticate."
117
- return
118
- end
119
-
120
- server = nil
121
- state = SecureRandom.hex(32)
122
- code_verifier = SecureRandom.urlsafe_base64(32)
123
- code_challenge = Base64.urlsafe_encode64(
124
- Digest::SHA256.digest(code_verifier),
125
- padding: false
126
- )
127
-
128
- server = TCPServer.new("127.0.0.1", 0)
129
- port = server.addr[1]
130
-
131
- host = ENV.fetch("FLARE_HOST", DEFAULT_HOST)
132
- authorize_url = "#{host}/cli/authorize?state=#{state}&port=#{port}&code_challenge=#{code_challenge}"
133
-
134
- puts "Opening browser to authorize Flare..."
135
- open_browser(authorize_url)
136
- puts
137
- puts "If the browser didn't open, visit:"
138
- puts " #{authorize_url}"
139
- puts
140
- puts "Waiting for authorization (up to 5 minutes)..."
141
-
142
- auth_code = wait_for_callback(server, state, TIMEOUT_SECONDS)
143
-
144
- unless auth_code
145
- puts "Timed out waiting for authorization."
146
- exit 1
147
- end
148
-
149
- token = exchange_code(auth_code, code_verifier)
150
- save_token(token)
151
- ensure
152
- server&.close
153
- end
154
-
155
- def wait_for_callback(server, expected_state, timeout)
156
- deadline = Time.now + timeout
157
-
158
- while Time.now < deadline
159
- readable = IO.select([server], nil, nil, 1)
160
- next unless readable
161
-
162
- client = server.accept
163
- request_line = client.gets
164
-
165
- unless request_line&.start_with?("GET /callback")
166
- client.print "HTTP/1.1 404 Not Found\r\nConnection: close\r\n\r\n"
167
- client.close
168
- next
169
- end
170
-
171
- # Read remaining headers (required by HTTP spec)
172
- while (line = client.gets) && line != "\r\n"; end
173
-
174
- params = parse_query_string(request_line)
175
- returned_state = params["state"]
176
- code = params["code"]
177
- error = params["error"]
178
-
179
- if error
180
- client.print http_response(error_page(error))
181
- client.close
182
- return nil
183
- elsif returned_state != expected_state
184
- client.print http_response(error_page("State mismatch. Please try again."))
185
- client.close
186
- return nil
187
- elsif code.nil? || code.empty?
188
- client.print http_response(error_page("No authorization code received."))
189
- client.close
190
- return nil
191
- else
192
- client.print http_response(success_page)
193
- client.close
194
- return code
195
- end
196
- end
197
-
198
- nil
199
- end
200
-
201
- def parse_query_string(request_line)
202
- return {} unless request_line
203
- path = request_line.split(" ")[1]
204
- return {} unless path
205
- query = URI(path).query
206
- return {} unless query
207
- URI.decode_www_form(query).to_h
208
- end
209
-
210
- def http_response(body)
211
- "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: #{body.bytesize}\r\nConnection: close\r\n\r\n#{body}"
212
- end
213
-
214
- def exchange_code(auth_code, code_verifier)
215
- host = ENV.fetch("FLARE_HOST", DEFAULT_HOST)
216
- uri = URI("#{host}/api/cli/exchange")
217
- http = Net::HTTP.new(uri.host, uri.port)
218
- http.use_ssl = uri.scheme == "https"
219
-
220
- request = Net::HTTP::Post.new(uri.path)
221
- request["Content-Type"] = "application/x-www-form-urlencoded"
222
- request.set_form_data(code: auth_code, code_verifier: code_verifier)
223
-
224
- response = http.request(request)
225
-
226
- unless response.is_a?(Net::HTTPSuccess)
227
- $stderr.puts "Failed to exchange code for token: #{response.code} #{response.message}"
228
- $stderr.puts response.body if response.body
229
- exit 1
230
- end
231
-
232
- data = JSON.parse(response.body)
233
- token = data["token"]
234
-
235
- if token.nil? || token.empty?
236
- $stderr.puts "No token received from server."
237
- exit 1
238
- end
239
-
240
- token
241
- end
242
-
243
- # --- Token storage ---
244
-
245
- def save_token(token)
246
- puts
247
- puts "Where would you like to save the token?"
248
- puts " 1. .env file"
249
- puts " 2. Rails credentials"
250
- puts " 3. Print token"
251
- print "Choose (1/2/3): "
252
-
253
- choice = $stdin.gets&.strip
254
-
255
- case choice
256
- when "1"
257
- @saved_to_dotenv = true
258
- save_to_dotenv(token)
259
- when "2"
260
- print_credentials_instructions(token)
261
- when "3"
262
- print_token(token)
263
- else
264
- puts "Invalid choice."
265
- save_token(token)
266
- end
267
- end
268
-
269
- def save_to_dotenv(token)
270
- env_path = File.join(Dir.pwd, ".env")
271
-
272
- if File.exist?(env_path)
273
- contents = File.read(env_path)
274
- if contents.match?(/^FLARE_KEY=/)
275
- contents.gsub!(/^FLARE_KEY=.*$/, "FLARE_KEY=#{token}")
276
- else
277
- contents = contents.chomp + "\nFLARE_KEY=#{token}\n"
278
- end
279
- File.write(env_path, contents)
280
- puts " Token saved to .env"
281
- else
282
- print " .env file not found. Create it? (y/n): "
283
- answer = $stdin.gets&.strip&.downcase
284
- if answer == "y" || answer == "yes"
285
- File.write(env_path, "FLARE_KEY=#{token}\n")
286
- puts " Created .env with FLARE_KEY"
287
- else
288
- print_dotenv_instructions(token)
289
- end
290
- end
291
- end
292
-
293
- def print_dotenv_instructions(token)
294
- puts
295
- puts "Add the following to your .env file:"
296
- puts
297
- puts " FLARE_KEY=#{token}"
298
- puts
299
- puts "Make sure .env is loaded in your app, for example with the dotenv gem:"
300
- puts
301
- puts " # Gemfile"
302
- puts " gem \"dotenv-rails\", groups: [:development, :test]"
303
- end
304
-
305
- def print_credentials_instructions(token)
306
- puts
307
- puts "Add the following to your Rails credentials:"
308
- puts
309
- puts " bin/rails credentials:edit"
310
- puts
311
- puts " flare:"
312
- puts " key: #{token}"
313
- puts
314
- puts "Or for a specific environment:"
315
- puts
316
- puts " bin/rails credentials:edit --environment production"
317
- puts
318
- puts " flare:"
319
- puts " key: #{token}"
320
- puts
321
- end
322
-
323
- def print_token(token)
324
- puts
325
- puts " FLARE_KEY=#{token}"
326
- end
327
-
328
- # --- Project setup ---
329
-
330
- def create_initializer
331
- path = File.join(Dir.pwd, "config/initializers/flare.rb")
332
- existed = File.exist?(path)
333
-
334
- if existed && !@force
335
- puts "#{checkmark} config/initializers/flare.rb already exists"
336
- puts " Run with --force to overwrite."
337
- return
338
- end
339
-
340
- FileUtils.mkdir_p(File.dirname(path))
341
- File.write(path, INITIALIZER_CONTENT)
342
-
343
- if existed
344
- puts "#{checkmark} Overwrote config/initializers/flare.rb"
345
- else
346
- puts "#{checkmark} Created config/initializers/flare.rb"
347
- end
348
- end
349
-
350
- def add_gitignore_entries
351
- gitignore_path = File.join(Dir.pwd, ".gitignore")
352
- return unless File.exist?(gitignore_path)
353
-
354
- contents = File.read(gitignore_path)
355
- entries_to_add = []
356
-
357
- entries_to_add << ".env" if @saved_to_dotenv && !contents.match?(/^\.env$/)
358
- entries_to_add << "flare.sqlite3*" unless contents.include?("flare.sqlite3*")
359
-
360
- return if entries_to_add.empty?
361
-
362
- File.open(gitignore_path, "a") do |f|
363
- f.puts "" unless contents.end_with?("\n")
364
- entries_to_add.each { |entry| f.puts entry }
365
- end
366
-
367
- puts "#{checkmark} Added #{entries_to_add.join(", ")} to .gitignore"
368
- end
369
-
370
- # --- Browser ---
371
-
372
- def open_browser(url)
373
- case RUBY_PLATFORM
374
- when /darwin/ then system("open", url)
375
- when /linux/ then system("xdg-open", url)
376
- when /mingw|mswin/ then system("start", url)
377
- end
378
- end
379
-
380
- def success_page
381
- page_shell("Authorized!", "You can close this window.")
382
- end
383
-
384
- def error_page(message)
385
- escaped = message.gsub("&", "&amp;").gsub("<", "&lt;").gsub(">", "&gt;").gsub('"', "&quot;")
386
- page_shell("Error", escaped)
387
- end
388
-
389
- def page_shell(title, subtitle)
390
- <<~HTML
391
- <!DOCTYPE html>
392
- <html>
393
- <head><title>Flare</title></head>
394
- <body style="font-family: system-ui, -apple-system, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background-color: #f5f3ef;">
395
- <div style="text-align: center; background: #fff; border-radius: 16px; padding: 48px 56px; box-shadow: 0 1px 3px rgba(0,0,0,0.04), 0 4px 12px rgba(0,0,0,0.04);">
396
- <h1 style="color: #3d3529; font-size: 28px; font-weight: 700; margin: 0 0 8px;">#{title}</h1>
397
- <p style="color: #8a8078; font-size: 15px; margin: 0;">#{subtitle}</p>
398
- </div>
399
- </body>
400
- </html>
401
- HTML
402
- end
403
- end
404
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "output"
4
- require_relative "../version"
5
-
6
- module Flare
7
- class StatusCommand
8
- include CLI::Output
9
-
10
- def run
11
- puts bold("Flare v#{VERSION}")
12
- puts
13
-
14
- puts bold("Environment")
15
- puts " RAILS_ENV: #{ENV.fetch("RAILS_ENV", dim("not set"))}"
16
- puts " FLARE_KEY: #{key_status}"
17
- puts " FLARE_URL: #{ENV.fetch("FLARE_URL", dim("https://flare.am (default)"))}"
18
- puts
19
-
20
- puts bold("Files")
21
- puts " Initializer: #{file_status("config/initializers/flare.rb")}"
22
- puts " .env: #{file_status(".env")}"
23
- puts " .gitignore: #{file_status(".gitignore")}"
24
- puts " Database: #{file_status("db/flare.sqlite3")}"
25
- end
26
-
27
- private
28
-
29
- def key_status
30
- if ENV["FLARE_KEY"] && !ENV["FLARE_KEY"].empty?
31
- green("set via ENV")
32
- else
33
- env_path = File.join(Dir.pwd, ".env")
34
- if File.exist?(env_path) && File.read(env_path).match?(/^FLARE_KEY=.+/)
35
- green("set in .env")
36
- else
37
- red("not configured")
38
- end
39
- end
40
- end
41
-
42
- def file_status(relative_path)
43
- path = File.join(Dir.pwd, relative_path)
44
- File.exist?(path) ? green("exists") : dim("not found")
45
- end
46
- end
47
- end
data/lib/flare/cli.rb DELETED
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "version"
4
-
5
- module Flare
6
- module CLI
7
- COMMANDS = {
8
- "setup" => "Authenticate and configure Flare for this project",
9
- "doctor" => "Check your Flare setup for issues",
10
- "status" => "Show current Flare configuration",
11
- "version" => "Print the Flare version",
12
- "help" => "Show this help message",
13
- }.freeze
14
-
15
- def self.start(argv)
16
- command = argv.first
17
-
18
- case command
19
- when "setup"
20
- require_relative "cli/setup_command"
21
- force = argv.include?("--force")
22
- SetupCommand.new(force: force).run
23
- when "doctor"
24
- require_relative "cli/doctor_command"
25
- DoctorCommand.new.run
26
- when "status"
27
- require_relative "cli/status_command"
28
- StatusCommand.new.run
29
- when "version", "-v", "--version"
30
- puts "flare #{Flare::VERSION}"
31
- when "help", nil, "-h", "--help"
32
- print_help
33
- else
34
- $stderr.puts "Unknown command: #{command}"
35
- $stderr.puts
36
- print_help
37
- exit 1
38
- end
39
- end
40
-
41
- def self.print_help
42
- puts "Usage: flare <command>"
43
- puts
44
- puts "Commands:"
45
- COMMANDS.each do |name, description|
46
- puts " %-12s %s" % [name, description]
47
- end
48
- end
49
- end
50
- end
data/lib/flare/engine.rb DELETED
@@ -1,43 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Flare
4
- class Engine < ::Rails::Engine
5
- isolate_namespace Flare
6
-
7
- # Load secrets from Rails credentials if not already set via ENV
8
- initializer "flare.defaults", before: :load_config_initializers do |app|
9
- ENV["FLARE_KEY"] ||= app.credentials.dig(:flare, :key)
10
- end
11
-
12
- # Serve static assets from the engine's public directory
13
- initializer "flare.static_assets" do |app|
14
- app.middleware.use(
15
- Rack::Static,
16
- urls: ["/flare-assets"],
17
- root: root.join("public"),
18
- cascade: true
19
- )
20
- end
21
-
22
- # Phase 1: Configure OTel SDK and instrumentations before middleware is
23
- # built so Rack/ActionPack can insert their middleware.
24
- initializer "flare.opentelemetry", before: :build_middleware_stack do
25
- Flare.configure_opentelemetry
26
- end
27
-
28
- # Phase 2: Start the metrics flusher after all initializers have run
29
- # so user config (metrics_enabled, flush_interval, etc.) is applied.
30
- config.after_initialize do
31
- Flare.start_metrics_flusher
32
- end
33
-
34
- # Auto-mount routes in development/test
35
- initializer "flare.routes", before: :add_routing_paths do |app|
36
- if Rails.env.development? || Rails.env.test?
37
- app.routes.prepend do
38
- mount Flare::Engine => "/flare"
39
- end
40
- end
41
- end
42
- end
43
- end
@@ -1,101 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Flare
4
- class HttpMetricsConfig
5
- class HostConfig
6
- attr_reader :rules
7
-
8
- def initialize
9
- @rules = []
10
- @all = false
11
- end
12
-
13
- def initialize_copy(source)
14
- @rules = source.rules.dup
15
- end
16
-
17
- def all?
18
- @all
19
- end
20
-
21
- # Track all paths for this host (normalized via normalize_path)
22
- def all
23
- @all = true
24
- end
25
-
26
- # Track paths matching this regex (normalized via normalize_path)
27
- def allow(pattern)
28
- @rules << {pattern: pattern, replacement: nil}
29
- end
30
-
31
- # Track paths matching this regex with a custom replacement string
32
- def map(pattern, replacement)
33
- @rules << {pattern: pattern, replacement: replacement}
34
- end
35
-
36
- # Returns the resolved path for a given raw path, or "*" if no match.
37
- # If :all, returns nil to signal "use normalize_path".
38
- # If a rule matches with a replacement, returns the replacement.
39
- # If a rule matches without a replacement, returns nil to signal "use normalize_path".
40
- # If no rules match, returns "*".
41
- def resolve(path)
42
- return nil if @all
43
-
44
- @rules.each do |rule|
45
- if rule[:pattern].match?(path)
46
- return rule[:replacement] # nil means use normalize_path
47
- end
48
- end
49
-
50
- "*"
51
- end
52
- end
53
-
54
- def initialize
55
- @hosts = {}
56
- end
57
-
58
- def initialize_copy(source)
59
- @hosts = source.instance_variable_get(:@hosts).transform_values(&:dup)
60
- end
61
-
62
- def host(hostname, mode = nil, &block)
63
- config = @hosts[hostname] ||= HostConfig.new
64
-
65
- if mode == :all
66
- config.all
67
- elsif block
68
- yield config
69
- end
70
- end
71
-
72
- # Resolve a host+path to the target path for metrics.
73
- # Returns "*" for unknown hosts or unmatched paths.
74
- # Returns nil to signal "use normalize_path".
75
- # Returns a string for custom replacements.
76
- def resolve(hostname, path)
77
- host_config = @hosts[hostname]
78
- return "*" unless host_config
79
-
80
- host_config.resolve(path)
81
- end
82
-
83
- DEFAULT = new.tap do |config|
84
- config.host "flare.am" do |h|
85
- h.allow %r{/api/metrics}
86
- end
87
-
88
- config.host "www.flippercloud.io" do |h|
89
- h.map %r{/adapter/features/[^/]+/(boolean|actors|groups|percentage_of_actors|percentage_of_time|expression|clear)}, "/adapter/features/:name/:gate"
90
- h.map %r{/adapter/features/[^/]+}, "/adapter/features/:name"
91
- h.map %r{/adapter/actors/[^/]+}, "/adapter/actors/:id"
92
- h.allow %r{/adapter/features}
93
- h.allow %r{/adapter/import}
94
- h.allow %r{/adapter/telemetry/summary}
95
- h.allow %r{/adapter/telemetry}
96
- h.allow %r{/adapter/events}
97
- h.allow %r{/adapter/audits}
98
- end
99
- end.freeze
100
- end
101
- end