앱, 작업 및 기능에 대한 로그 작성 및 보기

로깅은 IBM Cloud® Code Engine에서 문제점을 해결하는 데 도움을 줄 수 있습니다. 콘솔을 사용하거나 CLI를 사용하여 로그를 볼 수 있습니다.

차량용 로깅에 관심이 있으신가요? 플릿에 대한 통합 가시성 설정하기플릿에 대한 로그 및 모니터링 데이터 보기를 참조하세요.

로그 작성

로그 형식, 심각도 수준, 타임스탬프, 비정형 및 정형 로깅을 위한 여러 줄 항목 처리에 대한 모범 사례를 포함하여 IBM Cloud® Code Engine 에서 로그를 효과적으로 작성하는 방법에 대해 알아보세요.

로그 작성 시 고려 사항

표준 출력 및 오류에 로그 쓰기

Code Engine 에서는 로그 파일을 관리하기보다는 이벤트 스트림으로 취급할 것을 권장하는 Twelve-Factor 앱 가이드라인에 따라 워크로드에서 방출되는 로그 기록이 stdout 또는 stderr 에 기록될 때만 수집합니다. 클라우드 네이티브 애플리케이션 만들기: 12-팩터 애플리케이션 - 팩터 11 - 로그 을 참조하세요.

플랫폼의 로깅 파이프라인은 이 출력을 자동으로 캡처하고 처리하여 분석 및 문제 해결에 사용할 수 있도록 합니다. 컨테이너의 임시 파일 시스템에 있는 파일에 기록된 로그 줄은 로깅 인터페이스를 통해 수집, 유지 또는 노출되지 않습니다. 따라서 인스턴스가 다시 시작되거나 종료되면 임시 파일 시스템에 저장된 모든 로그가 손실되어 운영 디버깅이나 근본 원인 분석에 사용할 수 없게 됩니다.

로그 행에 타임스탬프를 추가해야 하나요?

Code Engine 인프라가 자동으로 타임스탬프를 캡처하고 표준화하므로 사용자 워크로드에서 생성된 로그 레코드는 자체 타임스탬프 정보를 포함하지 않아야 합니다. 애플리케이션 수준 타임스탬프를 포함하면 특히 시스템 클럭이 변동하거나 다를 수 있는 분산 또는 컨테이너화된 환경에서 워크로드가 실행되는 경우 서비스 전반에 걸쳐 불일치가 발생할 수 있습니다. 플랫폼의 타임스탬프를 사용하면 균일한 시간 형식, 정확한 순서, 다른 시스템 생성 로그와의 안정적인 상관관계를 보장하여 전체 배포에서 문제 해결, 감사 및 관찰을 간소화할 수 있습니다.

내 로그 수준은 IBM Cloud Logs 심각도에 어떻게 매핑되나요?

각 로그 레코드에 제공된 로그 수준은 로그 심각도를 IBM Cloud Logs 심각도에 매핑하기에서 설명한 대로 IBM Cloud Logs 심각도에 매핑됩니다. 다음 섹션에서는 비정형 로그와 정형 로그에 대해 로그 수준을 구문 분석하는 방법과 지원되는 로그 수준 값에 대해 자세히 설명합니다.

로그 데이터가 여러 줄인 경우 어떻게 하나요?

IBM Cloud Logs 검색 및 서식 지정 기능을 활용하려면 다음과 같이 로그 서식을 변경하세요.

  • 로그 줄이 여러 줄에 걸쳐 있는 경우 로그 형식과 출력 방식을 변경하여 한 줄에 표시되도록 합니다. IBM Cloud Logs 로 로그에 JSONL 형식( 로그 형식 참조)을 사용합니다.
  • 로그는 에 대한 제한 IBM Cloud Logs 을 준수해야 합니다.

로그 형식

로그 데이터는 두 가지 일반적인 형식으로 전송될 수 있습니다: 비정형 및 정형.

  • 비정형 로그는 생성하기 쉽고 사람이 읽을 수 있는 자유 형식의 텍스트이지만 백엔드 시스템에서 일관되게 구문 분석하기는 어렵습니다. 이로 인해 안정적인 필터링 및 상관관계가 제한됩니다.
  • 구조화된 로그는 필드를 예측 가능한 스키마(예: JSON)로 인코딩하여 로그 파이프라인이 요청 ID, 사용자 ID 또는 도메인별 메타데이터와 같은 속성을 색인하고 쿼리할 수 있도록 합니다. Code Engine 는 구조화된 로그에 대해 JSON을 지원하므로 사용자 정의 필드를 기계가 읽을 수 있고 통합 가시성 도구에서 쉽게 필터링할 수 있도록 도와줍니다.

필터링 가능한 사용자 지정 정보로 로그 행을 보강하려는 경우 구조화된 로깅을 사용하세요.

비정형 로그

예제

다음은 구조화되지 않은 로그 행(자유 형식 텍스트)을 표준 출력으로 작성하는 간단한 예제입니다.

예제는 Code Engine 공개 샘플 리포지토리( https://github.com/IBM/CodeEngine/blob/main/logging/README.md )에 게시되어 있습니다.

Node.js (JavaScript)

console.log('User signup succeeded for account abc123');

Python

print("User signup succeeded for account abc123")

Golang

package main

import (
    "fmt"
)

func main() {
    fmt.Println("User signup succeeded for account abc123")
}

Java

package com.ibm.cloud.codeengine.sample;

public class App {
    public static void main(String[] args) {
        System.out.println("User signup succeeded for account abc123");
    }
}

로그 수준 감지

각 로그 레코드에서 키워드를 검색하여 심각도를 결정합니다. 대소문자를 구분하지 않고 평가되는 심각도 값은 critical, error, warn, info, debug, verbose 입니다.

로그 행이 LEVEL MESSAGE, Code Engine 형식의 심각도 키워드로 시작하면 표시된 로그 메시지에서 감지된 수준을 제거하여 사용자가 IBM Cloud Logs 보기에서 심각도별로 정확하게 필터링하면서 핵심 콘텐츠에 집중할 수 있도록 합니다. 이 경우 추출된 심각도 값은 로그 레코드 필드 level 에 저장됩니다. 다음과 같은 대소문자를 구분하지 않는 심각도 수준이 지원됩니다: fatal, error, warn, info, debug, trace. 예를 들어 Node.js 에 다음과 같이 작성할 수 있습니다:

// Unstructured log with level prefix
console.log('ERROR Payment service timeout while creating invoice');

IBM Cloud Logs 에서 이 항목은 심각도 오류와**"송장 생성 중 결제 서비스 시간 초과** " 메시지 텍스트와 함께 표시되며, 심각도 = 오류를 기준으로 필터링하여 결과 범위를 좁힐 수 있습니다. 또한 구문 분석 및 심각도 규칙을 사용하여 레벨을 추출하고 일치시키는 방법을 사용자 환경에 맞게 조정할 수도 있습니다.

로그 수준 감지는 로그 줄이 LEVEL: MESSAGE 또는 [LEVEL] MESSAGE 과 같이 약간 다른 형식을 따르는 경우에도 작동합니다. 그러나 이러한 경우 심각도가 여전히 적절하게 분류되어 있어도 로그 메시지에서 수준 키워드는 제거되지 않습니다.

또한 탐지 로직은 처음뿐만 아니라 지원되는 키워드가 메시지 내 어디에서나 에 나타날 때 심각도 수준을 유추할 수 있습니다. 예를 들어 로그 라인이 있습니다:

The payment workflow encountered an unexpected error during validation

이 로그 줄은 메시지 텍스트에 오류라는 단어가 표시되므로 오류로 분류됩니다.

로그 수준 감지는 입력 스트림(stdout 또는 stderr)을 로그 수준 감지용으로 고려하지 않습니다. 따라서 표준 오류(stderr)에 기록된 로그 메시지는 순전히 메시지 텍스트에 대해서만 평가됩니다. 예를 들어 console.error("Some message") 는 stderr로 작성되었지만 정보로 분류됩니다.

함수 워크로드의 경우, 로그 줄의 시작 부분에서 LEVEL MESSAGE 형식으로 로그 레벨이 감지되더라도 표시된 로그 메시지에서 로그 레벨이 제거되지 않습니다.

타임스탬프 구문 분석 및 평가

Code Engine 은 로그가 수집될 때 정규화된 타임스탬프를 자동으로 할당하므로 애플리케이션 로그 행에 타임스탬프를 추가하는 것은 권장되지 않습니다. 로그 행의 시작 부분에 타임스탬프가 포함되어 있으면 시스템에서 구문 분석을 시도합니다. 지원되는 형식 중 하나와 일치하는 경우 로그 수준이 처리되는 방식과 유사하게 표시된 로그 메시지에서 타임스탬프가 제거됩니다. 지원되는 타임스탬프 형식은 다음과 같습니다:

  • 2026-02-08T20:30:45.123
  • 2026-02-08T20:30:45.123Z
  • 2026-02-08T21:03:45.123456Z
  • 2026-02-08T21:03:45.123456789Z
  • 2026-02-08 21:03:45.123Z
  • 2026-02-08 20:30:45.123

로그 줄의 시작 부분에 타임스탬프와 로그 수준이 모두 포함된 경우(예: TIMESTAMP LEVEL MESSAGE), 파이프라인은 둘 다 필드를 평가합니다. 두 패턴이 모두 지원되는 패턴과 일치하면 각각 적절하게 분류되어 렌더링된 로그 메시지에서 제거되고, 메시지 본문만 남기므로 쉽게 읽고 필터링할 수 있습니다. 예를 들어 다음 형식은 성공적으로 구문 분석됩니다:

  • 2026-02-08T21:03:45.123456789Z ERROR Payment service timeout
  • 2026-02-08 20:30:45.123 INFO Starting billing workflow

타임스탬프가 표시되지만 지원되는 형식과 일치하지 않는 경우에는 로그 행의 일부로 남아 일반 텍스트로 처리되지만 나머지 메시지는 여전히 정상적으로 처리됩니다.

함수 워크로드의 경우 타임스탬프는 로그 메시지에서 구문 분석, 평가 또는 제거되지 않습니다. 함수 로그에 포함된 모든 타임스탬프는 표시된 메시지의 일부로 남아 있습니다.

다중 회선 지원

Code Engine 는 여러 줄 로그 항목을 지원합니다. 그러나 로그를 내보낼 때 새줄 문자(\n)가 올바르게 인코딩 (\\n)되어 있어야 로깅 파이프라인에서 여러 줄 메시지를 올바르게 처리하고 렌더링할 수 있습니다. 예를 들어 Node.js 에서 다음과 같이 여러 줄의 로그 항목을 생성할 수 있습니다:

console.log("Starting billing workflow...\\nStep 1: Validating input...\\nStep 2: Processing payment...");

오류 로깅

워크로드에서 여러 줄의 오류 스택 추적을 생성하는 경우, 비정형 콘솔 출력 대신 정형화된 JSON 로그 형식을 사용하세요. 구조화된 로그는 여러 줄 필드를 안정적으로 보존하고 스택 추적이 단일 로그 레코드로 그룹화되도록 하며, 이는 구조화된 로그 섹션에서 다룹니다.

예를 들어 다음 로그 메시지는 로그 메시지에 "error" 키워드가 나타나기 때문에 오류로 분류됩니다. 그러나 err 객체에서 제공하는 스택 추적은 여러 로그 행으로 렌더링됩니다.

try {
  throw new Error("boom!");
} catch (err) {
  console.error("An error occurred", err);
}

구조화된 로그

예제

다음은 level 필드에 로그 수준과 message 필드에 로그 메시지를 포함하는 단일 JSON을 방출하는 각 언어 및 런타임에 대한 최소한의 구조화된 로깅 예제입니다.

예제는 Code Engine 공개 샘플 리포지토리( https://github.com/IBM/CodeEngine/blob/main/logging/README.md )에 게시되어 있습니다.

Node.js ( winston )

import winston from "winston";
const { combine, json } = winston.format;

// Create a custom logger
const logger = winston.createLogger({
  level: 'info',
  transports: [new winston.transports.Console()],
  format: combine(json())
});

// Usage
logger.info("User signup succeeded")
logger.error("Payment service timeout")

Python ( 로구루 )

from loguru import logger
import sys
import json
import traceback

# Define a custom JSON sink
def json_sink(message):
    record = message.record

    # Base fields: level + message, no timestamp
    payload = {
        "level": record["level"].name,   # e.g., "INFO"
        "message": record["message"],    # rendered message
    }

    # Merge in any bound extra fields as top-level keys
    # (skip reserved keys to avoid accidental overwrite)
    for k, v in record["extra"].items():
        if k not in ("level", "message", "stack"):
            payload[k] = v

    # If an exception is attached, render full stack trace into "stack"
    exc = record["exception"]
    if exc:
        # exc.type, exc.value, exc.traceback are available from Loguru
        stack_text = "".join(traceback.format_exception(exc.type, exc.value, exc.traceback))
        payload["stack"] = stack_text

    # Emit a single JSON line
    sys.stdout.write(json.dumps(payload, ensure_ascii=False) + "\n")
    sys.stdout.flush()


# Remove default handler (which includes timestamp, etc.) and add our custom sink
logger.remove()
logger.add(json_sink, level="DEBUG")  # lowest level you want to capture

# Usage
logger.info("User signup succeeded")
logger.error("Payment service timeout")

Golang ( 슬로건 )

package main

import (
    "log/slog"
    "os"
)

func main() {
    handler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
        // Remove time and rename msg->message
        ReplaceAttr: func(groups []string, attr slog.Attr) slog.Attr {
            // Drop the time attribute
            if attr.Key == slog.TimeKey {
                return slog.Attr{} // empty => removed
            }
            // Rename msg to message
            if attr.Key == slog.MessageKey {
                return slog.String("message", attr.Value.String())
            }
            return attr
        },
    })
    logger := slog.New(handler)

    // Usage
    logger.Info("User signup succeeded")
    logger.Error("Payment service timeout")
}

