# Elastic APM 基本介紹

### 本篇學習重點

* APM 的基本介紹與架構
* APM 所收集的資料模型
* APM 的應用場影

***

![17-Traces-APM-Overview](https://i.imgur.com/bBIZywf.png)

## 什麼是 Elastic APM (Application Performance Monitoring) ?

Elastic APM 是一個能讓你『即時』監控、觀察、分析應用程式及服務的工具，透過收集應用程式內元件之間溝通時的記錄，收集包含各種詳細與效能相關的資訊，例如以下的資訊：

* 前端使用者的即時行為資訊
* 前端對應用程式 API 的請求與回應
* 應用程式對內部服務 API 的請求與回應
* 內部服務對 Cache 的存取
* 內部服務對 Database 的存取
* 服務存取外部的第三方服務的請求與回應

除了效能相關的資訊之外，如果處理中有發生例外狀況的錯誤，甚至是程式錯誤發生時的 stacktrace 也都會被 APM 收集，另外也會順便收集某些有支援的系統或運作環境相關的 metrics，例如：JVM metrics, Go runtime metrics。

## Elastic APM 的基本架構

![17-apm-architecture-cloud](https://i.imgur.com/XxfxGWY.png)

Elastic APM 的基本架構如上圖共包含四個主要的元件：

* **APM Agents：** 提供各種語言實作的 Library，能協助開發人員加在應用程式之中，在應用程式執行的過程中負責收集各種效能相關的資訊或是錯誤的資訊，內含許多常用的 framework 或是 library 的整合，像是 cache 或 db 的存取 library，使用這些 library 時就不用額外自己開發要收集的資訊。
* **APM Server：** 以 libbeat 實作的 HTTP server，負責接收各個 APM Agents 所收集到的 APM 資訊，將這些資訊進行驗證及加工處理後，彙整並傳送給 Elasticsearch 進行 Indexing 及儲存。
* **Elasticsearch：** 負責 APM 資料的儲存，提供分析運算、資料生命週期的管理、資料備份等處理核心。
* **Kibana APM UI：** 讓存在 Elasticsearch 裡的 APM 資料能被快速的查閱、追縱、分析的 UI 工具。

## Elastic APM 的資料模型

Elastic APM 的資料，每一筆都會是一個事件 (event)，而這些事件總共有四種的類型：

* Transactions
* Spans
* Errors
* Metrics

除此之外，events 當中都可以在 APM Agent 端自行加上我們自己想收集的額外資訊，並定義在擴充的欄位當中。

以下分別對四種資料類型進行說明。

### Spans

Spans (跨度，可理解成片刻的一小段時間)，表示一個活動的開始到結束的記錄，也就是代表一段程式執行時發生的資訊，並且因為一連串執行與處理的過程中，一個 Span 可能也會與其他的 Span 有上、下層的關係，在 Span 裡面會記錄：

* `transaction.id`：屬於哪一個 Transaction。
* `parent.id`：如果是另個 Transaction 或是 Span 有上、下層關係時，會記錄他的上層。
* Span 的開始及結束時間。
* Span 的 `name`。
* `type`、`subtype`、`action`。
* 過程中有錯誤發生時會包含 `stacktrace` 的資訊。

### Transactions

Transactions (交易)，針對一個相對於 Span 更高層級的事件 (event) 的請求與回應，例如：發送一個外部的 Request、批次的作業處理、背景執行的工作、或是在程式執行中自行定義的一個處理行為…等，都可以是一個 Transaction，在一個 Transaction 之中，可以包含 0 到多個 Spans，Transaction 裡面會記錄：

* 事件發生的 `timestamp`。
* `unique id`、`type`、`name`。
* 事件發生的環境 (Environment) 相關的資訊，例如：
  * Service 的 `environment`、`framework`、`language`。
  * Host 的 `hostname`、`IP`。
  * Process 的 `pid`。
  * URL 的 `domain`、`port`、`query string`。
* 其他特定 APM Agent 所收集到的特定資訊。
* 使用者自行定義的 `labels` 或 `custom` 欄位的資訊。

### Errors

Errors (錯誤)，當 APM Agent 收到 Errors 的資訊時，會產生 Errors 這樣的 event，並且在裡面會記錄發生當時的 `exception` 資訊，或是 Error 發生當下的 `logs`，Error 裡面會記錄：

* 錯誤發生當時 `exception` 或 `error log` 所收集到的 `stacktrace` 資訊。
* `culprit` 記錄錯誤發生的地方。
* 與錯誤發生時相關的 Transaction 的 `transaction.id`。
* 事件發生的環境 (Environment) 相關的資訊，例如：
  * Service 的 `environment`、`framework`、`language`。
  * Host 的 `hostname`、`IP`。
  * Process 的 `pid`。
  * URL 的 `domain`、`port`、`query string`。
* 使用者自行定義的 `labels` 或 `custom` 欄位的資訊。

### Metrics

Metrics (指標)，APM Agent 會收集一些最基本的主機層級 (host-level) 的 metrics，例如：

* System metrics。
* Process 層級的 CPU 和 Memory metrics。
* JVM metrics。
* Go runtime metrics。

## APM 的運用場景

* 分散式追縱 (Distributed Tracing)：分散式追縱是維運微服務架構時不可缺少的重要工具，APM 透過定義 Trace，並在裡面包含了一組的 Transactions 及 Spans，用來代表一個特定的服務請求從到頭尾的過程，並且在跨服務之間透過在 Header 中加入 `trasc-id`、`span-id`、`parent-id`，來實現分散式追縱的功能，讓我們能透過 Kibana 能輕易的觀察一個橫跨多個服務的請求，過程中哪個環節的執行效能較慢、或是在發生錯誤時能快速的查看歷程中發生什麼樣的事。
* 真實使用者監控 (Real User Monitoring)：讓我們透過 Elastic's RUM Agent 收集前端使用者在 web 上的操作，幫助我們從真實的使用者情境，並且關注在使用者體驗來分析效能狀況、進行效能最佳化、或是更即時的發現系統存在的問題。
* 與 Elastic Observability 的整合，像是透過與先前介紹的 Logs 整合，在 Logs 寫入時也加入 APM event 的識別 ID，讓我們使用 APM 進行分析時，在追到某個需要深入探索的地方時，能輕易的接續到 Logs 的部份查閱事件發生上、下文的 Logs。

## 參考資料

1. [官方文件 - APM Overview](https://www.elastic.co/guide/en/apm/get-started/current/index.html)
