רישום ביומן וצפייה ביומנים ב-Cloud Run

‫Cloud Run שולח יומני עומסי עבודה אל Cloud Logging כדי שתוכלו לעקוב אחרי התקינות, לבדוק את התנועה ולפתור שגיאות באפליקציות. הצגה וכתיבה של יומנים מובְנים עוזרות לכם לאבחן בעיות בזמן הריצה במשאבים שלכם ב-Cloud Run.

ב-Cloud Run נאספים שלושה סוגים של יומנים. ביומני הבקשות מתועדות בקשות נכנסות לשירותים. יומני קונטיינרים מתעדים את הפלט מהקוד שלכם בכל המשאבים, כשהוא נכתב במיקומים נתמכים שמתוארים במאמר כתיבת יומני קונטיינרים. ביומני המערכת מתועדים אירועים בפלטפורמה של כל המשאבים ב-varlog/system.

צפייה ביומנים

יש כמה דרכים להציג את היומנים של משאב Cloud Run:

שתי השיטות לצפייה ביומנים במסוף בודקות את אותם יומנים שמאוחסנים ב-Cloud Logging, אבל ב-Logs Explorer של Cloud Logging יש יותר פרטים ויותר יכולות סינון.

צפייה ביומנים ב-Cloud Run

אתם יכולים לצפות ביומנים בדף Cloud Run של המשאבים הבאים:

שירותים

  1. נכנסים לדף Services של Cloud Run במסוף Google Cloud :

    כניסה ל-Cloud Run

  2. לוחצים על השירות ברשימה שמוצגת.

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

תעסוקה

כדי לראות את יומני המשימות בדף Cloud Run:

  1. נכנסים לדף Jobs של Cloud Run במסוף Google Cloud :

    כניסה ל-Cloud Run

  2. מאתרים את המשימה ברשימת המשימות ולוחצים עליה.

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

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

מאגרי Worker

כדי לראות את היומנים של מאגר ה-Workers בדף Cloud Run:

  1. במסוף Google Cloud , נכנסים לדף Worker pools ב-Cloud Run:

    כניסה ל-Cloud Run

  2. לוחצים על מאגר ה-workers ברשימה שמוצגת.

  3. לוחצים על הכרטיסייה Logs כדי לקבל את יומני הבקשות והקונטיינרים של כל הגרסאות של מאגר ה-Workers הזה. אפשר לסנן לפי רמת החומרה של היומן.

מכונות

כדי לראות את יומני המכונות, קראו את ההוראות במאמרים הצגת יומנים ב-Cloud Logging ורישום ביומן ביקורת ב-Cloud Run.

הצגת יומנים ב-Cloud Logging

כדי לראות את היומנים של Cloud Run ב-Cloud Logging Logs Explorer:

  1. נכנסים לדף Logs Explorer במסוףGoogle Cloud :

    כניסה לדף Logs Explorer

  2. בוחרים פרויקט קיים ב- Google Cloud בחלק העליון של הדף, או יוצרים פרויקט חדש.

  3. בתפריטים הנפתחים, בוחרים את המשאב:

    • גרסת Cloud Run של שירות
    • משימה ב-Cloud Run למשימה
    • מאגר Worker ב-Cloud Run למאגר Worker
    • מכונות של Cloud Run למכונה

מידע נוסף זמין במאמר שימוש ב-Logs Explorer.

הצגת יומני שירות באמצעות Google Cloud CLI

אתם יכולים להשתמש ב-Google Cloud CLI כדי להציג יומנים בזמן אמת או לקרוא יומנים קיימים של שירות Cloud Run בשורת הפקודה. כברירת מחדל, היומנים מעוצבים בפורמט של שורה אחת שמותאם למסוף.

כדי לעקוב אחרי יומנים, צריך להתקין את הרכיב log-streaming ב-Google Cloud CLI. אם הרכיב לא מותקן, תתבקשו להתקין אותו כשתצטרכו.

הצגת יומני tailing בשורת הפקודה

בשירות Cloud Run, אתם יכולים לעקוב אחרי היומנים בזמן אמת ישירות משורת הפקודה:

gcloud beta run services logs tail SERVICE --project PROJECT-ID

מחליפים את מה שכתוב בשדות הבאים:

  • ‫SERVICE: השם של שירות Cloud Run.
  • ‫PROJECT-ID: מזהה הפרויקט ב- Google Cloud . כדי לראות את מזהה הפרויקט, מריצים את הפקודה gcloud config get-value project.

קריאת יומנים בשורת הפקודה

בשירות Cloud Run, אפשר לקרוא יומנים קיימים בשתי דרכים:

  • בפורמט שמותאם לקונסולה:
    gcloud run services logs read SERVICE --limit=10 --project PROJECT-ID
  • ישירות מ-Cloud Logging:
    gcloud logging read "resource.type=cloud_run_revision AND resource.labels.service_name=SERVICE" --project PROJECT-ID --limit 10

מחליפים את מה שכתוב בשדות הבאים:

  • ‫SERVICE: השם של שירות Cloud Run.
  • ‫PROJECT-ID: מזהה הפרויקט ב- Google Cloud . כדי לראות את מזהה הפרויקט, מריצים את הפקודה gcloud config get-value project.

הצגת יומני שירות ב-Cloud Code

כדי להציג את היומנים ב-Cloud Code, קראו את המדריכים של IntelliJ ו-Visual Studio Code.

קריאת יומנים באופן פרוגרמטי

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

הפורמט והתוכן של יומני התאמת קנה המידה של המכונות

כשמופעים חדשים מתחילים בשירות Cloud Run, ב-Cloud Logging מופיעות רשומות ביומן בשם varlog/system שמסבירות למה כל מופע נוצר. הרשומה ביומן מופיעה בפורמט הבא:

Starting new instance. Reason: REASON - DESCRIPTION

בטבלה הבאה מפורטים תיאורי המכונות:

