pkg/ui/README.md
Loki's UI system is designed to work seamlessly in a distributed environment. Select a node/deployment type to run the UI by including the ui target. This node will be the main entry point for the UI APIs, and can proxy requests to other nodes in the cluster.
The UI is served by a combination of a Grafan pluing and an API Layer hosted by the Loki node running the UI target. Note all Loki pods will join the UI ring, so that the UI node can proxy requests to them when necesary.
graph TB
LB[Reverse Proxy /ui/]
subgraph Cluster[Loki Cluster]
subgraph GrafanaNode[Grafana]
UI1[Loki Operational UI Plugin]
end
subgraph Node1[Node 1]
API1[API Server]
PROXY1[Proxy Handler]
end
subgraph Node2[Node 2]
API2[API Server]
PROXY2[Proxy Handler]
end
subgraph Node3[Node 3]
API3[API Server]
PROXY3[Proxy Handler]
end
end
GrafanaNode --> LB
LB --> Node1
LB --> Node2
LB --> Node3
All endpoints are prefixed with /ui/
GET /ui/api/v1/cluster/nodes
GET /ui/api/v1/cluster/nodes/{nodename}/details
GET /ui/api/v1/proxy/{nodename}/*
GET /ui/api/v1/analytics
/ui/api/v1/cluster/nodesGrafana->Node 1: GET /ui/api/v1/cluster/nodes
Node 1->Node 2: Fetch status
Node 1->Node 3: Fetch status
Node 2-->Node 1: Status response
Node 3-->Node 1: Status response
Node 1-->Browser: Combined cluster state
/ui/api/v1/proxy/{nodename}/servicesGrafana->Node 1: GET /ui/api/v1/proxy/node2/services
Node 1->Node 2: Proxy request
Node 2-->Node 1: Service data
Node 1-->Browser: Proxied response
The UI service can be enabled by setting ui.enabled to true in the Loki config file.
ui:
enabled: <bool> # Enable the UI service
This will enable the UI ring, and allow the UI target to serve the API. Every node must have this configured to join the ring so the API can communicate with the whole cluster, while only one node needs the specify the ui target. Please note enabling the UI ring via this config does not start the UI target, that must be specified separately.
/ui/ prefix allows easy reverse proxy configurationThe Ring UI is a critical component for understanding the state of Loki's distributed hash ring. Here's how it works when accessed through a querier node. Since each ingester maintains the complete ring state, querying a single ingester is sufficient to view the entire ring:
sequenceDiagram
participant Grafana
participant Querier Node
participant Ingester
Grafana->>Querier Node: GET /ui/api/v1/cluster/nodes
Querier Node-->>Grafana: List of available nodes
Note over Grafana,Querier Node: User clicks on Ring view
Grafana->>Querier Node: GET /ui/api/v1/proxy/querier-1/ring
Note over Querier Node: Querier fetches ring state
Querier Node->>Ingester: Get ring status
Ingester-->>Querier Node: Complete ring state
Querier Node-->>Grafana: Ring state
Initial UI Load
GET /ui/api/v1/cluster/nodes
Ring State Request
GET /ui/api/v1/proxy/querier-1/ring
Ring Data Structure
{
"tokens": [
{
"token": "123456",
"ingester": "ingester-1",
"state": "ACTIVE",
"timestamp": "2024-02-04T12:00:00Z"
},
// ... more tokens
],
"ingesters": {
"ingester-1": {
"state": "ACTIVE",
"tokens": ["123456", "789012"],
"address": "ingester-1:3100",
"last_heartbeat": "2024-02-04T12:00:00Z"
}
// ... more ingesters
}
}