Created
August 13, 2025 18:40
-
-
Save xunker/91edd10c5e1917160fb8cebba81b39bc to your computer and use it in GitHub Desktop.
Get a CSV of all occurences of a Rollbar error or message
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env ruby | |
| # | |
| # Writes a CSV of all available occurences of a Rollbar exception/error/message. | |
| # | |
| # Run via `ruby rollbar_occurences.rb`, or `chmod +x rollbar_occurences.rb` | |
| # (one time only) and then `./rollbar_occurences.rb`. | |
| # | |
| # Requires the Rollbar-api gem (https://rubygems.org/gems/rollbar-api) and | |
| # Ruby v2.3 or greater. | |
| # | |
| # Also requires a project auth token from Rollbar for the project | |
| # | |
| # Released under terms of GPL v3 where applicable. | |
| # | |
| def usage(exit_status = 0) | |
| puts <<~USAGE | |
| usage: | |
| rollbar_occurences.rb <counterId> | |
| "counterId" is found in the Rollbar URL for an exception: | |
| https://app.rollbar.com/a/{orgName}/fix/item/{projectName}/{counterId} | |
| example: | |
| https://app.rollbar.com/a/contoso/fix/item/project-one/458356 | |
| Required Environment Variables: | |
| ROLLBAR_API_TOKEN The API token for the Rollbar project. A read-only | |
| token is recommended. | |
| ROLLBAR_API_PROJECT The name of the project("{projectName}" in URL). | |
| These can be set either via `export ROLLBAR_API_TOKEN=xxx` or inline as | |
| `ROLLBAR_API_TOKEN=xxx ROLLBAR_API_PROJECT=yyy rollbar_occurences.rb <id>` | |
| USAGE | |
| exit(exit_status) | |
| end | |
| def fatal_error(message, show_usage: false, exit_status: 0) | |
| puts "Error: #{message}" | |
| if show_usage | |
| puts '-'*80 | |
| usage(exit_status) | |
| else | |
| exit(exit_status) | |
| end | |
| end | |
| unless RUBY_VERSION.to_f >= 2.3 | |
| fatal_error("Ruby >= 2.3 is required, but you are using #{RUBY_VERSION}.", exit_status: 1) | |
| end | |
| begin | |
| require 'rollbar_api' | |
| rescue LoadError | |
| message = <<~MESSAGE | |
| The "rollbar-api" Gem (https://rubygems.org/gems/rollbar-api) is required. \ | |
| You can try to install it with "gem install rollbar-api". | |
| MESSAGE | |
| fatal_error(message, exit_status: 1) | |
| end | |
| %w[ROLLBAR_API_PROJECT ROLLBAR_API_TOKEN].each do |env_var| | |
| next if ENV[env_var].to_s.length.positive? | |
| fatal_error( | |
| "#{env_var} environment variable not found or not set.", | |
| exit_status: 1, | |
| show_usage: true | |
| ) | |
| end | |
| if %w[-h --help help].include?(ARGV[0]) | |
| usage | |
| end | |
| counter_id = ARGV[0].to_i | |
| unless counter_id.positive? | |
| fatal_error( | |
| 'counterId argument missing or not a number.', | |
| exit_status: 1, | |
| show_usage: true | |
| ) | |
| end | |
| # disable the noisy logger | |
| RollbarApi.logger = Logger.new(nil) | |
| RollbarApi::Project.configure( | |
| ENV['ROLLBAR_API_PROJECT'], | |
| ENV['ROLLBAR_API_TOKEN'] | |
| ) | |
| project = RollbarApi::Project.find(ENV['ROLLBAR_API_PROJECT']) | |
| item = project.get("/api/1/item_by_counter/#{counter_id}") | |
| item_id = item.result['itemId'] | |
| instance_list = [] | |
| more_to_load = true | |
| page = 1 | |
| File.open("instances_#{counter_id}.csv", 'w') do |file| | |
| puts "Created #{file.path}" | |
| file.puts( | |
| %i[ | |
| id | |
| when | |
| class | |
| message | |
| uri | |
| url | |
| requested_filename | |
| file_extention | |
| ip | |
| user_id | |
| user_agent | |
| body | |
| ].join(',') | |
| ) | |
| while more_to_load | |
| puts "loading page #{page}" | |
| instances = project.get( | |
| "api/1/item/#{item_id}/instances", | |
| page: page, | |
| limit: 100 | |
| ) | |
| instances.result.instances.each do |inst| | |
| user_agent = if !(headers = inst.data.request&.headers).nil? | |
| headers['User-Agent'] | |
| end | |
| request_url = inst.data.request&.url.to_s | |
| requested_filename = if (m = request_url.match(/\/([^\/]+)\z/)) | |
| m[1] | |
| end | |
| file_extention = if (requested_filename && (m = requested_filename.match(/\.(.{1,8})\z/))) | |
| m[1] | |
| end | |
| # `.gsub(',', '%2C')` serves to replace a comma with the URL-Encoding | |
| # equivalent "%2C" because there is no standard way to escape a comma in | |
| # a CSV file. | |
| # .gsub("\n", '\n') is the same, but for newline characters where they | |
| # are turned in to the literal '\n' string. | |
| file.puts [ | |
| inst.id, | |
| Time.at(inst.timestamp), | |
| inst.data.body&.trace&.exception&.class, | |
| inst.data.body&.trace&.exception&.message.to_s.gsub("\n", '\n'), | |
| inst.data.body&.trace&.extra&.uri.to_s.gsub(',', '%2C'), | |
| request_url.gsub(',', '%2C'), | |
| requested_filename.gsub(',', '%2C'), | |
| file_extention, | |
| inst.data.request&.user_ip, | |
| inst.data.body&.trace&.extra&.custom_params&.user_id, | |
| user_agent, | |
| inst.data.request&.body | |
| ].join(',') | |
| end | |
| page += 1 | |
| more_to_load = instances.result.instances.length.positive? | |
| end | |
| puts "Finished writing to #{file.path}" | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment