Logs API
The Logs API provides endpoints for searching, filtering, and retrieving container logs from Meilisearch.
Search Logs
Section titled “Search Logs”Search logs with full-text search and filters.
Endpoint
Section titled “Endpoint”GET /api/logs/searchQuery Parameters
Section titled “Query Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
query | String | No | Full-text search term |
container | String | No | Container name filter |
stream | String | No | stdout or stderr |
fromTimestamp | Number | No | Start time (Unix ms) |
toTimestamp | Number | No | End time (Unix ms) |
limit | Number | No | Max results (default: 50, max: 100) |
offset | Number | No | Skip N results (default: 0) |
Example Request
Section titled “Example Request”curl "http://localhost:3000/api/logs/search?query=error&container=nginx&limit=20"Example Response
Section titled “Example Response”{ "success": true, "total": 145, "returned": 20, "processingTimeMs": 12, "logs": [ { "id": "abc123-1705761234567-xyz", "containerId": "abc123def456", "containerName": "nginx", "timestamp": 1705761234567, "timestampISO": "2026-01-20T14:23:54.567Z", "message": "Connection timeout to upstream server", "stream": "stderr", "labels": { "loggator.enable": "true", "app": "web" } } ]}List Containers
Section titled “List Containers”Get a list of containers with log counts.
Endpoint
Section titled “Endpoint”GET /api/logs/containersExample Request
Section titled “Example Request”curl "http://localhost:3000/api/logs/containers"Example Response
Section titled “Example Response”{ "success": true, "totalCount": 1523, "containers": [ { "id": "abc123def456", "name": "nginx", "count": 845 }, { "id": "def456ghi789", "name": "api", "count": 523 }, { "id": "ghi789jkl012", "name": "database", "count": 155 } ]}Log Histogram
Section titled “Log Histogram”Get log count histogram over time.
Endpoint
Section titled “Endpoint”GET /api/logs/histogramQuery Parameters
Section titled “Query Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
minutes | Number | No | Time window (default: 60) |
container | String | No | Filter by container |
Example Request
Section titled “Example Request”curl "http://localhost:3000/api/logs/histogram?minutes=120&container=nginx"Example Response
Section titled “Example Response”{ "success": true, "buckets": [ { "minute": "2026-01-20T12:00:00Z", "count": 45, "timestamp": 1705752000000 }, { "minute": "2026-01-20T12:01:00Z", "count": 52, "timestamp": 1705752060000 } ], "total": 2547, "timeWindow": "120 minutes"}Search Examples
Section titled “Search Examples”Basic Search
Section titled “Basic Search”Find logs containing “error”:
curl "http://localhost:3000/api/logs/search?query=error"Container Filter
Section titled “Container Filter”Logs from specific container:
curl "http://localhost:3000/api/logs/search?container=nginx"Stream Filter
Section titled “Stream Filter”Only stderr logs:
curl "http://localhost:3000/api/logs/search?stream=stderr"Time Range
Section titled “Time Range”Logs from last hour:
NOW=$(date +%s)000HOUR_AGO=$((NOW - 3600000))curl "http://localhost:3000/api/logs/search?fromTimestamp=$HOUR_AGO&toTimestamp=$NOW"Combined Filters
Section titled “Combined Filters”Error logs from nginx’s stderr in the last 2 hours:
NOW=$(date +%s)000TWO_HOURS_AGO=$((NOW - 7200000))curl "http://localhost:3000/api/logs/search?query=error&container=nginx&stream=stderr&fromTimestamp=$TWO_HOURS_AGO"Pagination
Section titled “Pagination”Get results 20-40:
curl "http://localhost:3000/api/logs/search?query=error&limit=20&offset=20"Integration Examples
Section titled “Integration Examples”JavaScript/TypeScript
Section titled “JavaScript/TypeScript”interface LogSearchParams { query?: string; container?: string; stream?: "stdout" | "stderr"; fromTimestamp?: number; toTimestamp?: number; limit?: number; offset?: number;}
async function searchLogs(params: LogSearchParams) { const searchParams = new URLSearchParams();
Object.entries(params).forEach(([key, value]) => { if (value !== undefined) { searchParams.append(key, value.toString()); } });
const response = await fetch( `http://localhost:3000/api/logs/search?${searchParams}`, );
return await response.json();}
// Usageconst logs = await searchLogs({ query: "error", container: "nginx", limit: 50,});
console.log(`Found ${logs.total} logs, showing ${logs.returned}`);logs.logs.forEach((log) => { console.log(`[${log.timestampISO}] ${log.containerName}: ${log.message}`);});Python
Section titled “Python”import requestsfrom datetime import datetime, timedeltafrom typing import Optional
def search_logs( query: Optional[str] = None, container: Optional[str] = None, stream: Optional[str] = None, from_timestamp: Optional[int] = None, to_timestamp: Optional[int] = None, limit: int = 50, offset: int = 0): params = { 'limit': limit, 'offset': offset }
if query: params['query'] = query if container: params['container'] = container if stream: params['stream'] = stream if from_timestamp: params['fromTimestamp'] = from_timestamp if to_timestamp: params['toTimestamp'] = to_timestamp
response = requests.get( 'http://localhost:3000/api/logs/search', params=params )
return response.json()
# Usage - errors from last hourone_hour_ago = int((datetime.now() - timedelta(hours=1)).timestamp() * 1000)logs = search_logs( query='error', from_timestamp=one_hour_ago, limit=100)
print(f"Found {logs['total']} errors")for log in logs['logs']: print(f"{log['timestamp']}: {log['message']}")package main
import ( "encoding/json" "fmt" "net/http" "net/url" "time")
type LogSearchParams struct { Query string Container string Stream string FromTimestamp int64 ToTimestamp int64 Limit int Offset int}
type LogSearchResponse struct { Success bool `json:"success"` Total int `json:"total"` Logs []Log `json:"logs"`}
type Log struct { ID string `json:"id"` ContainerName string `json:"containerName"` Message string `json:"message"` Stream string `json:"stream"` TimestampISO string `json:"timestampISO"` Labels map[string]string `json:"labels"`}
func searchLogs(params LogSearchParams) (*LogSearchResponse, error) { baseURL := "http://localhost:3000/api/logs/search" queryParams := url.Values{}
if params.Query != "" { queryParams.Add("query", params.Query) } if params.Container != "" { queryParams.Add("container", params.Container) } if params.Limit > 0 { queryParams.Add("limit", fmt.Sprintf("%d", params.Limit)) }
resp, err := http.Get(baseURL + "?" + queryParams.Encode()) if err != nil { return nil, err } defer resp.Body.Close()
var result LogSearchResponse if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { return nil, err }
return &result, nil}
// Usagefunc main() { logs, err := searchLogs(LogSearchParams{ Query: "error", Container: "nginx", Limit: 50, })
if err != nil { panic(err) }
fmt.Printf("Found %d logs\n", logs.Total) for _, log := range logs.Logs { fmt.Printf("[%s] %s: %s\n", log.TimestampISO, log.ContainerName, log.Message) }}Bash/cURL
Section titled “Bash/cURL”#!/bin/bash
# Search functionsearch_logs() { local query=$1 local container=$2 local limit=${3:-50}
local url="http://localhost:3000/api/logs/search" local params="limit=$limit"
if [ -n "$query" ]; then params="$params&query=$query" fi
if [ -n "$container" ]; then params="$params&container=$container" fi
curl -s "$url?$params" | jq '.logs[] | "\(.timestampISO) [\(.containerName)] \(.message)"'}
# Usagesearch_logs "error" "nginx" 20Error Handling
Section titled “Error Handling”400 Bad Request
Section titled “400 Bad Request”Invalid parameters:
{ "success": false, "error": "Invalid parameter: limit must be between 1 and 100"}500 Internal Server Error
Section titled “500 Internal Server Error”Server error:
{ "success": false, "error": "Meilisearch connection failed"}Performance Tips
Section titled “Performance Tips”1. Use Appropriate Limits
Section titled “1. Use Appropriate Limits”Request only what you need:
- ❌
limit=1000(slow, may timeout) - ✅
limit=50(fast, paginate if needed)
2. Add Time Filters
Section titled “2. Add Time Filters”Reduce search scope:
# Last hour onlyfromTimestamp=$(($(date +%s) - 3600))0003. Use Container Filters
Section titled “3. Use Container Filters”Search specific containers:
container=nginx4. Leverage Caching
Section titled “4. Leverage Caching”Cache results when appropriate:
const cache = new Map();
async function getCachedLogs(params) { const key = JSON.stringify(params);
if (cache.has(key)) { return cache.get(key); }
const logs = await searchLogs(params); cache.set(key, logs);
return logs;}5. Implement Pagination
Section titled “5. Implement Pagination”For large result sets:
async function getAllLogs(query) { const allLogs = []; let offset = 0; const limit = 100;
while (true) { const response = await searchLogs({ query, limit, offset }); allLogs.push(...response.logs);
if (response.returned < limit) { break; // No more results }
offset += limit; }
return allLogs;}Next Steps
Section titled “Next Steps”- Containers API - Container information
- Chat API - AI-powered log analysis
- Log Search - Web UI search