SDK & Integrations

Gotcha doesn’t have its own wire protocol for sending data — it accepts events and transactions via the Sentry ingestion protocol, and metrics and profiles via OTLP and pprof respectively. That means connecting your application doesn’t require any special “Gotcha SDK”: you install the official Sentry SDK for your language and point it at your Gotcha project’s DSN. From there the SDK behaves exactly as documented upstream — Gotcha just happens to be on the other end of the DSN instead of sentry.io.

Below: install and minimal init for PHP (including Laravel), JavaScript/Node, JavaScript in the browser, Python, and Go, followed by environment & release, sending performance data (tracing), pointers to metrics and profiling ingest, and a troubleshooting section for connection issues.

Where to find your DSN

Your project’s DSN lives on the “Setup” page: right after creating a project you’re automatically redirected there (a URL like /projects/<id>/setup), and you can get back to it later via the “Setup” button in the projects list or the “DSN keys” section on the “Project settings” page. A DSN looks like this:

https://<PUBLIC_KEY>@<your-gotcha-host>/<PROJECT_ID>

In every example below, replace <YOUR_PROJECT_DSN> with this full string.

PHP (plain project)

composer require sentry/sentry

Repository: https://github.com/getsentry/sentry-php

<?php
require __DIR__ . '/vendor/autoload.php';

\Sentry\init([
    'dsn' => '<YOUR_PROJECT_DSN>',
    'environment' => getenv('APP_ENV') ?: 'production',
    'traces_sample_rate' => 0.2, // enables performance tracing; see the section below
]);

Send a test error — either just let an unhandled exception happen (the SDK hooks set_exception_handler automatically), or capture one explicitly:

try {
    throw new \RuntimeException('Gotcha test error');
} catch (\Throwable $e) {
    \Sentry\captureException($e);
}

The event shows up under your project’s “Issues” within a few seconds.

PHP (Laravel)

composer require sentry/sentry-laravel

Repository: https://github.com/getsentry/sentry-laravel

Publish the config and set the DSN in one go (this adds the variable to .env and creates config/sentry.php):

php artisan sentry:publish --dsn=<YOUR_PROJECT_DSN>

Or add it to .env manually:

SENTRY_LARAVEL_DSN=<YOUR_PROJECT_DSN>
SENTRY_TRACES_SAMPLE_RATE=0.2
SENTRY_ENVIRONMENT=production

The package registers itself into Laravel’s exception handler automatically — no extra init call is needed. Send a test event:

php artisan sentry:test

It shows up under “Issues” in the project whose DSN you configured.

JavaScript / Node.js (server)

npm install @sentry/node

Repository: https://github.com/getsentry/sentry-javascript

const Sentry = require("@sentry/node");
// or: import * as Sentry from "@sentry/node";

Sentry.init({
  dsn: "<YOUR_PROJECT_DSN>",
  environment: process.env.NODE_ENV || "production",
  tracesSampleRate: 0.2,
});

Test error:

try {
  throw new Error("Gotcha test error");
} catch (e) {
  Sentry.captureException(e);
}

Before a short-lived process exits (a CLI script, a serverless function, a worker that returns immediately), make sure to flush the buffer:

await Sentry.close(2000); // wait up to 2s for the event to be sent

JavaScript (browser)

npm install @sentry/browser
import * as Sentry from "@sentry/browser";

Sentry.init({
  dsn: "<YOUR_PROJECT_DSN>",
  environment: "production",
  tracesSampleRate: 0.2, // tracing + automatic Web Vitals collection (LCP/INP/CLS/FCP/TTFB)
});

Test error — any unhandled exception on the page is captured automatically; explicitly:

Sentry.captureException(new Error("Gotcha test error"));

If your site sets a Content-Security-Policy with connect-src, add your Gotcha instance’s address to it — otherwise the browser will silently block the request to your DSN.

Python

pip install sentry-sdk

Repository: https://github.com/getsentry/sentry-python

import sentry_sdk

sentry_sdk.init(
    dsn="<YOUR_PROJECT_DSN>",
    environment="production",
    traces_sample_rate=0.2,
)

Test error:

try:
    raise RuntimeError("Gotcha test error")
except Exception:
    sentry_sdk.capture_exception()

For Django/Flask/FastAPI and other frameworks, sentry-sdk auto-enables the matching integration when it detects the framework is installed — no separate opt-in is needed beyond calling sentry_sdk.init(...) at your app’s entry point.

Go

go get github.com/getsentry/sentry-go

Repository: https://github.com/getsentry/sentry-go

package main

