Skip to content

mertek-dev/go-bug-tracker

Repository files navigation

go-bug-tracker

A self-hosted, Sentry-SDK-compatible error & performance tracker. Point any Sentry SDK at it — just change the DSN — and get issues, stack traces, distributed traces, profiling, release health, cron/uptime monitors, and alerting. All from a single Go service backed by one SQLite file.


Global dashboard

Go React SQLite Sentry compatible License: MIT


Why

Sentry's self-hosted stack is heavy — Kafka, ClickHouse, Redis, ~20 containers. go-bug-tracker delivers the same day-to-day developer experience for small and medium teams from one container and one SQLite file. Your data stays on your infrastructure, and any existing Sentry SDK works unchanged: you only swap the DSN.

  • Drop-in compatible — implements Sentry's envelope ingestion protocol (/api/{id}/envelope/ plus the legacy /store/). Errors, transactions, sessions, check-ins, profiles, attachments, client reports and user feedback all flow through the SDKs you already use.
  • Lightweight — cgo-free SQLite (WAL), a streaming envelope parser, and an async digest worker. No external services required.
  • Complete surface — issues, performance, profiling, releases, source maps, monitors, alerts, feedback, dashboards, teams and scoped API tokens all ship.

Screenshots

Issue list — grouping, severity, sparkline trends, priority & assignee Issue detail — source-mapped stack trace, tags, activity
Performance — p50–p99 & throughput per transaction Trace waterfall — span tree with durations
Profiling — flamegraph from sampled profiles Release health — crash-free rate, adoption, deploys, commits
Monitors — cron check-ins + uptime checks Alerts — rules and channels (email / webhook / Slack)
Source maps — per-release artifacts for JS de-minification User feedback — reports linked to their issue

Email notifications

Issue alert email — exception, in-app frames, tags, user Weekly report email — totals, charts, top issues & transactions

Features

  • Error tracking — server-side grouping into issues, full stack traces, breadcrumbs, tags, contexts and user. Resolve / archive / mute, regression detection, priority, assignment, comments, subscriptions, and merge.
  • Performance — transactions, distributed tracing with a span waterfall, p50–p99 latency and throughput per transaction.
  • Profiling — flamegraphs from sampled profiles, tied to their transactions, with aggregate views.
  • Release health — sessions, crash-free sessions/users, adoption, per-release issues, plus deploys and commits via the CI-friendly API.
  • Source maps — upload minified bundles and their .map files per release (single artifact or zip bundle) so JavaScript stack traces resolve to original source, with inline code context.
  • Monitors — cron check-ins (missed / late / errored, auto-created on first check-in) and HTTP uptime checks.
  • Alerting — rules (new issue, regression, …) routed to channels: email, outbound webhook, Slack. Alert emails include the exception, key in-app stack frames, tags and the affected user.
  • Weekly report — an org-wide email digest of the past week (errors, transactions, issue breakdown, top issues, slowest transactions) with CSS-only charts; configurable first day of the week, skipped when the week had no events.
  • User feedback — collected via the SDK or the user-feedback endpoint, linked to events.
  • Dashboards — org-wide and per-project: event volume, crash-free trend, top issues, slowest transactions, and a per-project breakdown.
  • Org & access — first-run setup, teams, members & invitations, and scoped API tokens (Sentry-style event:* / project:* / org:* scopes) for automation.
  • i18n — English and Vietnamese out of the box (paraglide-js).

How it works

Layer Tech
HTTP / API Go + Fiber v2internal/transport/http is the only package that imports Fiber
Ingestion Streaming Sentry envelope parser with compressed and decompressed size caps (decompression-bomb guard) → durable job queue
Digest Async worker: grouping, storage, source-map resolution, alerting — never inline on the ingest request
Storage SQLite (modernc.org/sqlite, cgo-free, WAL) + a content-addressed blob store for large payloads
Frontend React 19 + Vite + TanStack Router, Tailwind v4, shadcn/ui (ui/)
Serving SPA served as static files from DIST_DIR (never go:embed-ed); runtime env injected at container boot
Migrations golang-migrate (migrations/)

Quick start

Requirements: Go 1.26+, Bun (frontend), Docker (optional, for deployment).

cp .env.example .env          # set SESSION_SECRET (32+ bytes) at minimum
bun --cwd=ui install
make dev                      # backend (:8080, live reload) + frontend (:3000, Vite)

In dev, Vite serves the SPA on :3000 and proxies /apihttp://localhost:8080. On an empty database the app shows a first-run setup wizard to create the admin (or pre-seed with BOOTSTRAP_ADMIN_EMAIL / BOOTSTRAP_ADMIN_PASSWORD).

Production

make build                        # builds ui/dist + the `server` and `run` binaries
docker build -t go-bug-tracker .  # or build the container image

Every push to main that touches app code publishes a nightly image (doc-only commits are skipped). Create a semver git tag (v1.0.0) to publish latest and the version tag (1.0.0):

docker pull ghcr.io/mertek-dev/go-bug-tracker:nightly   # tip of main
docker pull ghcr.io/mertek-dev/go-bug-tracker:latest    # latest release tag
docker pull ghcr.io/mertek-dev/go-bug-tracker:1.0.0     # specific release

docker run --rm -p 8080:8080 \
  -e SESSION_SECRET='change-me-please-32-bytes-minimum-required' \
  -e BASE_URL='http://localhost:8080' \
  -v gobugtracker-data:/app/data \
  ghcr.io/mertek-dev/go-bug-tracker:nightly

Release: git tag v1.0.0 && git push origin v1.0.0. For a private repo, docker login ghcr.io with a GitHub PAT that has read:packages.

server serves the built SPA from DIST_DIR (default ./dist) as static files. In a container the run entrypoint injects VITE_* env into dist/env.js (window.__ENV__) at boot — runtime reconfiguration without a rebuild — then execs server.

Send your first event

Create a project in the UI, then copy its DSN from Project settings. Point any Sentry SDK at it.

JavaScript / Next.js (instrumentation-client.ts):

import * as Sentry from "@sentry/nextjs";

Sentry.init({
  dsn: "http://<public_key>@localhost:8080/<project_number>",
  tracesSampleRate: 1.0,   // performance + release-health sessions
  release: "my-app@1.0.0",
  environment: "production",
});

Ingest protocol

Mounted under /api/{project_number}/ and authenticated by sentry_key (no session/CSRF):

Method Path Purpose
POST /api/{id}/envelope/ Primary — newline-delimited envelope (events, transactions, sessions, check-ins, profiles, attachments, client reports)
POST /api/{id}/store/ Legacy — a single bare event JSON body
POST /api/{id}/user-feedback/ User feedback linked to an event

Handled envelope item types: event, transaction, session, sessions, check_in, profile, attachment, client_report. Unknown types are skipped gracefully. See docs/steering/ingestion-protocol.md for the full contract (DSN format, auth resolution, size limits, rate limiting).

Automation & CI

Management endpoints under /api/_/ accept either a session cookie (+ CSRF) or a Bearer API token minted in Settings → API tokens with fine-grained scopes. Bearer tokens skip CSRF, so they're ideal for CI:

# Upload a source map for a release (project:releases scope)
curl -X POST "http://localhost:8080/api/_/projects/<project_id>/artifacts" \
  -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
  -d '{"release":"my-app@1.0.0","name":"app.min.js.map","type":"sourcemap","content_base64":"..."}'

# Record a deploy for a release
curl -X POST "http://localhost:8080/api/_/releases/<release_id>/deploys" \
  -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
  -d '{"environment":"production","name":"v1.0.0"}'

The full HTTP surface is documented in docs/openapi.yaml.

Configuration

Key environment variables (see .env.example for the complete list):

Variable Description
PORT HTTP port (default 8080)
BASE_URL Public URL; DSNs handed to SDKs are built from this
DATABASE_URL SQLite DSN (WAL, busy_timeout)
SESSION_SECRET Required, 32+ bytes; rotating it invalidates all sessions
BOOTSTRAP_ADMIN_EMAIL / _PASSWORD Pre-seed the first admin on an empty DB
MAX_ENVELOPE_COMPRESSED_BYTES / MAX_ENVELOPE_BYTES Decompression-bomb caps (on-wire + decoded)
RETENTION_MAX_EVENTS_PER_PROJECT Error retention cap (eviction by age + relevance)
PERF_RETENTION_DAYS Performance (transactions/spans/profiles) retention
SMTP_HOST / SMTP_PORT / SMTP_FROM Email alerts
SOURCEMAPS_ENABLED Enable JS de-minification

Development

go build ./...   && go vet ./...   && go test ./...      # backend gates (add -race for concurrency)
bun --cwd=ui run format && bunx --cwd ui biome check && bun --cwd=ui run test && bunx --cwd ui tsc --noEmit
bunx @redocly/cli lint docs/openapi.yaml                  # when the API changes

docs/openapi.yaml is the API contract — handler changes ship with the matching spec change. Tests ship with code.

Project layout

cmd/            server + run (container entrypoint) binaries
internal/       domain packages (issues, performance, profiles, releases, monitors,
                alerts, sourcemaps, sessions, digest, retention…) + transport/http
migrations/     golang-migrate SQL
ui/             React 19 + Vite SPA (TanStack Router, Tailwind v4, shadcn/ui)
docs/           steering docs, OpenAPI contract, roadmap, UI style spec

Documentation

License

MIT © mertek.dev

About

A self-hosted, **lightweight, Sentry-SDK-compatible** error & performance tracker. Point any Sentry SDK at it (just change the DSN) and get issues, stacktraces, performance traces, release health, and alerting — backed by GO and SQLite.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors