ЁЯУИ рдзрдбрд╛ 11 тАФ Monitoring: dashboard рдЖрдгрд┐ stopwatch
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 11 ┬╖ рдорд╛рдЧреЗ: lesson-10-custom-domains ┬╖ рдкреБрдвреЗ: lesson-12-private-waf-limits
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбреЗ 01тАУ10, рдЖрдгрд┐ office рдЪреНрдпрд╛ рдЖрдд рдХрд╕реЗ рдкрд╛рд╣рд╛рдпрдЪреЗ: CloudWatch metrics
(Count, 4XXError, 5XXError, Latency, IntegrationLatency, CacheHitCount,
CacheMissCount), $context variables рдЕрд╕рд▓реЗрд▓реЗ access logs, рдЖрдгрд┐ X-Ray traces.
рдореБрдЦреНрдп рдХреМрд╢рд▓реНрдп: рд╡реЗрд│ рдХреБрдареЗ рдЬрд╛рддреЛ рддреЗ рд╢реЛрдзрдгреНрдпрд╛рд╕рд╛рдареА Latency рд╡рд┐рд░реБрджреНрдз IntegrationLatency рд╡рд╛рдЪрдгреЗ.
apigw/demo.py рдордзрд▓реЗ monitor() рд╕рд╣рд╛ requests рдкрд╛рдард╡рддреЗ рдЖрдгрд┐
dashboard рд╡ visitor book рдЫрд╛рдкрддреЗ.
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
Front office рдЪреНрдпрд╛ рднрд┐рдВрддреАрд╡рд░ рдПрдХ dashboard ЁЯУК рдЖрд╣реЗ: рдЖрдЬ рдХрд┐рддреА visitors рдЖрд▓реЗ, рдХрд┐рддреА рдЬрдгрд╛рдВрдирд╛ рддреНрдпрд╛рдВрдЪреНрдпрд╛рдЪ рдЪреБрдХреАрдореБрд│реЗ рдкрд░рдд рдкрд╛рдард╡рд▓реЗ (4XX), рдХрд┐рддреА рдЬрдгрд╛рдВрдЪреА kitchen рдореБрд│реЗ рдирд┐рд░рд╛рд╢рд╛ рдЭрд╛рд▓реА (5XX), рдХрд┐рддреА рдЙрддреНрддрд░реЗ рд╕реВрдЪрдирд╛ рдлрд▓рдХрд╛рд╡рд░реВрди рдЖрд▓реА.
Clerk рдХрдбреЗ рджреЛрди stopwatches тП▒я╕П рд╕реБрджреНрдзрд╛ рдЖрд╣реЗрдд. рдкрд╣рд┐рд▓реЗ visitor рдЖрдд рдЖрд▓реНрдпрд╛рд╡рд░ рд╕реБрд░реВ рд╣реЛрддреЗ
рдЖрдгрд┐ рддреЛ рдмрд╛рд╣реЗрд░ рдкрдбрд▓реНрдпрд╛рд╡рд░ рдерд╛рдВрдмрддреЗ тАФ рд╕рдВрдкреВрд░реНрдг рднреЗрдЯ (Latency). рджреБрд╕рд░реЗ рдлрдХреНрдд visitor
kitchen рдЪреА рд╡рд╛рдЯ рдкрд╛рд╣рдд рдЕрд╕рддрд╛рдирд╛рдЪ рдЪрд╛рд▓рддреЗ (IntegrationLatency).
рд╕рдВрдкреВрд░реНрдг рднреЗрдЯреАрд▓рд╛ 42 рд╕реЗрдХрдВрдж рд▓рд╛рдЧрд▓реЗ рдЖрдгрд┐ kitchen рд▓рд╛ 38, рддрд░ kitchen рд╕рд╛рд╡рдХрд╛рд╢ рдЖрд╣реЗ. рд╕рдВрдкреВрд░реНрдг рднреЗрдЯреАрд▓рд╛ 42 рд▓рд╛рдЧрд▓реЗ рдЖрдгрд┐ kitchen рд▓рд╛ 2, рддрд░ рд╕рдорд╕реНрдпрд╛ desk рд╡рд░ рдЖрд╣реЗ тАФ рдХрджрд╛рдЪрд┐рдд badge рддрдкрд╛рд╕рдгреА рд╕рд╛рд╡рдХрд╛рд╢ рдЖрд╣реЗ.
рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ рднреЗрдЯ рдореНрд╣рдгрдЬреЗ visitor book ЁЯУТ рдордзрд▓реА рдПрдХ рдУрд│ тАФ рдХреЛрдг, рдХреЗрд╡реНрд╣рд╛, рдХреЛрдгрддреЗ рджрд╛рд░, рдХрд╛рдп рдЙрддреНрддрд░, рдХрд┐рддреА рд╡реЗрд│.
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart LR
in["ЁЯЩЛ request in"] --> office["ЁЯЫОя╕П office work<br/>auth ┬╖ throttle ┬╖ mapping<br/>тЙИ 4 ms in the model"]
office --> kitchen["ЁЯН│ kitchen<br/>IntegrationLatency 38 ms"]
kitchen --> out["ЁЯУд answer out"]
lat["тП▒я╕П Latency = 42 ms<br/>whole trip"] -.-> in
lat -.-> out
out --> cw["ЁЯУК CloudWatch<br/>Count ┬╖ 4XXError ┬╖ 5XXError ┬╖ Cache*"]
out --> log["ЁЯУТ access log<br/>$context.requestId ┬╖ status ┬╖ latencies"]
ЁЯЧ║я╕П рдХрд╛рдврд▓реЗрд▓реА рдЖрдХреГрддреА + рдПрдХ lab: https://school-edh.pages.dev/apigateway/lesson-diagrams.html#l11
тЭУ рдХрд╛рдп
- CloudWatch metrics (REST APIs, namespace
AWS/ApiGateway, dimensionsApiNameрдЖрдгрд┐Stage, рд╣рд╡реЗ рдЕрд╕рд▓реНрдпрд╛рд╕ рдкреНрд░рддреНрдпреЗрдХ method рд╕рд╛рдареА):CountтАФ requests;4XXError/5XXErrorтАФ client errors / server errors (SumрдХрд┐рдВрд╡рд╛Averageрд╡рд╛рдкрд░рд╛);LatencyтАФ office рд▓рд╛ request рдорд┐рд│рд╛рд▓реНрдпрд╛ рдХреНрд╖рдгрд╛рдкрд╛рд╕реВрди рддреЗ рдЙрддреНрддрд░ рдкрд╛рдард╡реЗрдкрд░реНрдпрдВрдд;IntegrationLatencyтАФ рдлрдХреНрдд back end рдЪрд╛ рднрд╛рдЧ;CacheHitCount/CacheMissCountтАФ рд╕реВрдЪрдирд╛ рдлрд▓рдХ (рдзрдбрд╛ 08). HTTP APIs рдордзреНрдпреЗ рд▓рд╣рд╛рди рдЕрдХреНрд╖рд░рд╛рдВрддреАрд▓ рдирд╛рд╡рд╛рдВрдЪреЗ (4xx,5xx) рдЕрд╕реЗрдЪ metrics рдЕрд╕рддрд╛рдд, рдЖрдгрд┐ cache рдЪреЗ metrics рдирд╕рддрд╛рдд.
- Latency тИТ IntegrationLatency = office рдЪрд╛ рд╕реНрд╡рддрдГрдЪрд╛ рд╡реЗрд│ (authorizers, mapping, throttling). рдореЛрдареЗ рдЕрдВрддрд░ тЖТ authorizer рдкрд╛рд╣рд╛; рдЫреЛрдЯреЗ рдЕрдВрддрд░ тЖТ back end рдкрд╛рд╣рд╛.
- Access logs тАФ рдкреНрд░рддреНрдпреЗрдХ request рдЪреА CloudWatch Logs (рдХрд┐рдВрд╡рд╛ Firehose) рдордзреНрдпреЗ рдПрдХ рдУрд│, рддреБрдореНрд╣реА
$contextvariables рдиреЗ рдирд┐рд╡рдбрд▓реЗрд▓реНрдпрд╛ format рдордзреНрдпреЗ:$context.requestId,$context.status,$context.responseLatency,$context.integrationLatency,$context.identity.sourceIp,$context.authorizer.principalId,$context.error.message. - Execution logs (REST) тАФ office рдЪреНрдпрд╛ рд╕реНрд╡рддрдГрдЪреНрдпрд╛ рдкрд╛рдпрд░реА-рдкрд╛рдпрд░реАрдЪреНрдпрд╛ рдиреЛрдВрджреА (
ERRORрдХрд┐рдВрд╡рд╛INFOlevel). Debugging рдХрд░рддрд╛рдирд╛ рдЙрдкрдпреЛрдЧреА;prodрдордзреНрдпреЗ рд╕рдВрдкреВрд░реНрдг request bodies log рдХрд░реВ рдирдХрд╛. - X-Ray (REST stages) тАФ office, Lambda рдЖрдгрд┐ рдкреБрдврдЪреНрдпрд╛ AWS calls рдордзреВрди request рдЪрд╛ рдорд╛рдЧ рдХрд╛рдврддреЛ, рдЖрдгрд┐ рд╡реЗрд│реЗрд╕рд╣ рдорд╛рд░реНрдЧ рдХрд╛рдвреВрди рджрд╛рдЦрд╡рддреЛ.
ЁЯдФ рдХрд╛
рдХрд╛рд░рдг "API рд╕рд╛рд╡рдХрд╛рд╢ рдЖрд╣реЗ" рдХрд┐рдВрд╡рд╛ "users рдирд╛ errors рдпреЗрддрд╛рдд" рд╣реЗ рддреБрдореНрд╣реА рджреБрд░реБрд╕реНрдд рдХрд░реВ рд╢рдХрдд рдирд╛рд╣реА. рддреБрдореНрд╣рд╛рд▓рд╛
рдХреЛрдгрддрд╛ route, рдХреЛрдгрддрд╛ status рдЖрдгрд┐ рдкреНрд░рд╡рд╛рд╕рд╛рдЪрд╛ рдХреЛрдгрддрд╛ рднрд╛рдЧ рд╣реЗ рдорд╛рд╣реАрдд рдЕрд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ. рджреЛрди
latency metrics рдХрд╛рд╣реА рд╕реЗрдХрдВрджрд╛рдВрдд рд╕рд╛рдВрдЧрддрд╛рдд рдХреА back-end team рд▓рд╛ рдмреЛрд▓рд╡рд╛рдпрдЪреЗ рдХреА
authorizer рдкрд╛рд╣рд╛рдпрдЪрд╛. requestId рдЕрд╕рд▓реЗрд▓реЗ access logs user рдЪреА рддрдХреНрд░рд╛рд░ рдПрдХрд╛ рдиреЗрдордХреНрдпрд╛
request рд╢реА рдЬреЛрдбрддрд╛рдд.
ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)
apigw/gateway.py рдордзрд▓рд╛ Gateway.handle() gw.metrics рдордзреНрдпреЗ Count,
4XXError, 5XXError, CacheHitCount рдЖрдгрд┐ CacheMissCount рдореЛрдЬрддреЛ, рдЖрдгрд┐
рдкреНрд░рддреНрдпреЗрдХ request рд╕рд╛рдареА requestId, stage,
httpMethod, path, status, principal, latencyMs рдЖрдгрд┐ integrationLatencyMs рдЕрд╕рд▓реЗрд▓реА рдПрдХ access-log dict gw.logs рдордзреНрдпреЗ рдЬреЛрдбрддреЛ.
Kitchen рдЪрд╛ рд╡реЗрд│ рдореНрд╣рдгрдЬреЗ route рдЪреА latency (/students/{id} рд╕рд╛рдареА 38 ms; /report рд╕рд╛рдареА 31 s,
29 s timeout рд▓рд╛ рдХрд╛рдкрд▓рд╛ рдЬрд╛рддреЛ), рдЖрдгрд┐ model рд╕реНрд╡рддрдГрдЪреНрдпрд╛ рдХрд╛рдорд╛рд╕рд╛рдареА OFFICE_MS = 4 рдЬреЛрдбрддреЗ
тАФ рдореНрд╣рдгреВрди рдЗрдереЗ latencyMs - integrationLatencyMs рдиреЗрд╣рдореА 4 рдЕрд╕рддреЛ.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
python3 apigw/demo.py monitor
python3 - <<'EOF'
import sys; sys.path.insert(0, "apigw"); from demo import office, Clock
c = Clock(); gw, _ = office(c)
for p in ("/students/7", "/students/7", "/students/9", "/students/404", "/broken", "/report", "/teachers", "/files/a.pdf"):
gw.handle("GET", p)
m = gw.metrics
print(m)
print(f"4XX rate {m['4XXError'] / m['Count']:.0%} ┬╖ 5XX rate {m['5XXError'] / m['Count']:.0%}")
for l in gw.logs:
print(f"{l['requestId']} {l['path']:<14} {l['status']} Latency {l['latencyMs']:>5} ms Integration {l['integrationLatencyMs']:>5} ms office {l['latencyMs'] - l['integrationLatencyMs']} ms")
EOF
тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ
monitor рдЫрд╛рдкрддреЗ Count=6 ┬╖ 4XXError=2 ┬╖ 5XXError=2 ┬╖ CacheHitCount=1 ┬╖ CacheMissCount=2
рдЖрдгрд┐ рд╕рд╣рд╛ log рдУрд│реА, рдЙрджрд╛.
{'requestId': 'req-0001', 'stage': 'prod', 'httpMethod': 'GET', 'path': '/students/7', 'status': 200, 'principal': None, 'latencyMs': 42, 'integrationLatencyMs': 38}
рдЖрдгрд┐, рд╕рд╛рд╡рдХрд╛рд╢ report рд╕рд╛рдареА,
{'requestId': 'req-0005', тАж, 'path': '/report', 'status': 504, тАж, 'latencyMs': 29004, 'integrationLatencyMs': 29000}.
рддреБрдордЪрд╛ snippet рдЫрд╛рдкрддреЛ
{'Count': 8, '4XXError': 2, '5XXError': 2, 'CacheHitCount': 1, 'CacheMissCount': 3},
4XX rate 25% ┬╖ 5XX rate 25%, рдЖрдгрд┐ рдПрдХ table:
req-0001 /students/7 200 Latency 42 ms Integration 38 ms office 4 ms
req-0002 /students/7 200 Latency 4 ms Integration 0 ms office 4 ms
req-0003 /students/9 200 Latency 42 ms Integration 38 ms office 4 ms
req-0004 /students/404 404 Latency 42 ms Integration 38 ms office 4 ms
req-0005 /broken 502 Latency 4 ms Integration 0 ms office 4 ms
req-0006 /report 504 Latency 29004 ms Integration 29000 ms office 4 ms
req-0007 /teachers 404 Latency 4 ms Integration 0 ms office 4 ms
req-0008 /files/a.pdf 200 Latency 4 ms Integration 0 ms office 4 ms
Cache hit (req-0002) рд▓рд╛ kitchen рдЪрд╛ рд╡реЗрд│ рдЕрдЬрд┐рдмрд╛рдд рд▓рд╛рдЧрд▓рд╛ рдирд╛рд╣реА; 504 рдиреЗ 29 s kitchen рдордзреНрдпреЗ рдШрд╛рд▓рд╡рд▓реЗ.
ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ
рджреЛрди рдЖрдХрдбреНрдпрд╛рдВрд╡рд░реВрди рддреБрдореНрд╣реА рд╡реЗрд│ рдХреБрдареЗ рдЧреЗрд▓рд╛ рддреЗ рд╕рд╛рдВрдЧреВ рд╢рдХрддрд╛, рдЖрдгрд┐ log рдУрд│реАрд╡рд░реВрди user рдЬреНрдпрд╛ рдПрдХрд╛
request рдмрджреНрджрд▓ рддрдХреНрд░рд╛рд░ рдХрд░рддреЛ рддреА рд╢реЛрдзреВ рд╢рдХрддрд╛ тАФ рддрд┐рдЪреНрдпрд╛ requestId рдиреЗ.
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
- рдлрдХреНрдд
Averagelatency рд╡рд░ alarm тАФ рдПрдХ рд╕рд╛рд╡рдХрд╛рд╢ route рдЕрдиреЗрдХ рдЬрд▓рдж routes рдорд╛рдЧреЗ рд▓рдкрддреЛ;p99рд╡рд╛рдкрд░рд╛ 4XXErrorрдореНрд╣рдгрдЬреЗ "рдЖрдордЪрд╛ bug" рдЕрд╕реЗ рд╡рд╛рдЪрдгреЗ тАФ рддреЗ рдмрд╣реБрддреЗрдХ callers рдЪреЗ рдЕрд╕рддрд╛рдд (401, 403, 429); access log рдордзреНрдпреЗ status рдиреБрд╕рд╛рд░ рд╡реЗрдЧрд│реЗ рдХрд░рд╛- access logs рдЕрдЬрд┐рдмрд╛рдд рдирд╕рдгреЗ, рддреНрдпрд╛рдореБрд│реЗ рддрдХреНрд░рд╛рд░ рдХреЛрдгрддреНрдпрд╛рд╣реА request рд╢реА рдЬреБрд│рд╡рддрд╛ рдпреЗрдд рдирд╛рд╣реА
prodрдордзреНрдпреЗ рд╕рдВрдкреВрд░реНрдг request data рд╕рд╣INFOlevel рд╡рд░ execution logs тАФ рдЦрд░реНрдЪ, рдЖрдгрд┐ logs рдордзреНрдпреЗ рд╡реИрдпрдХреНрддрд┐рдХ data
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд
рдЦрд▒реНрдпрд╛ account рд╡рд░ тАФ JSON рдордзреНрдпреЗ access logs рдЖрдгрд┐ X-Ray рдЪрд╛рд▓реВ (Terraform), рдЖрдгрд┐
5XXError рд╡рд░ alarm (CLI):
resource "aws_api_gateway_stage" "prod" {
rest_api_id = aws_api_gateway_rest_api.school.id
deployment_id = aws_api_gateway_deployment.school.id
stage_name = "prod"
xray_tracing_enabled = true
access_log_settings {
destination_arn = aws_cloudwatch_log_group.school_api_access.arn
format = jsonencode({
requestId = "$context.requestId"
ip = "$context.identity.sourceIp"
method = "$context.httpMethod"
path = "$context.resourcePath"
status = "$context.status"
latency = "$context.responseLatency"
integrationLatency = "$context.integrationLatency"
principal = "$context.authorizer.principalId"
})
}
}
aws cloudwatch put-metric-alarm --alarm-name school-api-prod-5xx \
--namespace AWS/ApiGateway --metric-name 5XXError \
--dimensions Name=ApiName,Value=school-api Name=Stage,Value=prod \
--statistic Sum --period 60 --evaluation-periods 3 --threshold 5 \
--comparison-operator GreaterThanOrEqualToThreshold \
--alarm-actions arn:aws:sns:ap-south-1:111122223333:on-call
рдЧреЗрд▓реНрдпрд╛ рддрд╛рд╕рд╛рд╕рд╛рдареА рджреЛрдиреНрд╣реА stopwatches рдЪреА рддреБрд▓рдирд╛ рдХрд░рд╛:
for m in Latency IntegrationLatency; do
aws cloudwatch get-metric-statistics --namespace AWS/ApiGateway --metric-name $m \
--dimensions Name=ApiName,Value=school-api Name=Stage,Value=prod \
--start-time $(date -u -v-1H +%FT%TZ) --end-time $(date -u +%FT%TZ) \
--period 3600 --extended-statistics p99
done
(date -v-1H рд╣реЗ macOS рдЪреЗ рдЖрд╣реЗ; Linux рд╡рд░ date -u -d '-1 hour' +%FT%TZ рд╡рд╛рдкрд░рд╛.)
ЁЯПн Production рдордзреНрдпреЗ рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ рдЖрд╣реЗ: рд╕рд╛рдзреНрдпрд╛ API dashboard рдордзреНрдпреЗ рдЪрд╛рд░ panels рдЕрд╕рддрд╛рдд тАФ requests, 4XX, 5XX, рдЖрдгрд┐ p99 IntegrationLatency рдЪреНрдпрд╛ рд╢реЗрдЬрд╛рд░реА p99 Latency тАФ рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ stage рд╕рд╛рдареА 5XX рд╡ latency рд╡рд░ alarms. рддреБрдореНрд╣реА рдкрд░рдд рджреЗрдд рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рдкреНрд░рддреНрдпреЗрдХ error message рдордзреНрдпреЗ
requestIdрдШрд╛рд▓рд╛.
тПня╕П рдкреБрдвреЗ
рддреБрдореНрд╣рд╛рд▓рд╛ рдЖрддрд╛ рд╕рдЧрд│реЗ рджрд┐рд╕рддреЗ. рд╢реЗрд╡рдЯрдЪрд╛ рдзрдбрд╛: рдХрдбрдХ рдорд░реНрдпрд╛рджрд╛ тАФ 29-second timeout, 10 MB limit, private APIs, WAF рдЖрдгрд┐ bill.
git checkout lesson-12-private-waf-limits