אינסטרומנטציה של יישומים עם OpenTelemetry SDK

פיזור של traces, metrics ו-logs בין מערכות שונות מקשה על איתור גורמי שורש ומאט את האבחון. אנחנו מיישמים instrumentation ליישומים באמצעות OpenTelemetry SDK, ומאחדים את כל ה-telemetry לסטנדרט אחד. הצוות שלנו מספק פרויקט turnkey—מביקורת והתקנה ועד תמיכה—ומבטיח פתרון אמין שגדל עם העסק שלכם.

היכולות שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1359
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • עיצוב לוגו לחברת B2B Advance
    עיצוב לוגו לחברת B2B Advance
    776
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח לוגו חברת AIDER
    פיתוח לוגו חברת AIDER
    1022
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1113

אינסטרומנטציה של יישומים עם OpenTelemetry SDK

ללא תקן טלמטריה אחיד, אתה מאבד עד 40% מהזמן באיתור שורש הבעיה: טרייסים במערכת אחת, מטריקות באחרת, לוגים בשלישית. OpenTelemetry מאחד הכל לממשק אחד, וחוסך עד 30% בעלויות תפעול. עבדנו עם מחסנית טכנולוגית זו למעלה מ-5 שנים ויישמנו אותה ביותר מ-50 פרויקטים—החיסכון האופייני מהיישום מסתכם ב-$5,000–$10,000 לחודש בשל הפחתת זמני השבתה.

אינסטרומנטציה פירושה הוספת נקודות תצפית לקוד: היכן פעולה מתחילה, היכן היא מסתיימת, אילו תכונות היא נושאת, והאם היא הושלמה בהצלחה. OpenTelemetry SDK מתקן תהליך זה: API אחד לטרייסים, מטריקות ולוגים, ללא קשר לאן הנתונים מגיעים בסופו של דבר.

קיימות שתי רמות של אינסטרומנטציה לכל שפה. אוטומטית—סוכן/תיקון (patch) מבצע אינסטרומנטציה לספריות פופולריות ללא שינויי קוד. ידנית—המפתח יוצר במפורש ספנים (spans) ללוגיקה עסקית: "ביצוע הזמנה," "חישוב הנחה," "קריאה ל-API של שותף חיצוני." אוטומטית אינה מחליפה ידנית—היא מכסה רק את שכבת התשתית.

למה לבחור ב-OpenTelemetry SDK לאינסטרומנטציה?

בניגוד לפתרונות קנייניים (Datadog, New Relic), OpenTelemetry אינו נועל אותך לספק מסוים: ניתן להחליף מערכות קצה (Prometheus, Jaeger, Grafana) ללא שכתוב קוד. זהו גם תקן פתוח הנתמך על ידי כל העננים והכלים המרכזיים. המהנדסים שלנו מוסמכים ב-Kubernetes ו-OpenTelemetry—אנו מבטיחים תצורה נכונה מההתחלה. OpenTelemetry חסכוני פי 3–5 מכלי APM קנייניים לפריסות בקנה מידה גדול.

אינסטרומנטציה ידנית: דפוסים נכונים

ב-Python באמצעות מנהל הקשר (הגישה הנכונה):

from opentelemetry import trace
from opentelemetry.trace import SpanKind

tracer = trace.get_tracer("order-service", "1.4.2")

def process_order(order_id: str, user_id: str) -> Order:
    with tracer.start_as_current_span(
        "order.process",
        kind=SpanKind.INTERNAL,
        attributes={
            "order.id": order_id,
            "user.id": user_id,
        }
    ) as span:
        try:
            order = fetch_order(order_id)
            span.set_attribute("order.total_amount", order.total)
            span.set_attribute("order.items_count", len(order.items))
            result = apply_discounts(order)
            span.add_event("discounts_applied", {"discount_percent": result.discount_percent})
            return result
        except OrderNotFoundException as e:
            span.record_exception(e)
            span.set_status(trace.StatusCode.ERROR, str(e))
            raise

from opentelemetry import trace from opentelemetry.trace import SpanKind tracer = trace.get_tracer("order-service", "1.4.2") def process_order(order_id: str, user_id: str) -> Order: with tracer.start_as_current_span( "order.process", kind=SpanKind.INTERNAL, attributes={ "order.id": order_id, "user.id": user_id, } ) as span: try: order = fetch_order(order_id) span.set_attribute("order.total_amount", order.total) span.set_attribute("order.items_count", len(order.items)) result = apply_discounts(order) span.add_event("discounts_applied", {"discount_percent": result.discount_percent}) return result except OrderNotFoundException as e: span.record_exception(e) span.set_status(trace.StatusCode.ERROR, str(e)) raise מוסיף אוטומטית מחסנית קריאות (stack trace) לאירועי ספן. record_exception() מאותת למערכות קצה ולמדיניות דגימה. ללא סטטוס ERROR מפורש, דוגם מבוסס-זנב (tail-based sampler) עשוי שלא לשמר את ספן החריגה.

מטריקות: Counter, Histogram, Gauge

from opentelemetry import metrics
meter = metrics.get_meter("order-service", "1.4.2")

# Счётчик запросов
order_counter = meter.create_counter(
    "orders.created.total",
    unit="1",
    description="Total number of orders created"
)

# Гистограмма времени обработки
processing_duration = meter.create_histogram(
    "orders.processing.duration",
    unit="ms",
    description="Order processing duration"
)

def create_order(order_data):
    start = time.monotonic()
    order = _create_order_internal(order_data)
    duration_ms = (time.monotonic() - start) * 1000
    order_counter.add(1, {"order.type": order.type, "region": order.region})
    processing_duration.record(duration_ms, {"order.type": order.type})

נקודה מרכזית לגבי תכונות מטריקה: כל שילוב ייחודי של תכונות הופך לסדרת זמן נפרדת ב-Prometheus. שימוש ב-set_status(ERROR) כתכונת מטריקה הוא אסון קרדינליות. from opentelemetry import metrics meter = metrics.get_meter("order-service", "1.4.2") # Счётчик запросов order_counter = meter.create_counter( "orders.created.total", unit="1", description="Total number of orders created" ) # Гистограмма времени обработки processing_duration = meter.create_histogram( "orders.processing.duration", unit="ms", description="Order processing duration" ) def create_order(order_data): start = time.monotonic() order = _create_order_internal(order_data) duration_ms = (time.monotonic() - start) * 1000 order_counter.add(1, {"order.type": order.type, "region": order.region}) processing_duration.record(duration_ms, {"order.type": order.type}) עם 5-10 ערכים הוא בסדר.

כיצד להימנע ממטריקות בקרדינליות גבוהה?

השתמש רק בתכונות בקרדינליות נמוכה: סוג בקשה, אזור, גרסת שירות. עבור מזהים ייחודיים (user_id, order_id) השאר אותם רק בספנים, לא במטריקות. זה שומר על ביצועי Prometheus ומונע עומס אחסון.

כיצד לבצע אינסטרומנטציה ליישומי Java?

עבור Spring Boot, קיימות שתי דרכים: אינסטרומנטציה אוטומטית דרך סוכן (מומלץ להתחלה):

-javaagent:opentelemetry-javaagent-2.x.jar
-Dotel.service.name=order-service
-Dotel.exporter.otlp.endpoint=http://otel-collector:4317
-Dotel.logs.exporter=otlp

Spring Boot Starter לאינסטרומנטציה ידנית—הוסף את התלות ל-pom.xml וחבר אוטומטית את Tracer באמצעות @Autowired. דוגמה:

<dependency>
  <groupId>io.opentelemetry.instrumentation</groupId>
  <artifactId>opentelemetry-spring-boot-starter</artifactId>
  <version>2.3.0-alpha</version>
</dependency>

לאחר מכן, ניתן להזריק OpenTelemetry וליצור ספנים ללוגיקה עסקית כפי שמוצג בתיעוד.

קורלציית לוגים עם טרייסים

כדי לנווט מ-Grafana Loki לטרייס ספציפי, שורות הלוג חייבות להכיל user.id ו-order.type. OTel מספק עזרים לספריות לוג פופולריות.

Python + structlog:

import structlog
from opentelemetry import trace

def add_trace_context(logger, method, event_dict):
    span = trace.get_current_span()
    if span.is_recording():
        ctx = span.get_span_context()
        event_dict["trace_id"] = format(ctx.trace_id, "032x")
        event_dict["span_id"] = format(ctx.span_id, "016x")
    return event_dict

structlog.configure(
    processors=[add_trace_context, structlog.processors.JSONRenderer()]
)

השוואה בין אינסטרומנטציה אוטומטית לידנית

פרמטר אוטומטית ידנית
שינויי קוד אין (סוכן מחובר) כן (נוספים ספנים)
כיסוי לוגיקה עסקית רק קריאות תשתית שליטה מלאה
זמן יישום לכל שירות 30 דקות 1–2 ימים
תלות בגרסת ספרייה כן (סוכן לכל גרסה) לא

אינסטרומנטציה ידנית מספקת פי 3 יותר נתונים שימושיים לניפוי באגים אך דורשת משמעת. אופטימלי: אוטומטית להתחלה מהירה + ידנית לפעולות מפתח.

ספריות מומלצות לשפות שונות

שפה אינסטרומנטציה אוטומטית SDK ידני
Java OpenTelemetry Java Agent opentelemetry-java
Python opentelemetry-distro opentelemetry-api / SDK
Go אין מקבילה מובנית opentelemetry-go
.NET OpenTelemetry .NET AutoInstrumentation OpenTelemetry .NET

הבחירה בין אוטומטי לידני תלויה בבשלות השירות וברמת הפירוט הנדרשת.

תוצרים מסחריים

  • ביקורת קוד ותשתית נוכחיים – יום אחד
  • תצורת OTel Collector עם סינון ודגימה – יומיים
  • אינטגרציה עם מערכות קצה (Prometheus, Loki, Jaeger) – יום אחד
  • יצירת חוזי טלמטריה (תיעוד תכונות ומטריקות) – יום אחד
  • הכשרת צוות (סדנה על אינסטרומנטציה וקורלציה) – יום אחד
  • שבועיים של תמיכה חינמית לאחר היישום – כלול
  • תיעוד שירותים שעברו אינסטרומנטציה – כלול

עבור פריסה של 10 מיקרוסרוויסים, מעבר מ-APM קנייני ל-OpenTelemetry חוסך כ-$4,000–$8,000 לחודש בעלויות רישוי.

רשימת בדיקה להשלמת אינסטרומנטציה

  • לכל קריאות ה-HTTP החיצוניות יש ספנים עם -javaagent:opentelemetry-javaagent-2.x.jar -Dotel.service.name=order-service -Dotel.exporter.otlp.endpoint=http://otel-collector:4317 -Dotel.logs.exporter=otlp , <dependency> <groupId>io.opentelemetry.instrumentation</groupId> <artifactId>opentelemetry-spring-boot-starter</artifactId> <version>2.3.0-alpha</version> </dependency> , trace_id
  • פעולות DB: span_id, import structlog from opentelemetry import trace def add_trace_context(logger, method, event_dict): span = trace.get_current_span() if span.is_recording(): ctx = span.get_span_context() event_dict["trace_id"] = format(ctx.trace_id, "032x") event_dict["span_id"] = format(ctx.span_id, "016x") return event_dict structlog.configure( processors=[add_trace_context, structlog.processors.JSONRenderer()] ) , http.request.method (ללא פרטי התחברות או PII)
  • שגיאות נרשמות דרך server.address ו-http.response.status_code
  • db.system זורם ללוגים
  • למטריקות אין תכונות בקרדינליות גבוהה (user_id, order_id)
  • שמות ספנים הם מחרוזות יציבות, שאינן מכילות מזהים דינמיים

דגימה מבוססת-ראש (למשל, ProbabilisticSampler) מחליטה האם לשמר טרייס בתחילתו. דגימה מבוססת-זנב (IdGenerator) מקבלת החלטה לאחר השלמתו על סמך שגיאות ומשך זמן. כדי לחסוך במשאבים, השתמש בדגימה מבוססת-ראש עם הסתברות של 10% ובדגימה מבוססת-זנב רק לאחסון טרייסים בעייתיים.

ציר הזמן של אינסטרומנטציה תלוי במספר השירותים ובמורכבות הלוגיקה העסקית: מיומיים-שלושה עבור 3-5 שירותים עד 1-2 שבועות עבור מחסנית רב-שפתית גדולה. צור קשר—נעריך את הפרויקט שלך ביום אחד ונציע תוכנית יישום. הזמן יישום וקבל שבועיים של תמיכה חינמית.

תיעוד OpenTelemetry