Logging
Observability

Logging

Send application logs to JuhJuh using simple JSON or OpenTelemetry format. Search, filter, and correlate logs with traces. Structured logging with custom attributes and automatic level detection.

Logs are the most direct signal your application produces. A request failed, a payment succeeded, a job timed out. JuhJuh ingests your logs, indexes them by service, level, and timestamp, and links them to distributed traces so you can follow a single request from log entry to full execution path.

Sending logs

Send logs to the ingestion endpoint:

POST /api/ingest/logs/
Authorization: Bearer jjk_YOUR_API_KEY
Content-Type: application/json

The endpoint auto-detects two formats from the request body. If the top-level key is resourceLogs, it parses OTLP. If the top-level key is logs, it parses simple JSON. No configuration flag needed.

Simple JSON format

The simplest way to send logs. No SDK required.

{
  "logs": [
    {
      "message": "Order #4521 payment processed",
      "level": "info",
      "service": "payment-service",
      "timestamp": "2026-04-09T14:30:00Z",
      "attributes": {
        "order_id": "4521",
        "amount": 59.99,
        "currency": "USD"
      }
    }
  ]
}
Field Required Default Description
message Yes The log message text
level No info One of: debug, info, warning, error, critical
service No unknown The service name that produced this log
timestamp No Server time ISO 8601 timestamp. If omitted, JuhJuh uses the time the request arrives
attributes No {} Key-value pairs for structured data. Any JSON-serializable values

OTLP format

If your application uses an OpenTelemetry SDK, the SDK sends logs in OTLP format automatically. The structure follows the OpenTelemetry Log Data Model:

{
  "resourceLogs": [
    {
      "resource": {
        "attributes": [
          { "key": "service.name", "value": { "stringValue": "payment-service" } }
        ]
      },
      "scopeLogs": [
        {
          "logRecords": [
            {
              "timeUnixNano": "1712672400000000000",
              "severityText": "INFO",
              "body": { "stringValue": "Order #4521 payment processed" },
              "attributes": [
                { "key": "order_id", "value": { "stringValue": "4521" } }
              ]
            }
          ]
        }
      ]
    }
  ]
}

JuhJuh extracts the service name from resource.attributes, maps severityText to the log level, reads the message from body.stringValue, and merges attributes from both the resource and log record levels.


Log levels

Use log levels consistently so you can filter effectively:

Level When to use
debug Detailed diagnostic information. Disabled in production by most frameworks, but useful when sent during active debugging
info Normal operations. User actions, request completions, job results
warning Something unexpected that did not cause a failure. Deprecated API usage, slow queries, retried operations
error A failure that affected a specific operation. Failed payment, broken external API call, unhandled exception
critical System-level failure. Database unreachable, out of memory, service cannot start

Structured logging

Plain text log messages are hard to search at scale. Structured logging adds key-value attributes to every log entry so you can filter on specific fields.

Why it matters

Compare these two approaches:

Unstructured:

"User usr_12345 failed to login from 192.168.1.1 after 3 attempts"

Structured:

{
  "message": "Login failed after maximum attempts",
  "level": "warning",
  "service": "auth-service",
  "attributes": {
    "user_id": "usr_12345",
    "ip": "192.168.1.1",
    "attempts": 3
  }
}

The structured version lets you query all failed logins for a specific user, filter by IP range, or count entries where attempts exceeded a threshold. The unstructured version requires regex parsing across millions of log lines.

These common attributes make logs more useful across services:

Attribute Example Purpose
trace_id "abc123def456" Links this log to a distributed trace for cross-signal correlation
user_id "usr_12345" Associates the log with a specific user
request_id "req_abc123" Groups all logs from a single HTTP request
environment "production" Distinguishes production logs from staging or development
version "2.4.1" Identifies which release of your service produced this log
error.type "TimeoutError" Categorizes errors for aggregation

Trace-to-log correlation

Include a trace_id attribute in your logs to connect them with distributed traces. When you view a trace in JuhJuh, all logs that share the same trace ID appear alongside the trace spans.

If you use an OpenTelemetry SDK for both tracing and logging, trace IDs are injected into logs automatically.


Batching

Send multiple log entries in a single request to reduce HTTP overhead:

{
  "logs": [
    { "message": "Request received", "level": "info", "service": "api" },
    { "message": "Database query completed", "level": "debug", "service": "api" },
    { "message": "Response sent", "level": "info", "service": "api" }
  ]
}
Batch size Behavior
1 to 50 entries Processed synchronously, returns 200
51+ entries Accepted with 202, processed asynchronously in the background

Async processing retries up to 3 times with 10-second delays if a transient error occurs.


Searching logs

The log viewer in your dashboard provides search and filtering across all ingested logs.

Filters

Filter What it does
Service Show logs from a specific service only
Level Filter by log level (debug, info, warning, error, critical)
Time range Narrow to a specific time window
Search Full-text search across log messages

Searching by trace

If you included a trace_id attribute in your logs, you can search for all logs associated with a specific trace. This is the fastest way to reconstruct what happened during a single request across multiple services.


Infrastructure logs

If your application runs on JuhJuh-managed VMs, container logs are collected automatically without any SDK or configuration. JuhJuh streams container output in real time and stores it alongside your application logs.

Infrastructure logs appear in the same log viewer as push-based logs. Filter by service name to distinguish between your application logs and container output.


Data retention

Logs are retained for 14 days by default. After the retention period, log entries are permanently deleted in daily cleanup cycles. Plan your log levels accordingly: sending everything at debug level fills your retention window faster than info and above.


Example: Python logging integration

Send structured logs from a Python application without an OpenTelemetry SDK:

import logging
import json
import requests

class JuhJuhHandler(logging.Handler):
    def __init__(self, endpoint, api_key, service_name):
        super().__init__()
        self.endpoint = endpoint
        self.api_key = api_key
        self.service_name = service_name
        self.buffer = []

    def emit(self, record):
        entry = {
            "message": record.getMessage(),
            "level": record.levelname.lower(),
            "service": self.service_name,
            "attributes": {
                "logger": record.name,
                "module": record.module,
            },
        }
        self.buffer.append(entry)
        if len(self.buffer) >= 50:
            self.flush()

    def flush(self):
        if not self.buffer:
            return
        requests.post(
            self.endpoint,
            json={"logs": self.buffer},
            headers={"Authorization": f"Bearer {self.api_key}"},
        )
        self.buffer = []

handler = JuhJuhHandler(
    endpoint="https://your-org.juhjuh.com/api/ingest/logs/",
    api_key="jjk_YOUR_API_KEY",
    service_name="my-service",
)
logging.getLogger().addHandler(handler)

This handler buffers log entries and flushes them in batches of 50. In production, add error handling around the HTTP request and flush on application shutdown.

  • Observability for an overview of all observability signals
  • Instrumentation for SDK setup and API key management
  • Tracing for distributed tracing and trace-to-log correlation
  • Metrics for time-series data and performance monitoring
  • Alerts for notifications when error logs spike
  • VMs for JuhJuh-managed infrastructure with automatic log collection