로깅 및 로그 보기

이 페이지에서는 Cloud Run을 사용할 때 이용 가능한 로그에 대한 정보를 제공하고, 로그를 열람하고 작성하는 방법을 설명합니다.

Cloud Run에는 두 가지 유형의 로그가 있으며 이러한 로그는 Cloud Logging으로 자동 전송됩니다.

  • 요청 로그(서비스만 해당): Cloud Run 서비스로 전송된 요청의 로그입니다. 이러한 로그는 자동으로 생성됩니다.
  • 컨테이너 로그(서비스 및 작업): 컨테이너 로그 작성에 설명된 대로 지원되는 위치에 작성된 인스턴스(일반적으로 자체 코드)에서 내보낸 로그입니다.

로그 보기

여러 가지 방법으로 서비스 또는 작업에 대한 로그를 열람할 수 있습니다.

로그를 보는 두 가지 콘솔 방법 모두 Cloud Logging에 저장된 동일한 로그를 검사하지만 Cloud Logging 로그 탐색기는 세부정보와 더 많은 필터링 기능을 제공합니다.

Cloud Run에서 로그 보기

해당 서비스 및 작업 페이지에서 서비스와 작업의 로그를 볼 수 있습니다.

서비스 로그 보기

Cloud Run 페이지에서 서비스 로그를 열람하려면 다음 안내를 따르세요.

  1. Cloud Run으로 이동

  2. 표시되는 목록에서 원하는 서비스를 클릭합니다.

  3. 로그 탭을 클릭하여 이 서비스의 모든 버전에 대한 요청 및 컨테이너 로그를 가져옵니다. 로그 심각도 수준으로 필터링할 수 있습니다.

작업 로그 보기

Cloud Run 페이지에서 작업 로그를 보려면 다음 안내를 따르세요.

  1. Cloud Run으로 이동

  2. 작업 탭을 클릭합니다.

  3. 작업 목록에서 작업을 찾아 클릭합니다.

  4. 로그 탭을 클릭하여 이 작업의 모든 실행에 대한 컨테이너 로그를 가져옵니다. 로그 심각도 수준으로 필터링할 수 있습니다.

  5. 또는 특정 작업 실행으로 사전 필터링된 로그를 보려면 작업 실행을 클릭한 다음 로그 탭을 클릭하세요.

Google Cloud CLI를 사용하여 서비스 로그 보기

명령줄에서 Google Cloud CLI를 사용하여 테일링 로그를 보거나 Cloud Run 서비스의 기존 로그를 읽을 수 있습니다. 기본적으로 로그는 콘솔에 최적화된 한 줄 형식으로 지정됩니다.

로그를 테일링하려면 Google Cloud CLI에 log-streaming 구성요소를 설치해야 합니다. 구성요소가 설치되지 않은 경우 필요할 때 설치하라는 메시지가 표시됩니다.

명령줄에서 테일링 로그 보기

Cloud Run 서비스의 경우 명령줄에서 직접 Cloud Run 서비스의 로그를 실시간으로 테일링할 수 있습니다.

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

바꾸기

  • SERVICE를 Cloud Run 서비스 이름으로 바꿉니다.
  • PROJECT-ID를 Google Cloud 프로젝트 ID로 바꿉니다. gcloud config get-value project 명령어를 실행하여 프로젝트 ID를 볼 수 있습니다.

명령줄에서 로그 읽기

Cloud Run 서비스의 경우 다음 두 가지 방법 중 하나로 기존 로그를 읽을 수 있습니다.

  • 콘솔 최적화 형식:
    gcloud beta 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 프로젝트 ID로 바꿉니다. gcloud config get-value project 명령어를 실행하여 프로젝트 ID를 볼 수 있습니다.

Cloud Logging에서 로그 보기

Cloud Logging 로그 탐색기에서 Cloud Run 로그를 보려면 다음 안내를 따르세요.

  1. Google Cloud 콘솔의 로그 탐색기로 이동합니다.

    로그 탐색기 페이지로 이동

  2. 페이지 상단에서 기존 Google Cloud 프로젝트를 선택하거나 새 프로젝트를 만듭니다.

  3. 드롭다운 메뉴를 사용하여 서비스에 리소스 Cloud Run 버전을 또는 작업에 Cloud Run 작업을 선택합니다.

자세한 내용은 로그 탐색기 사용을 참조하세요.

Cloud Code에서 서비스 로그 보기

Cloud Code에서 로그를 보려면 IntelliJVisual Studio Code 가이드를 참조하세요.

프로그래매틱 방식으로 로그 읽기

프로그래매틱 방식으로 로그를 읽으려면 다음 방법 중 하나를 사용하면 됩니다.

컨테이너 로그 작성

서비스 또는 작업에서 로그를 작성하면 로그가 다음 위치 중 한 곳에 작성되는 한 Cloud Logging에서 자동으로 감지됩니다.

대부분의 개발자는 표준 출력 및 표준 오류를 사용하여 로그를 작성할 수 있어야 합니다.

이러한 지원되는 위치에 작성된 컨테이너 로그는 Cloud Run 서비스, 버전, 위치 또는 Cloud Run 작업과 자동으로 연결됩니다. 이러한 로그에 포함된 예외는 Error Reporting에서 캡처하여 보고합니다.

로그에서 단순 텍스트와 구조화된 JSON 사용 비교

로그를 작성할 때 간단한 텍스트 문자열을 전송하거나 한 줄의 직렬화된 JSON('구조화된' 데이터라도 함)을 보낼 수 있습니다. 이 구조화된 JSON은 Cloud Logging에서 감지 후 파싱하여 jsonPayload에 배치합니다. 이에 반해 간단한 텍스트 메시지는 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))

Go

각 로그 항목의 구조는 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 구조체가 로깅되면 String 메서드가 호출되어 Cloud Logging에서 예상하는 JSON 형식으로 마샬링합니다.


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

logback.xml 구성에서 Logstash JSON 인코더를 사용 설정하여 LogbackSLF4J로 JSON 로깅을 사용 설정합니다.

// Build structured log messages as an object.
Object globalLogFields = null;

// 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];
  globalLogFields =
      kv(
          "logging.googleapis.com/trace",
          String.format("projects/%s/traces/%s", project, trace));
}
// -- End log correlation code --

// Create a structured log entry using key value pairs.
logger.error(
    "This is the default display field.",
    kv("component", "arbitrary-property"),
    kv("severity", "NOTICE"),
    globalLogFields);

표준 필드 이름을 맞춤설정하여 로그 페이로드에서 원치 않는 콘텐츠가 수집되지 않도록 제외합니다. 필드 이름 및 예상 데이터 형식의 목록은 Logging 에이전트 사용을 참조하세요.

<configuration>
  <appender name="jsonConsoleAppender" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="net.logstash.logback.encoder.LogstashEncoder">
      <!-- Ignore default logging fields -->
      <fieldNames>
        <timestamp>[ignore]</timestamp>
        <version>[ignore]</version>
        <logger>[ignore]</logger>
        <thread>[ignore]</thread>
        <level>[ignore]</level>
        <levelValue>[ignore]</levelValue>
      </fieldNames>
    </encoder>
  </appender>
  <root level="INFO">
    <appender-ref ref="jsonConsoleAppender"/>
  </root>
</configuration>

메시지의 특수 JSON 필드

구조화된 로그를 JSON 사전으로 제공하면 일부 특수 필드가 jsonPayload에서 삭제되고 특수 필드 문서에 설명된 대로 생성된 LogEntry의 해당 필드에 작성됩니다.

예를 들어 JSON에 severity 속성이 포함되어 있으면 이 속성은 jsonPayload에서 삭제되고 대신 로그 항목의 severity로 표시됩니다. message 속성이 있으면 이 속성은 로그 항목의 기본 표시 텍스트로 사용됩니다. 특수 속성에 대한 자세한 내용은 아래의 Logging 리소스 섹션을 참조하세요.

컨테이너 로그와 요청 로그의 상관관계(서비스만 해당)

로그 탐색기에서 trace가 동일하여 상관관계가 있는 여러 로그 항목을 '상위-하위' 형식으로 조회할 수 있습니다. 요청 로그 항목의 왼쪽에 있는 삼각형 아이콘을 클릭하면 해당 요청과 관련된 컨테이너 로그가 요청 로그 아래에 중첩되어 표시됩니다.

Cloud Logging 클라이언트 라이브러리를 사용하는 경우를 제외하고 컨테이너 로그와 요청 로그의 상관관계는 자동으로 지정되지 않습니다. 클라이언트 라이브러리를 사용하지 않고 컨테이너 로그와 요청 로그의 상관관계를 지정하려면 위의 구조화된 로깅 샘플에 표시된 대로 X-Cloud-Trace-Context 헤더에서 추출된 trace 식별자가 있는 logging.googleapis.com/trace 필드를 포함하는 구조화된 JSON 로그 줄을 사용할 수 있습니다.

요청 로그 리소스 사용량 제어(서비스만 해당)

요청 로그는 자동으로 생성됩니다. Cloud Run에서 직접 요청 로그의 양을 제어할 수 없지만 Cloud Logging의 로그 제외 기능을 사용할 수 있습니다.

Logging 에이전트에 대한 참고사항

Compute Engine과 같은 특정 Google Cloud 제품에서 Cloud Logging을 사용한 경우 Cloud Logging 로깅 에이전트를 사용했을 수 있습니다. Cloud Run은 기본적으로 로그 수집을 지원하므로 Logging 에이전트를 사용하지 않습니다.

리소스 이름 로깅

Cloud Run의 로깅 리소스 이름은 다음과 같습니다.

로깅 리소스

로그 탐색기에서 로그 항목을 클릭하면 JSON 형식의 로그 항목이 열리고 원하는 세부정보를 확인할 수 있습니다.

타임스탬프, 심각도, httpRequest와 같은 로그 항목의 모든 필드는 표준이며 로그 항목 문서에 설명되어 있습니다.

Cloud Run에서 로그 소스를 식별할 수 있도록 추가 메타데이터를 추가합니다. 여기에는 (Cloud Run 서비스에 설정한 라벨과) Cloud Run과 관련된 리소스 라벨이 포함됩니다.

서비스의 로그 항목 필드

다음은 Cloud Run 서비스의 로그 항목에서 찾을 수 있는 필드 목록입니다.

필드 값 및 참고
LogEntry.labels.instanceId 요청을 처리한 인스턴스입니다.
LogEntry.labels.mylabel,
LogEntry.labels.mysecondlabel
사용자가 서비스에 설정한 라벨입니다.
LogEntry.logName 요청 로그, 표준 오류, 표준 출력 등의 로그를 식별합니다.
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:  "us-central1"
   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 요청 로그, 표준 오류, 표준 출력 등의 로그를 식별합니다.
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 리소스 유형입니다.