Sentry
If you already use Sentry, you can send Packrat a copy of the same data with a few lines of configuration. Sentry keeps receiving everything, and Packrat gets a copy. This is called dual-shipping.
You can dual-ship from two places:
- Your Rails server, through
sentry-ruby. - Your pages, through Sentry's browser SDK,
@sentry/browser.
For a server in another language, use OpenTelemetry instead.
Before you begin
-
Sign up for Packrat. It's free.
-
Copy your ingest key from the setup page. It starts with
packrat_ingest_. -
Install the Packrat CLI and sign in, so you can check what Packrat receives:
curl -fsSL https://packrat.sh/cli | sh packrat login
On your Rails server
If your app runs sentry-ruby and sentry-rails, add a transport to your Sentry initializer. The
transport sends each event to Sentry, then sends a copy to Packrat. Packrat receives your
exceptions and your request and job traces.
If your app doesn't use Sentry yet, don't install it for Packrat. Follow the OpenTelemetry guide for Ruby on Rails instead.
Dual-ship from sentry-ruby
-
Set
PACKRAT_SENTRY_DSNwhere your app runs. It's made from your ingest key and your app's name in Packrat:PACKRAT_SENTRY_DSN=https://<your ingest key>@ingest.packrat.sh/<your app> -
Add the transport to
config/initializers/sentry.rb, and set it inSentry.init:# config/initializers/sentry.rb # Sends Packrat a copy of each envelope. module PackratSentry def self.transport @transport ||= begin config = Sentry.configuration.dup config.dsn = ENV["PACKRAT_SENTRY_DSN"] Sentry::HTTPTransport.new(config) end end end class PackratDualTransport < Sentry::HTTPTransport def send_data(data) super ensure begin PackratSentry.transport.send_data(data) rescue => e Sentry.sdk_logger.warn("[packrat] copy failed: #{e.class}: #{e.message}") end end end Sentry.init do |config| config.dsn = ENV["SENTRY_DSN"] config.release = ENV["GIT_COMMIT"] # the commit you deployed config.environment = Rails.env config.transport.transport_class = PackratDualTransport if ENV["PACKRAT_SENTRY_DSN"].present? end -
Deploy, or restart your app.
Sentry still receives each event first. If Packrat is unreachable, the copy fails and Sentry logs a warning.
Send to Packrat only
If you don't use Sentry, set Packrat's DSN as the only DSN in config/initializers/sentry.rb:
# config/initializers/sentry.rb
Sentry.init do |config|
config.dsn = ENV["PACKRAT_SENTRY_DSN"]
config.release = ENV["GIT_COMMIT"] # the commit you deployed
config.environment = Rails.env
config.traces_sample_rate = 1.0
end
Verify your server
Make a request to your app and wait about a minute. Then list the server's latest spans:
SELECT name, kind, json_extract_string(span_attributes, '$."sentry.op"') AS op, duration_ms
FROM packrat_spans(since := now()::TIMESTAMP - INTERVAL 10 MINUTE)
WHERE scope_name LIKE 'sentry.ruby%'
ORDER BY start_time DESC LIMIT 20
A request's first span has a kind of 2, and a job's has 5. Once the hour closes, packrat_traces
lists the requests and jobs themselves.
In the browser
Sentry's browser SDK can send Packrat your page loads, Web Vitals, JavaScript errors and session replays. Packrat stores them in the same app as your server's data.
If your pages don't run the SDK yet, install it with Sentry's JavaScript guide, then follow Send to Packrat only.
Create a browser ingest key
The key goes in your page's source, where anyone can read it. On your org's Keys page, create an ingest key for the browser only. You can then revoke it without affecting your servers.
Dual-ship from the browser SDK
Give Sentry.init a transport that sends each envelope to Sentry and a copy to Packrat. Replace
<your app> with the name your server's app has in Packrat, so the browser's data lands in the same
app, and set environment to the app's environment, such as production or staging.
const PACKRAT =
"https://ingest.packrat.sh/api/<your app>/envelope/?sentry_version=7&sentry_key=<browser ingest key>&environment=production";
Sentry.init({
dsn: "<your Sentry DSN>",
release: "<your deploy's commit SHA>",
integrations: [Sentry.browserTracingIntegration()],
tracesSampleRate: 1.0,
transport: (options) => {
const sentry = Sentry.makeFetchTransport(options);
const packrat = Sentry.makeFetchTransport({ ...options, url: PACKRAT });
return {
send: (envelope) => {
packrat.send(envelope);
return sentry.send(envelope);
},
flush: (timeout) =>
Promise.all([sentry.flush(timeout), packrat.flush(timeout)]).then(
(done) => done.every(Boolean),
),
};
},
});
Send to Packrat only
If you don't use Sentry, or no longer want the browser to report to it, use Packrat's DSN and send every envelope to Packrat:
const PACKRAT =
"https://ingest.packrat.sh/api/<your app>/envelope/?sentry_version=7&sentry_key=<browser ingest key>&environment=production";
Sentry.init({
dsn: "https://<browser ingest key>@ingest.packrat.sh/<your app>",
release: "<your deploy's commit SHA>",
integrations: [Sentry.browserTracingIntegration()],
tracesSampleRate: 1.0,
transport: (options) =>
Sentry.makeFetchTransport({ ...options, url: PACKRAT }),
});
Turn on session replays
To record sessions, add Sentry.replayIntegration() and set how many sessions to record. With
either transport above, Packrat receives the replays too:
Sentry.init({
// ...as above
integrations: [Sentry.browserTracingIntegration(), Sentry.replayIntegration()],
replaysSessionSampleRate: 0.1, // record 10% of sessions
replaysOnErrorSampleRate: 1.0, // and every session with an error
});
Each app's Replays page lists the sessions, and you can query them with packrat_replays and
packrat_replay_events. The API reference lists the columns.
Verify the browser SDK
Load a page, then check what Packrat receives. The browser shows up as the source Sentry browser
under traces, and under replays and exceptions once it sends them.
Run packrat status with your app's name, as <service>/<environment>:
packrat status --app shop/production
The output lists each signal (exceptions, traces, logs, metrics and replays), the sources that send
it, when each source last sent, and whether Packrat keeps it. A signal with no source hasn't arrived
yet. To see the names your apps report under, run packrat apps.
After about a minute, you can query the browser's spans:
SELECT name, json_extract_string(span_attributes, '$."sentry.op"') AS op, duration_ms
FROM packrat_spans(since := now()::TIMESTAMP - INTERVAL 10 MINUTE)
WHERE scope_name LIKE 'sentry.javascript.%'
ORDER BY start_time DESC LIMIT 20