404 Not Found

404 Not Found


nginx

القابلية للرصد

القابلية للرصد هي عيون عمليات الإنتاج—المقاييس تكشف الاتجاهات، والسجلات تحدد الأسباب، وبيانات التتبع تحدد الأسباب الجذرية. هذه الأعمدة الثلاثة لا غنى عنها جميعًا.

1. ما ستتعلمه


2. قصة حقيقية لمهندس SRE

(1) نقطة الألم: استكشاف الأخطاء في الصندوق الأسود عبر الإنترنت

عندما تواجه OrderFlow خطأ في الإنتاج، يبقى Bob يبحث في بحر من سجلات التطبيق: أي واجهة برمجة تطبيقات بطيئة؟ أي خدمة بها مشاكل؟ أي خدمات مصغرة مرّ بها الطلب؟ ليس لديه أي فكرة. يقضي Alice وBob غالبًا أربع ساعات في استكشاف مشكلة إنتاج واحدة، ثلاث منها في "تخمين" مكان المشكلة.

(2) مقاربات الأعمدة الثلاثة للقابلية للرصد

100%
graph LR
    A["القابلية للرصد<br/>ثلاثة أعمدة"] --> B["المقاييس<br/>ماذا حدث؟<br/>Prometheus"]
    A --> C["السجلات<br/>لماذا حدث؟<br/>ELK / Loki"]
    A --> D["التتبع<br/>أين حدث؟<br/>Jaeger / Zipkin"]

حدد المشاكل باستخدام المقاييس، وحلل السجلات لتحديد السبب، واستخدم تحليل التتبع لتحديد السبب الجذري.

(3) الإيرادات

بعد أن أنشأ Bob نظام القابلية للرصد، بدأت لوحات Grafana تعرض زمن استجابة P99 ومعدلات الخطأ في الوقت الفعلي، وأطلقت تنبيهات Prometheus إشعارات تلقائية، وحددت بيانات تتبع OpenTelemetry السبب الجذري للمشاكل في غضون 30 ثانية. انخفض متوسط وقت حل المشاكل من 4 ساعات إلى 15 دقيقة.


3. جمع بيانات Micrometer

(1) أربعة أنواع من المقاييس

النوع المعنى يزداد فقط السيناريوهات النموذجية
Counter عداد (زيادة فقط) نعم إجمالي الطلبات، عدد الطلبات المنشأة
Gauge القيمة الحالية (يمكن أن تزداد أو تنقص) لا عدد الاتصالات الحالي، طول قائمة الانتظار
Timer توزيع المدة لا وقت الاستجابة للطلب
DistributionSummary إحصائيات التوزيع لا توزيع حجم نص الطلب

(1) ▶ مثال: مقاييس أعمال مخصصة

JAVA
@Service
public class OrderMetrics {

    private final Counter orderCreatedCounter;
    private final Counter orderCancelledCounter;
    private final Timer orderCreationTimer;
    private final Gauge pendingOrdersGauge;

    public OrderMetrics(MeterRegistry registry, OrderRepository orderRepo) {
        this.orderCreatedCounter = Counter.builder("orderflow.orders.created")
            .description("إجمالي الطلبات المنشأة")
            .tag("service", "orderflow")
            .register(registry);

        this.orderCancelledCounter = Counter.builder("orderflow.orders.cancelled")
            .description("إجمالي الطلبات الملغاة")
            .register(registry);

        this.orderCreationTimer = Timer.builder("orderflow.orders.creation.duration")
            .description("مدة إنشاء الطلب")
            .publishPercentiles(0.5, 0.95, 0.99)
            .publishPercentileHistogram()
            .register(registry);

        this.pendingOrdersGauge = Gauge.builder("orderflow.orders.pending",
                orderRepo, repo -> repo.countByStatus("PENDING"))
            .description("عدد الطلبات المعلقة الحالي")
            .register(registry);
    }

    public void recordOrderCreated() {
        orderCreatedCounter.increment();
    }

    public Timer.Sample startCreationTimer() {
        return Timer.start(orderCreationTimer);
    }

    public void recordCreationComplete(Timer.Sample sample) {
        sample.stop(orderCreationTimer);
    }
}

الناتج:

TEXT
// التنفيذ ناجح