Java ( SLF4JLogback, 로그스태시-로그백-엔코더 사용 )

src/main/resources/logback.xml:

<configuration>
    <appender name="jsonConsoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="net.logstash.logback.encoder.LogstashEncoder">
            <timeZone>UTC</timeZone>
            <fieldNames>
                <timestamp>[ignore]</timestamp>
                <logger>[ignore]</logger>
                <version>[ignore]</version>
                <levelValue>[ignore]</levelValue>
                <threadName>[ignore]</threadName>
            </fieldNames>
        </encoder>
    </appender>

    <root level="DEBUG">
        <appender-ref ref="jsonConsoleAppender" />
    </root>
</configuration>

src/main/java/com/ibm/cloud/codeengine/sample/App.java:

package com.ibm.cloud.codeengine.sample;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class App {
  private static final Logger logger = LoggerFactory.getLogger(App.class);

  public static void main(String[] args) {
    logger.info("User signup succeeded");
    logger.error("Payment service timeout");
  }
}

로그 수준 감지

각 로그 레코드에서 키워드를 검색하여 심각도를 결정합니다. 대소문자를 구분하지 않고 평가되는 심각도 값은 critical, error, warn, info, debug, verbose 입니다.

구조화된 로그를 사용하는 경우 Code Engine 은 다음 필드 중 하나에 로그 레벨이 제공되면 자동으로 감지합니다: level, severity, 또는 logLevel. 이러한 필드의 값은 대소문자를 구분하지 않으므로 error, ERROR 또는 Error 과 같은 항목은 모두 동일한 심각도에 매핑됩니다. 다음과 같은 대소문자를 구분하지 않는 심각도 수준이 지원됩니다: critical, error, warn, info, debug, verbose. 지원되는 필드가 존재하고 이러한 값 중 하나를 포함하는 경우 로그 수준이 추출되고 정규화된 후 로그 UI 내에서 필터링 및 분류에 사용됩니다. 예를 들어 다음 구조화된 로그 행은 모두 오류 수준으로 올바르게 해석됩니다:

