Spring Boot Prometheus Advanced Monitoring Sinhala | Custom Metrics & Alerts
ආයුබෝවන් යාළුවනේ!
අද අපි කතා කරන්න යන්නේ මොකක්ද? අපේ Spring Boot applications නිතරම හොඳට වැඩ කරනවද කියලා බලාගන්න, ඒ වගේම ප්රශ්නයක් ආවොත් ඉක්මනටම දැනගන්න පුළුවන් විදිහට, Prometheus කියන powerful monitoring tool එක Spring Boot එක්ක advanced විදිහට පාවිච්චි කරන හැටි ගැනයි. Custom Metrics හදලා අපිට ඕන දේවල් මනින හැටි, ඒ වගේම ඒ metrics මත පදනම් වෙලා Custom Alerts හදන හැටි ගැන අපි මේ tutorial එකෙන් ගැඹුරින් බලමු.
සාමාන්යයෙන් Spring Boot Actuator එක්ක එන default metrics හොඳටම ප්රමාණවත් වුණත්, අපේ application එකේ business logic එකටම ආවේණික දේවල් measure කරන්න අපිට custom metrics ඕන වෙනවා. ඒ වගේම, ඒ metrics හරහා යම්කිසි තත්ත්වයක් ඇති වුණොත් (උදා: error rate එක වැඩි වුණොත්) අපිට automate කරලා alert එකක් එවන්න පුළුවන් නම්, ඒක අපේ system reliability එකට ලොකු රුකුලක්.
ඉතින්, Spring Boot applications දියුණු කරන ඔයාලාට මේක ගොඩක් වැදගත් වෙයි කියලා මම හිතනවා. එහෙනම්, අපි පටන් ගමුද?
Prometheus කියන්නේ මොකක්ද? පොඩි හැඳින්වීමක්
ගොඩක් අය දන්නවා ඇති, Prometheus කියන්නේ open-source monitoring system එකක්. මේකෙන් කරන්නේ අපේ applications වලින් එන metrics (සංඛ්යාත්මක දත්ත) එකතු කරලා, ඒවා ගබඩා කරලා, අපිට ඒ දත්ත visualize කරන්න (Grafana වගේ tools එක්ක) සහ alert කරන්න අවස්ථාව සලසන එකයි. Prometheus “pull model” එකක් පාවිච්චි කරන්නේ, ඒ කියන්නේ Prometheus server එක විසින් applications වල තියෙන metric endpoints වලට request කරලා දත්ත ලබා ගන්නවා.
Spring Boot වලදී, අපි Spring Boot Actuator සහ Micrometer කියන libraries පාවිච්චි කරලා Prometheus එක්ක integrate වෙනවා. Actuator වලින් අපිට default metrics ගොඩක් ලැබෙනවා, Micrometer වලින් අපිට custom metrics හදන්න පුළුවන්.
Spring Boot සහ Prometheus - මූලික Set Up එක
Advanced දේවල් වලට යන්න කලින්, පොඩ්ඩක් මතක් කරගමු සාමාන්යයෙන් Spring Boot application එකක් Prometheus එක්ක වැඩ කරන්න නම් මොනවද කරන්න ඕන කියලා.
මුලින්ම, අපේ pom.xml එකට මේ dependencies ටික එකතු කරන්න ඕන:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<scope>runtime</scope>
</dependency>
ඊට පස්සේ, application.properties (or application.yml) එකේ Actuator endpoints ටික enable කරන්න ඕන. විශේෂයෙන්ම /actuator/prometheus endpoint එක.
management.endpoints.web.exposure.include=health,info,prometheus
මෙහෙම කරාම, අපේ Spring Boot application එක http://localhost:8080/actuator/prometheus කියන URL එකෙන් Prometheus format එකට metrics expose කරනවා. Prometheus server එකට පුළුවන් මේ endpoint එක scrape කරලා metrics එකතු කරන්න.
Custom Metrics හදමු! (Let's Create Custom Metrics!)
දැන් අපි යමු වැඩේට. Micrometer කියන්නේ vendor-neutral metrics facade එකක්. ඒකෙන් අපිට Counter, Gauge, Timer, DistributionSummary වගේ metric types පාවිච්චි කරලා අපේ application එකට අදාළ custom metrics හදන්න පුළුවන්. මේවා පාවිච්චි කරන්න MeterRegistry එක අපිට ඕන වෙනවා.
1. Counter: සිදුවීම් ගණනය කරන්න
Counter එකක් පාවිච්චි කරන්නේ යම්කිසි සිදුවීමක් කොපමණ වාර ගණනක් සිදුවී ඇත්දැයි ගණනය කිරීමටයි. උදාහරණයක් විදිහට, API call එකක් ආවම, user registration එකක් වුණාම, හෝ යම්කිසි error එකක් generate වුණාම.
අපි හිතමු අපේ application එකේ /api/products කියන endpoint එකට එන requests ගණන monitor කරන්න ඕන කියලා. ඒ වගේම, successful requests සහ failed requests වෙන වෙනම monitor කරන්නත් ඕන.
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Service;
@Service
public class ProductService {
private final Counter productApiRequestsTotal;
private final Counter productApiSuccessRequests;
private final Counter productApiFailedRequests;
public ProductService(MeterRegistry meterRegistry) {
// Counter එකක් හදනකොට, නමක් (product.api.requests.total) සහ description එකක් දෙන්න පුළුවන්.
// Tags (status="total", endpoint="/products") වලින් metrics categorize කරන්න පුළුවන්.
this.productApiRequestsTotal = Counter.builder("product.api.requests.total")
.description("Total number of requests to the product API")
.tags("endpoint", "/products", "status", "total")
.register(meterRegistry);
this.productApiSuccessRequests = Counter.builder("product.api.requests")
.description("Number of successful requests to the product API")
.tags("endpoint", "/products", "status", "success")
.register(meterRegistry);
this.productApiFailedRequests = Counter.builder("product.api.requests")
.description("Number of failed requests to the product API")
.tags("endpoint", "/products", "status", "failed")
.register(meterRegistry);
}
public String processProductRequest(boolean success) {
productApiRequestsTotal.increment(); // මුළු requests ගණන වැඩි කරනවා
if (success) {
productApiSuccessRequests.increment(); // Successful නම් මේක වැඩි කරනවා
return "Product processed successfully!";
} else {
productApiFailedRequests.increment(); // Failed නම් මේක වැඩි කරනවා
throw new RuntimeException("Failed to process product!");
}
}
}
මේ ProductService එක Controller එකකින් call කරලා අපි requests check කරන්න පුළුවන්. දැන් /actuator/prometheus endpoint එකට ගියාම, මේ custom metrics අපිට පේන්න ඕන.
2. Gauge: වත්මන් අගයක් මනින්න
Gauge එකක් පාවිච්චි කරන්නේ යම්කිසි මොහොතක පවතින අගයක් (current value) මැනීමටයි. උදාහරණයක් විදිහට, pending tasks ගණන, active users ගණන, හෝ cache size එක.
අපි හිතමු අපේ application එකේ pending orders ටිකක් තියෙනවා කියලා. ඒ pending orders ගණන අපි monitor කරන්න ඕන.
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Service;
import java.util.concurrent.atomic.AtomicInteger;
@Service
public class OrderService {
private final AtomicInteger pendingOrders = new AtomicInteger(0);
public OrderService(MeterRegistry meterRegistry) {
Gauge.builder("orders.pending", pendingOrders, AtomicInteger::get)
.description("Current number of pending orders")
.tags("status", "pending")
.register(meterRegistry);
}
public void addPendingOrder() {
pendingOrders.incrementAndGet();
System.out.println("Added new pending order. Current: " + pendingOrders.get());
}
public void completeOrder() {
if (pendingOrders.get() > 0) {
pendingOrders.decrementAndGet();
System.out.println("Completed an order. Current: " + pendingOrders.get());
}
}
}
Gauge.builder() එකෙන් අපි pendingOrders කියන AtomicInteger එකේ current value එක expose කරනවා. මේක නිතරම update වෙනවා. Micrometer විසින් මේක නිතරම call කරලා current value එක ලබා ගන්නවා.
Advanced Meter Types - Timers සහ Distribution Summaries
1. Timer: ක්රියාකාරීත්වයේ කාලය මනින්න
Timer එකක් පාවිච්චි කරන්නේ යම්කිසි ක්රියාකාරීත්වයක් (method execution, external API call) සම්පූර්ණ වෙන්න ගතවන කාලය (latency) මැනීමටයි. මේකෙන් duration, count, max, average වගේ statistics ගොඩක් ලබා ගන්න පුළුවන්.
අපි හිතමු database එකට data save කරන්න යන කාලය monitor කරන්න ඕන කියලා.
import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Service;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
@Service
public class DataService {
private final Timer databaseWriteTimer;
public DataService(MeterRegistry meterRegistry) {
this.databaseWriteTimer = Timer.builder("database.write.latency")
.description("Time taken to write data to the database")
.tags("component", "database", "operation", "write")
.publishPercentiles(0.5, 0.9, 0.99) // 50th, 90th, 99th percentiles publish කරන්න
.register(meterRegistry);
}
public void saveData(String data) throws InterruptedException {
// Timer එක පටන් ගන්නවා
databaseWriteTimer.record(() -> {
try {
// Simulate database write operation
TimeUnit.MILLISECONDS.sleep(Math.round(Math.random() * 500) + 100); // 100ms - 600ms
System.out.println("Data saved: " + data);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
// Timer එක ඉවරයි, duration එක record වෙනවා
}
}
databaseWriteTimer.record(() -> { ... }); මෙතනින්, lambda එක ඇතුළේ තියෙන code block එක execute වෙන්න ගතවෙන කාලය automatically record වෙනවා. publishPercentiles කියන්නේ latency distribution එක තේරුම් ගන්න ගොඩක් වැදගත් දෙයක්.
2. DistributionSummary: අගයන්ගේ බෙදීම මනින්න
DistributionSummary එකක් පාවිච්චි කරන්නේ යම්කිසි set එකක තියෙන values වල බෙදීම (distribution) මැනීමටයි. උදාහරණයක් විදිහට, request payload size, batch process එකක processed items ගණන.
අපි හිතමු අපේ application එකට එන messages වල size (bytes වලින්) monitor කරන්න ඕන කියලා.
import io.micrometer.core.instrument.DistributionSummary;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Service;
@Service
public class MessageProcessor {
private final DistributionSummary messagePayloadSize;
public MessageProcessor(MeterRegistry meterRegistry) {
this.messagePayloadSize = DistributionSummary.builder("message.payload.size")
.description("Size of incoming message payloads in bytes")
.baseUnit("bytes") // ඒකකය bytes බව specify කරනවා
.publishPercentiles(0.5, 0.95)
.register(meterRegistry);
}
public void processMessage(String message) {
int sizeInBytes = message.getBytes().length;
messagePayloadSize.record(sizeInBytes); // message size එක record කරනවා
System.out.println("Processing message of size: " + sizeInBytes + " bytes");
}
}
messagePayloadSize.record(sizeInBytes); මේකෙන් අපි messages වල size එක record කරනවා. Prometheus මගින් මේ data එකතු කරලා, අපිට average, max, count, percentiles වගේ දේවල් බලාගන්න පුළුවන්.
Prometheus Alerting Rules හදමු!
දැන් අපි custom metrics හදාගත්තා. ඊළඟට කරන්න ඕන මේ metrics මත පදනම් වෙලා alerts හදන එක. Prometheus වල alerts manage කරන්නේ Alertmanager කියන component එකෙන්. Alerting rules අපි Prometheus server එකේ prometheus.yml file එකේ හෝ වෙනම rule files වල define කරනවා.
සාමාන්යයෙන්, alerting rules තියෙන්නේ වෙනම rules.yml වගේ file එකක. අපි prometheus.yml එකට මේ file එක load කරන්න පුළුවන්.
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'spring-boot-app'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['localhost:8080']
alerting:
alertmanagers:
- static_configs:
- targets: ['localhost:9093'] # Alertmanager running on this port
rule_files:
- "alert_rules.yml" # අපේ alerting rules තියෙන file එක
දැන් අපි alert_rules.yml file එක හදමු. මේකේ alerts define කරන්නේ මේ විදිහටයි:
# alert_rules.yml
groups:
- name: springboot_application_alerts
rules:
- alert: HighFailedProductRequests
expr: sum(rate(product_api_requests_total{status="failed"}[5m])) by (endpoint) > 0.5
for: 1m
labels:
severity: warning
annotations:
summary: "High rate of failed product requests on {{ $labels.endpoint }}"
description: "More than 0.5 failed product requests per second for the last 5 minutes on {{ $labels.endpoint }}. Please investigate!"
- alert: TooManyPendingOrders
expr: orders_pending > 10
for: 30s
labels:
severity: critical
annotations:
summary: "Too many pending orders"
description: "Current pending orders count is {{ $value }}. This is above the threshold of 10. Manual intervention might be needed."
- alert: HighDatabaseWriteLatency
expr: histogram_quantile(0.95, sum(rate(database_write_latency_bucket[5m])) by (le, component, operation)) > 0.5
for: 2m
labels:
severity: major
annotations:
summary: "High database write latency (P95)"
description: "95th percentile of database write latency is greater than 0.5 seconds for the last 5 minutes. Application performance might be degrading."
මේ alert_rules.yml එකේ තියෙන දේවල් පොඩ්ඩක් පැහැදිලි කරමු:
groups: Alerts එකට අදාළ rules categorize කරන්න පාවිච්චි කරනවා.alert: Alert එකේ නම.expr: Prometheus Query Language (PromQL) expression එක. මේක තමයි alert එක trigger වෙන්න ඕන condition එක.sum(rate(product_api_requests_total{status="failed"}[5m])) by (endpoint) > 0.5: මේකෙන් කියන්නේ,product_api_requests_totalකියන metric එකේstatus="failed"වෙලා තියෙන requests වල 5-minute average rate එක (එක තත්පරේකට request ගණන) 0.5ට වඩා වැඩි වුණොත් alert කරන්න කියලා.rate()function එක counter එකක increment rate එක මනිනවා.orders_pending > 10:orders_pendingකියන gauge metric එකේ අගය 10ට වඩා වැඩි වුණොත් alert කරන්න කියලා.histogram_quantile(0.95, sum(rate(database_write_latency_bucket[5m])) by (le, component, operation)) > 0.5:Timerඑකක් expose කරන histogram buckets වලින් 95th percentile එක calculate කරලා, ඒක 0.5 seconds (මිලි තත්පර 500) වලට වඩා වැඩි වුණොත් alert කරන්න කියලා.
for: Condition එක මේ කාලය (e.g.,1mfor 1 minute,30sfor 30 seconds) පුරාම true වුණොත් විතරයි alert එක trigger වෙන්නේ. මේකෙන් false alarms අඩු කරන්න පුළුවන්.labels: Alert එක categorize කරන්න පුළුවන් key-value pairs.severityකියන එක Alertmanager වලට alert එකේ වැදගත්කම කියන්න පාවිච්චි කරනවා.annotations: Alert එක ගැන වැඩි විස්තර දාන්න පුළුවන්. මේවා Alertmanager හරහා notification එකක් විදිහට එනකොට පේනවා.{{ $labels.endpoint }}වගේ variable interpolation පාවිච්චි කරන්න පුළුවන්.
ප්රායෝගික අභ්යාසය: Custom Alert එකක් Set Up කරමු!
දැන් අපි කලින් හැදුව MessageProcessor එකේ message.payload.size කියන DistributionSummary එක පාවිච්චි කරලා alert එකක් හදමු.
අපි හිතමු, අපේ application එකට එන messages වල average payload size එක යම්කිසි limit එකකට වඩා වැඩි වුණොත් alert කරන්න ඕන කියලා. ඒකෙන් අපිට system overload වෙන්න පුළුවන් බවක් indicate කරන්න පුළුවන්.
alert_rules.yml file එකට මේ rule එක එකතු කරන්න:
# alert_rules.yml (add this to the existing file)
- alert: LargeMessagePayloadDetected
expr: avg_over_time(message_payload_size_sum[5m]) / avg_over_time(message_payload_size_count[5m]) > 2048 # Average payload size > 2KB
for: 1m
labels:
severity: warning
annotations:
summary: "Average message payload size is too large"
description: "The average message payload size has been over 2KB for the last 1 minute. Current average: {{ $value }} bytes. This might indicate an issue with message producers or potential performance degradation."
මේ alert rule එකෙන් කරන්නේ message_payload_size_sum (මුළු payload size එක) message_payload_size_count (messages ගණන) වලින් බෙදලා, අවසාන මිනිත්තු 5ක සාමාන්ය payload size එක ගණනය කරන එක. ඒක 2KB (2048 bytes) වලට වඩා වැඩි වුණොත්, විනාඩියක් ඇතුළත warning alert එකක් trigger කරනවා.
මේක deploy කරන්න නම්:
- ඔබේ Spring Boot application එකේ
ProductService,OrderService,DataService,MessageProcessorclasses ටික add කරලා run කරන්න. - Prometheus server එක download කරලා (ඔබට Docker පාවිච්චි කරන්නත් පුළුවන්)
prometheus.ymlfile එකේ scrape config එක සහalert_rules.ymlfile එකට link එක update කරන්න. - Alertmanager download කරලා run කරන්න.
alertingsection එකේalertmanagerstarget එක Alertmanager එක run වෙන URL එකට හරවන්න. - Prometheus web UI (
localhost:9090) එකට ගිහින් "Status" -> "Targets" යටතේ ඔබේ Spring Boot app එක up ද කියලා බලන්න. - "Alerts" tab එකට ගිහින් alerts monitor කරන්න.
- ඔබේ Spring Boot app එකට requests යවලා, orders add/complete කරලා, messages process කරලා custom metrics generate කරන්න.
- Alert conditions trigger වෙන විදිහට data generate කරලා, alerts එනවද කියලා බලන්න. (උදා:
MessageProcessorඑකට ලොකු messages ගොඩක් යවන්න.)
නිගමනය
ඉතින් යාළුවනේ, අපි මේ tutorial එකෙන් Spring Boot applications වලට Prometheus එක්ක advanced monitoring setup කරන හැටි ගැන ගොඩක් දේවල් ඉගෙන ගත්තා. Custom metrics (Counter, Gauge, Timer, DistributionSummary) හදාගන්නේ කොහොමද, ඒ වගේම ඒ metrics මත පදනම් වෙලා powerful alerting rules හදාගන්නේ කොහොමද කියන එක අපි practical examples එක්ක බැලුවා.
මේ වගේ advanced monitoring techniques වලින් අපිට පුළුවන් අපේ applications වඩාත් ස්ථාවරව, කාර්යක්ෂමව පවත්වාගෙන යන්න. ප්රශ්න ඇතිවෙන්න කලින් ඒවා හඳුනාගෙන, ඉක්මනින්ම විසඳගන්න මේවා ගොඩක් උපකාරී වෙනවා. මතක තියාගන්න, හොඳ monitoring එකක් කියන්නේ හොඳ software engineering practice එකක අනිවාර්ය අංගයක්.
ඔයාලත් මේවා ඔයාලගේ project වලට implement කරලා බලන්න. මොනවා හරි ප්රශ්න තියෙනවා නම්, ඔයාලගේ අත්දැකීම් කොමෙන්ට් සෙක්ෂන් එකේ අපිත් එක්ක බෙදාගන්න. මේ වගේ තවත් technical guides ඉක්මනින්ම අරගෙන එන්නම්. එතකන්, code කරමු, ඉගෙන ගමු!