(2) ▶ مثال: استخدام المقاييس في خدمة

JAVA
@Service
public class OrderServiceImpl implements OrderService {

    private final OrderMetrics metrics;

    @Override
    @Transactional
    public Order createOrder(CreateOrderRequest request) {
        Timer.Sample sample = metrics.startCreationTimer();
        try {
            Order order = doCreateOrder(request);
            metrics.recordOrderCreated();
            return order;
        } finally {
            metrics.recordCreationComplete(sample);
        }
    }
}

الناتج:

TEXT
// التنفيذ ناجح

4. تكامل Prometheus

(1) ▶ مثال: تبعيات وتهيئة Prometheus

XML
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

الناتج:

TEXT
// التنفيذ ناجح
YAML
# application.yml
management:
  endpoints:
    web:
      exposure:
        include: health,prometheus,metrics
  metrics:
    tags:
      application: ${spring.application.name}
    export:
      prometheus:
        enabled: true

(2) ▶ مثال: تهيئة جمع Prometheus

YAML
# prometheus.yml
scrape_configs:
  - job_name: 'orderflow'
    metrics_path: '/actuator/prometheus'
    scrape_interval: 15s
    static_configs:
      - targets: ['orderflow:8080']

الناتج:

TEXT
تم تحميل تهيئة المراقبة
أهداف Prometheus: 3 نشطة
لوحة Grafana: جاهزة

(3) ▶ مثال: استعلامات PromQL والتنبيهات

YAML
# استعلامات PromQL
# زمن استجابة P99 لواجهة برمجة طلبات الطلبات
histogram_quantile(0.99, sum(rate(http_server_requests_seconds_bucket{uri=~"/api/v1/orders.*"}[5m])) by (le, uri))

# معدل الخطأ (استجابات 5xx)
sum(rate(http_server_requests_seconds_total{status=~"5.."}[5m]))
/
sum(rate(http_server_requests_seconds_total[5m]))

# طلبات في الدقيقة
rate(orderflow_orders_created_total[1m]) * 60

الناتج:

TEXT
تم تطبيق التهيئة بنجاح
YAML
# alert_rules.yml
groups:
- name: orderflow
  rules:
  - alert: HighErrorRate
    expr: |
      sum(rate(http_server_requests_seconds_total{status=~"5.."}[5m]))
      / sum(rate(http_server_requests_seconds_total[5m])) > 0.001
    for: 5m
    labels:
      severity: critical
    annotations:
      summary: "معدل خطأ OrderFlow يتجاوز 0.1%"

  - alert: HighP99Latency
    expr: |
      histogram_quantile(0.99, sum(rate(http_server_requests_seconds_bucket[5m])) by (le)) > 0.1
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "زمن استجابة P99 لـ OrderFlow يتجاوز 100 مللي ثانية"

5. لوحة Grafana

(1) مقاييس لوحة المعلومات الرئيسية

اللوحة المقياس PromQL
معدل الطلبات QPS sum(rate(http_server_requests_seconds_total[5m]))
زمن الاستجابة P50/P95/P99 توزيع وقت الاستجابة histogram_quantile(0.99, ...)
معدل الخطأ نسبة 5xx rate(...{status=~"5.."})/rate(...)
ذاكرة كومة JVM استخدام الذاكرة jvm_memory_used_bytes{area="heap"}
توقف GC مدة GC rate(jvm_gc_pause_seconds_sum[5m])
اتصالات HikariCP النشطة استخدام تجمع الاتصالات hikaricp_connections_active
معدل إنشاء الطلبات مقياس أعمال rate(orderflow_orders_created_total[1m])

(1) ▶ مثال: مقتطف JSON للوحة Grafana

