פורמט JSON של בקשה ליצירת הגדרות של מדדים

במדריך הזה מפורט הפורמט של בקשת JSON לנקודת הקצה /api/v2/generate_metrics_config של הכלי Metrics Configuration Generator ‏ (MCG). הפורמט הזה מאפשר להגדיר קמפיין טלמטריה – לציין איסוף נתונים, עיבוד במכשיר ויצירת דוחות – במבנה קריא לאנשים.

כלי ה-MCG מאמת את אובייקט ה-JSON הזה, בודק אם יש בעיות כמו אי-התאמות בסוגים, תלויות מעגליות או הפניות לא מוגדרות, ואז מקמפל אותו להודעת מאגר אחסון לפרוטוקולים (protobuf) של MetricsConfig. ההודעה הזו של MetricsConfig היא הפורמט הבינארי ששירות הטלמטריה במכשיר מפעיל כדי להריץ את הקמפיין.

דרישות מוקדמות: אתם צריכים להכיר סכימות JSON,‏ protobuf ומבני נתונים בסיסיים. לסקירה כללית של המושגים, קראו את המאמר מושגים שקשורים להגדרת מדדים.

איך כותבים תיאור של הגדרה

כדי לתכנן קמפיין לאיסוף מדדים, פועלים לפי השלבים הבאים:

  1. מציינים מקורות נתונים: מגדירים מאיפה הנתונים מגיעים.
  2. הגדרת לוגיקה ועיבוד: מגדירים כללים לגבי מתי לאסוף נתונים ואיך לעבד אותם.
  3. יצירת פלט: אריזת הנתונים שעובדו להודעה סופית.
  4. שדות ברמה העליונה: מוסיפים שדות ברמה העליונה כמו UUID, הגדרות של אותות ובקרת מחזור חיים.

דוגמה: דוח מהירות ממוצעת

במדריך הזה יש דוגמה שמראה איך כל הרכיבים משתלבים יחד. הוא יוצר דוח שמחשב את מהירות הרכב הממוצעת בכל דקה. הוא מגדיר מקור נתונים (SpeedSource) לאיסוף נתוני מהירות, טריגרים (OnNewSpeed, EveryMinute) לשליטה בתהליך הביצוע, אגרגטור (SpeedAggregator) לחישוב הממוצע והגדרת דוח מדדים (MinuteReport) לאריזת התוצאה. הדוגמאות בקטעים הניתנים להרחבה מבוססות על התרחיש הזה.

ציון מקורות נתונים

הטלמטריה תומכת באיסוף נתונים משירותי SDV (דרך SDV Middleware) ומבעלי תוכן דיגיטלי שמבוססים על Configurable Publisher Registry.

כדי להשתמש בנתונים ב-SDV, מגדירים מקור נתונים (concept) ומוסיפים אותו למערך data_sources.

שדות של אובייקט מקור נתונים (פריט ברשימה data_sources)
name מחרוזת שמוגדרת על ידי המשתמש ומזהה את מקור הנתונים הזה בהגדרת המדדים.
source_identifier המזהה שמשמש לאיתור השירות. לפרטים נוספים, קראו את המאמר פורמט source_identifier.
connection_type SUBSCRIPTION למקור נתונים רציף (נדרש בשביל טריגרים של נתונים), או ON_DEMAND לאחזור לפי דרישה (לפרטים, ראו הגדרת מקורות נתונים).
אופציונלי
configuration

רק RPC ו-Configurable Publisher Registry. אובייקט להגדרת מקור הנתונים עם השדות הבאים:

type_url ה-FQN של הודעת ה-protobuf של ההגדרה.
‫value_json,
value_textproto,
או value
המטען הייעודי (payload) בפורמט JSON,‏ textproto או base64.
שדות לסוג החיבור SUBSCRIPTION
אופציונלי
sub_sampling_interval_ms
Pub/Sub בלבד. מספר שלם לא שלילי (באלפיות השנייה) כדי להגביל את תדירות ההודעות על ידי ציון המרווח המינימלי בין ההודעות.
אופציונלי
fetch_last_message
(ברירת מחדל: false)
Pub/Sub בלבד. בוליאני. אם true, מאחזר את ההודעה האחרונה בזמן החיבור.

לא כל האפשרויות זמינות לכל סוגי מקורות הנתונים. מידע מפורט זמין במדריך לשילוב מקורות נתונים.

הפורמט של source_identifier

שירות הטלמטריה מקבל כמה פורמטים של מזהי מקור. לסקירה כללית, קראו את המאמר הגדרת מקור נתונים בהגדרות של מדדים.

‫MCG מסיק את סוג ההודעה של protobuf מ-source_identifier רק אם הוא משתמש בפורמט Unit Type Name. אם אתם משתמשים ב-FQIN או בשם מותאם אישית (מ-Configurable Publisher Registry), המערכת של MCG לא יכולה להסיק את הסוג. במקרים כאלה, צריך לספק data_source_message_types. אם הסוג לא נמצא בקטלוג, צריך לספק גם את ההגדרה שלו ב-descriptor_protos.

דוגמה: הגדרת מקור נתונים

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

משתמשים בקטלוג לדוגמה בבסיס הקוד של ה-SDV כדי לזהות את השירות הרלוונטי. בהתאם לפורמט של source_identifier, מציינים את סוג ההודעה של protobuf‏ mcg.test.subpkg.speed_msg. בדרך כלל המהירות מתפרסמת בתדירות גבוהה, לכן כדאי להשתמש ב-sub_sampling_interval_ms כדי להגביל את העדכונים להודעה אחת בשנייה:

{
  "name": "SpeedSource",
  "source_identifier": "mcg.test.subpkg.speed_msg",
  "connection_type": "SUBSCRIPTION",
  "sub_sampling_interval_ms": 1000 // Limit updates to 1 per second
}

הגדרת הלוגיקה והעיבוד

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

הבעות

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

ביטויים יכולים לבטא חישובים אריתמטיים, תנאים לוגיים והשוואות נתונים. התחביר המלא, כולל אופרטורים ופונקציות, מפורט במאמר תחביר של ביטויים.

עדכניות הנתונים: כשביטוי ניגש למקור נתונים, התנהגות השליפה תלויה בסוג החיבור:

  • ‫SUBSCRIPTION: משתמש בהודעה האחרונה שהתקבלה ונשמרה במטמון של שירות הטלמטריה. (הערה: אם מוגדר sub_sampling_interval_ms, יכול להיות שההודעה תהיה שונה מההודעה האחרונה שפורסמה).
  • ‫ON_DEMAND: מפעיל קריאה מיידית לאחזור ההודעה החדשה מהשירות.

אילוצי סוגים

  • מערכים: אין תמיכה בגישה ישירה לאינדקס של מערך (לדוגמה, my_data_source.my_array[0]).
  • מניעת שגיאות הקלדה: חשוב לוודא שמשווים בין סוגים תואמים (לדוגמה, לא להשוות בין שדה מחרוזת לרשימה של מספרים שלמים).

דוגמה: ביטויים

