# intro-to-mltp is a self contained Grafana observability sandbox

> intro-to-mltp is a Docker Compose environment that wires Mimir, Loki, Tempo, Pyroscope, Alloy, Beyla and k6 around a small four service application so metrics, logs, traces and profiles can be explored locally. It suits a Grafana user who wants a working end to end demo, and it is the wrong tool if you only need somewhere to send your own data.

**grafana/intro-to-mltp** — Introduction to Metrics, Logs, Traces and Profiles session companion code.

- Repository: https://github.com/grafana/intro-to-mltp
- Stars: 666 · Forks: 158
- Language: JavaScript
- License: AGPL-3.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/grafana-intro-to-mltp

## The four signal types and the stack that stores them

The repository is a companion to a presentation series on the three pillars of observability within Grafana, and its subject is the four signal types the products cover. The stack behind it maps one service to each signal. Mimir stores and serves metrics, Loki stores and serves logs, Tempo stores and serves trace information, and Pyroscope stores and serves profiling information. Grafana is the visualisation layer on top, and two more services sit between the application and the backends. Beyla watches the four service application and automatically generates signals from it, and Grafana Alloy receives traces and produces metrics and logs based on those traces. That last part is the interesting design decision in the whole environment, because it is why the pre-provisioned dashboard can show a RED, Rate Error Duration, overview where almost all metrics are being generated via trace spans rather than scraped. The repository layout follows the services, with directories named alloy/, beyla/, grafana/, k6/, loki/, mimir/, otel/, tempo/, source/ and cloud/, plus a tests/ directory and a renovate.json5 for dependency updates.

## The demo app is the reason this is more than a backend

The readme draws an explicit line between this repository and a plain backend, and the difference is the sample application. This repository ships a full demo: a sample microservice application, the Mythical Beasts services, and a load generator, alongside the complete observability stack, so you can explore metrics, logs, traces and profiles with data flowing out of the box. The application has four services. One requests data from a REST API server, that server receives the requests and uses a database to store and retrieve data for them, a recorder service stores messages to an AMQP bus, and a Postgres database holds the data. There is also a React-based frontend web interface for managing the REST API server, and a k6 service runs a load test against the application. The point of the load generator is that a demo with no traffic teaches you nothing about how signals behave under load, and k6 supplies that traffic. If you already have an instrumented application of your own, the readme says to use grafana/docker-otel-lgtm instead, which bundles the collector, Prometheus, Tempo, Loki, Pyroscope and Grafana into a single container with no sample application.

## One compose file brings up the whole stack

Running the environment is a single command, and the compose manifest is checked in at the root of the repository. The prerequisites are Docker and Docker Compose, with the readme noting that a recent Docker version has compose built in, and that with an older Docker plus a separate compose binary you should use docker-compose instead. The compose file declares the project name, the named volumes for Grafana and Postgres, and the services:

```yaml
name: grafana-intro-to-mltp
volumes:
  grafana:
  postgres:
services:
  # The Grafana dashboarding server.
  grafana:
    image: grafana/grafana:13.0.2
    volumes:
      - "./grafana/definitions:/var/lib/grafana/dashboards"
      - "./grafana/provisioning:/etc/grafana/provisioning"
    ports:
      - "3000:3000"
```

The Grafana service is configured with a long list of feature toggles enabled, including flameGraph, traceqlSearch, traceQLStreaming, correlations, metricsSummary, traceqlEditor, traceToMetrics, traceToProfiles and datatrails, and with the lokiexplore, exploretraces and pyroscope plugins installed. Anonymous access is enabled with the anonymous organisation role set to Admin and the login form disabled, which is convenient for a local sandbox and is exactly the setting you would not copy into a real deployment. The Alloy service in the same file is configured with a public-preview stability level and a batch of exposed ports, and it mounts a config.alloy file and an endpoints.json file from the alloy/ directory. The pre-built microservice images are pulled from the GitHub Container Registry under ghcr.io/grafana/intro-to-mltp, and the readme says they are no longer published to Docker Hub.

## Ports, dashboards and the path through the data

The readme walks the route through the environment, and the port numbers are the first thing that can go wrong on a busy machine. After starting the stack you log in to the local Grafana service at http://localhost:3000/, with a note that this assumes port 3000 is not already in use and that if it is you should edit the docker-compose.yml file and change the port mapping line to another free host port. The demo frontend is reached at http://localhost:3001/ and interacting with the data management interface there produces Faro session telemetry, which is the browser signal in the mix. From there you open the pre-provisioned MLT dashboard, which is served from the grafana/definitions/mlt.json provisioning file, and then use the Grafana Explorer to poke at the individual data sources, with the readme linking an Explorer view preloaded against Mimir over the last hour. The dashboards directory is mounted into the container at /var/lib/grafana/dashboards and the provisioning directory at /etc/grafana/provisioning, so the dashboards are part of the repository rather than something you click together in the UI. The readme also points at a data links feature in the Grafana documentation, which is the mechanism for jumping from a metric to a log or a trace.

## The pipeline runs through Alloy, which is where trace-derived metrics come from

The repository has a section on Grafana Alloy with two sub-parts, metrics generation and flow and river configuration, and that is the mechanism worth understanding before you start poking at dashboards. Alloy sits between the application and the backends. The compose comment says it batches and processes traces sent to it and generates auto-logs from those traces, and the overview lists it as receiving traces and producing metrics and logs based on those traces. The alternative path runs through Beyla, which watches the four service application and automatically generates signals. The two are not redundant. Beyla instruments from the outside, at the process level, and Alloy derives data from the trace stream that has already been produced, which is what allows a metric to be computed from span data. That is why the RED dashboard can show nearly all of its metrics as trace-derived. The readme also documents a section on span and service graph metrics generation, and there is a separate compose file for running the environment with the OpenTelemetry Collector, docker-compose-otel.yml, which is the path to take if you want to see the same topology driven by the collector rather than by Alloy. A cloud/ directory and docker-compose-cloud.yml cover the other option, sending the same sample application data to Grafana Cloud products.

## Where this sandbox is the wrong tool

The readme itself flags the boundary, and the first limitation is resource cost. This is a dozen plus containers, including a React frontend, four application services, Postgres, RabbitMQ, the four storage backends, Grafana, Alloy, Beyla, k6 and a Node Exporter that retrieves resource metrics from the local host. On a laptop with limited memory that is a heavy default, and the readme does not offer a reduced profile. The second limitation is that this is a teaching environment, not a template. The configuration is tuned for demonstration, with anonymous admin access on Grafana, a public-preview stability level on Alloy, and pre-baked dashboards, none of which is what you would run in production. The third is the dependency on pre-built images. The microservice images are pulled from the GitHub Container Registry and the readme states they are no longer published to Docker Hub, so an air-gapped or restricted-network user cannot run the demo at all without building them, and the source/ directory is where that work starts. The readme also mentions a NoQL exploration section and a smoke tests directory, and a k8s/ directory, which indicates the environment is meant to grow, but the documented path for a newcomer is the Docker Compose one. The honest alternative for a learner with an existing instrumented service is the single container image, and for a learner with no service at all, this repository is the better choice because the traffic generator and the pre-provisioned dashboards do the teaching for you.

## Conclusion

intro-to-mltp is worth running if you want to see how Grafana's four signals fit together in one place, since the environment ships a real application, a load generator and pre-provisioned dashboards rather than an empty backend, and the readme says it has been kept current with the product versions. It is the wrong choice for shipping your own application's telemetry, where the readme itself points to grafana/docker-otel-lgtm as the lighter option, and it is a poor fit for a machine that cannot spare the resources for a dozen containers. Verify first that the ports in docker-compose.yml are free on your machine, particularly 3000 and 3001, that your Docker version has the compose command built in or that the separate binary is installed, and that the pre-built microservice images are still published to the GitHub Container Registry. The last push was on 2026-10-20.

## FAQ

### How do I start the intro-to-mltp demonstration environment?

Run docker compose up from the repository root, then log in to the local Grafana service at http://localhost:3000/. The demo frontend is at http://localhost:3001/ and the pre-provisioned MLT dashboard is linked from the readme.

### What does intro-to-mltp include beyond the Grafana stack?

A full demo with a sample microservice application, the Mythical Beasts services, and a k6 load generator, alongside the observability stack. The app has four services, a Postgres database, an AMQP bus and a React frontend, so signals exist from the start.

### What is the difference between intro-to-mltp and grafana/docker-otel-lgtm?

The readme says to use docker-otel-lgtm when you have an instrumented app of your own and just want a quick local backend, since it bundles the collector, Prometheus, Tempo, Loki, Pyroscope and Grafana into a single container with no sample application. Use this repository when you want a ready-made end to end demo.

### What does Grafana Alloy do in this environment?

Alloy receives traces and produces metrics and logs based on those traces, which is why the pre-provisioned RED dashboard shows almost all metrics generated via trace spans. Beyla is the alternative path, watching the application and generating signals automatically.

### What are the prerequisites for running intro-to-mltp?

Docker and Docker Compose, with the readme noting that a recent Docker has compose built in and that older setups should use docker-compose. Port 3000 needs to be free for Grafana, otherwise you change the port mapping in docker-compose.yml.

## Sources

- [grafana/intro-to-mltp on GitHub](https://github.com/grafana/intro-to-mltp)
- [Issues](https://github.com/grafana/intro-to-mltp/issues)
- [License: AGPL-3.0](https://github.com/grafana/intro-to-mltp/blob/main/LICENSE)
- [README](https://github.com/grafana/intro-to-mltp/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/grafana-intro-to-mltp
