RepoPilotOpen in app →

grafana/loki

Like Prometheus, but for logs.

Healthy

Healthy across the board

worst of 4 axes
Use as dependencyConcerns

copyleft license (AGPL-3.0) — review compatibility

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit today
  • 27+ active contributors
  • Distributed ownership (top contributor 25% of recent commits)
Show 4 more →
  • AGPL-3.0 licensed
  • CI configured
  • Tests present
  • AGPL-3.0 is copyleft — check downstream compatibility
What would change the summary?
  • Use as dependency ConcernsMixed if: relicense under MIT/Apache-2.0 (rare for established libs)

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/grafana/loki)](https://repopilot.app/r/grafana/loki)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/grafana/loki on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: grafana/loki

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/grafana/loki shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across the board

  • Last commit today
  • 27+ active contributors
  • Distributed ownership (top contributor 25% of recent commits)
  • AGPL-3.0 licensed
  • CI configured
  • Tests present
  • ⚠ AGPL-3.0 is copyleft — check downstream compatibility

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live grafana/loki repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/grafana/loki.

What it runs against: a local clone of grafana/loki — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in grafana/loki | Confirms the artifact applies here, not a fork | | 2 | License is still AGPL-3.0 | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 30 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>grafana/loki</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of grafana/loki. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/grafana/loki.git
#   cd loki
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of grafana/loki and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "grafana/loki(\\.git)?\\b" \\
  && ok "origin remote is grafana/loki" \\
  || miss "origin remote is not grafana/loki (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(AGPL-3\\.0)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"AGPL-3\\.0\"" package.json 2>/dev/null) \\
  && ok "license is AGPL-3.0" \\
  || miss "license drift — was AGPL-3.0 at generation time"

# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
  && ok "default branch main exists" \\
  || miss "default branch main no longer exists"

# 4. Critical files exist
test -f "cmd/loki/main.go" \\
  && ok "cmd/loki/main.go" \\
  || miss "missing critical file: cmd/loki/main.go"
test -f "pkg/loki/loki.go" \\
  && ok "pkg/loki/loki.go" \\
  || miss "missing critical file: pkg/loki/loki.go"
test -f "pkg/querier/querier.go" \\
  && ok "pkg/querier/querier.go" \\
  || miss "missing critical file: pkg/querier/querier.go"
test -f "pkg/ingester/ingester.go" \\
  && ok "pkg/ingester/ingester.go" \\
  || miss "missing critical file: pkg/ingester/ingester.go"
test -f "pkg/storage/stores.go" \\
  && ok "pkg/storage/stores.go" \\
  || miss "missing critical file: pkg/storage/stores.go"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 30 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~0d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/grafana/loki"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Loki is a horizontally-scalable, multi-tenant log aggregation system that indexes logs by labels (like Prometheus does for metrics) rather than full-text indexing, storing compressed unstructured logs cheaply. It integrates with Prometheus label schemas and Grafana for querying, making it easy to switch between metrics and logs in the same observability stack. The core distinguishing feature is label-based indexing instead of inverted indices, reducing operational complexity and cost. Multi-language monorepo: core Go services in cmd/ (chunks-inspect, loki server components), Jsonnet for config/infrastructure in .github/jsonnetfile.json and .github/vendor/github.com/grafana/loki-release/workflows/, Helm charts (likely in helm/ or chart/), Ruby/Shell for scripting, and Yacc grammar files for query parsing. DevContainer support (.devcontainer/devcontainer.json) enables standardized local development. GitHub Actions workflows in .github/workflows/ orchestrate testing, building, and releases.

👥Who it's for

Kubernetes operators, platform engineers, and observability teams running Prometheus who want to add cost-effective log aggregation without switching mental models or infrastructure. DevOps teams evaluating centralized logging solutions. Grafana users who want native log exploration alongside metrics.

🌱Maturity & risk

