Logs & Traces
Swisblade provides built-in observability for every project. Logs and distributed traces are collected automatically — no code changes required.
Logs
Automatic collection
Every container's stdout/stderr is captured and stored automatically. You don't need to configure a logging library or set up log forwarding.
Viewing logs
Go to Project → Logs in the dashboard to see:
- Real-time log streaming for running containers
- Historical logs filterable by service
- Deploy logs with build output
Log format
Your application logs are captured as-is. For best results, use structured logging (JSON):
console.log(JSON.stringify({
level: "info",
message: "Order created",
orderId: "12345",
userId: "user-789"
}));
Structured logs are easier to search and filter in the dashboard.
Distributed traces
What are traces?
A trace follows a single request as it flows through your services. For example, an API request that queries a database and publishes a message to a queue creates a trace with three spans:
API (150ms)
├── PostgreSQL query (12ms)
└── RabbitMQ publish (3ms)
Automatic instrumentation
Swisblade injects OpenTelemetry instrumentation into your application automatically based on the runtime field:
| Runtime | What's traced |
|---|---|
node | HTTP requests, database queries, Redis commands, message queue operations |
python | HTTP requests, database queries, Redis commands, message queue operations |
java | HTTP requests, JDBC, Redis, messaging |
No code changes or dependencies needed. The instrumentation runs as a sidecar and intercepts standard library calls.
Viewing traces
Go to Project → Traces in the dashboard to see:
- List of recent traces with duration and status
- Waterfall view showing span timing
- Span details (HTTP method, status code, database statement, etc.)
- Error traces highlighted in red
Trace context
Traces are scoped to your project. Each trace carries your project's slug as part of the service name:
{project-slug}/{service-name}
This ensures traces from different projects are never mixed together.
Retention
| Data | Retention period |
|---|---|
| Logs | 24 hours |
| Traces | 24 hours |
Logs and traces older than 24 hours are automatically deleted.
Retention periods may increase with paid plans in the future.
Best practices
Structured logging
Use JSON logs with consistent fields:
import json, logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Good: structured
logger.info(json.dumps({"event": "user_signup", "user_id": "123"}))
# Bad: unstructured
logger.info(f"User 123 signed up")
Meaningful service names
Choose descriptive service names in stack.json. These appear in traces and logs:
"services": {
"api-gateway": { ... }, // ✓ Clear
"payment-worker": { ... }, // ✓ Clear
"svc1": { ... } // ✗ Not helpful
}
Error handling
Traces automatically capture exceptions and error status codes. Return appropriate HTTP status codes from your API so errors are visible in the trace view:
// Returns a trace span with status: ERROR
app.get("/order/:id", (req, res) => {
const order = db.find(req.params.id);
if (!order) return res.status(404).json({ error: "Not found" });
res.json(order);
});