JSON
{
  "dashboard": {
    "title": "OrderFlow Observability",
    "panels": [
      {
        "title": "معدل الطلبات (QPS)",
        "type": "timeseries",
        "targets": [{
          "expr": "sum(rate(http_server_requests_seconds_total{application=\"orderflow-service\"}[5m]))"
        }]
      },
      {
        "title": "زمن استجابة P99",
        "type": "timeseries",
        "targets": [{
          "expr": "histogram_quantile(0.99, sum(rate(http_server_requests_seconds_bucket{application=\"orderflow-service\"}[5m])) by (le))"
        }]
      },
      {
        "title": "معدل الخطأ",
        "type": "gauge",
        "targets": [{
          "expr": "sum(rate(http_server_requests_seconds_total{application=\"orderflow-service\",status=~\"5..\"}[5m])) / sum(rate(http_server_requests_seconds_total{application=\"orderflow-service\"}[5m]))"
        }],
        "fieldConfig": {
          "defaults": {
            "thresholds": {
              "steps": [
                {"value": 0, "color": "green"},
                {"value": 0.001, "color": "red"}
              ]
            }
          }
        }
      }
    ]
  }
}

الناتج:

JSON
{
  "dashboard": {
    "title": "OrderFlow Observability",
    "panels": [
      {
        "title": "معدل الطلبات (QPS)",
        "type": "timeseries",
        "targets": [
          {
            "expr": "sum(rate(http_server_requests_seconds_total{application=\"orderflow-service\"}[5m]))"
          }
        ]
      },
      {
        "title": "زمن استجابة P99",
        "type": "timeseries",
        "targets": [
          {
            "expr": "histogram_quantile(0.99, sum(rate(http_server_request

6. تتبع OpenTelemetry

(1) مفهوم التتبع الموزع

100%
graph LR
    A["العميل"] --> B["بوابة API<br/>Trace: abc123<br/>Span 1"]
    B --> C["خدمة الطلبات<br/>Span 2<br/>parent: Span 1"]
    C --> D["خدمة المنتجات<br/>Span 3<br/>parent: Span 2"]
    C --> E["قاعدة البيانات<br/>Span 4<br/>parent: Span 2"]
المفهوم المعنى
Trace المسار الكامل لطلب واحد
Span عملية واحدة في السلسلة
Context سياق التتبع المنقول بين Span
SpanId المعرف الفريد للـ span الحالي
TraceId المعرف الفريد للتتبع بالكامل

(1) ▶ مثال: تبعية OpenTelemetry

XML
<dependency>
    <groupId>io.opentelemetry.instrumentation</groupId>
    <artifactId>opentelemetry-spring-boot-starter</artifactId>
</dependency>

الناتج:

TEXT
// التنفيذ ناجح
YAML
# application.yml
otel:
  exporter:
    otlp:
      endpoint: http://otel-collector:4317
  resource:
    attributes:
      service.name: orderflow-service
  traces:
    exporter: otlp

(2) ▶ مثال: Span مخصص

JAVA
@Service
public class OrderService {

    private final Tracer tracer;

    public OrderService(Tracer tracer) {
        this.tracer = tracer;
    }

    public Order createOrder(CreateOrderRequest request) {
        Span span = tracer.spanBuilder("create-order")
            .setAttribute("product.id", request.productId())
            .setAttribute("quantity", request.quantity())
            .startSpan();

        try (Scope scope = span.makeCurrent()) {
            Order order = doCreateOrder(request);
            span.setAttribute("order.id", order.getId());
            return order;
        } catch (Exception e) {
            span.recordException(e);
            span.setStatus(StatusCode.ERROR, e.getMessage());
            throw e;
        } finally {
            span.end();
        }
    }
}

الناتج:

TEXT
// التنفيذ ناجح

7. مثال شامل: لوحة SLO لـ OrderFlow

YAML
# docker-compose.observability.yml
version: "3.9"
services:
  prometheus:
    image: prom/prometheus:latest
    ports: ["9090:9090"]
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - ./alert_rules.yml:/etc/prometheus/alert_rules.yml

  grafana:
    image: grafana/grafana:latest
    ports: ["3000:3000"]
    environment:
      GF_SECURITY_ADMIN_PASSWORD: admin
    volumes:
      - grafana-data:/var/lib/grafana

  otel-collector:
    image: otel/opentelemetry-collector:latest
    ports: ["4317:4317", "4318:4318"]
    volumes:
      - ./otel-collector-config.yml:/etc/otelcol/config.yaml

  jaeger:
    image: jaegertracing/all-in-one:latest
    ports: ["16686:16686"]

  app:
    build: .
    ports: ["8080:8080"]
    environment:
      OTEL_EXPORTER_OTLP_ENDPOINT: http://otel-collector:4317
      OTEL_SERVICE_NAME: orderflow-service
      MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE: health,prometheus,metrics
مقياس SLO الهدف عتبة التنبيه PromQL
زمن استجابة P99 < 100 مللي ثانية > 100 مللي ثانية لمدة 5 دقائق histogram_quantile(0.99, ...)
معدل الخطأ < 0.1% > 0.1% لمدة 5 دقائق rate(5xx)/rate(all)
التوفر > 99.9% < 99.9% لمدة 5 دقائق 1 - rate(5xx)/rate(all)
إنتاجية الطلبات > 1,000/دقيقة < 500/دقيقة لمدة 10 دقائق rate(orders_created)[1m]*60

❓ أسئلة شائعة

س ما الفرق بين المقاييس والسجلات؟
ج المقاييس هي قيم مجمعة (عدادات، مدرجات تكرارية) ومناسبة لمراقبة الاتجاهات وإطلاق التنبيهات. السجلات هي سجلات أحداث منفصلة ومناسبة لتحليل الأسباب المحددة. استخدم المقاييس لتحديد المشاكل والسجلات لتحليل أسبابها.
س ما أدوار Prometheus وGrafana على التوالي؟
ج Prometheus يتولى جمع البيانات وتخزينها (قاعدة بيانات السلاسل الزمنية) بالإضافة إلى قواعد التنبيه. Grafana يتولى التصوير (لوحات المعلومات). عند استخدامهما معًا، يعمل Prometheus كمصدر بيانات، وGrafana كطبقة عرض.
س ما العلاقة بين OpenTelemetry وJaeger؟
ج OpenTelemetry هو معيار "الجمع" (SDK + API)، بينما Jaeger هو الواجهة الخلفية "التخزين والتصوير". تستخدم التطبيقات OTel SDK لجمع بيانات التتبع وإرسالها إلى Jaeger للتخزين والاستعلام.
س ما الفرق بين publishPercentiles وhistogram_quantile؟
ج publishPercentiles يحسب النسب المئوية على جانب التطبيق (يوفر تخزين Prometheus، لكنه أقل دقة عبر مثيلات متعددة). histogram_quantile يحسب النسب المئوية على جانب Prometheus (يدعم تجميع المثيلات المتعددة وأكثر دقة). نوصي بالحساب على جانب Prometheus في بيئات الإنتاج.
س ما الفرق بين SLO وSLA؟
ج SLO (هدف مستوى الخدمة) هو هدف داخلي، مثل P99 < 100 مللي ثانية. SLA (اتفاقية مستوى الخدمة) هو التزام تجاه العملاء يتضمن تعويضًا عن الانتهاكات. SLO يشكل أساس SLA.
س كيف أختار واجهة خلفية للسجلات؟
ج ELK (Elasticsearch + Logstash + Kibana) قوية لكنها كثيفة الموارد؛ Loki (جزء من نظام Grafana البيئي) خفيف لكن قدرات الاستعلام محدودة. نوصي بـ Loki للمشاريع الصغيرة والمتوسطة وELK للمشاريع الكبيرة.

📖 ملخص


📝 تمارين

  1. تمرين أساسي (الصعوبة: ⭐): هيئ Micrometer + Prometheus لـ OrderFlow، واكشف نقطة النهاية /actuator/prometheus، وحدد ثلاثة مقاييس أعمال مخصصة (عدد الطلبات المنشأة، وقت معالجة الطلبات، عدد الطلبات المعلقة).

  2. تمرين متقدم (الصعوبة: ⭐⭐): هيئ Prometheus لجمع البيانات وأعد لوحة Grafana لعرض HTTP QPS وزمن استجابة P99 ومعدل الخطأ وذاكرة كومة JVM. اكتب قاعدتي تنبيه Prometheus (لمعدل الخطأ العالي وزمن الاستجابة العالي).

  3. تحدٍ (الصعوبة: ⭐⭐⭐): تكامل OpenTelemetry وJaeger لتنفيذ التتبع الموزع. أضف span مخصصًا إلى OrderService لتتبع تدفق تقديم الطلبات بالكامل (Controller → Service → Repository)، واعرض تفاصيل التتبع في واجهة Jaeger.

Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%