Production-ready and actively maintained. The project has significant Go codebase (~18MB), comprehensive CI/CD across .github/workflows/ (check.yml, helm-ci.yml, images.yml), Helm chart infrastructure, and integration with Grafana's ecosystem. Multiple .github/ISSUE_TEMPLATE/ types and a formal helm chart migration plan (March 2026) indicate mature governance. Recent additions like .devcontainer/devcontainer.json suggest active development for contributor experience.

Moderate dependency management: uses go-mod with pinned versions (golang/snappy, klauspost/compress, pierrec/lz4 visible in cmd/chunks-inspect/go.mod). The Helm chart migration to grafana-community/helm-charts (effective March 2026) introduces some organizational risk around chart maintenance. Large monorepo (Go + Jsonnet + Shell + Yacc + HCL) increases complexity. No visible single-maintainer risk given Grafana backing, but the jsonnet/HCL heavy ops tooling requires specific skill knowledge.

Active areas of work

Active CI/CD development: recent additions include claude-code-review.yml and claude.yml for AI-assisted reviews, helm-diff-ci.yml and helm-weekly-release-pr.yaml showing Helm chart automation, and conventional-commits.yml enforcing commit hygiene. Renovate bot (renovate.json5) actively manages dependencies. The devcontainer setup suggests ongoing contributor UX improvements. Backport workflow (backport.yml) indicates multi-version maintenance.

🚀Get running

git clone https://github.com/grafana/loki.git
cd loki
# Using devcontainer (VS Code / Cursor):
# Reopen in Container via Command Palette, or:
make build  # Makefile present (79KB)
# Check Makefile targets: make help or grep '^[a-z]' Makefile

Daily commands:

make build              # Compile binaries
make test              # Run test suite
make helm-test         # Test Helm charts (helm-ci.yml workflow reference)
make docker-build      # Build Docker images (Dockerfile present)
# Or use devcontainer: reopen in container, then make build
# Start Loki: ./loki -config.file=loki-local-config.yaml (check docs/)

🗺️Map of the codebase

  • cmd/loki/main.go — Entry point for the Loki binary; all contributors must understand how the application initializes and starts its core services.
  • pkg/loki/loki.go — Core Loki instance definition and lifecycle management; essential for understanding the main application structure and module composition.
  • pkg/querier/querier.go — Query execution engine; critical for understanding how log queries are processed and returned to clients.
  • pkg/ingester/ingester.go — Log ingestion and streaming service; fundamental to understanding how logs flow into the system.
  • pkg/storage/stores.go — Storage abstraction layer for managing index and log storage backends; essential for understanding data persistence strategy.
  • README.md — Project mission and architecture overview; required reading to grasp why Loki indexes labels rather than full text.
  • CONTRIBUTING.md — Contribution guidelines and development setup; mandatory for all contributor onboarding.

🛠️How to make changes

Add a new LogQL operator or aggregation function

  1. Define the operator/function signature in the LogQL AST (pkg/logql/logql.go)
  2. Implement the operator evaluation logic in the LogQL evaluator (pkg/logql/expr.go)
  3. Add parser grammar rule for the new syntax (pkg/logql/lexer.go)
  4. Write unit tests covering the operator behavior (pkg/logql/logql_test.go)

Add a new storage backend (S3, GCS, etc.)

  1. Create a new storage client implementing ObjectClient interface (pkg/storage/stores.go)
  2. Implement index and chunk store adapters for the backend (pkg/storage/stores/factory.go)
  3. Add configuration flags and validation in config struct (pkg/loki/config.go)
  4. Register the new backend in the storage factory (pkg/storage/stores/factory.go)

Add a new HTTP API endpoint or gRPC service method

  1. Define the proto message and service in logproto (pkg/logproto/logproto.proto)
  2. Implement the handler in the appropriate service (e.g., Querier, Distributor) (pkg/querier/querier.go)
  3. Register the HTTP route or gRPC handler (pkg/loki/loki.go)
  4. Add integration tests for the endpoint (integration/e2e/e2e_test.go)

Add validation for new tenant configuration options

  1. Extend the overrides/limits config struct (pkg/util/validation/limits.go)
  2. Add validation rules in the validation package (pkg/util/validation/validate.go)
  3. Update YAML/flag parsing in config loader (pkg/loki/config.go)
  4. Add test cases for the new validation rules (pkg/util/validation/validate_test.go)

🔧Why these technologies

  • gRPC + Protocol Buffers — Efficient serialization and low-latency inter-service communication for log ingestion and querying at scale
  • Consistent Hashing (Hash Ring) — Distributes write load uniformly across ingesters while enabling replication and enabling horizontal scaling without full rebalancing
  • Write-Ahead Log (WAL) — Durability guarantee for incoming logs before flushing to cloud storage; enables recovery from crashes
  • Chunk-based compression (Snappy, LZ4) — Reduces storage costs by 10-100x; log data is highly compressible and rarely accessed in full
  • Label-only indexing — Avoids expensive full-text indexing overhead; queries use label filters to find log streams, then read unindexed compressed chunks
  • Go with minimal dependencies — Single binary, fast compilation, excellent concurrency primitives; minimal operational overhead

⚖️Trade-offs already made

  • Label-only indexing instead of full-text search

    • Why: Full-text indexing requires 5-10x more storage and operational complexity; labels are usually sufficient to identify log sources
    • Consequence: Cannot query arbitrary log content; queries must filter by label first, then regex within results. Trade search flexibility for cost and simplicity.
  • Immutable chunks flushed to cloud storage

    • Why: Avoids maintaining expensive high-availability databases; uses cheap S3/GCS as durable storage
    • Consequence: Limited to time-range queries; cannot update/delete old logs in-place. Simplifies distributed consistency.
  • In-memory ingester caches and WAL for recent data

    • Why: Queries hit ingesters for recent logs (faster, cheaper) and only touch cold storage for historical data
    • Consequence: Ingesters must retain state; if all replicas fail simultaneously (rare), recent unflushed logs are lost. Requires monitoring and alerting.
  • Multi-tenant architecture built-in from day one

    • Why: Allows single Loki cluster to serve multiple organizations/teams safely; essential for SaaS deployments
    • Consequence: Adds complexity (tenant isolation checks, per-tenant limits, rate limiting); not suitable for single-tenant deployments that want to minimize overhead.
  • Horizontal scaling via consistent hash ring

    • Why: Each ingester/querier is stateless; add new nodes without rebalancing all data
    • Consequence: Requires service discovery (Consul, Kubernetes) and load balancing; operational complexity vs. simpler centralized approaches.

