כדי לספק חוויית משתמש עקבית יותר, כדאי לפרש שגיאות ולהגיב להן באופן יזום. בין אם אתם מפתחים תהליכי עבודה אוטומטיים בענן או יוצרים אינטראקציה עם ממשקי API מרוחקים, ספריות הלקוח של Rust מספקות דרכים לטפל בשגיאות בצורה חלקה. במדריך הזה נסביר איך:
- טיפול בשגיאות: בודקים את סוגי השגיאות ומפצלים את הלוגיקה של האפליקציה על סמך קודי סטטוס של השירות, למשל יצירת משאב חסר כשנתקלים בשגיאה
NotFound. - בדיקת פרטי השגיאה: אפשר לחלץ ולבדוק פרטי שגיאה מפורטים – כמו הפרות של שדות בקשות שגויות או כשלים במכסת השימוש – שמוחזרים על ידי Google Cloud השירותים כדי לפתור בעיות ב-API ולהתאים באופן דינמי את התנהגות זמן הריצה.
- פתרון שגיאות של קישור: מפרשים ופותרים שגיאות של קישור HTTP בצד הלקוח שנגרמות משדות בקשה לא תקינים או חסרים, כדי לוודא שהבקשות מגיעות לשירות בצורה חלקה.
דרישות מוקדמות
במדריך הזה נשתמש בשירות Secret Manager וב-Cloud Natural Language API כדי להדגים טיפול בשגיאות. כדי להריץ את הדוגמאות, קודם צריך:
- מפעילים את השירות Secret Manager.
- מפעילים את Cloud Natural Language API.
- מגדירים אימות.
תלויות
כדי להוסיף את יחסי התלות הנדרשים לקובץ Cargo.toml, משתמשים בפקודה הבאה:
cargo add google-cloud-secretmanager-v1 google-cloud-gax crc32c google-cloud-language-v2
טיפול בשגיאות
ספריות הלקוח של Rust מאפשרות לכם להציג שגיאות ולהגיב להן. לדוגמה, אפשר להשתמש באיתור שגיאות כדי להסתעף מההתנהגות: דפוס נפוץ בשירותי ענן הוא שימוש במשאב כאילו המאגר שלו קיים, ויצירת המאגר רק אם נתקלים בשגיאה. אם המאגר בדרך כלל קיים, הגישה הזו יעילה יותר מאשר בדיקה אם המאגר קיים לפני שליחת הבקשה.
בדוגמה הבאה מוצג אופן הטיפול במשאב חסר על ידי תפיסת השגיאה כשמנסים לעדכן סוד ב-Secret Manager – ויצירת הסוד אם הוא עדיין לא קיים.
מנסים ליצור גרסה חדשה של הסוד:
אם הפעולה
update_attemptמצליחה, מדפיסים את התוצאה ומחזירים:אם הפעולה
update_attemptנכשלת, צריך להסביר את הסיבה לכשל. יכול להיות שהבקשה נכשלה מסיבות רבות, למשל ניתוק של החיבור או שגיאה בטוקנים של האימות. אפשר לטפל ברוב השגיאות האלה באמצעות מדיניות של ניסיון חוזר. מחפשים שגיאות שהוחזרו על ידי השירות:מחפשים שגיאה שמתאימה לסוד חסר:
אם נתקלתם בשגיאה 'לא נמצא' (
Code::NotFound), נסו ליצור את הסוד:מנסים להוסיף שוב את הגרסה הסודית. הפעם, מחזירים שגיאה אם משהו נכשל:
דוגמת קוד: פונקציה ראשית (sample)
הקוד המלא של הדוגמה הזו מחולק לשלושה חלקים: פונקציית התיאום הראשית (sample), ואחריה שתי פונקציות העזר שלה (update_attempt ו-create_secret).
הפונקציה sample מנסה להוסיף גרסה חדשה לסוד. היא מאתרת את השגיאה שמוחזרת על ידי הלקוח ובודקת אם השגיאה היא שגיאת Code::NotFound. אם הסוד לא נמצא, הפונקציה יוצרת את הסוד שחסר בהתחלה ומנסה לעדכן שוב.
דוגמת קוד: שיטת עזר (update_attempt)
השיטה update_attempt מנסה להוסיף גרסה סודית, ומחשבת את סכום הביקורת CRC32c של נתוני המטען הייעודי:
דוגמת קוד: שיטת עזר (create_secret)
שיטת העזר create_secret יוצרת סוד חסר ומגדירה מדיניות מותאמת אישית לניסיון חוזר:
בדיקת פרטי השגיאה
שירותים מסוימים של Google Cloud כוללים פרטים נוספים על שגיאות כשבקשות נכשלות.
כדי לעזור בפתרון בעיות, ספריות הלקוח של Rust כוללות את הפרטים האלה כשמעצבים שגיאות באמצעות std::fmt::Display. אתם יכולים לבדוק את הפרטים האלה ולשנות את אופן הפעולה של האפליקציה בהתאם.
רק שגיאות שהשירות מחזיר מכילות מידע מפורט. ספריות הלקוח מחזירות enum StatusDetails עם סוגים שונים של פרטי שגיאה.
שליפת פרטי השגיאה
בדוגמה הזו נשלחת בכוונה בקשה לא תקינה אל Cloud Natural Language API ונבדקת השגיאה שמתקבלת.
יוצרים לקוח:
שליחת בקשה (בדוגמה הזו, חסר שדה מפתח):
אפשר לחלץ את השגיאה מהתוצאה באמצעות פונקציות Rust רגילות. סוג השגיאה מציג את כל פרטי השגיאה בפורמט שקריא לאנשים:
הפלט אמור להיראות כך:
request failed with error Error {
kind: Service {
status_code: Some(
400,
),
headers: Some(
{
"vary": "X-Origin",
"vary": "Referer",
"vary": "Origin,Accept-Encoding",
"content-type": "application/json; charset=UTF-8",
"date": "Sat, 24 May 2025 17:19:49 GMT",
"server": "scaffolding on HTTPServer2",
"x-xss-protection": "0",
"x-frame-options": "SAMEORIGIN",
"x-content-type-options": "nosniff",
"alt-svc": "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000",
"accept-ranges": "none",
"transfer-encoding": "chunked",
},
),
status: Status {
code: InvalidArgument,
message: "One of content, or gcs_content_uri must be set.",
details: [
BadRequest(
BadRequest {
field_violations: [
FieldViolation {
field: "document.content",
description: "Must have some text content to annotate.",
reason: "",
localized_message: None,
_unknown_fields: {},
},
],
_unknown_fields: {},
},
),
],
},
},
}
בדיקה של פרטי השגיאה באופן פרוגרמטי
לפעמים צריך לבדוק את פרטי השגיאה באופן פרוגרמטי. בדוגמה הזו, המערכת עוברת על מבנה הנתונים ומדפיסה את השדות הרלוונטיים ביותר.
רק שגיאות שהשירות מחזיר מכילות מידע מפורט, לכן קודם צריך לשלוח שאילתה לגבי השגיאה כדי לראות אם היא מכילה את סוג השגיאה הנכון. אם כן, תוכלו לפרט מידע ברמה העליונה על השגיאה:
חוזרים על הפעולה עם הפרטים:
כמו שצוין קודם, ספריות הלקוח מחזירות enum עם סוגים שונים של פרטי שגיאה StatusDetails. בדוגמה הזו נבדקות רק שגיאות BadRequest:
התג BadRequest מכיל רשימה של שדות שלא עומדים בדרישות. אפשר לחזור על הפעולה ולהדפיס את הפרטים של כל אחד מהם:
מידע כזה יכול להיות שימושי במהלך הפיתוח. יכול להיות שיהיה שימוש בענפים אחרים של
StatusDetails, כמו
QuotaFailure, בזמן הריצה כדי להגביל את קצב הבקשות של אפליקציה.
הפלט הצפוי
הפלט מפרטי השגיאה אמור להיראות כך:
status.code=400, status.message=One of content, or gcs_content_uri must be set., status.status=Some("INVALID_ARGUMENT")
the request field document.content has a problem: "Must have some text content to annotate."
דוגמת קוד: בדיקת פרטי השגיאה
הפונקציה sample שולחת בקשה לא תקינה בכוונה אל Cloud Natural Language API כדי ליצור שגיאת שירות. הוא מאתר את השגיאה ומחלץ באופן אוטומטי את StatusDetails כדי לבדוק ולהדפיס הפרות ספציפיות של השדה BadRequest.
פתרון שגיאות שקשורות לקישור
כשמשתמשים ב-HTTP כדי לשלוח בקשות לשירותים Google Cloud , הבקשה משתמשת במזהה Uniform Resource Identifier (URI) כדי לציין משאב. חלק מה-RPC מתאימים לכמה URI, והתוכן של הבקשה קובע באיזה URI נעשה שימוש.
ספריית הלקוח בודקת את כל כתובות ה-URI האפשריות ומחזירה שגיאת איגוד רק אם אף אחת מהן לא פועלת. בדרך כלל זה קורה כששדה חסר או כשהפורמט שלו לא תקין.
אם הבקשה לא כוללת שדות עם פורמט תקין לכל URI אפשרי, יכול להיות שתיתקלו בשגיאת קישור:
Error: cannot find a matching binding to send the request: at least one of the
conditions must be met: (1) field `name` needs to be set and match the template:
'projects/*/secrets/*' OR (2) field `name` needs to be set and match the
template: 'projects/*/locations/*/secrets/*'
השגיאה בדוגמה הקודמת התרחשה כי הדוגמה מנסה לאחזר את הפרטים של משאב בלי לציין את השם שלו. באופן ספציפי, השדה name ב-GetSecretRequest נדרש, אבל לא מוגדר בדוגמה:
איך לפתור שגיאות של קישור
כדי לתקן את השגיאה, צריך להגדיר את השדה הנדרש כך שיתאים לאחת מהתבניות שמוצגות בהודעת השגיאה:
'projects/*/secrets/*''projects/*/locations/*/secrets/*'
כל אחת מהתבניות מאפשרת לספריית הלקוח לשלוח בקשה לשרת. לדוגמה, הקוד הבא תואם לתבנית הראשונה:
לחלופין, הקוד הבא תואם לתבנית השנייה:
הסבר על תבניות
הודעת השגיאה של שגיאת binding כוללת מחרוזות תבנית שמציגות ערכים אפשריים לשדות הבקשה. רוב מחרוזות התבניות כוללות את התווים * ו-** כתווים כלליים להתאמה לערכי השדות.
תו כללי יחיד לחיפוש
התו הכללי לחיפוש * לבדו מייצג מחרוזת לא ריקה ללא /. אפשר לחשוב על זה כעל הביטוי הרגולרי [^/]+.
הנה כמה דוגמאות:
| תבנית | קלט | יש התאמה? |
|---|---|---|
* |
simple-string-123 |
true |
projects/* |
projects/p |
true |
projects/*/locations |
projects/p/locations |
true |
projects/*/locations/* |
projects/p/locations/l |
true |
* |
"" (ריק) |
false |
* |
string/with/slashes |
false |
projects/* |
projects/ (ריק) |
false |
projects/* |
projects/p/ (קו נטוי נוסף) |
false |
projects/* |
projects/p/locations/l |
false |
projects/*/locations |
projects/p |
false |
projects/*/locations |
projects/p/locations/l |
false |
תו כללי כפול לחיפוש
פחות נפוץ הוא התו הכללי **, שמייצג כל מחרוזת. המחרוזת יכולה להיות ריקה או להכיל כל מספר של לוכסנים (/). אפשר לחשוב עליה כעל הביטוי הרגולרי .*.
כשמגדירים תבנית שמסתיימת ב-/**, לא חובה להוסיף את לוכסן ההתחלה.
| תבנית | קלט | יש התאמה? |
|---|---|---|
** |
"" |
true |
** |
simple-string-123 |
true |
** |
string/with/slashes |
true |
projects/*/** |
projects/p |
true |
projects/*/** |
projects/p/locations |
true |
projects/*/** |
projects/p/locations/l |
true |
projects/*/** |
locations/l |
false |
projects/*/** |
projects//locations/l |
false |
בדיקת שגיאות בקישור
אם אתם צריכים לבדוק את השגיאה באופן פרוגרמטי, בדקו אם זו שגיאת קישור והמירו אותה ל-BindingError: