הפעם הראשונה שאתה באמת צריך צפייה היא לא כשאתה מסתכל בשלווה על לוח המחוונים. זה כאשר משתמש כותב "הקופה איטית", גרף השגיאות נראה תקין ובלוגים אתה מוצא רק שורה של הודעות מנותקות.
OpenTelemetry נוצר כדי למנוע את הרגע הזה: לא כדי שיהיה לך יותר גרפיקה, אלא כדי לחבר בין החלקים. בקשה נכנסת ל-API, מתקשרת למסד נתונים, עוברת דרך ספק חיצוני, מפרסמת עבודה בתור, ואולי נכשלת שלושה שירותים מאוחר יותר. ללא מעקב מבוזר, אתה משחזר את הסיפור הזה ביד. עם OpenTelemetry לפחות יש לך מפה.
הנקודה היא לא trace, זה הסיפור
trace הוא רצף של span. שים ככה זה נשמע קר. בפועל, כל span הוא חלק מהסיפור: POST /checkout, SELECT inventory, call payment provider, publish order.created.
הערך מגיע כשאתה מתחיל לענות על שאלות אמיתיות:
- איזה שירות חיצוני מאט?
- האם השגיאות מגיעות מגרסה מסוימת?
- האם הבעיה משפיעה על כולם או רק על דייר אחד?
- האם ניסיון חוזר מסתיר פסק זמן?
- העבודה האסינכרונית מתחילה אבל אז מתה במקום אחר?
לא ניתן לפתור את השאלות הללו על ידי console.log שנזרק בחיפזון. ואכן, לעתים קרובות היומן שנוסף במקרה חירום עוזר לך היום והופך לרעש מחר.
איך אכניס את זה לאפליקציה Node.js
ההגדרה הבריאה ביותר היא פשוטה: האפליקציה מייצרת טלמטריה, ה-Collector מחליט לאן לשלוח אותה.
Node.js app -> OpenTelemetry Collector -> backend di observability
למה לא לייצא ישירות לספק? מכיוון שבהתחלה זה נראה מהיר יותר, אז אתה מבין שלכל שירות יש תצורות שונות, ניסיונות חוזרים שונים, מסננים שונים ואין נקודה מרכזית להסרת נתונים רגישים או שינוי יעד.
ה-Collector משעמם בכל הדרכים הנכונות. הוא מקבל OTLP, עושה אצווה, יכול לסנן, יכול לבצע דגימה, יכול להוסיף תכונות נפוצות ויכול לייצא למערכות מרובות.
מכשור עצמי: טוב, אבל לא מספיק
בNode.js הייתי מתחיל עם מכשור אוטומטי. זה נותן לך נראות מיידית לתוך HTTP, מסגרות נתמכות, מסדי נתונים וספריות נפוצות.
npm install @opentelemetry/sdk-node \ @opentelemetry/auto-instrumentations-node \ @opentelemetry/exporter-trace-otlp-http
לאחר מכן אתה מאתחל את SDK לפני שאר האפליקציה:
import { NodeSDK } from '@opentelemetry/sdk-node'; import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'; import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'; const sdk = new NodeSDK({ traceExporter: new OTLPTraceExporter({ url: process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, }), instrumentations: [getNodeAutoInstrumentations()], }); sdk.start();
עם זאת, זה רואה את המסגרת, לא את המוצר שלך. הוא יודע שביצעת שאילתה, אבל הוא לא יודע שהשאילתה הזו הייתה ב"צור סדר" או "חידוש מנוי". בשביל זה אתה צריך span מדריכים בנקודות שבהן הדומיננטיות חשובה.
const span = tracer.startSpan('checkout.create_order'); try { span.setAttribute('cart.items_count', input.items.length); const order = await createOrder(input); span.setAttribute('order.id', order.id); return order; } catch (error) { span.recordException(error as Error); throw error; } finally { span.end(); }
לא הייתי שם מדריכים span בשום מקום. הייתי שם אותם במקום שבו, בשלוש לפנות בוקר, הייתי רוצה להבין מה קרה בלי לקרוא חצי מבסיס הקוד.
שלושה כללים שמונעים כאוס רב
כלל ראשון: לכל שירות חייב להיות service.name, סביבה וגרסה. זה נראה טריוויאלי, אבל בלי התכונות האלה trace הוא הרבה פחות שימושי. כאשר פריסה שוברת משהו, אתה רוצה לסנן לפי גרסה תוך שתי שניות.
כלל שני: אל תכניס נתונים רגישים למאפיינים. הודעות דוא"ל, אסימונים, מטענים שלמים וכתובות לא אמורים להסתיים ב-backend של צפייה בטעות. אם אתה צריך לזהות משתמש, שקול מזהים פנימיים, hashing או שדות פחות רגישים.
כלל שלישי: שימו לב לקרדינליות. user.id כתכונה של trace יכולה להיות הגיונית. בתור תווית מדד זה יכול להרוס את העלויות והביצועים שלך.
מדדים: מעטים, אבל טובים
הייתי מתחיל עם מדדים מעשיים מאוד:
- שיעורים, טעויות ומשך הבקשות;
- חביון של תלות חיצונית;
- מספר פסקי זמן וניסיונות חוזרים;
- עומק הזנבות;
- משך העבודה;
- אחוז השגיאות לגרסה.
השאר מתווסף בעת הצורך. לוחות מחוונים מלאים בגרפים שאף אחד לא מסתכל עליהם הם רהיטים, לא צפייה.
יומנים: עדיין שימושי, אבל מקושרים
יומנים לא נעלמים. הם פשוט הופכים הרבה יותר שימושיים כשהם נושאים trace_id וspan_id. אז אתה יכול להתחיל מיומן שגיאות ולפתוח את trace, או להתחיל מיומן trace איטי ולקרוא רק את היומנים שנוצרו בנתיב זה.
ללא קורלציה, אתה מחפש מחטים. עם קורלציה, לפחות אתה יודע באיזו מגירה להסתכל.
רשימת הבדיקה שהייתי משתמש בה לפני שאמרתי "אנחנו מכוסים"
- ה-trace למעשה חוצים מספר שירותים.
- היומנים כוללים
trace_idוspan_id. - ה-Collector מוגדר עם מגבלות אצווה וזיכרון.
- שגיאות נרשמות בspan.
- יש מדיניות דגימה.
- למדדים יש קרדינליות מבוקרת.
- נתונים רגישים מסוננים.
- התראות מתחילות מסימפטומים של משתמשים, לא גרפים אקראיים.
מסקנה
OpenTelemetry אינו פותר בעיות ייצור בעצמו. אבל הדרך שבה אתה מתמודד איתם משתנה. במקום להוסיף יומנים באופן עיוור, אתה מתחיל לעקוב אחר הנתיב האמיתי של בקשה.
עבורי הסימן שזה עובד הוא פשוט: כשמשהו קורה, הצוות מפסיק לשאול "איפה אנחנו מחפשים?" ומתחיל לשאול "למה הקטע הזה איטי?". זה המקום שבו הנראות הופכת לכלי, לא לאוסף של לוחות מחוונים.