Loggles

Loggles là một bộ thu nhật ký ưu tiên cục bộ với giao diện MCP, cho phép các tác nhân mã hóa (Claude Code, Cursor) truy vấn trực tiếp nhật ký ứng dụng.

GitHub
9
Dùng thử MCP nàyĐược tài trợ

Tài liệu

Loggles

License: ELv2 GitHub release GHCR

A local-first log sink that turns your coding agent into a runtime companion.

Instead of copy-pasting log output into Claude or Cursor, point your app at Loggles. Your agent queries exactly what it needs — filtered by service, level, trace ID, or time window — and gets back structured data it can reason over. No token waste, no manual copy-paste.

Your App  ──OTLP──▶  Loggles  ──MCP──▶  Claude Code / Cursor

Two use cases, same setup:

  • Investigating a bug — Claude reads your source, traces the failure through logs, and points to the line. You describe the problem; it does the digging.
  • Watching runtime behaviour — Ask "what did my app do when I hit that endpoint?" and Claude tails the logs, traces the request, and narrates what happened. Like a live debugger, without attaching one.

Quick start

Docker

docker run -d \
  -p 5000:5000 \
  -v loggles-data:/data \
  ghcr.io/bytesquashcom/loggles:latest

Add -e Auth__ApiKey=your-secret-key to enable API key protection (see Authentication).

dotnet run

git clone https://github.com/bytesquashcom/Loggles.git
cd Loggles/src/Loggles.Api
dotnet run
# Listening on http://localhost:5000

Sending logs to Loggles

Point your OTLP exporter at http://localhost:5000/v1/logs using HTTP/protobuf.

.NET

// dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
builder.Services.AddOpenTelemetry()
    .WithLogging(logging =>
    {
        logging.AddOtlpExporter(otlp =>
        {
            otlp.Endpoint = new Uri("http://localhost:5000/v1/logs");
            otlp.Protocol = OtlpExportProtocol.HttpProtobuf;
        });
    });

Node.js

npm install @opentelemetry/sdk-node @opentelemetry/exporter-logs-otlp-http @opentelemetry/sdk-logs
const { LoggerProvider, SimpleLogRecordProcessor } = require('@opentelemetry/sdk-logs');
const { OTLPLogExporter } = require('@opentelemetry/exporter-logs-otlp-http');

const provider = new LoggerProvider();
provider.addLogRecordProcessor(
  new SimpleLogRecordProcessor(
    new OTLPLogExporter({ url: 'http://localhost:5000/v1/logs' })
  )
);
provider.register();

Python

pip install opentelemetry-exporter-otlp-proto-http opentelemetry-sdk
from opentelemetry import _logs
from opentelemetry.sdk._logs import LoggerProvider
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter

provider = LoggerProvider()
provider.add_log_record_processor(
    BatchLogRecordProcessor(OTLPLogExporter(endpoint="http://localhost:5000/v1/logs"))
)
_logs.set_logger_provider(provider)

Go

go get go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp
exporter, _ := otlploghttp.New(context.Background(),
    otlploghttp.WithEndpointURL("http://localhost:5000/v1/logs"),
    otlploghttp.WithInsecure(),
)
provider := log.NewLoggerProvider(
    log.WithProcessor(log.NewBatchProcessor(exporter)),
)
global.SetLoggerProvider(provider)

Java

<!-- pom.xml -->
<dependency>
  <groupId>io.opentelemetry</groupId>
  <artifactId>opentelemetry-exporter-otlp</artifactId>
</dependency>
OtlpHttpLogRecordExporter exporter = OtlpHttpLogRecordExporter.builder()
    .setEndpoint("http://localhost:5000/v1/logs")
    .build();

SdkLoggerProvider provider = SdkLoggerProvider.builder()
    .addLogRecordProcessor(BatchLogRecordProcessor.builder(exporter).build())
    .build();

OpenTelemetrySdk.builder().setLoggerProvider(provider).buildAndRegisterGlobal();

Ruby

gem install opentelemetry-exporter-otlp opentelemetry-sdk
require 'opentelemetry/sdk'
require 'opentelemetry/exporter/otlp'

OpenTelemetry::SDK.configure do |c|
  c.add_span_processor(
    OpenTelemetry::SDK::Logs::Export::BatchLogRecordProcessor.new(
      OpenTelemetry::Exporter::OTLP::LogsExporter.new(
        endpoint: 'http://localhost:5000/v1/logs'
      )
    )
  )
end

PHP

composer require open-telemetry/exporter-otlp open-telemetry/sdk
$exporter = (new \OpenTelemetry\Contrib\Otlp\LogsExporter(
    \OpenTelemetry\Contrib\Otlp\OtlpUtil::createTransport('http://localhost:5000/v1/logs')
));

$provider = new \OpenTelemetry\SDK\Logs\LoggerProvider(
    new \OpenTelemetry\SDK\Logs\Processor\BatchLogRecordProcessor($exporter)
);

\OpenTelemetry\API\Logs\NoopLogger::setLoggerProvider($provider);

Any other language / collector

Set your OTLP exporter endpoint to http://localhost:5000/v1/logs using HTTP/protobuf transport. HTTP/JSON is also supported with Content-Type: application/json.


Connecting your coding agent

Claude Code

claude mcp add loggles --transport http http://localhost:5000/mcp

If an API key is configured, Claude Code negotiates authentication automatically via the OAuth PKCE flow — no manual token setup required.

Debug skill

This repository ships a Claude Code skill (.claude/skills/loggles-debug/) that activates automatically when you describe a bug, ask Claude to investigate an error, or want to observe your app's runtime behaviour. It puts Claude in one of two modes:

Investigative (something is broken):

  • Reads your source code first to understand the relevant service, map its log output, and identify error branches — then queries logs with that context
  • Cross-references log evidence against source to confirm a root cause and point to a specific file and line
  • Calls out missing instrumentation (correlation_id not propagated, IDs embedded in message strings) and explains the fix

Exploratory (observing runtime behaviour):

  • Starts from the logs directly — no upfront source reading
  • Tails live streams, traces requests by ID, and narrates what the service is actually doing
  • Useful during development and testing: "what did my app do when I hit that endpoint?"

The skill is loaded automatically when you open this project in Claude Code. To use it in your own application's repository, copy it:

mkdir -p /your-project/.claude/skills
cp -r /path/to/loggles/.claude/skills/loggles-debug /your-project/.claude/skills/

Cursor

Add to .cursor/mcp.json in your project root:

{
  "mcpServers": {
    "loggles": {
      "url": "http://localhost:5000/mcp"
    }
  }
}

If an API key is configured, add an Authorization: Bearer <key> header in your MCP client configuration.


MCP tools

ToolDescription
search_logsSearch with filters: time range, level, service, message text, structured properties. Supports pagination.
get_log_by_idRetrieve a single log event by ID
get_servicesList all source/service names that have emitted logs
get_log_levelsList distinct log levels present
get_propertiesList distinct structured property keys
get_property_valuesList distinct values for a property key within a time window
get_log_statsLog counts grouped by level and service
get_logs_by_trace_idRetrieve all logs sharing a trace/correlation ID
get_related_logsContext window of logs around a specific event
get_recent_errorsLast N error/critical log events, optionally filtered by service
tail_logsMost recent N log events
get_log_rateBucketed log counts over time — observe traffic volume and rhythm
get_message_templatesList distinct message templates, optionally filtered by service
find_log_patternsCluster messages by recurring pattern
get_error_spikesDetect time buckets where error count exceeded a threshold
audit_log_qualityReport instrumentation coverage: missing templates, unstructured messages, broken down by service
clear_logsDelete all log events from the store

Authentication

By default, with no key configured, all endpoints are open — zero friction for localhost use.

No authentication (default)

Leave Auth__ApiKey unset. All endpoints are publicly accessible. Suitable for localhost.

API key

# Docker
docker run ... -e Auth__ApiKey=your-secret-key ...

# dotnet run
export Auth__ApiKey=your-secret-key
dotnet run

Once set, all ingest and query endpoints require:

Authorization: Bearer your-secret-key

MCP clients (Claude Code, Cursor, etc.)

MCP clients that support OAuth (such as Claude Code) negotiate authentication automatically. When an API key is configured, Loggles exposes a local OAuth 2.0 + PKCE flow (RFC 6749 / RFC 7636) that issues your API key as the access token. The client handles this handshake transparently.

Discovery endpoints used by OAuth-aware clients:

EndpointDescription
GET /.well-known/oauth-authorization-serverOAuth server metadata (RFC 8414)
GET /.well-known/oauth-protected-resourceProtected resource metadata
POST /oauth/registerDynamic client registration (RFC 7591)
GET /oauth/authorizeAuthorization endpoint
POST /oauth/tokenToken endpoint — returns your configured API key

The OAuth flow can be toggled with Mcp__OAuthEnabled (default: true). Set to false to suppress discovery endpoints if your client does not support OAuth.


Configuration

All settings can be overridden with environment variables using __ as separator (e.g. Retention__Hours=24).

SettingDefaultDescription
Storage__ProvidersqliteStorage backend: sqlite or postgres
Storage__ConnectionStringData Source=logs.dbSQLite connection string, or PostgreSQL connection string when using postgres provider
Retention__Hours48How long to keep logs
Retention__PurgeIntervalMinutes15How often to run cleanup
Mcp__EnabledtrueEnable/disable the MCP endpoint
Mcp__OAuthEnabledtrueExpose OAuth discovery and token endpoints for MCP clients
Auth__ApiKey(empty)Static API key for Bearer token auth. If unset, auth is disabled
SelfDiagnostics__EnabledtrueSend Loggles' own logs back to itself via OTLP
SelfDiagnostics__OtlpEndpointhttp://localhost:5000OTLP endpoint for self-diagnostics

PostgreSQL

docker run -d \
  -p 5000:5000 \
  -e Storage__Provider=postgres \
  -e Storage__ConnectionString="Host=your-host;Database=loggles;Username=loggles;Password=secret" \
  ghcr.io/bytesquashcom/loggles:latest

REST API

Beyond MCP, a REST API is available for scripting or manual queries.

MethodPathDescription
POST/v1/logsIngest OTLP/HTTP logs (protobuf or JSON)
POST/searchSearch logs with filters
GET/logs/{id}Get log by ID
GET/meta/propertiesList distinct property keys
GET/stats/levelsLog counts by level

License

Elastic License 2.0 — free to use, self-host, and modify. You may not offer Loggles as a hosted or managed service to third parties.