import (
	"errors"
	"time"

	"github.com/getsentry/sentry-go"
)

func main() {
	err := sentry.Init(sentry.ClientOptions{
		Dsn:              "<YOUR_PROJECT_DSN>",
		Environment:      "production",
		TracesSampleRate: 0.2,
	})
	if err != nil {
		panic(err)
	}
	// REQUIRED: without Flush the process can exit before the event
	// buffer has actually been sent over the network.
	defer sentry.Flush(2 * time.Second)

	sentry.CaptureException(errors.New("Gotcha test error"))
}

Environment & release

environment and release are two fields worth setting from day one: they get attached to every event, transaction, and metric, and are used for filtering across nearly every section of Gotcha.

\Sentry\init([
    'dsn' => '<YOUR_PROJECT_DSN>',
    'environment' => 'staging',
    'release' => 'my-app@' . trim(shell_exec('git rev-parse --short HEAD')),
]);

That way production errors don’t drown among your staging environment’s noise, and a performance regression can be traced back to the exact release it started in.

Performance & tracing (transactions)

The traces_sample_rate option (tracesSampleRate in JS) turns on transactions — the unit of performance data that powers the Performance section. Its value is the fraction of requests to trace: 1.0 traces everything, 0.2 traces one in five, and 0 (the default) disables tracing entirely, sending only errors.

On top of that, “Project Settings → Performance” has a server-side sampling knob (sample_rate, 0..1) that’s applied on top of whatever the SDK already sent — useful for trimming stored transaction volume without redeploying your app. In the browser, enabling tracing also automatically collects Web Vitals (LCP/INP/CLS/FCP/TTFB) — no separate opt-in needed.

Metrics (OTLP)

Numeric metrics (counter/gauge/histogram) are accepted by Gotcha over the OpenTelemetry protocol (OTLP/HTTP), not through the Sentry SDK. Point your application’s OTLP exporter (or an OpenTelemetry Collector) at:

POST https://<your-gotcha-host>/v1/metrics
Authorization: Bearer <PUBLIC_KEY>

<PUBLIC_KEY> is the public key part of your project’s DSN (the segment between https:// and @), not the full DSN. Most OTel exporters have a built-in way to set headers (headers: in a Collector config, OTEL_EXPORTER_OTLP_METRICS_HEADERS as an env var). More on metric types, aggregations, and threshold alerts: Metrics.

Profiling (pprof)

Besides the profiles a Sentry SDK sends alongside traces (profiles_sample_rate in the Python/PHP/JS/Go SDKs), Gotcha also accepts raw pprof profiles directly:

POST https://<your-gotcha-host>/profiles/pprof?service=<service-name>&environment=<environment>
Authorization: Bearer <PUBLIC_KEY>
Content-Type: application/octet-stream

The body is a regular gzip-compressed pprof profile (e.g. the output of go tool pprof or runtime/pprof). More on flame graphs, in-app vs. system frames, and regressions: Profiling.

Not seeing an event?

If an error you sent hasn’t shown up under “Issues” after a reasonable wait, check these in order:

CauseHow to check
Wrong or revoked DSNCompare it against what’s shown under “Project Settings → DSN keys”; ingest returns 401/403 for an unknown or revoked public key. Reissuing a key immediately invalidates the old DSN.
DSN from a different projectThe project_id in the DSN must match the project the key actually belongs to — otherwise ingest returns 403 sentry_key does not match project.
Network/firewallYour application needs HTTPS/HTTP reachability to your Gotcha instance’s address (GOTCHA_BASE_URL) — try curl -i <your-gotcha-host>/healthz from the same machine/container the app runs on. A corporate proxy or egress firewall can silently drop outbound requests.
Event/body too largeBy default ingest caps request bodies at 1 MB (GOTCHA_MAX_EVENT_BYTES on the instance); exceeding it returns 413. This can bite events with very long stack traces or large breadcrumb trails.
Organization quota exhaustedIngest returns 429 with Retry-After once the monthly quota is used up; check “Organization settings → Usage & rate limits”. The oss edition defaults to unlimited (0), but the instance admin may have set a cap.
SDK didn’t flush in timeIn short-lived processes (CLI scripts, serverless functions, workers that exit immediately), call Flush/close before exiting — see the Go and Node examples above; without it, the event buffer may never actually be sent.
CSP blocking the request in the browserIf the page sets a Content-Security-Policy, add your Gotcha host to connect-src.

If none of these explain it, turn on the SDK’s debug mode (debug: true on most Sentry SDKs) and see what it logs when it tries to send — that almost always pinpoints the exact cause.