ASP.NET CORE 에서 AppMetrics 사용 시 어떻게 표시되는지 알아보기 위한 테스트
AppMetrics 는 제니퍼나 핀포인트같은 APM 은 아니고...
모니터링 할만한 데이터를 좀 더 쉽게 구하여 저장할 수 있도록 도와주는 라이브러리.
grafana, slack, influxdb, prometheus, elsticsearch, http, socket, console, appinsights, text file 로 연동 가능
(https://www.app-metrics.io/reporting/)
- 환경
AppMetrics 3.1.0 (https://www.app-metrics.io/)
InfluxDB 1.7.7
Grafana 6.2.5
.Net Core 2.2 - ASP.NET API 프로젝트 (https://yamoe.tistory.com/528)
# 참고.
AppMetrics 메뉴얼(https://www.app-metrics.io/) 및 Github 의 최신 샘플인 Sample.V2(https://github.com/AppMetrics/Samples.V2) 는
AppMetrics 2.0 기준으로 되어있어 3.1.0과 인터페이스 차이가 있으나 아직 문서가 없음.
- 구성
ASP.NET의 AppMetrics가 데이터들을 InfluxDB 에 저장해주고
Grafana가 InfluxDB를 조회하여 그래프를 그려줌
.NET(AppMetrics) ------> InfluxDB <------- Grafana
- 테스트한 ASP.NET Core API 소스
- InfluxDB 설치
-- 설치
다운로드 페이지 : https://portal.influxdata.com/downloads/
InfluxDB 1.7.7 windows 64bit 버전 다운로드 (https://dl.influxdata.com/influxdb/releases/influxdb-1.7.7_windows_amd64.zip)
C:\apm\influxdb 에 압축해제
-- 설정
C:\apm\influxdb\influxdb.conf
[meta]
dir = "C:\\apm\\influxdb\\meta"
[data]
dir = "C:\apm\\influxdb\\data"
wal-dir = "C:\apm\\influxdb\\wal"
-- 실행
C:\apm\influxdb>influxd -config ./influxdb.conf
-- 접속
C:\apm\influxdb>influx -host 127.0.0.1 -port 8086
Connected to http://localhost:8086 version 1.7.7
InfluxDB shell version: 1.7.7
>
// 주요 모듈
using App.Metrics;
using App.Metrics.AspNetCore;
using App.Metrics.AspNetCore.Health;
using App.Metrics.Formatters.InfluxDB;
using App.Metrics.Formatters.Json;
using App.Metrics.Filtering;
using App.Metrics.Health;
using App.Metrics.Reporting.InfluxDB;
.... 생략 ....
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
return WebHost.CreateDefaultBuilder(args)
.ConfigureHealthWithDefaults(
options =>
{
// Health 체크 설정
}
)
.ConfigureMetricsWithDefaults(
builder =>
{
builder.Report.ToInfluxDb(
options =>
{
// InfluxDB 관련 설정
}
);
}
)
.UseMetricsWebTracking() // metrics 수집
.UseHealth() // Enable Report Health
.UseMetricsEndpoints() // Metrics 관련 Endpoint 노출 : /metrics, /metrics-text, /env
.UseHealthEndpoints() // Health 관련 Endpoint 노출 : /health, /ping
.UseMetrics() // Enable Metrics
.... 생략 ....
}
}
}
using App.Metrics;
using App.Metrics.Histogram;
using App.Metrics.Timer;
namespace SampleProject
{
public class Registry
{
// influxdb 의 hist__hist1 테이블(measurement) 에 기록됨
public static HistogramOptions Hist1 = new HistogramOptions
{
Context = "hist",
Name = "hist1",
MeasurementUnit = Unit.Bytes
};
// influxdb 의 hist__hist2 테이블(measurement) 에 기록됨
public static HistogramOptions Hist2 = new HistogramOptions
{
Context = "hist",
Name = "hist2",
MeasurementUnit = Unit.Bytes
};
// influxdb 의 timer__timer1 테이블(measurement) 에 기록됨
public static TimerOptions Timer1 = new TimerOptions
{
Context = "Timer",
Name = "Timer1",
MeasurementUnit = Unit.Requests,
DurationUnit = TimeUnit.Milliseconds,
RateUnit = TimeUnit.Milliseconds
};
}
}
Registry.cs 의 metrics 사용하기 위해 endpoint 에 코드 삽입
namespace SampleProject.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
public static Random Rnd { get; } = new Random();
private readonly IMetrics _metrics;
public ValuesController(IMetrics metrics)
{
// DI(의존성 주입)
_metrics = metrics ?? throw new ArgumentNullException(nameof(metrics));
}
... 생략 ...
// GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
_metrics.Measure.Histogram.Update(Registry.Hist1, new MetricTags("key1", "value1"), Rnd.Next(1, 500));
_metrics.Measure.Histogram.Update(Registry.Hist2, new MetricTags("key2", "value2"), Rnd.Next(1, 500));
_metrics.Measure.Timer.Time(Registry.Timer1, Rnd.Next(1,100).ToString());
return "value";
}
... 생략 ...
- 자동생성된 Endpoint 확인
-- Health Endpoints
UseHealthEndpoints() 코드에 의해 /health, /ping 엔드포인트가 자동 생성됨.
--- http://localhost/ping 응답 결과
pong
--- http://localhost/health 응답 결과
{
// 코드상 추가한 커스텀 필드
"healthy": {
"DatabaseConnected": "Database Connection OK"
},
// 원본
"status": "Healthy"
}
-- Metrics Endpoints
.UseMetricsEndpoints() 코드에 의해 /metrics, /metrics-text, /env 엔드포인트가 자동 생성됨.
--- http://localhost/metrics 응답 결과
{
"timestamp":"2019-08-06T07:39:30.5193067Z",
"contexts":[
{
"context":"Application.HttpRequests",
"apdexScores":[
{
"name":"Apdex|server:DESKTOP-AA,app:SampleProject,env:development",
"frustrating":0,
"sampleSize":6,
"satisfied":6,
"score":1,
"tolerating":0,
"tags":{
"server":"DESKTOP-AA",
"app":"SampleProject",
"env":"development"
}
}
],
"counters":[
{
"name":"Active|server:DESKTOP-AA,app:SampleProject,env:development",
"unit":"Active Requests",
"count":1,
"items":[],
"tags":{
"server":"DESKTOP-AA",
"app":"SampleProject",
"env":"development"
}
}
],
"gauges":[ ],
"histograms":[ ],
"meters":[ ],
"timers":[
{
"name":"Transactions|server:DESKTOP-AA,app:SampleProject,env:development",
"unit":"req",
"activeSessions":2,
"count":6,
"durationUnit":"ms",
"histogram":{
"lastValue":44.2118,
"max":203.1857,
"mean":44.658915653236896,
"median":44.2118,
"min":0.36779999999999996,
"percentile75":44.2118,
"percentile95":51.0657,
"percentile98":203.1857,
"percentile99":203.1857,
"percentile999":203.1857,
"sampleSize":6,
"stdDev":35.03442755073794,
"sum":304.0806
},
"rate":{
"fifteenMinuteRate":29.25993514138139,
"fiveMinuteRate":19.342214039341584,
"meanRate":1.8059570115079762,
"oneMinuteRate":1.6505125267202088
},
"rateUnit":"min",
"tags":{
"server":"DESKTOP-AA",
"app":"SampleProject",
"env":"development"
}
}
]
},
{
"context":"Application",
"apdexScores":[ ],
"counters":[ ],
"gauges":[ ],
"histograms":[ ],
"meters":[ ],
"timers":[ ]
},
{
"context":"Application.Health",
"apdexScores":[ ],
"counters":[ ],
"gauges":[
{
"name":"Results|health_check_name:DatabaseConnected,server:DESKTOP-AA,app:SampleProject,env:development",
"unit":"items",
"value":1,
"tags":{
"health_check_name":"DatabaseConnected",
"server":"DESKTOP-AA",
"app":"SampleProject",
"env":"development"
}
},
{
"name":"Score|server:DESKTOP-AA,app:SampleProject,env:development",
"unit":"Health Score",
"value":1,
"tags":{
"server":"DESKTOP-AA",
"app":"SampleProject",
"env":"development"
}
}
],
"histograms":[ ],
"meters":[ ],
"timers":[ ]
},
{
"context":"appmetrics.internal",
"apdexScores":[ ],
"counters":[
{
"name":"report_success|server:DESKTOP-AA,app:SampleProject,env:development",
"unit":"items",
"count":1,
"items":[
{
"count":1,
"item":"App.Metrics.Reporting.InfluxDB.InfluxDbMetricsReporter",
"percent":100
}
],
"tags":{
"server":"DESKTOP-AA",
"app":"SampleProject",
"env":"development"
}
}
],
"gauges":[ ],
"histograms":[ ],
"meters":[ ],
"timers":[ ]
}
]
}
--- http://localhost/metrics-text 응답 결과
# TIMESTAMP: 637006741983695184
# MEASUREMENT: [Application.HttpRequests] Apdex
# TAGS:
server = DESKTOP-AA
app = SampleProject
env = development
mtype = apdex
unit = result
# FIELDS:
samples = 9
score = 1
satisfied = 9
tolerating = 0
frustrating = 0
--------------------------------------------------------------
# TIMESTAMP: 637006741983695184
# MEASUREMENT: [Application.HttpRequests] Active
# TAGS:
server = DESKTOP-AA
app = SampleProject
env = development
mtype = counter
unit = Active Requests
# FIELDS:
value = 1
--------------------------------------------------------------
# TIMESTAMP: 637006741983695184
# MEASUREMENT: [Application.HttpRequests] Transactions
# TAGS:
server = DESKTOP-AA
app = SampleProject
env = development
mtype = timer
unit = req
unit_dur = ms
unit_rate = min
# FIELDS:
count.meter = 9
rate1m = 1.04030877914232
rate5m = 9.37132333699066
rate15m = 22.8314473155257
rate.mean = 1.26407352957666
samples = 9
last = 9.378
count.hist = 9
sum = 314.9379
min = 0.3678
max = 203.1857
mean = 5.80460754651153
median = 9.378
stddev = 8.84548253284347
p999 = 51.0657
p99 = 44.2118
p98 = 9.378
p95 = 9.378
p75 = 9.378
--------------------------------------------------------------
# TIMESTAMP: 637006741983695184
# MEASUREMENT: [Application.Health] Results
# TAGS:
health_check_name = DatabaseConnected
server = DESKTOP-AA
app = SampleProject
env = development
mtype = gauge
unit = items
# FIELDS:
value = 1
--------------------------------------------------------------
# TIMESTAMP: 637006741983695184
# MEASUREMENT: [Application.Health] Score
# TAGS:
server = DESKTOP-AA
app = SampleProject
env = development
mtype = gauge
unit = Health Score
# FIELDS:
value = 1
--------------------------------------------------------------
# TIMESTAMP: 637006741983695184
# MEASUREMENT: [appmetrics.internal] report_success items
# TAGS:
server = DESKTOP-AA
app = SampleProject
env = development
item = App.Metrics.Reporting.InfluxDB.InfluxDbMetricsReporter
mtype = counter
unit = items
# FIELDS:
total = 0
percent = 0
--------------------------------------------------------------
# TIMESTAMP: 637006741983695184
# MEASUREMENT: [appmetrics.internal] report_success
# TAGS:
server = DESKTOP-AA
app = SampleProject
env = development
mtype = counter
unit = items
# FIELDS:
value = 0
--------------------------------------------------------------
--- http://localhost/env 응답 결과
Assembly Name = SampleProject
Assembly Version = 1.0.0.0
Framework Description = .NET Core 4.6.27817.03
Local Time = 2019-08-06T16:36:11.1830+09:00
Machine Name = DESKTOP-AA
OS Architecture = X64
OS Platform = WINDOWS
OS Version = Microsoft Windows 10.0.18362
Process Architecture = X64
- influxdb 저장되고 있는 데이터 확인
api 를 몇번 호출한 후 influxdb에 잘 저장되었는지 확인.
아래 주소를 3~4번씩 호출
http://localhost/api/values/asdf <--- 400 고의적 유발
influx cli 확인
C:\apm\influxdb>influx
Connected to http://localhost:8086 version 1.7.7
InfluxDB shell version: 1.7.7
> show databases
name: databases
name
----
_internal
AspDotNet
> use AspDotNet
Using database AspDotNet
> show measurements
name: measurements
name
----
application.health__results
application.health__score
application.httprequests__active
application.httprequests__apdex
application.httprequests__transactions
appmetrics.internal__report_success
appmetrics.internal__report_success__items
hist__hist1
hist__hist2
timer__timer1
> select * from "hist__hist1" order by time desc limit 3
name: hist__hist1
time app count.hist env key1 last max mean median min mtype p75 p95 p98 p99 p999 samples server stddev sum unit
---- --- ---------- --- ---- ---- --- ---- ------ --- ----- --- --- --- --- ---- ------- ------ ------ --- ----
1565079034481917300 SampleProject 1 development value1 328 328 328 328 328 histogram 328 328 328 328 328 1 DESKTOP-L0EG94H 0 328 B
1565079033465981300 SampleProject 1 development value1 328 328 328 328 328 histogram 328 328 328 328 328 1 DESKTOP-L0EG94H 0 328 B
1565079032459731300 SampleProject 1 development value1 328 328 328 328 328 histogram 328 328 328 328 328 1 DESKTOP-L0EG94H 0 328 B
> select * from "hist__hist2" order by time desc limit 3
name: hist__hist2
time app count.hist env key2 last max mean median min mtype p75 p95 p98 p99 p999 samples server stddev sum unit
---- --- ---------- --- ---- ---- --- ---- ------ --- ----- --- --- --- --- ---- ------- ------ ------ --- ----
1565079034481917300 SampleProject 1 development value2 149 149 149 149 149 histogram 149 149 149 149 149 1 DESKTOP-L0EG94H 0 149 B
1565079033465981300 SampleProject 1 development value2 149 149 149 149 149 histogram 149 149 149 149 149 1 DESKTOP-L0EG94H 0 149 B
1565079032459731300 SampleProject 1 development value2 149 149 149 149 149 histogram 149 149 149 149 149 1 DESKTOP-L0EG94H 0 149 B
> select * from "timer__timer1" order by time desc limit 3
name: timer__timer1
time app count.hist count.meter env last max mean median min mtype p75 p95 p98 p99 p999 rate.mean rate15m rate1m rate5m samples server stddev sum unit unit_dur unit_rate
---- --- ---------- ----------- --- ---- --- ---- ------ --- ----- --- --- --- --- ---- --------- ------- ------ ------ ------- ------ ------ --- ---- -------- ---------
1565079034481917300 SampleProject 1 1 development 20.9639 20.9639 20.9639 20.9639 20.9639 timer 20.9639 20.9639 20.9639 20.9639 20.9639 0.0000686206224211598 0.000197790077858784 0.000169296344978123 0.000193443220096401 1 DESKTOP-L0EG94H 0 20.9639 req ms ms
1565079033465981300 SampleProject 1 1 development 20.9639 20.9639 20.9639 20.9639 20.9639 timer 20.9639 20.9639 20.9639 20.9639 20.9639 0.0000737638277855976 0.000198891969600979 0.000184008882925865 0.000196694290764324 1 DESKTOP-L0EG94H 0 20.9639 req ms ms
1565079032459731300 SampleProject 1 1 development 20.9639 20.9639 20.9639 20.9639 20.9639 timer 20.9639 20.9639 20.9639 20.9639 20.9639 0.0000796773367448619 0.000198891969600979 0.000184008882925865 0.000196694290764324 1 DESKTOP-L0EG94H 0 20.9639 req ms ms
> select * from "application.httprequests__transactions" order by time desc limit 3
name: application.httprequests__transactions
time app count.hist count.meter env last max mean median min mtype p75 p95 p98 p99 p999 rate.mean rate15m rate1m rate5m samples server stddev sum unit unit_dur unit_rate
---- --- ---------- ----------- --- ---- --- ---- ------ --- ----- --- --- --- --- ---- --------- ------- ------ ------ ------- ------ ------ --- ---- -------- ---------
1565079034481917300 SampleProject 2 2 development 54.1359 161.4807 107.405764547511 54.1359 54.1359 timer 161.4807 161.4807 161.4807 161.4807 161.4807 7.76122503227651 23.7348093430541 20.3155613973747 23.2131864115681 2 DESKTOP-L0EG94H 53.6708904991289 215.6166 req ms min
1565079033465981300 SampleProject 2 2 development 54.1359 161.4807 107.405764547511 54.1359 54.1359 timer 161.4807 161.4807 161.4807 161.4807 161.4807 8.30717709017904 23.8670363521175 22.0810659511038 23.6033148917188 2 DESKTOP-L0EG94H 53.6708904991289 215.6166 req ms min
1565079032459731300 SampleProject 2 2 development 54.1359 161.4807 107.405764547511 54.1359 54.1359 timer 161.4807 161.4807 161.4807 161.4807 161.4807 8.92911727401431 23.8670363521175 22.0810659511038 23.6033148917188 2 DESKTOP-L0EG94H 53.6708904991289 215.6166 req ms min
>
- Grafana 설치
-- 다운로드
다운로드 페이지 : https://grafana.com/grafana/download?platform=windows
Grafana 6.2.5 windows 64 bit zip file 버전 다운로드 (https://dl.grafana.com/oss/release/grafana-6.2.5.windows-amd64.zip)
C:\apm\grafana 에 압축해제
-- 설정
C:\apm\grafana\conf 의 sample.ini 를 custom.ini 로 복사 후 원하는 설정 변경 (복사만하고 그냥 진행함)
-- 실행
C:\apm\grafana\bin>grafana-server
-- 접속
admin/admin
-- dashboard 참고
https://grafana.com/grafana/dashboards?search=app+metrics
https://grafana.com/grafana/dashboards/2125
- Grafana Dashboard 설치
OAuth2 는 사용하지 않으므로 Web Dashboard 만 설치 및 확인.
Web Dashboard : https://grafana.com/grafana/dashboards/2125
OAuth2 Dashboard : https://grafana.com/grafana/dashboards/2137
-- InfluxDB Data Source 생성
-- Web Dashboard 설치
-- 플러그인 설치 및 grafana 재시작
Web Dashboard 가 pie chart 를 사용하고 있어서 설치 함.
플러그인 설치
C:\apm\grafana\bin>grafana-cli plugins install grafana-piechart-panel
grafana 종료 후 재시작
C:\apm\grafana\bin>grafana-server
- Grafana Dashboard 확인
# 데이터가 별로 안나오는 상황은?
에러나 POST 등의 요청이 있어야 기록되기 때문에 호출된 적이 없으면 그래프가 안나올 수 있음.
아래 주소를 3~4번씩 호출 후 다시 확인
http://localhost/api/values/asdf <--- 400 고의적 유발
- 기타
* dotnet-architecture/PerformanceMonitor
https://github.com/dotnet-architecture/PerformanceMonitor
* microsoft/ApplicationInsights-aspnetcore
https://github.com/microsoft/ApplicationInsights-aspnetcore
* Prometheus With Aspnetcore
https://www.kimsereylam.com/dotnetcore/csharp/prometheus/2019/01/11/prometheus-with-aspnetcore.html
'C#' 카테고리의 다른 글
숫자 범위 추출 및 확장 (0) | 2021.11.03 |
---|---|
C# LZ4 (0) | 2021.10.20 |
dictionary 에 action 매핑시 instance method 호출 방법 (0) | 2021.10.16 |
[ASP.NET] .net core 2.2 singleton controller (0) | 2019.08.29 |
[asp.net] asp.net core 2.2 iis 게시 (0) | 2019.08.03 |
C# (0) | 2011.05.15 |
WPF (0) | 2011.05.08 |
C# 기초 (0) | 2010.12.19 |