Real-time log streaming using Server-Sent Events (SSE).
Connect to this endpoint to receive a stream of events as logs are created and hosts are registered.
GET /api/v1/events
Authentication: None required (public endpoint)
The endpoint sets standard SSE headers:
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
Access-Control-Allow-Origin: *
Upon connecting, you'll receive an initial connected event:
event: connected
data: {"status":"connected","timestamp":"2026-01-18T23:10:45Z"}
A : keep-alive comment is sent periodically to prevent proxies from closing idle connections.
Emitted when a new log entry is created.
Payload Schema:
| Field | Type | Description |
|---|---|---|
id |
integer | Unique log identifier |
host_id |
integer | ID of the host that created the log |
level |
string | Log level (trace, debug, info, warn, error, fatal) |
message |
string | Log message |
fields |
object (optional) | Additional structured data |
timestamp |
string | ISO 8601 timestamp when the log occurred |
created_at |
string | ISO 8601 timestamp when the log was stored |
host |
object (optional) | Host details (name, tags, status) |
Example:
event: log.created
data: {"id":1234,"host_id":5,"level":"error","message":"Database connection failed","fields":{"error":"timeout","retry_count":3},"timestamp":"2026-01-18T23:10:45Z","created_at":"2026-01-18T23:10:45Z","host":{"id":5,"name":"production-api","tags":["prod","api"],"status":"healthy"}}
Emitted when a new host is registered.
Payload Schema:
| Field | Type | Description |
|---|---|---|
id |
integer | Unique host identifier |
name |
string | Host name |
tags |
array | List of tag strings |
status |
string | Host status (unknown, healthy, degraded, down) |
created_at |
string | ISO 8601 timestamp when host was registered |
last_seen |
string | ISO 8601 timestamp of last activity |
log_count |
integer | Total number of logs from this host |
error_count |
integer | Number of error-level logs |
error_rate |
float | Error rate as percentage |
description |
string (optional) | Host description |
api_key |
string | API key for this host |
Example:
event: host.registered
data: {"id":5,"name":"production-api","tags":["prod","api"],"status":"unknown","created_at":"2026-01-18T23:10:45Z","last_seen":"2026-01-18T23:10:45Z","log_count":0,"error_count":0,"error_rate":0,"api_key":"glog_v1_b7cfad39c28529d5124da53fcb34493d132d706a82f2fa"}
Emitted when host information is updated (e.g., status change, statistics refresh).
Payload Schema: Same as host.registered
curl -N http://localhost:6016/api/v1/eventsThe -N flag disables buffering, ensuring events are displayed as they arrive.
const eventSource = new EventSource('http://localhost:6016/api/v1/events');
// Connection established
eventSource.addEventListener('connected', (e) => {
console.log('SSE connected:', JSON.parse(e.data));
});
// New log created
eventSource.addEventListener('log.created', (e) => {
const log = JSON.parse(e.data);
console.log('New log:', log.message, `(${log.level})`);
// Update UI, trigger alerts, etc.
});
// Host registered
eventSource.addEventListener('host.registered', (e) => {
const host = JSON.parse(e.data);
console.log('New host:', host.name);
});
// Host updated
eventSource.addEventListener('host.updated', (e) => {
const host = JSON.parse(e.data);
console.log('Host updated:', host.name, `status: ${host.status}`);
});
// Connection error handling
eventSource.onerror = (error) => {
console.error('SSE error:', error);
// EventSource will attempt to reconnect automatically
};
// Close connection when done
// eventSource.close();function connectEvents() {
const eventSource = new EventSource('/api/v1/events');
eventSource.onopen = () => {
console.log('Events connected');
};
eventSource.addEventListener('log.created', (e) => {
const log = JSON.parse(e.data);
onLogCreated(log);
});
eventSource.onerror = (e) => {
console.error('Connection lost, reconnecting...');
eventSource.close();
// Exponential backoff before reconnect
setTimeout(connectEvents, 5000);
};
}
connectEvents();import requests
import json
def stream_events():
with requests.get('http://localhost:6016/api/v1/events', stream=True) as response:
response.raise_for_status()
for line in response.iter_lines():
if line:
line = line.decode('utf-8')
if line.startswith('event: '):
event_type = line[7:]
elif line.startswith('data: '):
data = json.loads(line[6:])
print(f"Event: {event_type}, Data: {data}")
stream_events()package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
)
type Event struct {
Type string
Data json.RawMessage
}
func streamEvents() error {
resp, err := http.Get("http://localhost:6016/api/v1/events")
if err != nil {
return err
}
defer resp.Body.Close()
decoder := json.NewDecoder(resp.Body)
var eventType string
var eventData json.RawMessage
reader := io.Reader(resp.Body)
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, "event: ") {
eventType = strings.TrimPrefix(line, "event: ")
} else if strings.HasPrefix(line, "data: ") {
data := strings.TrimPrefix(line, "data: ")
if err := json.Unmarshal([]byte(data), &eventData); err != nil {
continue
}
fmt.Printf("Event: %s, Data: %s\n", eventType, eventData)
}
}
return scanner.Err()
}Browsers reconnect automatically. Other clients should implement exponential backoff.
If a client receives events slower than they arrive, its channel fills and the server disconnects it. The client will reconnect and resume from the current stream position.
Always close the EventSource or HTTP connection when done.
- Reconnection: SSE includes automatic reconnection in browsers. For other clients, implement exponential backoff.
- Buffer Management: Set appropriate buffer sizes for high-volume scenarios. Events may be dropped if the client can't keep up.
- Event Filtering: Consider server-side filtering for specific hosts or log levels to reduce bandwidth.
- Graceful Shutdown: Always close the EventSource or HTTP connection when done to free server resources.
- Verify the server is running:
curl http://localhost:6016/health - Check for proxy or firewall blocking SSE connections
- Ensure the client doesn't have buffering enabled
- SSE automatically reconnects in browsers
- Implement custom reconnection logic for other clients
- Check server logs for client timeout issues
- Close unused connections
- Consider implementing server-side event filtering
- Monitor
/healthendpoint for active client count