בדוגמה הזו צריך לחלץ את ערך המהירות כדי לחשב את הממוצע שלו. הוא גם צריך לקבוע אם הרכב נוסע במהירות מופרזת (מעל 100 קמ"ש) בשביל הטריגר המותנה. אפשר למצוא את שמות השדות (במקרה הזה, speed) בהגדרה של הודעת ה-protobuf שבה משתמש מקור הנתונים. הביטויים הבאים מבצעים את הפעולה הזו:

  • ‫SpeedSource.speed: מאחזר את הערך של השדה speed ממקור הנתונים SpeedSource.
  • ‫SpeedSource.speed > 27.7: הערך שמוחזר הוא true אם המהירות גבוהה מ-27.7 מטר לשנייה (בערך 100 קמ"ש).

טריגרים: הגדרת הזמן שבו הפעולות מתרחשות

טריגרים מגדירים מתי הפעולות מתבצעות: הערכת אגרגטור, יצירת דוח או שליטה במחזור החיים של האיסוף. מוסיפים את כל הטריגרים שהוגדרו למערך triggers ברמה העליונה.

שדות של אובייקט טריגר (פריט ברשימה triggers)
name מזהה ייחודי של הטריגר הזה בהגדרת המדדים.
periodic
data
conditional
כדי להגדיר את ההתנהגות, צריך למלא בדיוק אחד מהשדות האלה.

טריגר נתונים

מופעל כשמקור נתונים מסוג SUBSCRIPTION מספק הודעה חדשה (קונספט).

שדות של האובייקט data (בטריגר)
source_name ה-name של ה-data_source שהטריגר הזה מאזין לו.

דוגמה: טריגר נתונים

בדוגמה, מעדכנים את חישוב המהירות הממוצעת בכל פעם ש-SpeedSource מפרסם הודעה חדשה. הטריגר הזה מופעל בכל פעם שמתרחש האירוע הבא:

{
  "name": "OnNewSpeed",
  "data": {
    "source_name": "SpeedSource" // Reference to the defined data source
  }
}

טריגר תקופתי

מופעל במרווחי זמן קבועים (קונספט).

שדות של האובייקט periodic (בטריגר)
period_ms מספר לא שלילי שמגדיר את המרווח באלפיות השנייה.

דוגמה: טריגר תקופתי

בדוגמה הזו נדרש דוח בכל דקה. הטריגר התקופתי הזה מופעל כל 60,000 אלפיות השנייה כדי ליצור את הדוח:

{
  "name": "EveryMinute",
  "periodic": {
    "period_ms": 60000 // 60,000 ms = 60 seconds
  }
}

טריגר מותנה

מופעל על סמך הערכה של ביטוי (קונספט). כדי להתחיל את ההערכה, צריך טריגר הורה אחד או יותר. לרוב מדובר בטריגר של נתונים למקורות הנתונים או לאגרגטורים בביטוי, או בטריגר תקופתי לדגימת נתונים.

שדות של האובייקט conditional (בטריגר)
triggers מערך עם שם אחד לפחות של טריגר הורה. כשטריגר הורה מופעל, הטריגר המותנה מעריך את הביטוי.
expression הביטוי שצריך להעריך. למידע נוסף על ביטויים
condition_type מציין מתי הטריגר צריך לפעול, על סמך הערכת הביטוי.
סוגי התנאים

המילון condition_type חייב להכיל בדיוק אחד מסוגי התנאים הזמינים כמפתח. מידע נוסף זמין במאמר טריגרים מותנים.

שדות של האובייקט condition_type (לא יכולים להתקיים בו-זמנית)
is_true

is_false
מופעל כשביטוי בוליאני מקבל את הערך true או false, בהתאמה.
rising_edge

אם הערך מספרי, הוא מופעל כשהערך עולה. אם הביטוי הוא בוליאני, הטריגר מופעל כשהוא משתנה מ-false ל-true.

יכול להכיל אובייקט rising_options (ראו אפשרויות של Edge).

falling_edge

אם מדובר בערך מספרי, הטריגר מופעל כשהערך יורד. אם הביטוי הוא בוליאני, הטריגר מופעל כשהוא משתנה מ-true ל-false.

יכול להכיל אובייקט falling_options (ראו אפשרויות של Edge).

all_changes

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

יכול להכיל את rising_options, את falling_options או את שניהם (ראו אפשרויות של Edge).

אפשרויות קצה

האובייקטים rising_options ו-falling_options מכילים את השדות הבאים. אם מציינים את המאפיין הזה, המעבר המתאים חייב לעמוד בדרישות לגבי משך הזמן. מעברים בלי אפשרויות מוגדרות מופעלים באופן מיידי.

שדות לאובייקטים של אפשרויות קצה
min_duration_ms מספר לא שלילי (באלפיות השנייה) שמציין כמה זמן התנאי צריך להתקיים במצב החדש לפני שהטריגר מופעל.
אופציונלי
require_exact
בוליאני. אם הערך הוא true, כל הערכים שפורסמו במהלך משך הזמן צריכים להיות זהים כדי שהטריגר יופעל.

דוגמה: טריגר מותנה

הטריגר הבא משתמש באפשרויות של קצוות. הוא מופעל אם המהירות עולה על 27.7 מטר לשנייה ונשארת גבוהה למשך 5 שניות לפחות:

{
  "name": "SpeedingFor5Seconds",
  "conditional": {
    "triggers": ["OnNewSpeed"],
    "expression": "SpeedSource.speed > 27.7",
    "condition_type": {
      "rising_edge": {
        "rising_options": {
          "min_duration_ms": 5000 // Condition must hold for 5s in new state
        }
      }
    }
  }
}

אגרגטורים: הגדרת אופן עיבוד הנתונים

שימוש באגרגטור לעיבוד נתונים זמניים עם שמירת מצב (מושג). מגדירים אגרגטור ומוסיפים אותו למערך aggregators.

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

שדות של אגרגטור (פריט ברשימה aggregators)
name מחרוזת שמוגדרת על ידי המשתמש ומזהה את האגרגטור הזה. ביטויים יכולים להפנות לצבירה הזו לפי השם שלה כדי לגשת לתוצאות שלה.
trigger_names מערך של שם טריגר אחד או יותר שגורם להערכה של הצבירה הזו.
אופציונלי
reset_on_get
ערך בוליאני, ברירת המחדל: `false`. אם הערך הוא `true`, המערכת מאפסת את מצב הצבירה אחרי שגורם צבירה אחר, דוח מדדים או טריגר מותנה ניגשים לערך שלו.
message_builder מגדיר את הנתונים שצריך לקרוא, לעבד ולצבור. השדות של הודעת הפלט הופכים למקור נתונים עבור דוחות ורכיבי צבירה אחרים. הוא משתמש ב-field_assignments, כאשר כל הקצאה מגדירה שדה בהודעת הפלט.

הכלי ליצירת הודעות

אובייקט message_builder מגדיר את מבנה הודעת הפלט ואת הלוגיקה של הצבירה שמשמשת לחישוב השדות שלה. הוא משמש גם לצבירת נתונים וגם להגדרות של דוחות.

שדות של אובייקט message_builder (בכלי צבירת הנתונים או בדוח)
message_type השם המלא של סוג ההודעה של protobuf לפלט. אם משמיטים את הפרמטר, MCG יוצר סוג הודעה בהתאמה אישית על סמך סוגי הפלט המשוערים של field_assignments. צריך להשתמש בזה רק אם בונה ההודעות הוא חלק מדוח מדדים, והדוח חייב להתאים להגדרה ספציפית ומוגדרת מראש של הודעת protobuf.
field_assignments מערך של אובייקטים להגדרת שדות. כל אובייקט מציין שדה בהודעת הפלט ואת הלוגיקה לחישוב הערך שלו.
שדות של אובייקט הקצאת שדות (פריט ברשימה field_assignments)
field_name שם שהמשתמש מגדיר לשדה. הוא מזהה את הערך הספציפי בתוך האובייקט כשמשתמשים בסימון נקודה בביטויים (aggregator_name.field_name).
aggregation

אובייקט שמגדיר איך המערכת מחשבת את הערך של השדה, עם השדות הבאים:

@type פונקציית הצבירה.

  • ‫avg, min, max, sum, stddev: סטטיסטיקות מתמטיות רגילות.
  • ‫count: סופר כמה פעמים הצובר הזה הופעל.
  • ‫delta: ההפרש בין הערך הנוכחי לערך הקודם.
  • ‫vector: יוצרת רשימה של ערכים (מאגר נתונים מעגלי).
  • ‫none: מעביר את הערך הגולמי.
expression ביטוי הקלט לצבירה. חובה לכל סוגי הצבירה, חוץ מ-count.
max_length רק ל-@type: "vector". מספר שלם אופציונלי שמגביל את גודל הווקטור ויוצר מאגר נתונים זמני (buffer) מעגלי.

דוגמה: אתר אגרגטור

לדוגמה, חישוב נתונים סטטיסטיים בין דוחות של דקות. האגרגטור הזה מופעל על ידי OnNewSpeed כדי לחשב את המהירות הממוצעת (avg), לספור את הקריאות (count) ולאחסן את 5 ערכי המהירות האחרונים (vector). מגדירים את reset_on_get לערך true. הפעולה הזו מאפסת את הנתונים הסטטיסטיים בכל פעם ש-MinuteReport קורא אותם, ומתחילה חלון איסוף חדש לצבירה בדקה הבאה:

{
  "name": "SpeedAggregator",
  "trigger_names": ["OnNewSpeed"], // Update aggregation on new speed data
  "reset_on_get": true, // Reset stats after they are read by the report configuration
  "message_builder": {
    "field_assignments": [
      {
        "field_name": "average_speed",
        "aggregation": {
          "@type": "avg",
          "expression": "SpeedSource.speed"
        }
      },
      {
        "field_name": "speed_reading_count",
        "aggregation": {
          "@type": "count" // Counts triggers (that is, processed speed readings) since last reset
        }
      },
      {
        "field_name": "speed_history_last5",
        "aggregation": {
          "@type": "vector",
          "expression": "SpeedSource.speed",
          "max_length": 5 // Keep last 5 readings
        }
      }
    ]
  }
}

יצירת פלט

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

אתם יכולים לשלוט ביצירת הדוחות באמצעות השדה trigger_names. בנוסף, אפשר להשתמש ב-report_initial כדי ליצור דוח מיד כשההגדרה מופעלת, וב-report_incomplete כדי ליצור דוח סופי כשיש הפרעה באיסוף הנתונים.

הערה: כדי לחבר את העיבוד לפלט, משתמשים בסוג הצבירה none (@type: "none") כדי לקרוא ערכים שחושבו מראש מ-Aggregator. בדרך כלל, דוחות הם תמונות מצב בלי שמירת מצב, ולכן הלוגיקה המורכבת של שמירת המצב נשארת בתוך האגרגטורים, והדוחות משמשים רק לעיצוב.

שדות של אובייקט הגדרת דוח (פריט ברשימה report_configs)
name שם ייחודי לדוח. השם הזה מופיע במטא-נתונים של הדוח שנוצר.
trigger_names מערך של שמות טריגרים שגורמים ליצירה ולפרסום של הדוח.
message_builder פרטים נוספים זמינים בקטע הכלי ליצירת הודעות. המאפיין הזה מגדיר את תוכן הדוח. הצבירות נבדקות רק כשהדוח מופעל. לדוגמה, צבירת וקטורים מוסיפה ערך אחד לכל דוח, וצבירת ספירה משקפת את מספר הדוחות.
אופציונלי
report_incomplete
(ברירת המחדל: "false")
ערך בוליאני. אם הערך הוא True, המערכת יוצרת דוח סופי כשהיא נכבית או כשאיסוף הנתונים מסתיים, גם אם חסרים נתונים.
אופציונלי
report_initial
(ברירת המחדל: "false")
ערך בוליאני. אם הערך הוא `true`, המערכת יוצרת דוח מיד כשהגדרת המדדים מופעלת.

דוגמה: הגדרת הדוח

בשלב האחרון, מגדירים את הדוח לדוגמה. הוא מופעל על ידי EveryMinute. הוא קורא את המהירות הממוצעת המחושבת ואת מספר הקריאות מ-SpeedAggregator באמצעות צבירה מסוג none, שמעבירה את הערך שנצבר מראש לדוח:

{
  "name": "MinuteReport",
  "trigger_names": ["EveryMinute"], // Generate report every minute
  "message_builder": {
    "field_assignments": [
      {
        "field_name": "average_speed",
        "aggregation": {
          "@type": "none", // Read the value directly from the aggregator
          "expression": "SpeedAggregator.average_speed"
        }
      },
      {
        "field_name": "reading_count",
        "aggregation": {
          "@type": "none",
          "expression": "SpeedAggregator.speed_reading_count"
        }
      }
    ]
  }
}

שדות ברמה העליונה

בנוסף למערכים data_sources,‏ aggregators,‏ triggers ו-report_configs, התיאור של הגדרת המדדים דורש הפניה לקטלוג האותות. אפשר גם לכלול שדות אופציונליים כדי להקצות UUID ספציפי ולנהל את מחזור החיים של האוסף.

הגדרת UUID

לכל MetricsConfig נדרש מזהה ייחודי אוניברסלי (UUID). אם תספקו existing_uuid, המערכת תשתמש בו. אחרת, המערכת יוצרת מזהה אקראי. כדי לשמור על עקביות בין פריסות וכלים, צריך לציין existing_uuid.

המחרוזת חייבת להיות UUID תקין עם מקפים, שמכיל רק אותיות קטנות.

"existing_uuid": "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8",

הגדרות של אותות

כדי לאמת את השמות והסוגים של האותות, ל-MCG נדרשת גישה לקטלוג האותות של הרכב. זהו protobuf FileDescriptorSet שמכיל את הגדרות ה-VSIDL .proto (ארוזות ומועלות ל-MCG). פרטים נוספים על יצירה והעלאה של קטלוג זמינים במאמר קטלוגים של אותות רכב.

מציינים את גרסת הקטלוג בשדה vs_version של אובייקט ה-JSON:

"vs_version": "v1.0",

הגדרת טריגרים של מחזור חיים

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

כך אפשר להתאים את איסוף הנתונים לדפוסי השימוש ברכב, כמו "נסיעה" (IgnitionOn עד IgnitionOff) או "סשן טעינה", בלי להשבית את ההגדרות האישיות.

  • שליטה בסשן (התחלה/השהיה): משתמשים ב-start_trigger_name וב-stop_trigger_name כדי לשלוט במועד האיסוף. לדוגמה, כדי לאסוף נתונים רק כשהרכב בנסיעה, משתמשים ב-IgnitionOn כטריגר להתחלה וב-IgnitionOff כטריגר לעצירה. ההגדרה נשארת פעילה במכשיר, אבל למעשה היא "מושהית" (מפסיקה לאסוף ולעבד נתונים) כשהטריגר להפסקה מופעל, ומתחדשת רק כשהטריגר להפעלה מופעל שוב.

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

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

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

שדות מחזור חיים ברמה העליונה (אובייקט ברמה הבסיסית)
אופציונלי
start_trigger_name
השם של הטריגר שמתחיל את סשן האיסוף. אפשר להגדיר בלי stop_trigger_name.
אופציונלי
stop_trigger_name
השם של טריגר שמשהה את סשן האיסוף (לדוגמה, כשהרכב לא בתנועה). אם המדיניות הזו מוגדרת, חובה להגדיר גם את start_trigger_name.
אופציונלי
deactivate_trigger_name
השם של טריגר שמסיים את הפעולה של `MetricsConfig` ומשבית אותו לגמרי.

מתקדם: הגדרות proto בהתאמה אישית

יש שני מקרים עיקריים שבהם vs_version לבדו לא מספיק כדי ש-MCG יבין את כל סוגי ההודעות בתיאור של הגדרת המדדים:

  1. כשל בהסקת סוג: כפי שמוסבר בפורמט source_identifier, MCG לא יכול להסיק את הסוג כש-source_identifier משתמש ב-FQIN או בשם מותאם אישית.
  2. הודעות בהתאמה אישית: התיאור של הגדרת המדדים משתמש בהודעות protobuf שלא נמצאות בקטלוג VSIDL שצוין ב-vs_version. זה קורה כשמגדירים את message_type ב-message_builder לפורמט של דוח בהתאמה אישית.

במקרים כאלה, משתמשים ב-data_source_message_types כדי לעזור ל-MCG להסיק סוגים וב-descriptor_protos כדי לספק הגדרות של הודעות.

data_source_message_types

ממפים את המחרוזת source_identifier לסוג ההודעה המלא של protobuf. המפתח ב-data_source_message_types צריך להתאים לערך של source_identifier מהרשומה של data_sources:

"data_source_message_types": {
  "MyCustomSpeedService": "com.sdv.example.SampleMessage"
}

descriptor_protos

צריך לספק הגדרות לכל סוגי ההודעות שנעשה בהם שימוש ב-data_source_message_types או ב-message_builder, שלא נמצאים ב-vs_version שהוגדר.

מעבירים את הערך של descriptorpb.FileDescriptorSet בקידוד Base64 במערך descriptor_protos. אפשר ליצור את זה מקובצי .proto באמצעות המהדר של Protobuf‏ protoc.

"descriptor_protos": [
  "Cu8BCiZtY2cvdGVzdGRhdGEvbWF4YXZnY3..." // Base64 string
]

דוגמה: תיאור מלא של ההגדרה

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

הרכיבים הם:

  • מקור נתונים (SpeedSource) כדי לקבל נתוני מהירות עד פעם בשנייה.
  • טריגר נתונים (OnNewSpeed) שמופעל כשנשלחים נתונים מ-SpeedSource.
  • טריגר תקופתי (EveryMinute) שמופעל כל 60 שניות.
  • אגרגטור (SpeedAggregator) שמשתמש ב-OnNewSpeed כדי לחשב את המהירות הממוצעת, לספור את הקריאות ולאחסן את הערכים האחרונים, ומתאפס כשהוא נקרא.
  • הגדרת דוח (MinuteReport) שמשתמשת ב-EveryMinute כדי להפעיל דוח שמכיל את המהירות הממוצעת ואת הספירה מ-SpeedAggregator.
  • שדות ברמה העליונה (existing_uuid,‏ vs_version) כדי לזהות את הגדרת המדדים ולציין באיזה קטלוג VSIDL להשתמש להגדרות האותות.

כשמשלבים את החלקים האלה, הם יוצרים את התיאור המלא של הגדרת המדדים:

{
  "existing_uuid": "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8", // Unique identifier for the configuration
  "vs_version": "example_version", // Version of the VSIDL catalog to use
  "data_sources": [
    {
      "name": "SpeedSource",
      "source_identifier": "mcg.test.subpkg.speed_msg",
      "connection_type": "SUBSCRIPTION",
      "sub_sampling_interval_ms": 1000
    }
  ],
  "aggregators": [
    {
      "name": "SpeedAggregator",
      "trigger_names": ["OnNewSpeed"],
      "reset_on_get": true,
      "message_builder": {
        "field_assignments": [
          {
            "field_name": "average_speed",
            "aggregation": {
              "@type": "avg",
              "expression": "SpeedSource.speed"
            }
          },
          {
            "field_name": "speed_reading_count",
            "aggregation": { "@type": "count" }
          },
          {
            "field_name": "speed_history_last5",
            "aggregation": {
              "@type": "vector",
              "expression": "SpeedSource.speed",
              "max_length": 5
            }
          }
        ]
      }
    }
  ],
  "triggers": [
    {
      "name": "OnNewSpeed",
      "data": { "source_name": "SpeedSource" }
    },
    {
      "name": "EveryMinute",
      "periodic": { "period_ms": 60000 }
    }
  ],
  "report_configs": [
    {
      "name": "MinuteReport",
      "trigger_names": ["EveryMinute"],
      "message_builder": {
        "field_assignments": [
          {
            "field_name": "average_speed",
            "aggregation": {
              "@type": "none",
              "expression": "SpeedAggregator.average_speed"
            }
          },
          {
            "field_name": "reading_count",
            "aggregation": {
              "@type": "none",
              "expression": "SpeedAggregator.speed_reading_count"
            }
          }
        ]
      }
    }
  ]
}

תבנית של קובץ עזר

הגדרת ה-API מופיעה במאמרי העזרה של ה-API.

בקטעים הבאים מפורטות כל ההגדרות של המדדים. אפשר להשתמש בו כמדריך ליצירת תיאור משלכם להגדרת מדדים.

שדות ברמה העליונה

{
  "existing_uuid": "1cbec8e6-46f5-4649-9fa2-09f81bc93f8b", // Optional
  "vs_version": "example_version", // Optional
  "descriptor_protos": ["..."], // Optional. Base64 encoded FileDescriptorSet
  "data_source_message_types": {
    "ExampleServiceName": "com.example.ProtoMessage"
  }, // Optional
  "start_trigger_name": "DataTriggerExample", // Optional
  "stop_trigger_name": "ConditionalTriggerExample", // Optional
  "deactivate_trigger_name": "PeriodicTriggerExample" // Optional
}

קלט: מקורות נתונים ואגרגטורים

{
  "data_sources": [
    {
      "name": "SubscriptionExample",
      "source_identifier": "com.example.sdv.ExampleMessage|example-unit",
      "connection_type": "SUBSCRIPTION", // Options: SUBSCRIPTION (default), ON_DEMAND
      "sub_sampling_interval_ms": 100, // Optional
      "fetch_last_message": false // Optional. Default: false
    },
    {
      "name": "RegistryExample",
      // Configurable Publisher Registry-based publisher (matches data_source_message_types)
      "source_identifier": "ExampleServiceName",
      "connection_type": "SUBSCRIPTION"
    },
    {
      "name": "GetterExample",
      "source_identifier": "com.example.sdv.ExampleConfig|example-unit",
      "connection_type": "ON_DEMAND",
      "configuration": {
        "type_url": "type.googleapis.com/example.Config",
        "value_json": {} // Or value_textproto, value (base64)
      }
    }
  ],
  "aggregators": [
    {
      "name": "AggregatorExample",
      "trigger_names": ["DataTriggerExample"],
      "reset_on_get": false, // Optional. Default: false. If true, resets state after it's read
      "message_builder": {
        "message_type": ".com.example.AggregatedMessage", // Optional
        "field_assignments": [
          {
            "field_name": "avg_example",
            "aggregation": {
              // Options: avg, count, min, max, sum, stddev, delta, vector, none
              "@type": "avg",
              "expression": "SubscriptionExample.value"
            }
          },
          {
            "field_name": "count_example",
            "aggregation": {
              "@type": "count" // Counts number of evaluations. No expression needed
            }
          },
          {
            "field_name": "vector_example",
            "aggregation": {
              "@type": "vector",
              "expression": "SubscriptionExample.value",
              "max_length": 10 // Optional. If set, creates a ring buffer
            }
          }
        ]
      }
    }
  ]
}

לוגיקה ועיבוד: טריגרים

{
  "triggers": [
    {
      "name": "PeriodicTriggerExample",
      "periodic": { "period_ms": 1000 }
    },
    {
      "name": "DataTriggerExample",
      "data": { "source_name": "SubscriptionExample" }
    },
    {
      "name": "ConditionalTriggerExample",
      "conditional": {
        "triggers": ["PeriodicTriggerExample"],
        "expression": "SubscriptionExample.value > 0",
        "condition_type": {
          // Options: is_true, is_false, rising_edge, falling_edge, all_changes
          "rising_edge": {
            "rising_options": { "min_duration_ms": 0, "require_exact": false }
          }
        }
      }
    }
  ]
}

פלט: הגדרות הדוח

{
  "report_configs": [
    {
      "name": "ReportExample",
      "trigger_names": ["PeriodicTriggerExample"],
      "report_incomplete": false, // Optional. Default: false
      "report_initial": false, // Optional. Default: false
      "message_builder": {
        "message_type": ".com.example.ReportMessage", // Optional. Must be defined in VSIDL catalog or descriptor_protos. Message type will be inferred if not provided
        "field_assignments": [
          {
            "field_name": "avg_example",
            "aggregation": {
              "@type": "none", // Passthrough since aggregation is done in AggregatorExample
              "expression": "AggregatorExample.avg_example"
            }
          }
        ]
      }
    }
  ]
}

תחביר של ביטויים

קטגוריה תחביר תיאור
גישה לנתונים source_name
source_name.field
source_name.field.subfield
גישה להודעה מלאה ממקור נתונים או מצובר
גישה לשדה ספציפי בהודעה (כולל שדות בתצוגת עץ)
חשבון +, -, *, /, %, ** מתמטיקה רגילה. ‫** היא העלאה בחזקה.
לוגי &&, ||, !, ^ AND, ‏ OR, ‏ NOT, ‏ XOR.
יחסי ==, !=, <, <=, >, >= == ו-!= פועלים בכל הסוגים. באחרים צריך להזין מספרים.
רשימה contains(list, item)
doesnotcontain(list, item)
alleq(list, value)
פועלת על וקטורים (מערכים). הפונקציה alleq(list, value) מחזירה את הערך true אם כל הפריטים ב-list שווים ל-value.
פונקציות timestamp(clock_type) השעה הנוכחית במיקרו-שניות.
clock_type: ‫REALTIME_CLOCK או
MONOTONIC_TIME_SINCE_BOOT_OR_RESUME
abs(n) ערך מוחלט
floor(n), round(n), ceil(n) פונקציות עיגול
סדר הפעולות () קיבוץ רגיל לפי קדימות