{"id":129055,"date":"2025-05-28T13:21:52","date_gmt":"2025-05-28T13:21:52","guid":{"rendered":"\/tutorials\/?p=129055"},"modified":"2026-03-10T09:26:23","modified_gmt":"2026-03-10T09:26:23","slug":"how-to-set-up-lgtm-stack","status":"publish","type":"post","link":"\/ca\/tutorials\/how-to-set-up-lgtm-stack","title":{"rendered":"How to set up the LGTM stack for end-to-end observability"},"content":{"rendered":"<?xml encoding=\"utf-8\" ?><p>The LGTM stack &ndash; consisting of <strong>Loki<\/strong> for logs, <strong>Grafana<\/strong> for visualization, <strong>Tempo<\/strong> for tracing, and <strong>Mimir<\/strong> for metrics &ndash; is an open-source observability suite developed by Grafana Labs.<\/p><p>This powerful stack unifies metrics, logs, and traces into a single platform, giving teams a complete view of system performance.<\/p><p>In this guide, you&rsquo;ll set up the LGTM stack on a virtual private server (VPS). You&rsquo;ll configure each component and create a comprehensive observability dashboard to gain clear, end-to-end visibility into your apps and infrastructure.<\/p><p>\n\n\n\n<\/p><h2 class=\"wp-block-heading\" id=\"h-what-is-end-to-end-observability\"><strong>What is end-to-end observability?<\/strong><\/h2><p>End-to-end observability means monitoring and analyzing an app&rsquo;s entire lifecycle, from user interactions on the front end to services and infrastructure components on the back end.<\/p><p>Unlike traditional monitoring, which tracks only predefined metrics to measure system health and alert on known issues, end-to-end observability provides a unified view of:<\/p><ul class=\"wp-block-list\">\n<li><strong>User interactions<\/strong> &ndash; tracking frontend metrics and user behavior.<\/li>\n\n\n\n<li><strong>App performance<\/strong> &ndash; monitoring back-end services and internal APIs.<\/li>\n\n\n\n<li><strong>Infrastructure health<\/strong> &ndash; assessing the status of servers, databases, and networks.<\/li>\n\n\n\n<li><strong>Third-party services<\/strong> &ndash; observing dependencies like payment gateways or cloud providers.<\/li>\n<\/ul><p>By correlating data across all layers, teams gain insights into how changes in one area impact overall system performance, and can quickly spot issues wherever they occur.<\/p><p>The LGTM stack supports end-to-end observability by instrumenting apps to collect telemetry data: <strong>logs<\/strong>, <strong>metrics<\/strong>, and <strong>traces<\/strong>. The stack aggregates this data through its components and visualizes it in Grafana dashboards for easy analysis.<\/p><p>This approach delivers several benefits:<\/p><ul class=\"wp-block-list\">\n<li><strong>Comprehensive monitoring<\/strong> &ndash; the LGTM stack provides a holistic view of system behavior, enabling proactive issue detection and resolution.<\/li>\n\n\n\n<li><strong>Improved troubleshooting<\/strong> &ndash; correlating data from multiple sources helps teams quickly identify root causes, reducing the mean time to resolution (MTTR).<\/li>\n\n\n\n<li><strong>Scalability<\/strong> &ndash; each LGTM component scales horizontally to support complex, distributed systems.<\/li>\n\n\n\n<li><strong>Cost-effectiveness<\/strong> &ndash; as an open-source solution, the LGTM stack eliminates licensing fees associated with proprietary observability tools.<\/li>\n<\/ul><h2 class=\"wp-block-heading\" id=\"h-prerequisites\"><strong>Prerequisites<\/strong><\/h2><p>Before setting up the LGTM stack, prepare a VPS instance to host it. Grafana, the main interface for visualizing observability data, doesn&rsquo;t require heavy resources. You can run the full LGTM stack on a VPS with as little as:<\/p><ul class=\"wp-block-list\">\n<li><strong>1<\/strong> CPU core.<\/li>\n\n\n\n<li><strong>512 MB<\/strong> of RAM.<\/li>\n<\/ul><p>But since the LGTM stack monitors system performance and app behavior, choose a VPS plan that matches your system&rsquo;s scale and usage.<\/p><p>The <a href=\"\/ca\/vps-hosting\">VPS service from Hostinger<\/a> is a great choice, offering plans from <strong>CA$ 9.09<\/strong> to <strong>CA$ 36.29\/month<\/strong>.<\/p><p>Our plans scale up to <strong>8<\/strong> vCPU cores, <strong>32 GB<\/strong> of RAM, and <strong>400 GB<\/strong> of NVMe storage. You can upgrade anytime if your observability stack needs more power or space.<\/p><?xml encoding=\"utf-8\" ?><figure class=\"wp-block-image size-large\"><a class=\"hgr-tutorials-cta hgr-tutorials-cta-vps-hosting\" href=\"\/ca\/vps-hosting\" target=\"_blank\" rel=\"noreferrer noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"300\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2023\/02\/VPS-hosting-banner-1024x300.png\" alt=\"\" class=\"wp-image-77934\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure><p>Next, configure your firewall. Open the following ports on your VPS to ensure the LGTM components run smoothly:<\/p><figure tabindex=\"0\" class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>Port<\/strong><\/td><td><strong>Component<\/strong><\/td><td><strong>Purpose<\/strong><\/td><\/tr><tr><td><strong>3000\/TCP<\/strong><\/td><td>Grafana<\/td><td>Web interface for dashboards and data source management<\/td><\/tr><tr><td><strong>3100\/TCP<\/strong><\/td><td>Loki<\/td><td>Receives log data and serves log queries<\/td><\/tr><tr><td><strong>3200\/TCP<\/strong><\/td><td>Tempo<\/td><td>Handles trace data collection and querying<\/td><\/tr><tr><td><strong>9090\/TCP<\/strong><\/td><td>Mimir (builds on Prometheus)<\/td><td>Exposes Prometheus-compatible APIs for metric storage and querying<\/td><\/tr><tr><td><strong>4318\/TCP<\/strong><\/td><td>OpenTelemetry Collector (additional tool)<\/td><td>Accepts telemetry data in OTLP\/HTTP format<\/td><\/tr><\/tbody><\/table><\/figure><p>If you just purchased a VPS or haven&rsquo;t configured a firewall yet, you can skip this step.<\/p><p>For users with <a href=\"\/ca\/tutorials\/how-to-configure-firewall-on-ubuntu-using-ufw\">Uncomplicated Firewall (UFW) enabled<\/a>, open your terminal and run these commands:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo ufw allow 3000\/tcp    # Grafana  \nsudo ufw allow 3100\/tcp    # Loki  \nsudo ufw allow 3200\/tcp    # Tempo  \nsudo ufw allow 9090\/tcp    # Mimir  \nsudo ufw allow 4318\/tcp    # OpenTelemetry Collector<\/pre><p>Then, verify that UFW is active and the rules are applied by running:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo ufw status<\/pre><h2 class=\"wp-block-heading\" id=\"h-how-to-set-up-the-lgtm-stack-on-a-vps\"><strong>How to set up the LGTM stack on a VPS<\/strong><\/h2><p>You can set up the LGTM stack on your VPS in several ways. This tutorial uses <strong>Docker Compose<\/strong>, which lets you quickly deploy and manage all components in a single file. It&rsquo;s the easiest method and works well for beginners.<\/p><p>If you prefer more control or want to avoid Docker, we&rsquo;ll also provide instructions for installing each component manually.<\/p><h3 class=\"wp-block-heading\" id=\"h-1-prepare-the-environment\"><strong>1. Prepare the environment<\/strong><\/h3><p>Start by updating your VPS&rsquo;s package lists and upgrading installed packages to the latest versions. This ensures your server has the newest security patches and software improvements:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo apt update &amp;&amp; sudo apt upgrade -y<\/pre><p>Optionally, remove unused packages and dependencies to free up disk space:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo apt autoremove -y<\/pre><p>Next, <a href=\"\/ca\/tutorials\/how-to-install-docker-on-ubuntu\">install Docker on your server<\/a> to enable containerized deployment and use Docker Compose.<\/p><p>Hostinger VPS customers can simplify setup by using a one-click preconfigured Docker template. Otherwise, install the platform manually using Linux commands.<\/p><div class=\"wp-block-image\"><figure data-wp-context='{\"imageId\":\"69e1e5bbc1f27\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"371\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2025\/05\/hpanel-vps-operating-system-docker-highlighted-1024x371.png\" alt=\"The Docker template in hPanel's VPS\" class=\"wp-image-129058\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>If you don&rsquo;t plan to use Docker, feel free to skip this part.<\/p><p>After installation, verify that Docker is running by executing:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl status docker<\/pre><div class=\"wp-block-image\"><figure data-wp-context='{\"imageId\":\"69e1e5bbc2ccb\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"466\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2025\/05\/terminal-docker-active-running-highlighted-1024x466.png\" alt=\"A terminal output showing that Docker is active and running\" class=\"wp-image-129059\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>Press <strong>Ctrl + C<\/strong> to exit the status view.<\/p><p>Once done, create a new directory for your LGTM stack files and navigate into it. Replace <strong>grafana-lgtm<\/strong> with your preferred directory name:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">mkdir grafana-lgtm\n\ncd grafana-lgtm<\/pre><h3 class=\"wp-block-heading\" id=\"h-2-set-up-loki-for-log-aggregation\"><strong>2. Set up Loki for log aggregation<\/strong><\/h3><p>Loki handles log aggregation by collecting and storing logs from various sources.<\/p><p>It indexes only metadata instead of full log content, reducing storage costs and boosting query performance, especially when dealing with large volumes of log data.<\/p><p>Inside your <strong>grafana-lgtm<\/strong> directory, create a new file named <strong>loki-local-config.yaml <\/strong>using the <a href=\"\/ca\/tutorials\/how-to-install-and-use-nano-text-editor\">nano text editor<\/a>:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo nano loki-local-config.yaml<\/pre><p>Paste the following configuration into the file:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">auth_enabled: false\n\nserver:\n  http_listen_port: 3100\n\nschema_config:\n  configs:\n    - from: 2020-10-24\n      store: boltdb-shipper\n      object_store: filesystem\n      schema: v11\n      index:\n        prefix: index_\n        period: 24h\n\nstorage_config:\n  boltdb_shipper:\n    active_index_directory: \/tmp\/loki\/boltdb-shipper-active\n    cache_location: \/tmp\/loki\/boltdb-shipper-cache\n    cache_ttl: 24h\n  filesystem:\n    directory: \/tmp\/loki\/chunks\n\nlimits_config:\n  reject_old_samples: true\n  reject_old_samples_max_age: 168h\n  allow_structured_metadata: false\n\ningester:\n  lifecycler:\n    address: 127.0.0.1\n    ring:\n      kvstore:\n        store: inmemory\n      replication_factor: 1\n    final_sleep: 0s\n  chunk_idle_period: 5m\n  chunk_retain_period: 30s\n\ncommon:\n  path_prefix: \/tmp\/loki\n\ncompactor:\n  working_directory: \/tmp\/loki\/compactor\n<\/pre><div class=\"wp-block-image\"><figure data-wp-context='{\"imageId\":\"69e1e5bbc3b9a\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"621\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2025\/05\/terminal-nano-loki-local-config-yaml-1024x621.png\" alt=\"The Loki configuration file's content\" class=\"wp-image-129060\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>When you finish, press <strong>Ctrl + X &rarr; Y &rarr; Enter<\/strong> to save the file and exit <strong>nano<\/strong>.<\/p><p>If you prefer, you can learn <a href=\"\/ca\/tutorials\/how-to-install-loki\">how to install Loki<\/a> manually by following our detailed guide.<\/p><h3 class=\"wp-block-heading\" id=\"h-3-configure-mimir-for-metric-storage\"><strong>3. Configure Mimir for metric storage<\/strong><\/h3><p>Grafana Mimir builds on Prometheus and extends it by offering scalable, long-term storage and high-performance querying for large volumes of time-series data.<\/p><p>But in this guide, we use Prometheus alone because it integrates better with OpenTelemetry Collector to gather metrics for this setup.<\/p><p>If you also want to use Mimir for advanced scaling and storage, check out our <a href=\"\/ca\/tutorials\/how-to-install-grafana-mimir\">Mimir installation<\/a> article to learn how to set it up alongside Prometheus.<\/p><p>Create a new <strong>prometheus.yml<\/strong> file using <strong>nano<\/strong>, just like you did for Loki&rsquo;s config. Then, paste the configuration below:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">global:\n  scrape_interval: 5s            # Scraping interval, shortened to 5 seconds to get data faster (default is 1m)\nscrape_configs:\n  - job_name: 'otel-collector'\n    static_configs:\n      - targets: ['otel-collector:9464']   # Target is the Prometheus Exporter port of OTel Collector<\/pre><div class=\"wp-block-image\"><figure data-wp-context='{\"imageId\":\"69e1e5bbc49d0\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"141\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2025\/05\/terminal-nano-prometheus-yml-1024x141.png\" alt=\"The Prometheus configuration file's content\" class=\"wp-image-129061\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>Save the file when you&rsquo;re done.<\/p><h3 class=\"wp-block-heading\" id=\"h-4-integrate-tempo-for-distributed-tracing\"><strong>4. Integrate Tempo for distributed tracing<\/strong><\/h3><p>Grafana Tempo is a high-scale, distributed tracing back end that collects, stores, and queries trace data across microservice architectures.<\/p><p>Using Tempo, you can visualize the path of requests as they travel through various services. This helps identify bottlenecks quickly and effectively.<\/p><p>Like the previous components, create a file named <strong>tempo-local.yaml<\/strong> to store Tempo&rsquo;s configuration:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">distributor:\n  receivers:\n    otlp:\n      protocols:\n        http:\n          endpoint: \"0.0.0.0:4318\"\n\nstorage:\n  trace:\n    backend: local\n    local:\n      path: \/tmp\/tempo\/blocks\n    wal:\n      path: \/tmp\/tempo\/wal\n\ningester:\n  trace_idle_period: 30s\n  max_block_duration: \"5m\"\n  lifecycler:\n    ring:\n      kvstore:\n        store: inmemory\n      replication_factor: 1\n\ncompactor:\n  compaction:\n    block_retention: 1h\n\nquerier: {}  # &#11088; Must be added, otherwise it will automatically exit\n\nmultitenancy_enabled: false  # &#11088; Recommended to add, to avoid single-tenant environment errors\n<\/pre><div class=\"wp-block-image\"><figure data-wp-context='{\"imageId\":\"69e1e5bbc5713\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"600\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2025\/05\/terminal-nano-tempo-local-yaml-1024x600.png\" alt=\"The Tempo configuration file's content\" class=\"wp-image-129063\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>We also provide a tutorial on setting up Tempo manually for those who prefer a hands-on approach.<\/p><h3 class=\"wp-block-heading\" id=\"h-5-install-grafana-for-observability\"><strong>5. Install Grafana for observability<\/strong><\/h3><p>Grafana serves as the central visualization layer in the LGTM stack, integrating data from all other components into one place. This simplifies spotting and resolving system anomalies.<\/p><p>You can <a href=\"\/ca\/tutorials\/how-to-install-grafana\">install Grafana on your VPS<\/a> either manually or as part of the services in a Docker Compose file.<\/p><p>If you choose the latter, start by creating a new folder named <strong>grafana<\/strong> inside the <strong>grafana-lgtm<\/strong> directory:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">mkdir grafana\n\ncd grafana<\/pre><p>Next, create a file named <strong>datasources.yml<\/strong> inside <strong>grafana-lgtm\/grafana<\/strong> to configure data sources. Paste the following content:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">apiVersion: 1\ndatasources:\n  - name: Prometheus\n    type: prometheus\n    access: proxy\n    url: http:\/\/prometheus:9090\n    isDefault: true\n\n  - name: Loki\n    type: loki\n    access: proxy\n    url: http:\/\/loki:3100\n    isDefault: false\n\n  - name: Tempo\n    type: tempo\n    access: proxy\n    url: http:\/\/tempo:3200\n    isDefault: false\n<\/pre><div class=\"wp-block-image\"><figure data-wp-context='{\"imageId\":\"69e1e5bbc62be\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"658\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2025\/05\/terminal-nano-grafana-datasources-yml-1024x658.png\" alt=\"The Grafana data sources file's content\" class=\"wp-image-129064\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>Then, create another file called <strong>dashboards.yml<\/strong> in the same folder to set up dashboard providers:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">apiVersion: 1\nproviders:\n  - name: 'Local Dashboards'\n    orgId: 1\n    folder: ''\n    type: file\n    disableDeletion: false\n    updateIntervalSeconds: 5\n    options:\n      path: \/var\/lib\/grafana\/dashboards\n<\/pre><div class=\"wp-block-image\"><figure data-wp-context='{\"imageId\":\"69e1e5bbc70e7\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"378\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2025\/05\/terminal-nano-grafana-dashboards-yml-1024x378.png\" alt=\"The Grafana dashboard providers file's content\" class=\"wp-image-129065\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>After that, create a <strong>dashboards<\/strong> folder and navigate into it:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">mkdir dashboards\n\ncd dashboards<\/pre><p>Add a file named <strong>springboot-observability.json<\/strong>. This file serves as a sample dashboard:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">{\n    \"uid\": \"springboot-observability\",\n    \"title\": \"Spring Boot OTEL Demo Dashboard\",\n    \"time\": {\n        \"from\": \"now-5m\",\n        \"to\": \"now\"\n    },\n    \"panels\": [\n        {\n            \"type\": \"timeseries\",\n            \"title\": \"JVM Heap Memory Used\",\n            \"datasource\": \"Prometheus\",\n            \"targets\": [\n                {\n                    \"expr\": \"process_runtime_jvm_memory_usage{service_name=\"springboot-otel-demo\", type=\"heap\"}\"\n                }\n            ],\n            \"fieldConfig\": {\n                \"defaults\": {\n                    \"unit\": \"bytes\"\n                }\n            },\n            \"gridPos\": {\n                \"x\": 0,\n                \"y\": 0,\n                \"w\": 12,\n                \"h\": 8\n            }\n        },\n        {\n            \"type\": \"logs\",\n            \"title\": \"Application Logs (springboot-otel-demo)\",\n            \"datasource\": \"Loki\",\n            \"targets\": [\n                {\n                    \"expr\": \"{service_name=\"springboot-otel-demo\"}\"\n                }\n            ],\n            \"gridPos\": {\n                \"x\": 0,\n                \"y\": 8,\n                \"w\": 24,\n                \"h\": 8\n            }\n        }\n    ]\n}\n<\/pre><div class=\"wp-block-image\"><figure data-wp-context='{\"imageId\":\"69e1e5bbc7ebb\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"596\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2025\/05\/terminal-nano-grafana-sprintboot-observability-json-1024x596.png\" alt=\"The Grafana sample dashboard file's content\" class=\"wp-image-129067\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><h3 class=\"wp-block-heading\" id=\"h-6-create-a-docker-compose-file\"><strong>6. Create a Docker Compose file<\/strong><\/h3><p>After configuring each component, create a Docker Compose file. This file defines and manages all LGTM stack services in one place, making deployment simple and consistent.<\/p><p>You can skip this step if you installed all components manually without Docker.<\/p><p>First, return to the <strong>grafana-lgtm<\/strong> directory, then create a <strong>docker-compose.yml <\/strong>file:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">cd ~\/grafana-lgtm\nsudo nano docker-compose.yml<\/pre><p>Add the configuration below to the file:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">services:\n\n  prometheus:\n    image: prom\/prometheus:latest\n    container_name: prometheus\n    volumes:\n      - .\/prometheus.yml:\/etc\/prometheus\/prometheus.yml:ro\n    ports:\n      - \"9090:9090\"\n\n  loki:\n    image: grafana\/loki:latest\n    container_name: loki\n    user: \"0:0\"  # Run as root user\n    volumes:\n      - .\/loki-local-config.yaml:\/etc\/loki\/local-config.yaml:ro\n      - loki-data:\/tmp\/loki\n    command: -config.file=\/etc\/loki\/local-config.yaml\n    ports:\n      - \"3100:3100\"\n\n  tempo:\n    image: grafana\/tempo:latest\n    container_name: tempo\n    user: \"0:0\"  # Run as root user\n    volumes:\n      - .\/tempo-local.yaml:\/etc\/tempo\/tempo-local.yaml:ro\n      - tempo-data:\/tmp\/tempo\n    command: [\"-config.file=\/etc\/tempo\/tempo-local.yaml\"]\n    ports:\n      - \"3200:3200\"   # HTTP query port\n\n  grafana:\n    image: grafana\/grafana:latest\n    container_name: grafana\n    environment:\n      - GF_SECURITY_ADMIN_USER=admin \n      - GF_SECURITY_ADMIN_PASSWORD=admin \n    volumes:\n      - .\/grafana\/datasources.yml:\/etc\/grafana\/provisioning\/datasources\/datasources.yml:ro\n      - .\/grafana\/dashboards.yml:\/etc\/grafana\/provisioning\/dashboards\/dashboards.yml:ro\n      - .\/grafana\/dashboards\/:\/var\/lib\/grafana\/dashboards:ro\n    ports:\n      - \"3000:3000\"\n    depends_on:\n      - prometheus\n      - loki\n      - tempo\n\nvolumes:\n  loki-data: {}\n  tempo-data: {}\n<\/pre><p>Pay attention to the <strong>GF_SECURITY_ADMIN_USER<\/strong> and <strong>GF_SECURITY_ADMIN_PASSWORD<\/strong> values under the <strong>grafana<\/strong> service. These are your default login credentials for the Grafana dashboard. Change them to improve security.<\/p><div class=\"wp-block-image\"><figure data-wp-context='{\"imageId\":\"69e1e5bbc8fc4\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"767\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2025\/05\/terminal-nano-docker-compose-yml-gf-security-admin-highlighted-1024x767.png\" alt=\"The Docker Compose file's content\" class=\"wp-image-129068\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>Don&rsquo;t forget to save the file after editing.<\/p><p>Next, deploy all services on your server with:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">docker compose up -d<\/pre><p>To verify the services are running, execute:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">docker compose ps<\/pre><div class=\"wp-block-image\"><figure data-wp-context='{\"imageId\":\"69e1e5bbc9da1\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"269\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2025\/05\/terminal-docker-compose-ps-1024x269.png\" alt=\"A terminal output showing the running Docker services\" class=\"wp-image-129070\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><h3 class=\"wp-block-heading\" id=\"h-7-access-the-grafana-dashboard\"><strong>7. Access the Grafana dashboard<\/strong><\/h3><p>Open your browser and go to the Grafana dashboard using this URL. Replace <strong>your_vps_ip<\/strong> with your server&rsquo;s actual IP address:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">http:\/\/your_vps_ip:3000<\/pre><p>If you host your LGTM stack on Hostinger&rsquo;s VPS, find your IP address in hPanel under <strong>VPS &rarr; Manage &rarr; Overview &rarr; VPS details<\/strong>.<\/p><div class=\"wp-block-image\"><figure data-wp-context='{\"imageId\":\"69e1e5bbcadd8\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"411\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2025\/05\/hpanel-vps-overview-ipv4-highlighted-1-1024x411.png\" alt=\"The IP address information in hPanel's VPS\" class=\"wp-image-129073\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>Log in using the username and password you set in the Compose file. If you use the default credentials, Grafana will prompt you to change your password on the next screen.<\/p><div class=\"wp-block-image\"><figure data-wp-context='{\"imageId\":\"69e1e5bbcc134\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"851\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2025\/05\/grafana-login-1024x851.png\" alt=\"The Grafana login page\" class=\"wp-image-129074\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>The dashboard interface has a left sidebar with navigation menus and a main workspace on the right where you view and manage dashboards.<\/p><p>If you set up the components via Docker Compose, Grafana automatically adds all data sources. To verify, go to <strong>Connections &rarr; Data sources<\/strong>.<\/p><div class=\"wp-block-image\"><figure data-wp-context='{\"imageId\":\"69e1e5bbccecf\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"415\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2025\/05\/grafana-connections-data-sources-1024x415.png\" alt=\"The Data sources menu in Grafana\" class=\"wp-image-129084\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>If you installed components manually, you must add data sources yourself. Hit <strong>Add new data source<\/strong>, search for the component name, and select it.<\/p><figure data-wp-context='{\"imageId\":\"69e1e5bbcdbb5\"}' data-wp-interactive=\"core\/image\" class=\"wp-block-image aligncenter size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"285\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2025\/05\/grafana-add-data-source-1024x285.png\" alt=\"The Add data source option in Grafana\n\" class=\"wp-image-129086\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><p>Then, fill in the <strong>URL<\/strong> field for each component as follows:<\/p><ul class=\"wp-block-list\">\n<li><strong>Loki<\/strong> &ndash; http:\/\/loki:3100<\/li>\n\n\n\n<li><strong>Mimir and Prometheus<\/strong> &ndash; http:\/\/prometheus:9090<\/li>\n\n\n\n<li><strong>Tempo<\/strong> &ndash; http:\/\/tempo:3200<\/li>\n<\/ul><div class=\"wp-block-image\"><figure data-wp-context='{\"imageId\":\"69e1e5bbceba4\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"468\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2025\/05\/grafana-loki-configuration-1024x468.png\" alt=\"The data source configuration page for Loki in Grafana\" class=\"wp-image-129087\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>After entering each data source, scroll down and click <strong>Save &amp; test<\/strong>.<\/p><h3 class=\"wp-block-heading\" id=\"h-8-explore-data-sources\"><strong>8. Explore data sources<\/strong><\/h3><p>Next, let&rsquo;s view your data by running queries. Each component uses its query language: <strong>LogQL<\/strong> for Loki, <strong>PromQL<\/strong> for Mimir and Prometheus, and <strong>TraceQL<\/strong> for Tempo.<\/p><p>From the dashboard&rsquo;s left sidebar, select <strong>Explore<\/strong>, then choose your preferred data source from the <strong>dropdown menu<\/strong> at the top.<\/p><p>For Loki and Prometheus, click the <strong>Code<\/strong> section. For Tempo, select <strong>TraceQL<\/strong>. Type your query and press <strong>Shift + Enter<\/strong> to run it.<\/p><figure data-wp-context='{\"imageId\":\"69e1e5bbcf937\"}' data-wp-interactive=\"core\/image\" class=\"wp-block-image aligncenter size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"425\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2025\/05\/grafana-explore-prometheus-code-highlighted-1024x425.png\" alt=\"The Explore section for Prometheus in Grafana\n\" class=\"wp-image-129089\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><p>Here are some basic query examples for each data source:<\/p><p><strong>Loki<\/strong><\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">{service_name= \"my-app\"}       # Show all logs for a specific service  \n{service_name=\"my-app\"} |= \"debug\"  # Show only debug logs<\/pre><p>Explore more queries in the<a href=\"https:\/\/grafana.com\/docs\/loki\/latest\/query\" target=\"_blank\" rel=\"noopener\"> LogQL official documentation<\/a>.<\/p><p><strong>Mimir and Prometheus<\/strong><\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">{service_name= \"my-app\"}       # Show all metrics for a specific service  \nprocess_cpu_usage{service_name=\"my-app\"}  # Show CPU usage<\/pre><p>Find advanced query examples in the<a href=\"https:\/\/prometheus.io\/docs\/prometheus\/latest\/querying\/basics\" target=\"_blank\" rel=\"noopener\"> PromQL documentation<\/a>.<\/p><p><strong>Tempo<\/strong><\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">{ resource.service.name = \"my-app\" &amp;&amp; status = error }         # Show error traces for a specific service  \n{ resource.service.name = \"my-app\" &amp;&amp; duration &gt; 500ms }      # Show traces with long durations<\/pre><p>Learn more about<a href=\"https:\/\/grafana.com\/docs\/tempo\/latest\/traceql\" target=\"_blank\" rel=\"noopener\"> basic and advanced TraceQL queries<\/a> on its documentation page.<\/p><h3 class=\"wp-block-heading\" id=\"h-9-create-a-unified-observability-dashboard\"><strong>9. Create a unified observability dashboard<\/strong><\/h3><p>Open the <strong>Dashboards<\/strong> menu in the left sidebar to visualize your metrics, logs, and traces in one comprehensive view.<\/p><p>If you set up the LGTM stack using Docker Compose, you already have a sample dashboard that provides a quick overview of memory usage and logs for apps instrumented with OpenTelemetry.<\/p><div class=\"wp-block-image\"><figure data-wp-context='{\"imageId\":\"69e1e5bbd078a\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"283\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2025\/05\/grafana-dashboards-1024x283.png\" alt=\"The Dashboards menu in Grafana\" class=\"wp-image-129091\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>You can also create a new dashboard by clicking <strong>New &rarr; New dashboard &rarr; Add visualization<\/strong>.<\/p><div class=\"wp-block-image\"><figure data-wp-context='{\"imageId\":\"69e1e5bbd1365\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"683\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2025\/05\/grafana-dashboard-add-visualization-highlighted-1024x683.png\" alt=\"The Add visualization button in Grafana's Dashboards menu\" class=\"wp-image-129092\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>Next, select a data source from your components. In the panel editor, rename the panel to reflect the component name, then type your query in the dedicated field to display the desired data.<\/p><div class=\"wp-block-image\"><figure data-wp-context='{\"imageId\":\"69e1e5bbd1fd1\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"694\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2025\/05\/grafana-panel-tempo-1024x694.png\" alt=\"The panel editor page for Tempo in Grafana\" class=\"wp-image-129093\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>Once done, click <strong>Back to dashboard &rarr; Add &rarr; Visualization<\/strong> and repeat this process to add panels for all components.<\/p><p>After adding panels, use the <strong>resize handle<\/strong> in the bottom-right corner of each panel to adjust its width and height. When you finish customizing, hit <strong>Save dashboard<\/strong> and give it a name to save your work.<\/p><div class=\"wp-block-image\"><figure data-wp-context='{\"imageId\":\"69e1e5bbd2d4a\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"678\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2025\/05\/grafana-dashboards-save-dashboard-highlighted-1024x678.png\" alt=\"The Save dashboard button in Grafana\" class=\"wp-image-129094\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><h3 class=\"wp-block-heading\" id=\"h-10-add-apps-to-the-observability-system\"><strong>10. Add apps to the observability system<\/strong><\/h3><p>In the previous step, you saw that the dashboard was empty because you had yet to add any apps to monitor.<\/p><p>There are several ways to do so. Since you set up the stack using Docker Compose, we&rsquo;ll guide you through adding the <strong>OpenTelemetry Collector<\/strong>.<\/p><p>It&rsquo;s a vendor-neutral agent that collects telemetry data from your apps and forwards it to the right components in a standardized way.<\/p><p>To set up OpenTelemetry Collector, open your terminal and navigate to the <strong>grafana-lgtm<\/strong> directory. Then, create a file named <strong>otel-collector-config.yaml <\/strong>using <strong>nano<\/strong>:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">cd grafana-lgtm\nsudo nano otel-collector-config.yaml<\/pre><p>Add the following configuration to the file. This setup receives data from your apps and routes it to the correct components:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">receivers:\n  otlp:\n    protocols:\n      http:\n        endpoint: 0.0.0.0:4318    # Listen on OTLP\/HTTP, port should match the Compose definition\n      grpc:\n        endpoint: 0.0.0.0:4317    # Listen on OTLP\/gRPC, optional\n\nprocessors:\n  batch: {}  # Batch processor, sends telemetry data in batches to improve performance\n\nexporters:\n  # Export metrics as a Prometheus scraping endpoint\n  prometheus:\n    endpoint: \"0.0.0.0:9464\"\n    # Enable conversion of Resource attributes to metric labels, ensuring service.name etc. appear in Prometheus labels\n    resource_to_telemetry_conversion:\n      enabled: true\n\n  # Export logs to Loki via OTLP HTTP (using Loki's native OTLP log receiver)\n  otlphttp\/loki:\n    endpoint: \"http:\/\/loki:3100\/loki\/api\/v1\/push\"  # Loki's OTLP log receiver HTTP API\n    # Loki receives OTLP logs using otlphttp exporter\n\n  # Export traces to Tempo via OTLP HTTP\n  otlphttp\/tempo:\n    endpoint: \"http:\/\/tempo:3200\/v1\/traces\"\n\n# Define processing pipelines for each type of telemetry data\nservice:\n  pipelines:\n    metrics:\n      receivers: [otlp]\n      processors: [batch]\n      exporters: [prometheus]        # Metrics are processed and exposed in Prometheus format\n    logs:\n      receivers: [otlp]\n      processors: [batch]\n      exporters: [otlphttp\/loki]     # Logs are processed and sent to Loki (OTLP HTTP)\n    traces:\n      receivers: [otlp]\n      processors: [batch]\n      exporters: [otlphttp\/tempo]     # Traces are processed and sent to Tempo (OTLP HTTP)<\/pre><div class=\"wp-block-image\"><figure data-wp-context='{\"imageId\":\"69e1e5bbd3c60\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"580\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2025\/05\/terminal-nano-otel-collector-config-yaml-1024x580.png\" alt=\"The OpenTelemetry Collector configuration file's content\" class=\"wp-image-129095\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>Next, edit your <strong>docker-compose.yml<\/strong> file and add the <strong>otel-collector<\/strong> service under the existing <strong>services<\/strong> section:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">  otel-collector:\n    image: otel\/opentelemetry-collector-contrib:latest\n    container_name: otel-collector\n    volumes:\n      - .\/otel-collector-config.yaml:\/etc\/otel-collector-config.yaml:ro\n    command: [\"--config\", \"\/etc\/otel-collector-config.yaml\"]\n    ports:\n      - \"4318:4318\"                   # OTLP HTTP\n      - \"9464:9464\"                   # Prometheus metrics\n    depends_on:\n      - prometheus\n      - loki\n      - tempo<\/pre><div class=\"wp-block-image\"><figure data-wp-context='{\"imageId\":\"69e1e5bbd4bfa\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"441\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2025\/05\/terminal-nano-docker-compose-yml-otel-collector-1024x441.png\" alt=\"The OpenTelemetry Collector service's content in the Docker Compose file\" class=\"wp-image-129096\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>After updating the Compose file, restart all services to apply the changes:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">docker compose down -v\ndocker compose up -d<\/pre><p>Next, configure your app to send telemetry data to the OpenTelemetry Collector. This depends on your app&rsquo;s language and framework. For example:<\/p><p><strong>Node.js-based apps<\/strong><\/p><p>Install the required OpenTelemetry packages:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">npm install @opentelemetry\/sdk-node @opentelemetry\/exporter-trace-otlp-http @opentelemetry\/exporter-metrics-otlp-http @opentelemetry\/exporter-logs-otlp-http<\/pre><p>Add this initialization code to your app:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">const { NodeSDK } = require('@opentelemetry\/sdk-node');\nconst { OTLPTraceExporter } = require('@opentelemetry\/exporter-trace-otlp-http');\nconst { OTLPMetricExporter } = require('@opentelemetry\/exporter-metrics-otlp-http');\nconst { OTLPLogExporter } = require('@opentelemetry\/exporter-logs-otlp-http');\nconst sdk = new NodeSDK({\ntraceExporter: new OTLPTraceExporter({\nurl: 'http:\/\/localhost:4318\/v1\/traces'\n}),\nmetricExporter: new OTLPMetricExporter({\nurl: 'http:\/\/localhost:4318\/v1\/metrics'\n}),\nlogExporter: new OTLPLogExporter({\nurl: 'http:\/\/localhost:4318\/v1\/logs'\n}),\nserviceName: 'my-nodejs-app'\n});\nsdk.start();<\/pre><p><strong>Java-based apps<\/strong><\/p><p>Download the OpenTelemetry Java agent:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">curl -L -o opentelemetry-javaagent.jar https:\/\/github.com\/open-telemetry\/opentelemetry-java-instrumentation\/releases\/latest\/download\/opentelemetry-javaagent.jar<\/pre><p>Run your app with the agent attached, replacing <strong>my-app<\/strong> with your service name:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">java -javaagent:opentelemetry-javaagent.jar \n\n-Dotel.exporter.otlp.endpoint=http:\/\/localhost:4318 \n\n-Dotel.resource.attributes=service.name=my-app \n\n-jar your-application.jar<\/pre><p>Return to your Grafana dashboard to see your app&rsquo;s telemetry data flowing in. This gives you real-time insights into its performance, logs, and traces.<\/p><h2 class=\"wp-block-heading\" id=\"h-conclusion\"><strong>Conclusion<\/strong><\/h2><p>The LGTM stack unifies logs, metrics, traces, and visualization in one place. This integration helps you monitor complex systems more effectively, troubleshoot issues faster, and gain actionable insights to optimize performance.<\/p><p>In this guide, we&rsquo;ve covered how to set up the LGTM stack on a VPS:<\/p><ol class=\"wp-block-list\">\n<li>Prepare your server environment.<\/li>\n\n\n\n<li>Install and configure Loki to collect logs.<\/li>\n\n\n\n<li>Set up Mimir to gather metrics.<\/li>\n\n\n\n<li>Deploy Tempo to trace distributed requests.<\/li>\n\n\n\n<li>Integrate Grafana for centralized visualization.<\/li>\n\n\n\n<li>Define services using Docker Compose.<\/li>\n\n\n\n<li>Log in to the Grafana dashboard.<\/li>\n\n\n\n<li>Query your data sources.<\/li>\n\n\n\n<li>Create a comprehensive observability dashboard.<\/li>\n\n\n\n<li>Connect your apps via OpenTelemetry Collector.<\/li>\n<\/ol><p>To expand your observability setup, try using LogQL, TraceQL, and PromQL for advanced queries. You can also add alerting rules to your dashboard to receive notifications when performance metrics or logs reach critical thresholds.<\/p><h2 class=\"wp-block-heading\" id=\"h-lgtm-stack-faq\"><strong>LGTM stack FAQ<\/strong><\/h2><div class=\"schema-faq wp-block-yoast-faq-block\"><div class=\"schema-faq-section\" id=\"faq-question-1748428600318\"><h3 class=\"schema-faq-question\"><strong>Why should I use the LGTM stack for observability?<\/strong><\/h3> <p class=\"schema-faq-answer\">The LGTM stack lets you visualize metrics, logs, and traces in a single platform. It simplifies monitoring, speeds up troubleshooting, and provides deeper insights to help you optimize system and app performance efficiently.<\/p> <\/div> <div class=\"schema-faq-section\" id=\"faq-question-1748428604585\"><h3 class=\"schema-faq-question\"><strong>Is the LGTM stack open-source?<\/strong><\/h3> <p class=\"schema-faq-answer\">Yes. The LGTM stack is fully open source. Its components &ndash; Loki, Grafana, Tempo, and Mimir &ndash; are maintained by Grafana Labs and the developer community, allowing free use, customization, and contribution.<\/p> <\/div> <div class=\"schema-faq-section\" id=\"faq-question-1748428631867\"><h3 class=\"schema-faq-question\"><strong>Can I integrate the LGTM stack with other tools?<\/strong><\/h3> <p class=\"schema-faq-answer\">Yes. You can integrate the LGTM stack with various <a href=\"\/ca\/tutorials\/best-observability-tools\">observability and monitoring tools<\/a>, like OpenTelemetry Collector, through standard protocols and exporters. This enables flexible data collection and visualization alongside your existing systems.<\/p> <\/div> <\/div>\n","protected":false},"excerpt":{"rendered":"<p>The LGTM stack &ndash; consisting of Loki for logs, Grafana for visualization, Tempo for tracing, and Mimir for metrics &ndash; is an open-source observability suite developed by Grafana Labs. This powerful stack unifies metrics, logs, and traces into a single platform, giving teams a complete view of system performance. In this guide, you&rsquo;ll set up [&#8230;]<\/p>\n<p><a class=\"btn btn-secondary understrap-read-more-link\" href=\"\/ca\/tutorials\/how-to-set-up-lgtm-stack\">Read More&#8230;<\/a><\/p>\n","protected":false},"author":411,"featured_media":139119,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"rank_math_title":"How to set up the LGTM stack for end-to-end observability","rank_math_description":"The LGTM stack (Loki, Grafana, Tempo, Mimir) provides complete observability for your system. Learn how to set it up in this article.","rank_math_focus_keyword":"lgtm stack","footnotes":""},"categories":[22703,22699],"tags":[],"class_list":["post-129055","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-managing-monitoring-and-security","category-vps"],"hreflangs":[{"locale":"en-US","link":"https:\/\/www.hostinger.com\/tutorials\/how-to-set-up-lgtm-stack","default":0},{"locale":"en-CA","link":"https:\/\/www.hostinger.com\/ca\/tutorials\/how-to-set-up-lgtm-stack","default":0},{"locale":"en-UK","link":"https:\/\/www.hostinger.com\/uk\/tutorials\/how-to-set-up-lgtm-stack","default":0},{"locale":"en-PH","link":"https:\/\/www.hostinger.com\/ph\/tutorials\/how-to-set-up-lgtm-stack","default":0},{"locale":"en-MY","link":"https:\/\/www.hostinger.com\/my\/tutorials\/how-to-set-up-lgtm-stack","default":0},{"locale":"en-IN","link":"https:\/\/www.hostinger.com\/in\/tutorials\/how-to-set-up-lgtm-stack","default":0},{"locale":"en-AU","link":"https:\/\/www.hostinger.com\/au\/tutorials\/how-to-set-up-lgtm-stack","default":0},{"locale":"en-NG","link":"https:\/\/www.hostinger.com\/ng\/tutorials\/how-to-set-up-lgtm-stack","default":0}],"_links":{"self":[{"href":"https:\/\/www.hostinger.com\/ca\/tutorials\/wp-json\/wp\/v2\/posts\/129055","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.hostinger.com\/ca\/tutorials\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.hostinger.com\/ca\/tutorials\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.hostinger.com\/ca\/tutorials\/wp-json\/wp\/v2\/users\/411"}],"replies":[{"embeddable":true,"href":"https:\/\/www.hostinger.com\/ca\/tutorials\/wp-json\/wp\/v2\/comments?post=129055"}],"version-history":[{"count":12,"href":"https:\/\/www.hostinger.com\/ca\/tutorials\/wp-json\/wp\/v2\/posts\/129055\/revisions"}],"predecessor-version":[{"id":137039,"href":"https:\/\/www.hostinger.com\/ca\/tutorials\/wp-json\/wp\/v2\/posts\/129055\/revisions\/137039"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.hostinger.com\/ca\/tutorials\/wp-json\/wp\/v2\/media\/139119"}],"wp:attachment":[{"href":"https:\/\/www.hostinger.com\/ca\/tutorials\/wp-json\/wp\/v2\/media?parent=129055"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.hostinger.com\/ca\/tutorials\/wp-json\/wp\/v2\/categories?post=129055"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.hostinger.com\/ca\/tutorials\/wp-json\/wp\/v2\/tags?post=129055"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}