No-SDK Setup
Use LogTide without installing any SDK. Just print to stdout - works with any language (Go, Rust, Python, Java, .NET, Ruby, PHP).
No SDK Required
LogTide supports stdout-based logging via Fluent Bit (self-hosted) or Docker logging drivers (cloud). Simply write to stdout/stderr and your logs will be automatically ingested.
Choose Your Method
Use Docker's Fluentd logging driver to send logs directly to LogTide Cloud.
- No Fluent Bit container needed
- Configure once in docker-compose.yml
- Zero code changes required
Add Fluent Bit to your LogTide installation to collect logs from all Docker containers automatically.
- Optional Fluent Bit configuration
- Automatic metadata enrichment
- Full control over log processing
How It Works
LogTide uses Fluent Bit to automatically collect logs from Docker containers:
/var/lib/docker/containers/*/.
/api/v1/ingest/single with
your API key automatically.
Setup Instructions (Cloud)
For LogTide Cloud, configure your Docker containers to use the Fluentd logging driver:
1. Configure docker-compose.yml
Add logging configuration to each service in your
docker-compose.yml:
services:
my-app:
image: my-app:latest
logging:
driver: fluentd
options:
fluentd-address: api.logtide.dev:24224
fluentd-async: "true"
tag: "lp_your_api_key_here.{{.Name}}"
labels: "service"
labels:
service: "my-app" Coming Soon
LogTide Cloud is currently in beta. Sign up at logtide.dev to get early access and we'll notify you when Fluentd logging driver support is available.
Setup Instructions (Self-Hosted)
1. Generate API Key
Create an API key in your LogTide project settings.
2. Configure Fluent Bit API Key
Add your API key to the docker/.env file:
# In docker/.env
FLUENT_BIT_API_KEY=lp_your_api_key_here 3. Restart Fluent Bit
docker compose restart fluent-bit Setup Complete
All Docker containers now automatically send logs to LogTide. No code changes needed!
Language Examples
Just write to stdout/stderr using your language's standard logging. No special library needed.
Go
package main
import (
"log"
"encoding/json"
"os"
)
func main() {
// Simple text logging
log.Println("Server started on port 8080")
// Structured logging (JSON format recommended)
logData := map[string]interface{}{
"level": "info",
"message": "User logged in",
"user_id": 12345,
"ip": "192.168.1.1",
}
json.NewEncoder(os.Stdout).Encode(logData)
} Rust
use log::{info, error};
use env_logger;
fn main() {
env_logger::init();
info!("Application started");
error!("Database connection failed");
// Or use serde_json for structured logs
println!("{}", serde_json::json!({
"level": "info",
"message": "Request processed",
"duration_ms": 150
}));
} Python
import logging
import json
# Standard logging
logging.basicConfig(level=logging.INFO)
logging.info("Application started")
# Structured JSON logging
log_data = {
"level": "info",
"message": "User action",
"user_id": 12345,
"action": "login"
}
print(json.dumps(log_data)) Java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Map;
import java.util.HashMap;
public class App {
private static final Logger logger = LoggerFactory.getLogger(App.class);
public static void main(String[] args) throws Exception {
// Simple logging
logger.info("Application started");
// Structured logging (use Logback with JSON encoder)
Map<String, Object> logData = new HashMap<>();
logData.put("level", "info");
logData.put("message", "Request received");
logData.put("request_id", "abc123");
System.out.println(new ObjectMapper().writeValueAsString(logData));
}
} .NET (C#)
using Serilog;
using Serilog.Formatting.Json;
using System;
using System.Text.Json;
class Program
{
static void Main()
{
// Using Serilog with console sink
Log.Logger = new LoggerConfiguration()
.WriteTo.Console(new JsonFormatter())
.CreateLogger();
Log.Information("Application started");
Log.Error("Database connection failed", new { UserId = 123 });
// Or manual JSON
var logData = new {
level = "info",
message = "User login",
user_id = 12345
};
Console.WriteLine(JsonSerializer.Serialize(logData));
}
} Ruby
require 'logger'
require 'json'
# Standard logging
logger = Logger.new(STDOUT)
logger.info("Application started")
# Structured JSON logging
log_data = {
level: 'info',
message: 'User action',
user_id: 12345,
action: 'login'
}
puts log_data.to_json PHP
<?php
// Simple logging
error_log("Application started");
// Structured JSON logging
$logData = [
'level' => 'info',
'message' => 'User login',
'user_id' => 12345,
'ip' => $_SERVER['REMOTE_ADDR']
];
echo json_encode($logData) . "
";
?> Docker Configuration
Add Fluent Bit to your docker-compose.yml to enable
automatic log collection from Docker containers:
# Add this service to your docker-compose.yml
fluent-bit:
image: fluent/fluent-bit:4.2.2 # For ARM64/Raspberry Pi: cr.fluentbit.io/fluent/fluent-bit:4.2.2
container_name: logtide-fluent-bit
volumes:
- ./fluent-bit.conf:/fluent-bit/etc/fluent-bit.conf:ro
- ./parsers.conf:/fluent-bit/etc/parsers.conf:ro
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
LOGTIDE_API_KEY: ${FLUENT_BIT_API_KEY}
LOGTIDE_API_HOST: backend
depends_on:
- backend
restart: unless-stopped - Tails logs from
/var/lib/docker/containers/*/*.log - Parses Docker JSON logs and extracts metadata
- Adds container name, ID, and image as metadata
- Sends to LogTide API with automatic retries (3x)
- Flushes logs every 5 seconds
Fluent Bit Configuration (Advanced)
If you want to customize Fluent Bit or use it outside of LogTide's Docker Compose setup, here's the complete configuration:
fluent-bit.conf
Main configuration file for Fluent Bit. This collects Docker container logs and sends them to LogTide:
# Fluent Bit Configuration for LogTide
[SERVICE]
# Flush logs every 5 seconds
Flush 5
# Run in foreground
Daemon Off
# Log level (error, warning, info, debug, trace)
Log_Level info
# Parsers configuration file
Parsers_File /fluent-bit/etc/parsers.conf
# =============================================================================
# INPUT - Docker Container Logs
# =============================================================================
[INPUT]
Name tail
Path /var/lib/docker/containers/*/*.log
Parser docker
Tag docker.*
Refresh_Interval 5
Mem_Buf_Limit 5MB
Skip_Long_Lines On
Path_Key filepath
# =============================================================================
# FILTER - Parse and Enrich
# =============================================================================
# Extract container metadata (name, id, image)
[FILTER]
Name parser
Match docker.*
Key_Name log
Parser docker_json
Reserve_Data On
Preserve_Key On
# Add required fields for LogTide API
[FILTER]
Name modify
Match docker.*
# Set default level if not present
Add level info
# Rename 'log' field to 'message'
Rename log message
# Set service name from container_name
Copy container_name service
# Remove unnecessary fields to reduce log size
[FILTER]
Name record_modifier
Match docker.*
Remove_key stream
Remove_key filepath
Remove_key container_name
# =============================================================================
# OUTPUT - Send to LogTide
# =============================================================================
[OUTPUT]
Name http
Match docker.*
Host ${LOGTIDE_API_HOST}
Port 8080
URI /api/v1/ingest/single
Format json_lines
Header X-API-Key ${LOGTIDE_API_KEY}
Header Content-Type application/json
# Date/time settings
Json_date_key time
Json_date_format iso8601
# Retry settings
Retry_Limit 3
# TLS (disable for internal Docker network)
tls Off parsers.conf
Parser definitions for Docker JSON logs:
# Fluent Bit Parsers Configuration
# Parser for Docker JSON logs
[PARSER]
Name docker_json
Format json
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L%z
Time_Keep On
# Parser for Docker container logs
[PARSER]
Name docker
Format json
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L%z
Time_Keep On extract_container_id.lua (Optional)
Lua script to extract container ID from file path (used in LogTide's setup for metadata enrichment):
-- Extract container ID from Docker log file path
-- Path format: /var/lib/docker/containers/<container_id>/<container_id>-json.log
function extract_container_id(tag, timestamp, record)
local filepath = record["filepath"]
if filepath == nil then
return 0, timestamp, record
end
-- Extract container ID from path
-- Example: /var/lib/docker/containers/abc123.../abc123...-json.log
local container_id = filepath:match("/var/lib/docker/containers/([^"]+)/", 1)
if container_id then
record["container_id"] = container_id
record["container_short_id"] = container_id:sub(1, 12)
end
-- Return code: 1 = modified and keep, 0 = no change
return 1, timestamp, record
end Usage with docker-compose.yml
If you want to add Fluent Bit to your own project (not using LogTide's Docker Compose):
services:
fluent-bit:
image: fluent/fluent-bit:4.2.2 # For ARM64/Raspberry Pi: cr.fluentbit.io/fluent/fluent-bit:4.2.2
container_name: my-fluent-bit
volumes:
# Mount configuration files
- ./fluent-bit.conf:/fluent-bit/etc/fluent-bit.conf:ro
- ./parsers.conf:/fluent-bit/etc/parsers.conf:ro
# Optional: Lua scripts for advanced processing
- ./extract_container_id.lua:/fluent-bit/etc/extract_container_id.lua:ro
# Docker logs directory (read-only)
- /var/lib/docker/containers:/var/lib/docker/containers:ro
# Docker socket (read-only)
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
# For LogTide Cloud
LOGTIDE_API_KEY: lp_your_api_key_here
LOGTIDE_API_HOST: api.logtide.dev
# Or for self-hosted
# LOGTIDE_API_KEY: lp_your_api_key_here
# LOGTIDE_API_HOST: localhost # or your server IP
restart: unless-stopped
networks:
- your-network
networks:
your-network:
driver: bridge Important Notes
-
• Fluent Bit needs access to
/var/lib/docker/containersto read container logs -
• The
LOGTIDE_API_KEYenvironment variable is used in the configuration via$