---
# System prepended metadata

title: Spring Actuator 學習
tags: [Grafana, Actuator, Prometheus, SpringBoot]

---

# Actuator

* 默認**啟動**

## 端點(endpoint)

* management.endpoints.web.base-path：Actuator 端點在 Web 介面（HTTP）下的「根路徑」
    * 默認：`/actuator`
* management.endpoints.access.default：是否啟用暴露端點
    * 默認：true
    * 最底層的設定(（保底設定)
    * 3.4.0 取代 `management.endpoints.enabled-by-default`
* management.endpoints.endpoint.\<id>.access：針對某個端點的**存取**進行設定
    * id：端點
    * 值：
        * none：無法**存取**
        * read-only：預設只允許查看資訊（`@ReadOperation`），禁止修改
        * full：預設允許所有操作（讀取、寫入、刪除）
* management.endpoints.jmx.exposure.include：決定哪些監控端點（Endpoints）可以透過 JMX 協定被外部存取
* management.endpoints.web.exposure.include：決定哪些監控端點（Endpoints）可以透過 HTTP/REST 協定被外部存取
    * 值：
        * \*號：暴露所有端點
        * 默認：health和info

## health 端點

* 需多組件都有訂製health的子節點指標：
    * redis
    * jdbc
* management.endpoint.health.show-details：顯示health的**詳細指標**配置
    * 值：
        * never：不顯示**詳細指標**
        * when_authorized：需要通過授權時，可以顯示**詳細指標**
        * always：都會顯示**詳細指標**

## conditions 端點

* 顯示 `@Conditional` 註解的指標

## env 端點

* 顯示
    * JVM 系統屬性
    * 作業系統環境變數
    * 應用程式配置：
        * application.properties
        * application.yml
        * Spring Cloud Config
    * 命令列參數
    * Servlet 環境資訊

## loggers 端點

* 要在Actuator查看日誌，log需要儲存在檔案中，需要設定logfileName

## heapdump 端點

* **生成**並**下載**當前 JVM 的堆積記憶體快照（`Heap Dump`）文件

## metrics 端點

* 指標信息
* 具體的量化數據
    * 例如：記憶體用了多少、CPU 負載、HTTP 請求處理了幾毫秒
* **核心類**：**MetricsProperties**

### 配置

* 將應用程式名稱綁定到所有指標的 application 標籤上(`重要`)
    * `management.metrics.tags.application=${spring.application.name}`
    * 沒有會缺少`application`標籤
* `management.metrics.enable`：各 Metrics 開啟，默認開啟
    * `r2dbc`：management.metrics.enable.r2dbc
* **關閉某些的Metrics**
    * **關閉 r2dbc.pool的Metrics**：`management.metrics.enable.r2dbc.pool=false`

## mappings 端點

* 路徑映射信息

## shutdown 端點

* 對應設定`server.shutdown`
    * 值：
        * graceful：默認，優雅關閉
        * immediate：立即關閉

# Micrometer

* 一個應用指標的門面
* 支持多種監控系統
* 開箱及用：
    * 提供一系列API
    * 提供緩存、類加載器、GC、jvm內存、cpu利用率、線程的指標信息(由actuator整合至SpringBoot中)
* SpringBoot 建議注入 **MeterRegistry**

```java
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;

public void t() {
    Gauge.builder(GAUGE_ROOM_ACTIVE, this, (chatRoomManager) -> chatRoomManager.getActiveRoomIds().size())
            .description("Total active chat rooms")
            .register(meterRegistry);
}
```

## 查看某個tag

* tag：`Tags.of("userName", "root1")`
    * key：userName
    * value：root1
    * **查詢語法**：`tag=key:value`
        * http://localhost:8809/pulse-chat/actuator/metrics/login.count?tag=userName:root1
    * **多個tag**：`tag=userName:root1&tag=status:success`

## 計數器 - counter

* 用於增長類型的統計：
    * 下單、支付次數、請求統計
* Metric.counter()
    * 指標名稱
    * tag
        * 空tag：Tags.empty()
* 自增
* ：`.increment()`
    * Metric.counter("chat.room",Tags.empty()).increment()

## 紀錄執行時間 - Timer

* 紀錄指定方法、任務(`MQ處裡`、`數據查詢`)的**執行時間**
* 建立Timer：
    * Timer timer = Metrics.timer("login.time");

## 獲取當前紀錄值 - Gauge

* 作用是顯示一個 **「瞬時的數值」**
    * 可增可減，不累積
* 建立：
    * Metrics.gauge("A",1)
        * 單值

## 摘要 - Summary

* 跟縱事件的分布
    * 使用方式類似Timer
    * 紀錄不依賴時間單位的紀錄值的測量
    * 例：百分比數值
        * CPU有效負載值
        * 緩存命中率
* 建立：
    * `DistributionSummary distributionSummary = Metrics.summary("AA", Tags.empty());`
* 使用：紀錄Double
    * distributionSummary.record(1.5);

# R2dbc 指標

* 開啟指標：
    * `management.metrics.enable.r2dbc=true`
        * **默認開啟**
* PoolMetrics：R2dbc 指標

## 指標

### 連線

| 指標                   | 說明                               | prometheus                       |
|----------------------|----------------------------------|----------------------------------|
| r2dbc.pool.acquired  | 已取得連線                            | r2dbc_pool_acquired_connections  |
| r2dbc.pool.idle      | 閒置連線                             | r2dbc_pool_idle_connections      |
| r2dbc.pool.allocated | 連線池內所有連線的總和(`acquired` + `idle`) | r2dbc_pool_allocated_connections |

