Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 0 additions & 44 deletions .github/actions/slogx-replay/README.md

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/test_slogx_replay.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
head -10 slogx_logs/auth-service.ndjson

- name: Test slogx-replay action
uses: ./.github/actions/slogx-replay
uses: ./replay
with:
log_paths: ./sdk/ts/slogx_logs/auth-service.ndjson
github_token: ${{ secrets.GITHUB_TOKEN }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/web_ui.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ jobs:
run: npx playwright install --with-deps

- name: Run E2E tests
run: SLOGX_PYTHON="$GITHUB_WORKSPACE/.venv/bin/python" npm run test:e2e
run: npm run test:e2e

- uses: actions/upload-artifact@v6
if: always()
Expand Down
161 changes: 115 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,49 +1,57 @@
![](public/assets/full_logo.png)

# slogx — `console.log()` but better for backend debugging
# slogx — good ol' print debugging, but better

slogx is a tool that streams structured logs from your backend to a web UI over WebSockets. It's designed to make it trivial for developers to debug locally.
slogx is a structured logging toolkit for backend developers. One SDK gives you two ways to view logs: stream them live to a browser UI during local development, or write them to a file during CI and replay them later. Same logging calls, different outputs depending on the environment.

https://github.com/user-attachments/assets/616ddfb8-20f5-48fe-be58-0dd64e3a0fa3

**Why use slogx?**
- Fast setup: install the SDK and call `init()` once. No external agents or complicated config.
- Structured logs: captures arguments, stack traces, and source metadata (file/line/function/service).
- Language support: first-class SDK examples for Node, Python, Go, and Rust.
- WebSocket-first: low-latency streaming to the browser for immediate debugging.
## Quickstart

**Quickstart (run UI + demo backend)**
Install the SDK for your language, call `init()` once, and start logging:

- Install dependencies and start the UI:
```js
// npm install @binhonglee/slogx
import { slogx } from '@binhonglee/slogx';

```bash
git clone https://github.com/binhonglee/slogx.git
cd slogx
npm install
npm run dev
slogx.init({ isDev: true, port: 8080, serviceName: 'api' });
slogx.info('Server started', { port: 8080 });
```

- Start the demo backend (TypeScript demo included):
To view logs locally, run the UI:

```bash
npm run server
git clone https://github.com/binhonglee/slogx.git
cd slogx && npm install && npm run dev
```

- Open the UI in your browser (Vite usually serves at `http://localhost:3000`). Use the Setup modal to add `ws://localhost:8083` (or the port printed by the demo server) and watch logs stream in real time.
Open `http://localhost:3000/app.html` and connect to `localhost:8080`.

## SDK Reference

Note: the `server` script uses the TypeScript demo in `sdk/ts/server.ts` which initializes a local log server and emits sample log events.
### init() options

**Minimal integration (copy-paste)**
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `isDev` | boolean | required | Safety flag to prevent accidental production use |
| `port` | number | 8080 | WebSocket server port (live mode) |
| `serviceName` | string | required | Identifies the service in logs |
| `ciMode` | boolean | auto | Force CI mode; auto-detects CI environments if not set |
| `logFilePath` | string | `./slogx_logs/<serviceName>.ndjson` | Output file path for CI mode |
| `maxEntries` | number | 10000 | Max log entries before rolling (CI mode) |

Pick your language and add the SDK snippet below. Each SDK provides:
- `init(isDev, port, serviceName)` — starts a WebSocket server on the given port (default 8080). The `isDev` flag is required to prevent accidental production use.
- logging helpers: `debug`, `info`, `warn`, `error` that accept message strings, objects, Error/Exception values, or multiple arguments.
### Logging methods

- Node (local/dev):
All SDKs provide: `debug`, `info`, `warn`, `error`

Each accepts a message string and optional data (objects, errors, arrays).

### Language examples

**Node.js**
```js
// Requires: npm install @binhonglee/slogx
import { slogx } from 'slogx';
// npm install @binhonglee/slogx
import { slogx } from '@binhonglee/slogx';

slogx.init({
isDev: process.env.NODE_ENV !== 'production',
Expand All @@ -55,10 +63,9 @@ slogx.info('Server started', { env: process.env.NODE_ENV });
slogx.error('Operation failed', new Error('timeout'));
```

- Python (local/dev):

**Python**
```py
# Requires: pip install slogx
# pip install slogx
import os
from slogx import slogx

Expand All @@ -70,10 +77,9 @@ slogx.init(
slogx.info('Started', {'env': 'dev'})
```

- Go (local/dev):

**Go**
```go
// Requires: go get github.com/binhonglee/slogx
// go get github.com/binhonglee/slogx
import (
"os"
"github.com/binhonglee/slogx"
Expand All @@ -89,10 +95,9 @@ func main() {
}
```

- Rust (local/dev):

**Rust**
```rust
// Requires: cargo add slogx
// cargo add slogx
#[tokio::main]
async fn main() {
let is_dev = std::env::var("ENV").unwrap_or_default() != "production";
Expand All @@ -101,19 +106,81 @@ async fn main() {
}
```

If you don't want to run the SDK server inside your app, you can run the demo server from `sdk/ts/server.ts` or adapt the SDK to connect to a central logging service that forwards messages to the UI.
## Viewing Modes

### Live Mode

In live mode (the default), the SDK starts a WebSocket server. Connect the slogx UI to see logs as they happen.

1. Your app calls `slogx.init()` — this starts a WebSocket server
2. Open the slogx UI (`/app.html`)
3. Enter your server's address (e.g., `localhost:8080`)
4. Watch logs stream in real-time

The UI auto-reconnects if the connection drops.

### Replay Mode (CI)

In CI mode, logs are written to an NDJSON file instead of being streamed. You can replay them later in the browser.

**Enable CI mode:**
```js
slogx.init({
isDev: true,
serviceName: 'api',
ciMode: true, // Force CI mode
logFilePath: './slogx_logs/api.ndjson'
});
```

**Or let it auto-detect** — the SDK checks for these environment variables:
- `CI`, `GITHUB_ACTIONS`, `GITLAB_CI`, `JENKINS_HOME`, `CIRCLECI`, `BUILDKITE`, `TF_BUILD`, `TRAVIS`

**WebSocket & message format**
**View replay logs:**
1. Open the replay UI (`/replay.html`)
2. Drop in an `.ndjson` file or paste a URL
3. Browse logs with the same filtering and search as live mode

slogx streams JSON log entries over WebSockets. The UI will accept either a single JSON object or an array of objects per message. Each log entry follows this schema (fields produced by SDKs in this repo):
## GitHub Action

Automatically publish CI logs and comment a replay link on PRs:

```yaml
# .github/workflows/test.yml
- name: Run tests
run: npm test # Your app logs with ciMode: true

- name: Publish slogx replay
uses: binhonglee/slogx/replay@main
with:
log_paths: ./slogx_logs/*.ndjson
github_token: ${{ secrets.GITHUB_TOKEN }}
```

This pushes log files to a `slogx-artifacts` branch and comments a replay link on the PR.

**Action options:**

| Input | Default | Description |
|-------|---------|-------------|
| `log_paths` | required | Comma-separated paths to NDJSON files |
| `github_token` | required | Token with `contents:write` and `pull-requests:write` |
| `replay_base_url` | `https://binhonglee.github.io/slogx/replay.html` | URL to replay viewer |
| `artifact_branch` | `slogx-artifacts` | Branch for storing log files |
| `max_runs` | `500` | Max CI runs to keep before pruning |
| `comment` | `true` | Whether to comment on the PR |

## Message Format

Log entries are JSON objects with this schema:

```json
{
"id": "<uuid>",
"timestamp": "2025-12-22T12:34:56.789Z",
"level": "INFO|DEBUG|WARN|ERROR",
"args": [ /* JSON-serializable values; strings, objects, arrays */ ],
"stacktrace": "optional full stack or call-site frames",
"args": [ /* JSON-serializable values */ ],
"stacktrace": "optional stack trace",
"metadata": {
"file": "handler.go",
"line": 123,
Expand All @@ -124,11 +191,13 @@ slogx streams JSON log entries over WebSockets. The UI will accept either a sing
}
```

Important implementation notes:
- The frontend `validateWsUrl()` normalizes `http://` -> `ws://` and `https://` -> `wss://`, accepts raw host:port, and supports relative paths (e.g. `/slogx`).
- The UI automatically reconnects if the WebSocket closes.
In live mode, entries are sent over WebSocket (single object or array per message). In CI mode, entries are written as newline-delimited JSON (NDJSON).

## Testing & Development

**Testing & debugging**
- Unit tests: `npm run test` runs Vitest unit tests.
- E2E tests: `npm run test:e2e` runs Playwright tests.
- Coverage output placed under `coverage/`.
```bash
npm run test # Unit tests (Vitest)
npm run test:e2e # E2E tests (Playwright)
npm run dev # Start dev server
npm run build # Build standalone HTML files
```
13 changes: 13 additions & 0 deletions app.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>slogx</title>
<link rel="icon" type="image/png" href="/assets/icon.png" />
</head>
<body>
<div id="root"></div>
<script type="module" src="/main.tsx"></script>
</body>
</html>
Loading