🚫Non-goals (don't propose these)

  • Does not perform full-text indexing of log content
  • Not intended for real-time alerting (use Prometheus + Alertmanager)
  • Does not support arbitrary schema updates (logs are immutable once flushed)
  • Not designed for sub-second query latency (typical 100-300ms for large ranges)
  • Does not support delete/update operations on historical logs in-place

🪤Traps & gotchas

Jsonnet learning curve: Config and release workflows use Jsonnet (not JSON/YAML), unfamiliar to many Go developers — check .github/vendor/github.com/grafana/loki-release/workflows/ examples first. Multi-language build: Go, Yacc, Jsonnet, Ruby scripts all involved; make help may not list all targets. Helm chart migration: As of March 2026, Helm chart moves to grafana-community/helm-charts — PRs targeting helm/ may be redirected. Devcontainer vs. local: .devcontainer/devcontainer.json exists but may not be mandatory; check if local Go 1.26.2 + specific tools are required. Compression codec selection: chunks-inspect/go.mod shows multiple compression libraries (snappy, lz4, klauspost/compress); incorrect codec can corrupt stored logs — verify config.

🏗️Architecture

💡Concepts to learn

  • Label-based Indexing (vs. Inverted Index) — Core design choice that makes Loki cheaper and simpler — it indexes only metadata labels (e.g., pod name, namespace) not log contents, so you must understand this tradeoff and how to structure labels for queryability
  • Log Streams & Chunks — Loki groups logs with identical label sets into streams, then compresses them into time-bounded chunks (visible in cmd/chunks-inspect); understanding chunk structure is essential for performance tuning and debugging
  • Multi-tenancy via Labels — Loki enforces data isolation between tenants using a special label in requests (typically from reverse proxy or auth layer) — critical for SaaS deployments and understanding authorization flow
  • LogQL (Loki Query Language) — Yacc grammar files in the repo define LogQL syntax; queries filter by labels then apply optional line-level filters or parsers — you'll write and debug these constantly
  • Compression Codecs (Snappy, LZ4, Deflate) — chunks-inspect/go.mod lists snappy, lz4, and klauspost/compress; incorrect codec selection during storage migration can corrupt logs — storage layer config is critical
  • Jsonnet for Infrastructure-as-Code — Loki's Helm charts and CI workflows are templated in Jsonnet (not plain YAML/JSON); you'll need to read and modify .github/vendor/.../*.jsonnet for deployment automation
  • Prometheus Remote Write Protocol — Loki accepts logs via a modified Prometheus remote-write protocol (push model, not pull); understanding protobuf message format helps with client integration and debugging
  • grafana/alloy — Official successor to Promtail; the agent for collecting and forwarding logs to Loki (mentioned in README as the modern log collection layer)
  • prometheus/prometheus — Spiritual predecessor and companion; Loki mirrors Prometheus's label-based indexing philosophy but for logs instead of metrics
  • grafana/grafana — Native integration target; Loki queries are executed from Grafana dashboards, and the UI/query language design assumes Grafana as the consumer
  • grafana-community/helm-charts — Destination for Helm chart migration (effective March 2026); Loki charts will move here, making it the future canonical source for K8s deployments
  • cortexproject/cortex — Sister project in Grafana's observability stack; Cortex handles metrics storage at scale using similar horizontally-scalable, label-based architecture

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive unit tests for chunks-inspect cmd module

The chunks-inspect tool (cmd/chunks-inspect) is a utility for inspecting Loki chunk files, but based on the go.mod file showing only compression dependencies, there's likely minimal test coverage. This is critical infrastructure for debugging and operations. Adding tests would improve reliability and make the codebase more maintainable for contributors working on chunk storage logic.

  • [ ] Create cmd/chunks-inspect/*_test.go files with unit tests for main parsing logic
  • [ ] Add test fixtures (sample chunk files) in cmd/chunks-inspect/testdata/
  • [ ] Test all compression formats (snappy, lz4, zstd) mentioned in go.mod dependencies
  • [ ] Add integration test in .github/workflows/check.yml or create dedicated test workflow for chunks-inspect

Create missing LogQL analyzer GitHub Action workflow documentation

The repo has a .github/workflows/logql-analyzer.yml workflow file but no corresponding documentation explaining what the analyzer does, how to run it locally, or how contributors should handle analyzer failures. This creates friction for new contributors who encounter analyzer failures in their PRs.

  • [ ] Create docs/sources/logql-analyzer.md documenting the analyzer's purpose and rules
  • [ ] Add troubleshooting section with common failures and solutions
  • [ ] Document how to run the analyzer locally in CONTRIBUTING.md (if it exists) or create one
  • [ ] Add comments to .github/workflows/logql-analyzer.yml explaining what each step validates

Add CI workflow for Go version compatibility testing

The go.mod specifies go 1.26.2, but there's no dedicated GitHub Action workflow testing multiple Go versions (e.g., 1.25.x, 1.26.x). This is especially important for a widely-used project like Loki to ensure compatibility across minor versions that users might have deployed.

  • [ ] Create .github/workflows/go-version-matrix.yml with strategy.matrix for Go 1.25.x and 1.26.x
  • [ ] Test across Linux and Darwin platforms using matrix strategy
  • [ ] Run 'go build ./...' and 'go test ./...' for each Go version combination
  • [ ] Add badge to README.md linking to this workflow for visibility

🌿Good first issues

  • Add unit tests for cmd/chunks-inspect (go.mod exists but no visible test coverage mentioned) — start by writing tests in cmd/chunks-inspect/*_test.go for the main chunk inspection CLI.
  • Document the Jsonnet workflow syntax in CONTRIBUTING.md or docs/ — the .github/vendor/github.com/grafana/loki-release/workflows/ directory is powerful but undocumented; extract examples and explain how to modify release pipelines.
  • Create a Makefile help target: parse .PHONY targets and print descriptions, since the 79KB Makefile likely has many hidden targets not discoverable via make help — similar to Python's make help.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 35ca2f6 — feat(logql): Report estimated_query_bytes from index-stats lookups (#21796) (hundredwatt)
  • 318f8e8 — test: Fix race in bloom planner cancellation test (#21797) (paul1r)
  • 620bd56 — chore(compaction): Replace postings/stats RowReader with columnar Reader (#21785) (trevorwhitney)
  • 96a0574 — feat(dataobj): Reduce postings indexing allocations via observe/aggregate pattern (#21610) (trevorwhitney)
  • deff86d — feat: On-disk serialization for postings and stats index sections (#21591) (trevorwhitney)
  • b5b2170 — chore: Remove Bigtable backup tool (#21794) (chaudum)
  • 962470c — chore(ci): Cache build container (#21790) (chaudum)
  • d4ce29a — fix(tsdb): Do not try to ship TSDBs that cannot be opened upon start (#21769) (chaudum)
  • da5a172 — fix(querytee): Fix TestProxyEndpoint_QuerySplitting clock-drift bug (#21779) (jnewbigin)
  • fe7f43b — feat: Write all Kafka records at once (#21542) (grobinson-grafana)

🔒Security observations

The chunks-inspect module has moderate security concerns primarily centered on outdated and incompatible compression library dependencies. The most critical issue is the use of the incompatible lz4 library (v2.6.1+incompatible) which requires immediate attention. Indirect dependencies lack explicit management. No hardcoded secrets or obvious injection vulnerabilities were detected in the visible file structure. The project would benefit from dependency auditing, compression input validation implementation, and modern Go version targeting. The broader Loki project demonstrates good security practices (fuzzing badge, security scanning workflows), but this specific module requires attention.

  • High · Outdated lz4 Compression Library — cmd/chunks-inspect/go.mod. The dependency 'github.com/pierrec/lz4 v2.6.1+incompatible' is marked as incompatible and uses an outdated version. LZ4 compression libraries have had historical vulnerabilities. The '+incompatible' suffix indicates potential API breaking changes or maintenance issues. Fix: Update to a maintained, compatible version of lz4. Consider using 'github.com/pierrec/lz4/v4' or evaluate alternative compression libraries with active maintenance.
  • Medium · Indirect Dependency Without Direct Control — cmd/chunks-inspect/go.mod. The dependency 'github.com/frankban/quicktest v1.7.2' is listed as an indirect dependency (// indirect comment). This testing library may not be actively maintained (v1.7.2 appears to be an older version). Indirect dependencies can introduce vulnerabilities without explicit awareness. Fix: Review whether this transitive dependency is necessary. If it is, consider updating it or replacing it with a more actively maintained testing framework. Run 'go mod why' to understand the dependency chain.
  • Medium · Potential Compression Bomb Vulnerability — cmd/chunks-inspect/go.mod. The chunks-inspect tool uses multiple compression libraries (snappy, lz4, klauspost/compress) without clear input validation context visible in the file structure. Compression libraries are common attack vectors for denial-of-service via crafted compressed payloads. Fix: Implement size limits and decompression timeout mechanisms. Validate compressed input before decompression. Set maximum decompressed size limits to prevent memory exhaustion attacks.
  • Low · Go Version Compatibility — cmd/chunks-inspect/go.mod. The module specifies 'go 1.26.2' which appears to be a future/unreleased Go version (as of current knowledge cutoff). This may indicate a configuration error or development-only setup. Fix: Verify the correct Go version target. Use a stable, released version of Go (e.g., 1.22.x or 1.23.x). Document the minimum supported Go version clearly.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · grafana/loki — RepoPilot