### 排隊與等待 (效能瓶頸指標)

| 指標                     | 說明                                | prometheus                         |
|------------------------|-----------------------------------|------------------------------------|
| r2dbc.pool.pending     | 等待中的請求                            | r2dbc_pool_pending_connections     |
| r2dbc.pool.max.pending | 最大等待上限(無法修改，為`Integer.MAX_VALUE`) | r2dbc_pool_max_pending_connections |

### 配置上限

* `r2dbc.pool.max.allocated`：**最大允許分配數**
    * 對應配置中的 `maxSize`
    * 用來計算**連線池使用率**
    * **prometheus**：`r2dbc_pool_max_allocated_connections`

## 使用

| 監控需求       | 推薦公式 (PromQL)                                          |
|------------|--------------------------------------------------------|
| 連線池使用率 (%) | (r2dbc_pool_acquired / r2dbc_pool_max_allocated) * 100 |
| 是否有人在排隊？   | r2dbc_pool_pending > 0 (應設定告警)                         |
| 連線浪費情況     | r2dbc_pool_idle                                        |

## AI 建議

### 關鍵狀態看板 - Table

* 現在的健康程度
* 使用率 (%)：
    * 公式：(r2dbc_pool_acquired / r2dbc_pool_max_allocated) * 100
    * 呈現：使用 `Gauge` 或 `Stat`。設定閾值（Thresholds），例如 80% 變橘色，95% 變紅色。
* 等待隊伍 (Pending)：
    * 公式：`r2dbc_pool_pending`
    * 呈現：使用 `Stat`。如果`值 > 0`，背景直接變紅色閃爍，這代表使用者正在排隊，系統效能已受損

### 動態趨勢圖 - Time Series Chart

* 將四個核心指標放在同一個線圖中，觀察隨時間變化的連線行為
* 使用 Time series 圖表
* 建議組合：
    * acquired (實線) - 實際負載。
    * allocated (點線) - 池子目前大小。
    * max.allocated (紅虛線) - 這是你的「天花板」，用來對比剩餘空間。
    * idle (淺色線) - 觀察是否有過多資源被閒置。

# Grafana

## DashBord Setting - Variables

### application

* Variable type

### General

* name：變數名
    * Panel 語法裡要用的代號(寫成 `$application`)
* Label：Dashboard 頂端選單顯示給你看的名字
* Description：說明
* Hide：
    * Nothing
    * Variable
    * Label

### Query options - prometheus

* Data source：選擇數據源
    * prometheus
* Query Type：查詢類型
    * **選項**：**prometheus 的 Query Type**
        * **Label values**：列出 Prometheus 裡某個（Label）裡所有出現過的值
            * **選單中的數據**：列出 Prometheus 裡所有的**標籤**（`Label`）
            * 例：**選job標籤**
                * 下面的query result就會列出該job標籤中所有出現過的值
        * **Label names**：列出 Prometheus 裡所有的**標籤**（`Label`）
        * Metrics：列出 Prometheus 裡所有的「指標名稱」
            * 當你想做一個可以切換「我要看連線數」還是「看記憶體」的選單
        * Query result：
            * 用途：當你想「過濾掉沒用的選項」時
        * Series query：找**標籤**(`Label`)組合
            * 用途：非常少用，通常用於底層排錯。
        * Classic query：舊版模式

#### Query Type - Label values

* Label：標籤名稱
* Metric：指標名稱
* Label filters：過濾Label values

#### Query Type - Label names

* Metric regex：正則過濾Label清單

#### Query Type - Metrics

* Metric regex：正則過濾Metric清單

#### Query Type - Query result

* Query：填入prometheus Query

#### Query Type - Series query

* Series query：填入Series query

#### Query Type - Classic query

* Classic query：填入Classic query

# Prometheus

* 關聯式資料庫 vs. Prometheus 的映射關係
    * Metric：Table name
    * Label(`標籤`)：Columns

## Metric

* **Metric 永遠帶著 標籤(Labels) 一起出現**
    * 例：chatroom_rooms_active
        * `{__name__="chatroom_rooms_active", application="pulse-chat", instance="pulse-chat:8080", job="pulse-chat"}`
            * `__name__`：指標叫什麼
            * `job`：這個任務叫什麼？
                * 這是 Prometheus 任務名稱，在 `prometheus.yml` 設定檔中定義
                * 代表這筆數據屬於哪一組抓取規則
            * `instance`：具體執行實例，網路位址
                * 這筆數據是從哪一台機器（IP:Port）抓出來的
            * `application`：這個服務在業務邏輯上的名字
                * 這是你在 Spring Boot 裡透過 `management.metrics.tags.application` 定義的 自定義欄位
        * 通常 `job` 和 `application` 的值會`一樣`，但 job 主要是給 Prometheus 系統管理用的，而 application 則是給 Grafana
          看板使用者看的
        * 總結：
          |屬性名稱|角色|來源|為什麼重要？|
          |---|---|---|---|
          |`__name__`|指標名稱|程式代碼定義|決定你要看「哪種」數據（如 CPU、內存、聊天室數）|
          |  `application`        |   業務維度 |  `application.properties`    | 決定你是看「哪個專案」                         |
          |  `instance`        | 物理維度   |  網路位址 (IP:Port)    |  決定你是看「哪台機器」                        |
          | `job`         |  系統維度  |Prometheus 設定      | 決定這筆資料是由哪個監控任務抓回來的。                         |