סיבה תיאור
MANUAL_OR_CUSTOMER_MIN_INSTANCE המכונה הופעלה בגלל מספר מינימלי של מכונות או התאמה ידנית לעומס שהלקוח הגדיר.
AUTOSCALING המכונה הופעלה בגלל גורמים לקביעת קנה מידה שהוגדרו (כמו ניצול מעבד, קצב העברת נתונים של בקשות וכו') או בגלל שאין מספיק קיבולת קיימת לתנועה הנוכחית.
DEPLOYMENT_ROLLOUT המכונה הופעלה בגלל העברת תנועה בין גרסאות בעקבות פריסה, התאמה של חלוקת התנועה או בדיקת תקינות של הפריסה.

כתיבת יומני קונטיינרים

כשכותבים יומנים מהשירות, מהמשימה או ממאגר ה-workers, הם נאספים באופן אוטומטי על ידי Cloud Logging, כל עוד היומנים נכתבים באחד מהמיקומים הבאים:

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

יומני הקונטיינרים שנכתבים במיקומים הנתמכים האלה משויכים באופן אוטומטי לשירות, לגרסה ולמיקום של Cloud Run, למאגר ה-workers, לגרסה ולמיקום של Cloud Run או למשימה של Cloud Run. חריגות שכלולות ביומנים האלה מתועדות ומדווחות ב-Error Reporting.

הרישום ביומן שמשולב ב-App Engine מאזן בין אמינות לבין שימוש במשאבים, והוא אמור להתאים לרוב האפליקציות. כתיבת רשומות ביומן באמצעות רישום משולב לא צורכת מכסה של מספר הבקשות של entries.write לדקה ב-Cloud Logging API.

אם לאפליקציה שלכם יש דרישות לנפח גבוה יותר או לאמינות, מומלץ להשתמש ישירות ב-Cloud Logging API, כספרייה בתוך האפליקציה או כקונטיינר משני (sidecar) נפרד.

שימוש בטקסט פשוט לעומת JSON מובנה ביומנים

כשכותבים יומנים, אפשר לשלוח מחרוזת טקסט פשוטה או שורה אחת של JSON שעבר סריאליזציה, שנקרא גם נתונים "מובְנים". המידע הזה נאסף ומנותח על ידי Cloud Logging ומועבר אל jsonPayload. לעומת זאת, הודעת ה-SMS הפשוטה ממוקמת ב-textPayload.

כתיבת יומנים מובְנים

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

Node.js


// Uncomment and populate this variable in your code:
// const project = 'The project ID of your function or Cloud Run service';

// Build structured log messages as an object.
const globalLogFields = {};

// Add log correlation to nest all log messages beneath request log in Log Viewer.
// (This only works for HTTP-based invocations where `req` is defined.)
if (typeof req !== 'undefined') {
  const traceHeader = req.header('X-Cloud-Trace-Context');
  if (traceHeader && project) {
    const [trace] = traceHeader.split('/');
    globalLogFields['logging.googleapis.com/trace'] =
      `projects/${project}/traces/${trace}`;
  }
}

// Complete a structured log entry.
const entry = Object.assign(
  {
    severity: 'NOTICE',
    message: 'This is the default display field.',
    // Log viewer accesses 'component' as 'jsonPayload.component'.
    component: 'arbitrary-property',
  },
  globalLogFields
);

// Serialize to a JSON string and output.
console.log(JSON.stringify(entry));

Python

# Uncomment and populate this variable in your code:
# PROJECT = 'The project ID of your Cloud Run service';

# Build structured log messages as an object.
global_log_fields = {}

# Add log correlation to nest all log messages.
# This is only relevant in HTTP-based contexts, and is ignored elsewhere.
# (In particular, non-HTTP-based Cloud Functions.)
request_is_defined = "request" in globals() or "request" in locals()
if request_is_defined and request:
    trace_header = request.headers.get("X-Cloud-Trace-Context")

    if trace_header and PROJECT:
        trace = trace_header.split("/")
        global_log_fields[
            "logging.googleapis.com/trace"
        ] = f"projects/{PROJECT}/traces/{trace[0]}"

# Complete a structured log entry.
entry = dict(
    severity="NOTICE",
    message="This is the default display field.",
    # Log viewer accesses 'component' as jsonPayload.component'.
    component="arbitrary-property",
    **global_log_fields,
)

print(json.dumps(entry))

המשך

המבנה של כל רשומה ביומן מסופק על ידי סוג Entry:


// Entry defines a log entry.
type Entry struct {
	Message  string `json:"message"`
	Severity string `json:"severity,omitempty"`
	Trace    string `json:"logging.googleapis.com/trace,omitempty"`

	// Logs Explorer allows filtering and display of this as `jsonPayload.component`.
	Component string `json:"component,omitempty"`
}

// String renders an entry structure to the JSON format expected by Cloud Logging.
func (e Entry) String() string {
	if e.Severity == "" {
		e.Severity = "INFO"
	}
	out, err := json.Marshal(e)
	if err != nil {
		log.Printf("json.Marshal: %v", err)
	}
	return string(out)
}

כשמבנה Entry מתועד ביומן, מתבצעת קריאה ל-method‏ String כדי להמיר אותו לפורמט JSON שנדרש על ידי Cloud Logging:


func init() {
	// Disable log prefixes such as the default timestamp.
	// Prefix text prevents the message from being parsed as JSON.
	// A timestamp is added when shipping logs to Cloud Logging.
	log.SetFlags(0)
}

func indexHandler(w http.ResponseWriter, r *http.Request) {
	// Uncomment and populate this variable in your code:
	// projectID = "The project ID of your Cloud Run service"

	// Derive the traceID associated with the current request.
	var trace string
	if projectID != "" {
		traceHeader := r.Header.Get("X-Cloud-Trace-Context")
		traceParts := strings.Split(traceHeader, "/")
		if len(traceParts) > 0 && len(traceParts[0]) > 0 {
			trace = fmt.Sprintf("projects/%s/traces/%s", projectID, traceParts[0])
		}
	}

	log.Println(Entry{
		Severity:  "NOTICE",
		Message:   "This is the default display field.",
		Component: "arbitrary-property",
		Trace:     trace,
	})

	fmt.Fprintln(w, "Hello Logger!")
}

Java

כדי להפעיל רישום ביומן בפורמט JSON באמצעות Logback ו-SLF4J, מגדירים את Logging Logback appender בהגדרות של logback.xml:

// Add log correlation to nest all log messages beneath request log in Log Viewer.
// TODO(developer): delete this code if you're creating a Cloud
//                  Function and it is *NOT* triggered by HTTP.
String traceHeader = req.headers("x-cloud-trace-context");
if (traceHeader != null && project != null) {
  String trace = traceHeader.split("/")[0];
  MDC.put(
      "logging.googleapis.com/trace",
      String.format("projects/%s/traces/%s", project, trace));
}
// -- End log correlation code --

// Create a structured log entry using MDC (Mapped Diagnostic Context) keys.
// For instantiating the "logger" variable, see
// https://cloud.google.com/run/docs/logging#run_manual_logging-java
MDC.put("component", "arbitrary-property");

logger.info("This is the default display field.");

// Clear MDC at the end of the request to avoid resource leaks
MDC.clear();

מגדירים את LoggingAppender כך שיפנה את היומנים לפלט סטנדרטי (stdout) בפורמט JSON מובנה, כדי ש-Cloud Run יוכל לתעד אותם. לפרטים נוספים, קראו את המאמר הגדרת Logback.

<configuration>
  <appender name="CLOUD" class="com.google.cloud.logging.logback.LoggingAppender">
    <!-- Optional : filter logs at or above a level -->
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <level>INFO</level>
    </filter>
    <log>application.log</log> <!-- Optional : default java.log -->
    <resourceType>gae_app</resourceType> <!-- Optional : default: auto-detected, fallback: global -->
    <enhancer>com.example.logging.logback.enhancers.ExampleEnhancer</enhancer> <!-- Optional -->
    <flushLevel>WARN</flushLevel> <!-- Optional : default ERROR -->
    <!-- Redirect logs to stdout in JSON format for Cloud Run to capture -->
    <redirectToStdout>true</redirectToStdout>
  </appender>
  <root level="INFO">
    <appender-ref ref="CLOUD"/>
  </root>
</configuration>

כך נוצר המבנה הבא של יומן הפלט:

{"severity":"INFO","time":"YYYY-MM-DDTHH:MM:SS.SSSZ","logging.googleapis.com/labels":{"component":"arbitrary-property","levelName":"INFO","loggerName":"com.example.cloudrun.App","levelValue":"20000"},"logging.googleapis.com/trace_sampled":false,"message":"This is the default display field."}

שדות JSON מיוחדים בהודעות

כשמספקים יומן מובנה כמילון JSON, חלק מהשדות המיוחדים מוסרים מ-jsonPayload ונכתבים בשדה התואם ב-LogEntry שנוצר, כפי שמתואר במסמכי התיעוד של השדות המיוחדים.

לדוגמה, אם קובץ ה-JSON כולל מאפיין severity, הוא יוסר מ-jsonPayload ויופיע במקום זאת בתור severity של רשומת היומן. המאפיין message משמש כטקסט התצוגה הראשי של רשומת היומן, אם הוא קיים. למידע נוסף על מאפיינים מיוחדים, קראו את הקטע משאב רישום ביומן שבהמשך.

קישור בין יומני הקונטיינר ליומן הבקשות (שירותים בלבד)

ב-Logs Explorer, אפשר לראות את היומנים שקשורים לאותו trace בפורמט "הורה-צאצא": כשלוחצים על סמל המשולש שמימין לרשומת יומן הבקשות, יומני הקונטיינר שקשורים לבקשה הזו מוצגים כשהם מקוננים מתחת ליומן הבקשות.

יומני קונטיינרים לא משויכים באופן אוטומטי ליומני בקשות, אלא אם משתמשים בספריית לקוח של Cloud Logging. כדי לקשר בין יומני קונטיינרים ליומני בקשות בלי להשתמש בספריית לקוח, אתם יכולים להשתמש בשורת יומן מובנית בפורמט JSON שמכילה שדה logging.googleapis.com/trace עם מזהה המעקב שחולץ מהכותרת X-Cloud-Trace-Context, כמו שמוצג בדוגמה שלמעלה לרישום מובנה ביומן.

שליטה בשימוש במשאבים של יומן בקשות הבקרה (שירותים בלבד)

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

הערה לגבי סוכני Logging

אם השתמשתם ב-Cloud Logging עם מוצרים מסוימים של Google Cloud , כמו Compute Engine, יכול להיות שהשתמשתם בסוכני Logging של Cloud Logging. ב-Cloud Run לא משתמשים בסוכני Logging כי יש תמיכה מובנית באיסוף יומנים.

שמות המשאבים של Cloud Logging

שמות המשאבים של Cloud Run ב-Logging הם:

משאבי רישום ביומן

לחיצה על רשומת יומן ב-Logs Explorer פותחת רשומת יומן בפורמט JSON, כדי שתוכלו להציג את הפרטים שאתם רוצים.

כל השדות ברשומת יומן, כמו חותמות זמן, חומרת האירוע ו-httpRequest, הם שדות סטנדרטיים ומתוארים במסמכי התיעוד של רשומת יומן.

‫Cloud Run מוסיף מטא-נתונים נוספים, כדי שתוכלו לזהות את המקור של היומן. הן כוללות את (התוויות שהגדרתם בשירות Cloud Run) ואת תוויות המשאבים הספציפיות ל-Cloud Run.

שדות של רשומות ביומן של שירות

ברשימה הבאה מפורטים השדות שאפשר למצוא ברשומת היומן של שירות Cloud Run:

שדה ערכים והערות
LogEntry.labels.instanceId המזהה הזה ממפה למופע מסוים בשירות הזה כשהוא גדל וקטן.
LogEntry.labels.run.googleapis.com/base_image_versions גרסת קובץ האימג' הבסיסי שבה השירות משתמש. מופיע רק בשירותים שנפרסו מהמקור ואם עדכוני האבטחה האוטומטיים מופעלים.
LogEntry.labels.run.googleapis.com/cloud_event_id מזהה CloudEvent. מופיע רק בשירותים שמקבלים אירועים מ-Eventarc.
LogEntry.labels.run.googleapis.com/cloud_event_source מקור ה-CloudEvent. מופיע רק בשירותים שמקבלים אירועים מ-Eventarc.
LogEntry.labels.mylabel,
LogEntry.labels.mysecondlabel
התוויות שהגדרתם בשירות.
LogEntry.logName מזהה את היומן, למשל יומן בקשות, שגיאה סטנדרטית (stderr), פלט סטנדרטי (stdout) וכו'.
LogEntry.resource.labels.location מזהה את Google Cloud המיקום של השירות.
LogEntry.resource.labels.project_id הפרויקט שבו השירות פרוס.
LogEntry.resource.labels.revision_name הגרסה שטיפלה בבקשה.
LogEntry.resource.labels.service_name השירות שטיפל בבקשה.
LogEntry.resource.type ‫cloud_run_revision: סוג המשאב של Cloud Run.

הנה דוגמה לרשומת יומן בקשות של שירות Cloud Run:

{
 httpRequest: {…}
 insertId:  "5c82b3d1000ece0000000000"
 labels: {
  instanceId:  "00bf4bf00000fb59c906a00000c9e29c2c4e06dce91500000000056008d2b6460f163c0057b97b2345f2725fb2423ee5f0bafd36df887fdb1122371563cf1ff453717282afe000001"
  mylabel: "mylabelvalue"
  mysecondlabel: "mysecondlabelvalue"
 }
 logName:  "projects/my-project/logs/run.googleapis.com%2Frequests"
 receiveTimestamp:  "2019-03-08T18:26:25.981686167Z"
 resource: {
  labels: {
   configuration_name:  "myservice"
   location:  "europe-west1"
   project_id:  "my-project"
   revision_name:  "myservice-00002"
   service_name:  "myservice"
  }
  type:  "cloud_run_revision"
 }
 severity:  "INFO"
 timestamp:  "2019-03-08T18:26:25.970397Z"
}

שדות של רשומות ביומן למשימות

ברשימה הבאה מפורטים השדות שאפשר למצוא ברשומת היומן של משימת Cloud Run:

שדה ערכים והערות
LogEntry.labels.instanceId המזהה הזה ממפה למכונה מסוימת ששימשה להרצת משימה או עבודה מסוימת.
LogEntry.labels.mylabel,
LogEntry.labels.mysecondlabel
התוויות שהגדרתם במשימה.
LogEntry.logName מזהה את היומן, למשל, שגיאה סטנדרטית (stderr), פלט סטנדרטי (stdout) וכו'.
LogEntry.resource.labels.location מזהה את Google Cloud מיקום המשרה.
LogEntry.resource.labels.project_id הפרויקט שבו פורסים את המשימה.
LogEntry.resource.labels.job_name שם המשרה.
LogEntry.labels.execution_name שם המשימה שבוצעה.
LogEntry.labels.task_index אינדקס המשימה.
LogEntry.labels.task_attempt כמה פעמים ניסו לבצע את המשימה הזו.
LogEntry.resource.type ‫cloud_run_job: סוג המשאב של Cloud Run.

שדות של רשומות ביומן למאגרי Worker

ברשימה הבאה מפורטים השדות שאפשר למצוא ברשומה ביומן של מאגר Worker ב-Cloud Run:

שדה ערכים והערות
LogEntry.labels.instanceId המזהה הזה ממפה למכונה מסוימת במאגר ה-workers הזה כשהוא גדל וקטן.
LogEntry.labels.mylabel,
LogEntry.labels.mysecondlabel
התוויות שהגדרתם במאגר ה-workers.
LogEntry.logName מזהה את היומן, למשל, שגיאה סטנדרטית (stderr), פלט סטנדרטי (stdout) וכו'.
LogEntry.resource.labels.location Google Cloud המיקום של מאגר ה-Workers.
LogEntry.resource.labels.project_id הפרויקט שבו נפרס מאגר ה-workers.
LogEntry.resource.labels.workerpool_name השם של מאגר ה-workers.
LogEntry.resource.type ‫cloud_run_workerpool: סוג המשאב של Cloud Run.

שדות של רשומות ביומן למכונות

ברשימה הבאה מפורטים השדות שאפשר למצוא ברשומה ביומן של מכונה ב-Cloud Run:

שדה ערכים והערות
LogEntry.labels.instance_name שם המכונה.
LogEntry.labels.instanceId המזהה הזה ממפה לגרסה מסוימת של המכונה של Cloud Run, ומשתנה בכל פעם שהמכונה מופעלת מחדש.
LogEntry.labels.mylabel,
LogEntry.labels.mysecondlabel
התוויות שהגדרתם במכונה.
LogEntry.logName מזהה את היומן, למשל, שגיאה סטנדרטית (stderr), פלט סטנדרטי (stdout) וכו'.
LogEntry.resource.labels.location המיקום של המכונה ( Google Cloud ).
LogEntry.resource.labels.project_id הפרויקט שבו המכונה פרוסה.

המאמרים הבאים

  • אתם יכולים להשתמש ב-Gemini Cloud Assist Investigations כדי לאבחן בעיות, לאסוף תובנות פרקטיות ולפתור בעיות. במאמר פתרון בעיות באמצעות Gemini Cloud Assist Investigations שבמסמכי התיעוד של Gemini מוסבר איך מתחילים חקירה ב-Logs Explorer בדרכים שונות.