الفصل 2: النقاط النهائية لـ Actuator
مقدمة
يوفر Actuator العديد من النقاط النهائية الجاهزة للاستخدام. يستكشف هذا الفصل الأكثر فائدة منها ويعرض لك كيفية إنشاء نقاطك النهائية الخاصة.
🎯 أهداف الفصل
في نهاية هذا الفصل، ستعرف:
- ✅ استخدام جميع النقاط النهائية الأصلية
- ✅ فهم متى تستخدم كل نقطة نهائية
- ✅ إنشاء نقاط نهائية مخصصة
- ✅ تصفية وتنسيق الردود
1. قائمة النقاط النهائية
النقاط النهائية الأساسية
| النقطة النهائية | الوصف | حساس؟ |
|---|---|---|
/actuator | يسرد جميع النقاط النهائية | لا |
/actuator/health | حالة الصحة | لا |
/actuator/info | معلومات التطبيق | لا |
نقاط التحليل النهائية
| النقطة النهائية | الوصف | حساس؟ |
|---|---|---|
/actuator/beans | يسرد جميع beans في Spring | نعم |
/actuator/conditions | شروط التكوين التلقائي | نعم |
/actuator/configprops | خصائص التكوين | نعم |
/actuator/env | متغيرات البيئة | نعم |
/actuator/mappings | جميع @RequestMapping | نعم |
نقاط القياس النهائية
| النقطة النهائية | الوصف | حساس؟ |
|---|---|---|
/actuator/metrics | يسرد القياسات | لا |
/actuator/metrics/\{name\} | قياس محدد | لا |
/actuator/prometheus | تنسيق Prometheus | لا |
نقاط التصحيح النهائية
| النقطة النهائية | الوصف | حساس؟ |
|---|---|---|
/actuator/loggers | مستويات السجل | نعم |
/actuator/threaddump | تفريغ الخيوط | نعم |
/actuator/heapdump | تفريغ الذاكرة (ملف) | نعم |
/actuator/httptrace | تاريخ HTTP | نعم |
نقاط الإجراءات النهائية
| النقطة النهائية | الوصف | حساس؟ |
|---|---|---|
/actuator/shutdown | إيقاف التطبيق | نعم |
/actuator/refresh | تحديث التكوين | نعم |
2. النقاط النهائية بالتفصيل
/actuator/beans
يسرد جميع beans في Spring للتطبيق:
curl http://localhost:8080/actuator/beans
{
"contexts": {
"application": {
"beans": {
"userService": {
"aliases": [],
"scope": "singleton",
"type": "com.example.service.UserService",
"dependencies": ["userRepository"]
},
"userController": {
"aliases": [],
"scope": "singleton",
"type": "com.example.controller.UserController",
"dependencies": ["userService"]
}
}
}
}
}
الفائدة: تصحيح حقن التبعيات.
/actuator/conditions
يوضح لماذا تم تطبيق التكوينات التلقائية أو لم يتم:
curl http://localhost:8080/actuator/conditions
{
"contexts": {
"application": {
"positiveMatches": {
"DataSourceAutoConfiguration": [{
"condition": "OnClassCondition",
"message": "@ConditionalOnClass found required classes 'javax.sql.DataSource'"
}]
},
"negativeMatches": {
"RedisAutoConfiguration": {
"notMatched": [{
"condition": "OnClassCondition",
"message": "@ConditionalOnClass did not find required class 'org.springframework.data.redis.core.RedisOperations'"
}]
}
}
}
}
}
الفائدة: فهم لماذا تم تفعيل/تعطيل ميزة معينة.
/actuator/env
يعرض جميع مصادر التكوين:
curl http://localhost:8080/actuator/env
{
"activeProfiles": ["dev"],
"propertySources": [
{
"name": "systemProperties",
"properties": {
"java.version": {"value": "17.0.1"}
}
},
{
"name": "applicationConfig: [classpath:/application.properties]",
"properties": {
"spring.datasource.url": {"value": "jdbc:h2:mem:testdb"}
}
}
]
}
خاصية محددة:
curl http://localhost:8080/actuator/env/spring.datasource.url
/actuator/mappings
يسرد جميع النقاط النهائية HTTP للتطبيق:
curl http://localhost:8080/actuator/mappings
{
"contexts": {
"application": {
"mappings": {
"dispatcherServlets": {
"dispatcherServlet": [
{
"handler": "com.example.controller.UserController#getAll()",
"predicate": "{GET /api/users}",
"details": {
"requestMappingConditions": {
"methods": ["GET"],
"patterns": ["/api/users"]
}
}
}
]
}
}
}
}
}
الفائدة: رؤية جميع النقاط النهائية المتاحة.
/actuator/loggers
عرض وتعديل مستويات السجل في الوقت الفعلي:
# عرض جميع loggers
curl http://localhost:8080/actuator/loggers
# logger محدد
curl http://localhost:8080/actuator/loggers/com.example.service
{
"configuredLevel": null,
"effectiveLevel": "DEBUG"
}
تعديل مستوى في الوقت الفعلي (POST):
curl -X POST http://localhost:8080/actuator/loggers/com.example.service \
-H "Content-Type: application/json" \
-d '{"configuredLevel": "DEBUG"}'
الفائدة: تفعيل DEBUG في الإنتاج دون إعادة التشغيل!
/actuator/threaddump
يعرض حالة جميع الخيوط:
curl http://localhost:8080/actuator/threaddump
{
"threads": [
{
"threadName": "http-nio-8080-exec-1",
"threadId": 23,
"blockedTime": -1,
"blockedCount": 0,
"waitedTime": -1,
"waitedCount": 2,
"lockName": null,
"threadState": "RUNNABLE",
"stackTrace": [
{
"className": "java.net.SocketInputStream",
"methodName": "socketRead0",
"lineNumber": -2,
"nativeMethod": true
}
]
}
]
}
الفائدة: اكتشاف حالات الجمود، الخيوط المحظورة.
/actuator/heapdump
ينشئ ملف تفريغ الذاكرة (انتبه: ثقيل!):
curl -O http://localhost:8080/actuator/heapdump
# ينشئ ملف heapdump يمكنك تحليله باستخدام VisualVM أو MAT
الفائدة: تحليل تسريبات الذاكرة.
/actuator/shutdown (خطير!)
يوقف التطبيق بشكل نظيف:
# يجب تفعيله صراحة
management.endpoint.shutdown.enabled=true
curl -X POST http://localhost:8080/actuator/shutdown
{
"message": "Shutting down, bye..."
}
⚠️ يجب تأمينه تمامًا!
3. النقاط النهائية المخصصة
إنشاء نقطة نهائية بسيطة
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.stereotype.Component;
@Component
@Endpoint(id = "custom")
public class CustomEndpoint {
@ReadOperation
public Map<String, Object> customInfo() {
return Map.of(
"status", "operational",
"timestamp", LocalDateTime.now(),
"version", "1.0.0"
);
}
}
curl http://localhost:8080/actuator/custom
{
"status": "operational",
"timestamp": "2024-01-15T10:30:00",
"version": "1.0.0"
}
نقطة نهائية مع معلمات
@Component
@Endpoint(id = "features")
public class FeaturesEndpoint {
private final Map<String, Boolean> features = new ConcurrentHashMap<>();
@ReadOperation
public Map<String, Boolean> getAllFeatures() {
return features;
}
@ReadOperation
public Boolean getFeature(@Selector String name) {
return features.getOrDefault(name, false);
}
@WriteOperation
public void setFeature(@Selector String name, boolean enabled) {
features.put(name, enabled);
}
@DeleteOperation
public void deleteFeature(@Selector String name) {
features.remove(name);
}
}
# قراءة جميع الميزات
curl http://localhost:8080/actuator/features
# قراءة ميزة معينة
curl http://localhost:8080/actuator/features/dark-mode
# تفعيل ميزة
curl -X POST "http://localhost:8080/actuator/features/dark-mode?enabled=true"
# حذف ميزة
curl -X DELETE http://localhost:8080/actuator/features/dark-mode
نقطة نهائية لإحصائيات الأعمال
@Component
@Endpoint(id = "business-stats")
@RequiredArgsConstructor
public class BusinessStatsEndpoint {
private final OrderRepository orderRepository;
private final UserRepository userRepository;
@ReadOperation
public Map<String, Object> getStats() {
return Map.of(
"totalUsers", userRepository.count(),
"totalOrders", orderRepository.count(),
"ordersToday", orderRepository.countByCreatedAtAfter(LocalDate.now().atStartOfDay()),
"revenue", orderRepository.sumTotalAmount()
);
}
}
4. النقاط النهائية للويب مقابل JMX
التعرض عبر الويب (HTTP)
# التعرض عبر HTTP
management.endpoints.web.exposure.include=health,info,metrics
التعرض عبر JMX
# التعرض عبر JMX (لـ JConsole, VisualVM)
management.endpoints.jmx.exposure.include=*
# تعطيل JMX إذا لم يكن مستخدمًا
spring.jmx.enabled=false
5. الملخص
النقاط النهائية الموصى بها في الإنتاج
| النقطة النهائية | التعرض | الاستخدام |
|---|---|---|
/health | عام | موازن التحميل، K8s |
/info | عام | الإصدار، البناء |
/metrics | داخلي | Prometheus |
/prometheus | داخلي | Scraping |
/loggers | إداري | تصحيح في الوقت الفعلي |
النقاط النهائية التي يجب تأمينها
/actuator/env → كشف الأسرار!
/actuator/heapdump → بيانات حساسة!
/actuator/shutdown → إيقاف التطبيق!
/actuator/beans → البنية الداخلية
إنشاء نقطة نهائية
@Component
@Endpoint(id = "my-endpoint")
public class MyEndpoint {
@ReadOperation // GET
public Data read() { }
@WriteOperation // POST
public void write() { }
@DeleteOperation // DELETE
public void delete() { }
}
🎯 الخطوة التالية
النقاط النهائية جيدة، ولكن كيف تقيس الأداء؟ حان الوقت للانتقال إلى القياسات!
➡️ الفصل 3: القياسات مع Micrometer