{ "level": "error", "message": "Payment service timeout" }
{ "severity": "ERROR", "message": "Failed to connect to database" }
{ "logLevel": "eRrOr", "message": "Workflow aborted" }

사용된 대문자나 특정 필드 값에 관계없이 플랫폼은 로그 수준을 올바르게 식별하여 구조화된 로그 데이터 전반에서 필터링, 그룹화 및 분석에 적용합니다.

타임스탬프 평가

구조화된 로그의 경우 사용자 지정 타임스탬프는 구문 분석되거나 평가되지 않습니다. 사용자가 제공하는 모든 타임스탬프 필드는 순전히 페이로드 데이터로만 취급되며, 플랫폼은 주문 및 필터링을 위해 항상 자체 수집 타임스탬프를 적용합니다.

아래 예제에서 "timestamp" 값은 보존되지만 로그 타이밍은 무시됩니다.

{ "level": "INFO", "message": "Processing started", "timestamp": "2026-02-08T20:30:45.123Z" }

추가 컨텍스트 정보 추가하기

사용자 정의 필드(예: requestId, userId, 또는 도메인별 메타데이터)를 사용하여 구조화된 로그를 보강할 수 있습니다. 다음은 앞서 사용된 각 스택에 대한 최소한의 예시입니다.

사용자 정의 필드(예: ID, 코드 또는 작은 열거형)를 간결하고 안정적으로 유지하여 로깅 인스턴스에서 필터링 가능성을 극대화하고 카디널리티를 최소화하세요.

Node.js ( winston )

logger.debug("A structured log entry that contains an extra key", {
  extra_key: "extra_value",
});

Python ( 로구루 )

logger.bind(extra_key="extra_value").debug("A structured log entry that contains an extra key")

Golang ( 슬로건 )

logger.Debug("A structured log entry that contains an extra key",
  slog.String("extra_key", "extra_value"),
)

Java ( SLF4JLogback, 로그스태시-로그백-엔코더 사용 )

logger.atDebug().addKeyValue("extra_key", "extra_value")
                .log("A structured log entry that contains an extra key");

오류 로깅

구조화된 로그에서 오류 메시지와 스택 추적을 모두 캡처하려면 표준 필드(level, message)와 stack (또는 이와 유사한) 필드를 포함하는 JSON 레코드를 내보냅니다.

Node.js ( winston )

// Error logging
try {
  throw new Error("boom!");
} catch (err) {
  // The error stack trace is rendered in a single log message (see field stack)
  logger.error("An error occurred", err);
}

Python ( 로구루 )

try:
  raise RuntimeError("boom!")
except Exception:
  # logger.exception() automatically attaches the current exception info
  logger.exception("An error occurred")

Golang ( 슬로건 )

err := errors.New("boom!")
logger.Error("An error occurred",
    slog.Any("err", err),
    // The error stack trace is rendered in a single log message (see field stack)
    slog.String("stack", string(debug.Stack())),
)

Java ( SLF4JLogback, 로그스태시-로그백-엔코더 사용 )

try {
    throw new RuntimeException("boom!");
} catch (Exception e) {
    logger.atError()
            .setCause(e) // The error stack trace is rendered in a single log message (see field stack_trace)
            .log("An error occurred");
}

함수 워크로드는 여러 줄 로그를 처리하지만 각 줄 바꿈 문자는 별도의 로그 항목을 생성합니다. 구조화된 로깅 프레임워크를 사용하여 스택 추적을 로깅할 때, 단일 로그 항목으로 제대로 렌더링되도록 하기 위해 개행 문자를 수동으로 이스케이프해야 할 수 있습니다.

로깅 필드

Code Engine 로깅 필드.
필드 이름 설명 예제 값
app 플랫폼 로그 라인을 방출한 IBM Cloud 서비스입니다. Code Engine 의 경우 항상 codeengine 이 됩니다. codeengine
tag 플루언트비트에 의해 설정되고 플루언트비트 설정에서 설정된 입력 ID에서 파생된 필드입니다. platform.<id>.codeengine
stream 로그 레코드를 수신한 출력 스트림입니다. 가능한 값: stdout 또는 stderr
originator Code Engine 시스템 구성 요소 또는 사용자 워크로드가 로그 행을 내보냈는지 여부를 나타냅니다. system 또는 user
resourceGroupId Code Engine 프로젝트의 리소스 그룹 CRN. <resource group CRN>
messageKey 로그 필터링 및 문제 해결을 위한 사람이 읽을 수 있는 고유 식별자(선택 사항)입니다. 사용자 정의 문자열
codeengine.region Code Engine 프로젝트의 지역. us-south
codeengine.project Code Engine 프로젝트 이름. 사용자 정의 문자열
codeengine.projectGuid Code Engine 프로젝트의 GUID입니다. <project GUID>
codeengine.projectSubdomain Code Engine 프로젝트의 네임스페이스입니다. edf5a781
codeengine.componentType 로그 라인을 방출한 컴포넌트 유형입니다. 가능한 값 app, job, job_run, fleet, function, build, build_run, container
codeengine.component 로그 라인을 방출한 컴포넌트 이름입니다. 사용자 정의 문자열
codeengine.subcomponentType 로그 라인을 방출한 하위 컴포넌트 유형입니다. 가능한 값: app_revision, job_run, fleet_instance, function, build_run, container
codeengine.subcomponent 로그 라인을 방출한 하위 컴포넌트 이름입니다. 사용자 정의 문자열
codeengine.instanceId 파드 이름(앱, 잡, 빌드의 경우) 또는 컨테이너 인스턴스 ID(함수 및 플릿의 경우). my-app-0001-pod-abcde
label.Namespace 더 이상 사용되지 않습니다. Code Engine 프로젝트의 하위 도메인 이름입니다. 대신 codeengine.projectSubdomain 을 사용하세요. 이 필드는 2026년 6월 15일 이후 삭제됩니다. edf5a781
label.Project 더 이상 사용되지 않습니다. Code Engine 프로젝트의 이름입니다. 대신 codeengine.project 을 사용하세요. 이 필드는 2026년 6월 15일 이후 삭제됩니다. 사용자 정의 문자열
label.Stream 더 이상 사용되지 않습니다. 로그 레코드를 수신한 출력 스트림입니다. 대신 stream 을 사용하세요. 이 필드는 2026년 6월 15일 이후 삭제됩니다. 가능한 값: stdout 또는 stderr
level 선택사항입니다. 로그 메시지의 심각도를 정의합니다. 이 값은 비정형 로그 메시지에서 로그 수준을 추출할 수 있는 경우에만 설정됩니다. 값은 대소문자를 구분하지 않습니다. 가능한 값: fatal, error, warn, info, debug, trace
logtag 더 이상 사용되지 않습니다. 선택사항입니다. 수신된 로그 행이 일부 로그 행인지 전체 로그 행인지를 나타냅니다. 이 필드는 함수 워크로드에는 설정되어 있지 않습니다. 이 필드는 2026년 6월 15일 이후에는 대체 항목 없이 삭제됩니다. 가능한 값: F 또는 P
message.message 사람이 읽을 수 있는 로그 메시지입니다. 시스템 구성 요소 또는 사용자가 정의한 문자열
message.logSourceCRN Code Engine 프로젝트의 CRN입니다. <code engine project CRN>
message.saveServiceCopy 더 이상 사용되지 않습니다. 플랫폼 로그 행을 IBM Cloud® Code Engine 의 시스템 로그에도 복사할지 여부를 정의합니다. 이 필드는 2026년 6월 15일 이후에는 대체 항목 없이 삭제됩니다. false
message.serviceName 더 이상 사용되지 않습니다. 해당 로그 행을 전송한 IBM Cloud 서비스의 이름입니다. 대신 app 을 사용하세요. 이 필드는 2026년 6월 15일 이후 삭제됩니다. codeengine
message._app 더 이상 사용되지 않습니다. 인스턴스 이름(앱, 작업 및 빌드의 경우) 또는 컴포넌트 이름(함수의 경우)입니다. 대신 codeengine.instanceId, codeengine.component 또는 둘 다 사용하세요. 이 필드는 2026년 6월 15일 이후 삭제됩니다. my-app-0001-pod-abcde
message.* 선택사항입니다. 사용자가 대시보드나 알림을 만드는 데 유용한 메타 정보입니다. durationSeconds

콘솔에서 로그 보기

로깅이 활성화된 상태에서 콘솔에서 Code Engine 앱, 작업, 함수 또는 빌드로 작업하면 로그가 IBM Cloud Logs 서비스로 전달되어 색인화되므로 생성된 모든 메시지를 통해 전체 텍스트를 검색하고 특정 필드에 따라 편리하게 쿼리할 수 있습니다.

플랫폼 로그를 수신하는 IBM Cloud Logs 인스턴스는 Code Engine 프로젝트와 같은 지역에 있을 필요는 없으며, Code Engine 컴포넌트로 작업하기 전에 이 인스턴스를 생성할 필요는 없습니다. 콘솔의 Code Engine 앱, 작업, 함수 또는 빌드 페이지에서 언제든지 로깅 기능을 추가할 수 있습니다.

모든 플랫폼 서비스에 대한 로그를 생성하려면 지역당, 계정당 한 번만 로깅을 사용 설정하면 됩니다.

콘솔에서 로그를 볼 때 고려할 사항

콘솔에서 로깅을 사용하려면 먼저 IBM Cloud 로그 라우팅을 사용하여 Code Engine 로깅 데이터를 수신하도록 IBM Cloud Logs 플랫폼 로그를 구성해야 합니다. 활성 IBM Cloud Logs 인스턴스를 확인하려면 관찰 가능성 대시보드를 참조하세요.

보존, 검색 및 로그 분석 요구 사항을 고려할 때 IBM Cloud Logs 서비스 요금제 정보를 검토하세요.

Code Engine 애플리케이션, 작업 실행 또는 빌드 실행에 대한 로그 데이터를 볼 때 IBM Cloud Logs 에서 데이터를 사용할 수 있기 전에 지연이 발생할 수 있습니다. 예를 들어, Store and search 데이터 파이프라인을 사용하는 경우 로그 데이터가 IBM Cloud Logs 에 표시되는 데 약 5~10분이 소요될 수 있습니다.

데이터 파이프라인에 대한 설명서를 검토하여 IBM Cloud Logs 인스턴스의 로그 지연 시간과 비용의 균형을 맞추는 옵션에 대해 알아보세요.

CLI로 로깅을 사용하는 경우 Code Engine CLI 로깅은 데이터를 다르게 가져오므로 IBM Cloud Logs 플랫폼 로그를 구성할 필요가 없습니다.

CLI를 통해 제공되는 로깅 기능은 제한적이며 개발 목적으로만 사용해야 합니다. 프로덕션 워크로드를 실행할 때는 항상 로그 보존, 필터 및 검색 기능을 제공하는 IBM Cloud Logs 인스턴스를 사용하세요.

IBM Cloud Logs 데이터에 필터를 적용할 수 있나요?

필요에 따라 필터를 수정하고 범위를 지정하여 특정 수준 또는 특정 애플리케이션 리비전, 작업 실행 또는 빌드 실행에 대한 보다 세분화된 수준으로 로그 데이터를 표시하도록 IBM Cloud Logs 페이지에서 필터를 수정하고 범위를 지정할 수 있습니다.

  • app:"codeengine" 을 설정하면 Code Engine 로그만 표시됩니다.

  • codeengine.project:'<project_name>' 을 설정하면 특정 프로젝트의 로그만 표시됩니다.

  • codeengine.component:'<your_component_name>' 을 설정하면 지정된 구성 요소(애플리케이션, 작업 또는 빌드)의 로그만 표시됩니다. Code Engine 구성 요소가 동일한 이름을 공유하는 경우 필터에는 이러한 구성 요소의 로그가 포함됩니다. 예를 들면 다음과 같습니다.

    • app:"codeengine" AND codeengine.component:"myapp" 필터는 myapp 애플리케이션 수준까지 로그의 범위를 지정합니다.
    • app:"codeengine" AND codeengine.subcomponent:"myapp\-00002" 필터는 myapp-0002 애플리케이션 리비전 레벨로 로그의 범위를 지정합니다.
    • app:"codeengine" AND codeengine.component:"myjob" 필터는 특정 myjob 작업 수준으로 로그의 범위를 지정합니다.
    • app:"codeengine" AND codeengine.subcomponent:"myjob\-jobrun\-t6m7l" 필터는 특정 myjob-jobrun-t6m7l 작업 실행 수준으로 로그의 범위를 지정합니다.
    • app:"codeengine" AND codeengine.component:"mybuild" 필터는 특정 mybuild 빌드 레벨로 로그의 범위를 지정합니다.
    • app:"codeengine" AND codeengine.subcomponent:"mybuild\-run\-121212" 필터는 특정 mybuild-run-121212 빌드 실행 레벨로 로그의 범위를 지정합니다.

콘솔에서 로깅을 구성하고 시작하는 방법에 대한 자세한 내용은 콘솔에서 앱, 작업 또는 함수 로그 보기를 참조하세요.

콘솔에서 앱, 작업 또는 기능 로그 보기

앱, 작업 또는 기능에 대한 로그를 볼 수 있습니다. 콘솔에서 이러한 항목을 보는 단계는 매우 유사합니다.

작업하려는 프로젝트를 선택한 후에는 Code Engine 개요 페이지나 애플리케이션, 작업 또는 기능 페이지와 같은 하위 페이지 중 하나 또는 애플리케이션, 작업 또는 기능에 해당하는 페이지에서 로깅 기능을 추가할 수 있습니다. 다음 단계에서는 특정 Code Engine 페이지에서 작업하고 있다고 가정합니다.

  1. 만들고 배포한 앱, 작업 또는 기능으로 이동합니다. Code Engine 콘솔의 프로젝트 페이지에서 프로젝트를 선택한 다음 애플리케이션, 작업 또는 함수를 적절히 선택합니다. 작업할 앱, 작업 또는 기능을 선택합니다.
  2. 이전에 IBM Cloud Logs 인스턴스를 만든 경우 로깅을 클릭하여 IBM Cloud Logs 서비스를 엽니다.
  3. 로깅 기능을 추가하고 구성하려면 다음 단계를 완료하세요:
    1. 애플리케이션 테스트, 작업 제출 또는 기능 테스트 옵션 메뉴에서 로깅 추가를 클릭하여 IBM Cloud Logs 인스턴스를 만듭니다. 이 조치는 IBM Cloud Logs 서비스를 엽니다.
    2. IBM Cloud Logs 서비스에서 로깅 인스턴스를 작성하십시오. 로깅 인스턴스가 작성되었는지 확인하려면 관찰 가능성 대시보드를 확인하십시오.
    3. Code Engine 앱, 작업 또는 기능 페이지에서 테스트 애플리케이션, 작업 제출 또는 기능 테스트 옵션 메뉴에서 로깅 추가를 클릭합니다. 이번에는 플랫폼 로그를 수신할 IBM Cloud Logs 인스턴스를 선택합니다. 이전 단계에서 만든 로깅 인스턴스를 선택합니다. 선택 을 클릭하세요. Code Engine Code Engine 로깅 데이터를 수신하려면 플랫폼 로그가 활성화되어 있어야 합니다. 이 작업을 완료하면 Code Engine 에서 플랫폼 로깅을 사용하도록 설정합니다.
  4. 이제 플랫폼 로그가 구성되었으므로 Code Engine 앱, 작업 또는 기능 페이지에서 애플리케이션 테스트, 작업 제출 또는 기능 테스트 옵션 메뉴에서 로깅을 클릭하여 플랫폼 로그 창을 엽니다. 해당 지역에 대한 플랫폼 로그가 설정되었는지 확인하려면 관찰 가능성 대시보드를 확인하십시오.
  5. (선택 사항) 필요한 경우 검색 필터를 세분화합니다.
  6. 다음 단계 중 하나를 완료하여 구성을 확인합니다:
    • 애플리케이션 또는 함수의 경우 테스트하려면 애플리케이션 테스트 또는 함수 테스트를 적절히 클릭한 다음 요청 보내기를 클릭합니다. 웹 페이지에서 애플리케이션 또는 기능을 열려면 애플리케이션 URL 또는 기능 URL 을 클릭합니다. 플랫폼 로그 창에서 테스트의 플랫폼 로그를 볼 수 있습니다.
    • 작업 실행: 작업 실행 영역에서 작업 제출을 클릭하여 작업을 실행합니다. 작업 실행 구성 값을 제공하거나 기본값을 사용할 수 있습니다. 작업 제출을 클릭하여 작업을 실행하십시오. 플랫폼 로그 창에서 실행된 작업의 플랫폼 로그를 볼 수 있습니다.

이제 IBM Cloud Logs 인스턴스가 Code Engine 앱, 작업 또는 기능에 대한 플랫폼 로깅을 수신할 수 있도록 구성되었습니다.

또는 Observability 대시보드를 사용하여 인스턴스를 만든 다음 플랫폼 로그 라우팅을 구성하여 IBM Cloud Logs 인스턴스를 구성할 수 있습니다.

콘솔에서 빌드 로그 보기

콘솔에서 특정 빌드 실행 인스턴스에 대한 로그를 표시할 수 있습니다.

  1. Code Engine 대시보드로 이동하십시오.
  2. 프로젝트를 선택하거나 프로젝트를 만듭니다.
  3. 프로젝트 페이지에서 이미지 빌드를 클릭하십시오.
  4. 이미지 빌드 탭에서 이미지 빌드 이름을 클릭하여 정의된 빌드에 대한 빌드 페이지를 열거나 빌드를 만듭니다.
  5. 정의된 빌드에 대한 빌드 페이지의 빌드 실행 섹션에서 빌드 실행 인스턴스의 이름을 클릭하십시오. 빌드 실행을 작성하려면 빌드 제출을 클릭해야 합니다. 플랫폼 로그 창에서 빌드 실행의 플랫폼 로그를 볼 수 있습니다. 또는 빌드 실행 인스턴스 페이지에서 빌드 단계 세부 정보에 대한 빌드 로그 정보를 볼 수도 있습니다. 특정 빌드 단계 로그 데이터에 대한 빌드 단계를 확장합니다. 필요한 경우 선택적으로 검색 필터를 세분화할 수 있습니다.

CLI를 사용하여 로그 보기

CLI로 로깅 출력을 보려면 앱 또는 작업의 실행 중인 인스턴스가 있어야 합니다. 앱의 크기가 0으로 조정되거나 작업 실행 인스턴스가 완료되면 ibmcloud ce app logsibmcloud ce jobrun logs 명령의 출력에는 로그 데이터가 없습니다. 또는 IBM Cloud Logs 서비스를 사용하여 로그 데이터를 볼 수 있습니다.

CLI를 사용하여 애플리케이션 로그 보기

CLI를 사용하여 특정 앱에 대한 앱 로그를 보려면 application logs 명령을 사용하십시오. 모든 앱 인스턴스에 대한 로그를 표시하거나 특정 앱 인스턴스에 대한 로그를 표시할 수 있습니다. app get 명령은 앱의 실행 중인 인스턴스를 포함하여 앱에 대한 세부사항을 표시합니다.

  • myapp 앱의 모든 인스턴스에 대한 로그를 보려면 --app 옵션으로 앱의 이름을 지정합니다. 예를 들어, 다음과 같습니다.

    ibmcloud ce app logs --app myapp
    

    출력 예

    Getting logs for all instances of application 'myapp'...
    OK
    
    myapp-ii18y-2-deployment-7657c5f4f9-dgk5f:
    Server running at http://0.0.0.0:8080/
    
  • 앱의 특정 인스턴스에 대한 로그를 보려면 --instance 옵션을 사용하여 앱의 특정 인스턴스 이름을 지정합니다. 예를 들어, 다음과 같습니다.

    ibmcloud ce app logs --instance myapp-ii18y-2-deployment-7657c5f4f9-dgk5f
    

    출력 예

    Getting logs for application instance 'myapp-a5yp2-2-deployment-65766594d4-hj6c5'...
    OK
    
    myapp-a5yp2-2-deployment-65766594d4-hj6c5:
    Server running at http://0.0.0.0:8080/
    

CLI를 사용하여 작업 로그 보기

CLI를 사용하여 특정 작업 실행에 대한 로그를 보려면 jobrun logs 명령을 사용하십시오. 작업 실행의 모든 인스턴스에 대한 로그를 표시하거나 작업 실행의 특정 인스턴스에 대한 로그를 표시할 수 있습니다. jobrun get 명령으로 작업 실행의 인스턴스를 포함한 작업 실행에 대한 세부사항이 표시됩니다.

  • testjobrun 작업 실행의 모든 인스턴스에 대한 로그를 보려면 --jobrun 옵션으로 작업 실행의 이름을 지정합니다. 예를 들어, 다음과 같습니다.

    ibmcloud ce jobrun logs --jobrun testjobrun
    

    출력 예

    Getting jobrun 'testjobrun'...
    Getting instances of jobrun 'testjobrun'...
    Getting logs for all instances of job run 'testjobrun'...
    OK
    
    testjobrun-1-0:
    Hello World!
    
    testjobrun-2-0:
    Hello World!
    
    testjobrun-3-0:
    Hello World!
    
    testjobrun-4-0:
    Hello World!
    
    testjobrun-5-0:
    Hello World!
    
  • testjobrun-1-0 작업 실행 인스턴스에 대한 로그를 보려면 --instance 옵션을 사용하여 특정 작업 실행 인스턴스의 이름을 지정합니다. 예를 들어, 다음과 같습니다.

    ibmcloud ce jobrun logs --instance testjobrun-1-0
    

    출력 예

    Getting logs for job run instance 'testjobrun-1-0'...
    OK
    
    testjobrun-1-0:
    Hello World!
    

CLI를 사용하여 빌드 로그 보기

CLI를 사용하여 특정 빌드 실행에 대한 빌드 로그를 보려면 buildrun logs 명령을 사용하십시오. 빌드 실행의 이름을 기반으로 빌드 실행의 모든 인스턴스에 대한 로그를 표시할 수 있습니다.

mybuildrun 빌드 실행의 모든 인스턴스에 대한 로그를 보려면 --name 옵션으로 빌드 실행의 이름을 지정합니다. 예를 들어, 다음과 같습니다.

ibmcloud ce buildrun logs --name mybuildrun

출력 예

Getting build run 'mybuildrun'...
Getting instances of build run 'mybuildrun'...
Getting logs for build run 'mybuildrun'...
OK

mybuildrun-zg5rj-pod-z5gzb/step-git-source-source-r9fcf:
{"level":"info","ts":1614363665.8331757,"caller":"git/git.go:169","msg":"Successfully cloned https://github.com/IBM/CodeEngine @ 8b514ce871e50d67cfea3e344b90cade4bd26e90 (grafted, HEAD, origin/main) in path /workspace/source"}
{"level":"info","ts":1614363666.82988,"caller":"git/git.go:207","msg":"Successfully initialized and updated submodules in path /workspace/source"}

mybuildrun-zg5rj-pod-z5gzb/step-build-and-push:
INFO[0002] Retrieving image manifest node:12-alpine
INFO[0002] Retrieving image node:12-alpine
INFO[0003] Retrieving image manifest node:12-alpine
INFO[0003] Retrieving image node:12-alpine
INFO[0003] Built cross stage deps: map[]
INFO[0003] Retrieving image manifest node:12-alpine
INFO[0003] Retrieving image node:12-alpine
INFO[0004] Retrieving image manifest node:12-alpine
INFO[0004] Retrieving image node:12-alpine
INFO[0004] Executing 0 build triggers
INFO[0004] Unpacking rootfs as cmd RUN npm install requires it.
INFO[0008] RUN npm install
INFO[0008] Taking snapshot of full filesystem...
INFO[0010] cmd: /bin/sh
INFO[0010] args: [-c npm install]
INFO[0010] Running: [/bin/sh -c npm install]
npm WARN saveError ENOENT: no such file or directory, open '/package.json'
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN enoent ENOENT: no such file or directory, open '/package.json'
npm WARN !invalid#2 No description
npm WARN !invalid#2 No repository field.
npm WARN !invalid#2 No README data
npm WARN !invalid#2 No license field.

up to date in 0.267s
found 0 vulnerabilities

INFO[0011] Taking snapshot of full filesystem...
INFO[0011] COPY server.js .
INFO[0011] Taking snapshot of files...
INFO[0011] EXPOSE 8080
INFO[0011] cmd: EXPOSE
INFO[0011] Adding exposed port: 8080/tcp
INFO[0011] CMD [ "node", "server.js" ]

mybuildrun-zg5rj-pod-z5gzb/step-image-digest-exporter-ngl6j:
2021/02/26 18:21:02 warning: unsuccessful cred copy: ".docker" from "/tekton/creds" to "/tekton/home": unable to open destination: open /tekton/home/.docker/config.json: permission denied
{"severity":"INFO","timestamp":"2021-02-26T18:21:26.372494581Z","caller":"logging/config.go:116","message":"Successfully created the logger."}
{"severity":"INFO","timestamp":"2021-02-26T18:21:26.372621756Z","caller":"logging/config.go:117","message":"Logging level set to: info"}