Logwell
Self-hosted logging platform with real-time streaming, full-text search, and OTLP-compatible ingestion. Deploy in minutes, own your data.
Install / Use
/learn @Divkix/LogwellREADME
What is Logwell?
Logwell is a lightweight, self-hosted log aggregation platform for developers who want structured logging without the complexity of ELK or the costs of cloud services.
Use Logwell when you need:
- A simple logging backend for your side project or startup
- Full-text search across logs without managing Elasticsearch
- Real-time log streaming during development and debugging
- Complete data ownership with no vendor lock-in
Logwell is NOT for:
- High-volume production systems (10k+ logs/second) — use Loki or Clickhouse
- Teams needing RBAC, audit trails, or compliance features — use a managed service
- Distributed tracing or metrics — Logwell is logs-only
Features
- OTLP-native ingestion — Standard OpenTelemetry protocol, no proprietary SDKs required
- PostgreSQL backend — Full-text search via tsvector, no separate search cluster needed
- Real-time streaming — SSE-powered live log tailing with batching
- Incident intelligence — Error/fatal fingerprinting with incident timeline and correlation hints
- Project isolation — Per-project API keys with separate log streams
- Zero telemetry — No phone-home, no tracking, fully air-gapped deployments supported
- Clean UI — Minimal interface with dark mode and log level color coding
Preview
<p align="center"> <video src="static/demo.mp4" width="100%" autoplay loop muted playsinline></video> <br> <em>Real-time log streaming demo</em> </p> <table> <tr> <td width="50%"> <img src="static/logview-screen.png" alt="Log Viewer"> <p align="center"><em>Real-time log viewer with level filtering</em></p> </td> <td width="50%"> <img src="static/logs-view-empty.png" alt="Quick Start"> <p align="center"><em>Quick Start with pre-filled API key</em></p> </td> </tr> <tr> <td width="50%"> <img src="static/project-settings.png" alt="Project Settings"> <p align="center"><em>API key management and code snippets</em></p> </td> <td width="50%"> <img src="static/stats-screen.png" alt="Statistics"> <p align="center"><em>Log level distribution analytics</em></p> </td> </tr> </table>Why Logwell?
| vs | Logwell advantage | |----|-------------------| | Loki/Grafana | Built-in UI, no LogQL to learn, just PostgreSQL | | ELK | Lightweight PostgreSQL backend, not Elasticsearch | | Datadog/etc | Self-hosted, no per-GB pricing, own your data |
Tech Stack
| Layer | Technology | |-------|------------| | Framework | SvelteKit | | Database | PostgreSQL | | ORM | Drizzle | | Auth | better-auth | | UI | shadcn-svelte + Tailwind CSS v4 | | Real-time | Server-Sent Events | | Runtime | Bun |
Prerequisites
Quick Start
# Clone the repository
git clone https://github.com/divkix/logwell.git
cd logwell
# Install dependencies
bun install
# Set up environment
cp .env.example .env
# Edit .env with your values (see Environment Variables below)
# Start PostgreSQL
docker compose up -d
# Run database migrations
bun run db:migrate
# Create admin user
bun run db:seed
# Start development server
bun run dev
Open http://localhost:5173 and sign in with:
- Username:
admin(or yourADMIN_USERNAMEfrom.env) - Password: Your
ADMIN_PASSWORDfrom.env
Note: Development runs on port 5173 (Vite). Production builds run on port 3000.
Environment Variables
Create a .env file with the following:
# Database connection
DATABASE_URL="postgres://root:mysecretpassword@localhost:5432/local"
# Authentication secret (minimum 32 characters)
BETTER_AUTH_SECRET="your-32-character-secret-key-here"
# Admin user password (minimum 8 characters)
ADMIN_PASSWORD="your-admin-password"
# Admin username (optional, defaults to "admin")
# ADMIN_USERNAME="admin"
# Production URL (required for auth behind reverse proxies)
ORIGIN="https://your-domain.com"
# Log retention (optional, defaults shown)
# LOG_RETENTION_DAYS="30" # 0 = never auto-delete
# LOG_CLEANUP_INTERVAL_MS="3600000" # Cleanup job interval (1 hour)
# INCIDENT_AUTO_RESOLVE_MINUTES="30" # Incident resolves after N quiet minutes
Generate a secure secret:
openssl rand -base64 32
Usage
Create a Project
- Sign in to the dashboard
- Click New Project
- Enter a project name
- Copy the generated API key (
lw_...)
Send Logs
Logwell provides two ingestion APIs:
| API | Endpoint | Best For |
|-----|----------|----------|
| Simple API | POST /v1/ingest | Quick integration, any HTTP client |
| OTLP API | POST /v1/logs | OpenTelemetry SDKs, rich metadata |
Simple API (Recommended for quick start)
The simple API accepts flat JSON with minimal boilerplate:
curl -X POST http://localhost:5173/v1/ingest \
-H "Authorization: Bearer lw_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"level": "info", "message": "User signed in"}'
Batch multiple logs:
curl -X POST http://localhost:5173/v1/ingest \
-H "Authorization: Bearer lw_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '[
{"level": "info", "message": "Request started"},
{"level": "error", "message": "Database timeout", "metadata": {"query": "SELECT..."}}
]'
Available fields:
| Field | Required | Type | Description |
|-------|----------|------|-------------|
| level | Yes | debug | info | warn | error | fatal | Log severity |
| message | Yes | string | Log message |
| timestamp | No | ISO8601 string | Defaults to current time |
| service | No | string | Service name for filtering |
| metadata | No | object | Additional structured data |
await fetch('http://localhost:5173/v1/ingest', {
method: 'POST',
headers: {
'Authorization': 'Bearer lw_YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({ level: 'info', message: 'Hello from Node.js' })
});
</details>
<details>
<summary><strong>Python (no SDK needed)</strong></summary>
import requests
requests.post('http://localhost:5173/v1/ingest',
headers={'Authorization': 'Bearer lw_YOUR_API_KEY'},
json={'level': 'info', 'message': 'Hello from Python'})
</details>
<details>
<summary><strong>Go (no SDK needed)</strong></summary>
body := []byte(`{"level": "info", "message": "Hello from Go"}`)
req, _ := http.NewRequest("POST", "http://localhost:5173/v1/ingest", bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer lw_YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
http.DefaultClient.Do(req)
</details>
TypeScript/JavaScript SDK
For Node.js, browsers, and edge runtimes (Cloudflare Workers, etc.):
npm install logwell
import { Logwell } from 'logwell';
const logger = new Logwell({
apiKey: 'lw_YOUR_API_KEY',
endpoint: 'http://localhost:5173',
});
// Log at different levels
logger.info('User signed in', { userId: '123' });
logger.error('Database failed', { host: 'db.local' });
// Flush before shutdown
await logger.shutdown();
Features: Zero dependencies, automatic batching, retry with backoff, TypeScript-first, opt-in source location capture.
Deno users: Install from JSR with
deno add jsr:@divkix/logwelland import from@divkix/logwell
Python SDK
For Python applications with automatic batching and retries:
pip install logwell
import asyncio
from logwell import Logwell
client = Logwell({
'api_key': 'lw_YOUR_API_KEY',
'endpoint': 'http://localhost:5173',
'service': 'my-app',
})
# Log at different levels
client.info('User signed in', {'us
Related Skills
tmux
353.1kRemote-control tmux sessions for interactive CLIs by sending keystrokes and scraping pane output.
diffs
353.1kUse the diffs tool to produce real, shareable diffs (viewer URL, file artifact, or both) instead of manual edit summaries.
terraform-provider-genesyscloud
Terraform Provider Genesyscloud
blogwatcher
353.1kMonitor blogs and RSS/Atom feeds for updates using the blogwatcher CLI.
