2세대 런타임(Java 11+)의 로깅은 1세대 런타임(Java 8)과 다릅니다. 1세대 런타임과 달리 2세대 런타임에서는 앱 로그가 로그 탐색기 내의 요청 로그 아래에 그룹화되지 않습니다. 또한 2세대 런타임에서 App Engine은 요청과 관련된 각 앱 로그를 Cloud Logging의 개별 로그 항목으로 작성합니다.
이 가이드에서는 1세대 런타임 앱에서 사용한 것과 동일한 로깅 방법을 구현하고 앱을 Java 11+로 마이그레이션할 때 거의 동일한 필터링 및 로깅 상관관계 결과를 달성하는 방법을 설명합니다.
주요 차이점
다음 표에서는 1세대 런타임과 2세대 런타임 로깅 간의 차이점을 설명합니다.
1세대 런타임(Java 8) | 2세대 런타임(Java 11+) | |
---|---|---|
요청 및 앱 로그(애플리케이션 로그라고도 함) | App Engine이 모든 앱 로그를 요청 로그 내에 삽입합니다. | App Engine이 앱 로그를 요청 로그 내에 삽입하지 않습니다. |
stdout 및 stderr |
App Engine이 stdout 및 stderr 에 작성된 로그를 요청 로그 내에 삽입합니다. |
App Engine이 stdout 및 stderr 에 작성된 로그를 삽입하지 않습니다.
|
App Engine 플랫폼 로그 | App Engine이 내부 플랫폼 로그를 내보내지 않습니다. | App Engine이 인스턴스를 시작하거나 종료할 때 /var/log/google_init.log 로그 이름을 사용하여 내부 플랫폼 로그를 내보냅니다.
|
Cloud Logging API 할당량 | 각 요청은 한 번의 Cloud Logging 쓰기 작업에 해당합니다. | 요청과 연결된 각 앱 로그 항목은 한 번의 Cloud Logging 쓰기 작업에 해당합니다. Cloud Logging API 사용량은 2세대 런타임에서 증가합니다. |
요청 로그 및 앱 로그
1세대 런타임과 2세대 런타임의 로깅 동작은 다음과 같은 점에서 차이가 있습니다.
1세대 런타임에서 App Engine은 요청 로그의
protoPayload.line
필드에 앱 로그를 삽입합니다. 로그 탐색기에서 요청을 확장하여 앱 로그를 볼 수 있습니다.다음 이미지는 1세대 런타임에서 상관관계가 지정된 요청과 앱 로그를 보여줍니다.
2세대 런타임에서는
protoPayload.line
필드가 요청 로그에 없기 때문에 요청 로그에 앱 로그 항목이 포함되지 않습니다. 대신 App Engine이 각 앱 로그를 개별 항목으로 로깅합니다. 로그 이름은 로깅 설정에 따라 달라집니다.var/log/app
에는java.util.logging
또는 Java용 단순 로깅 퍼사드(SLF4J)와 같은 표준 로깅 프레임워크를 사용하여 내보내는 로그가 포함됩니다.stderr
및stdout
로그에는System.err.print()
또는System.out.print()
를 사용하여 로깅되는 앱 로그가 포함됩니다.다음 이미지는 2세대 런타임의 별도의 요청 로그와 앱 로그를 보여줍니다.
stdout
및 stderr
1세대 런타임에서 App Engine은 stdout
및 stderr
로 내보낸 로그를 앱 로그로 간주하고 이러한 앱 로그 항목을 연관된 요청 로그 아래에 자동으로 그룹화합니다.
2세대 런타임에서 App Engine은 기본적으로 stdout
및 stderr
로 내보낸 로그를 연결하지 않습니다. stdout
및 stderr
을 사용하여 앱 로그 항목을 요청 로그와 그룹화하려면 stdout
및 stderr
에 구조화된 로그 작성의 안내를 따르세요.
특정 App Engine 플랫폼 로그(JVM, Jetty, 내부 인프라 로그)도 stderr
로 내보내기 때문에 stdout
및 stderr
에 로깅은 권장되지 않습니다. 앱 로그 및 플랫폼 로그는 stderr
로그 이름을 사용하여 표시되기 때문에 모호성이 발생합니다. App Engine에 더 많은 수의 플랫폼 로그가 생성되기 때문에 2세대 런타임에서 이 문제가 더 커집니다.
App Engine 플랫폼 로그
1세대 런타임에서 App Engine은 플랫폼 로그를 내보내지 않습니다.
2세대 런타임에서 App Engine은 인스턴스를 시작하거나 종료할 때 로그 이름 /var/log/google_init.log
를 사용하여 플랫폼 로그를 내보냅니다.
플랫폼 로그는 무시해도 됩니다. 이러한 로그가 표시되지 않도록 하려면 logName="/var/log/google_init.log"
쿼리를 사용해서 로그 탐색기에 필터를 추가합니다.
다음 이미지는 2세대 런타임의 플랫폼 로그를 표시합니다.
Cloud Logging API 할당량
1세대 런타임에서 App Engine은 단일 요청 로그에 요청을 수행하는 동안 내보낸 모든 앱 로그를 삽입하고 삽입된 요청을 Cloud Logging으로 전송합니다. 각 요청은 한 번의 Cloud Logging 쓰기 작업에 해당합니다.
2세대 런타임에서 App Engine은 각 앱 로그를 개별 로그 항목으로 Cloud Logging에 전송하여 요청당 총 Cloud Logging 쓰기 작업 수를 늘립니다.
Google Cloud는 Cloud Logging에 사용되는 전체 스토리지를 기반으로 청구를 결정합니다. 로그에 필요한 전체 스토리지가 크게 증가하지 않더라도 App Engine이 요청당 작성하는 앱 로그 수에 따라 분당 쓰기 작업이 증가합니다. 앱이 Cloud Logging 쓰기 할당량을 초과하면 사용 할당량의 증가를 요청할 수 있습니다.
자세한 내용은 Cloud Logging의 가격 책정을 참조하세요.
마이그레이션 프로세스 개요
앱 로그가 2세대 런타임의 요청 로그 내에 삽입되지 않은 경우에도 1세대 앱과 같은 로그 보기 환경을 유지할 수 있습니다.
2세대 런타임에서 로깅을 설정하기 위해 다음 옵션 중 하나를 선택할 수 있습니다.
java.util.logging
(JUL) 패키지 사용: App Engine에는 trace ID를 사용해서 요청 및 앱 로그를 연결하기 위한 기본 제공되는 지원이 포함됩니다. trace ID가 앱 로그에 있으면 로그 탐색기가 요청 로그 내에 그룹화된 앱 로그를 렌더링합니다.Java용 단순 로깅 퍼사드(SLF4J) 사용: 앱에 사용되는 다음 로깅 백엔드에 따라 trace ID를 추가하도록 소스 코드를 수정해야 합니다.
java.util.logging
(JUL) 패키지 사용
1세대 런타임을 사용하는 앱이 모든 로깅 요구사항에 대해 java.util.logging
패키지를 구현하는 경우 2세대 런타임으로 마이그레이션하기 위해서는 코드 변경이 필요하지 않습니다.
다음 샘플에서는 2세대 런타임에서 로깅을 위해 java.util.logging
패키지를 사용하는 방법을 보여줍니다.
package com.example.appengine.my_app;
import java.io.IOException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.util.logging.Logger;
@WebServlet(name = "HelloAppEngine", value = "/")
public class HelloAppEngine extends HttpServlet {
// Use the java.util.logging.Logger to log messages
private static final Logger logger = Logger.getLogger(HelloAppEngine.class.getName());
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// Sample log messages
logger.info("Info message");
logger.warning("Warning message");
logger.severe("Severe message");
response.setContentType("text/plain");
response.getWriter().println("Hello App Engine");
}
}
요청 로그로 앱 로그 그룹화
2세대 런타임에서 요청 로그의 protoPayload.line
필드에는 앱 로그가 포함되지 않습니다. 로그 탐색기는 trace
필드를 사용해서 요청 로그 및 앱 로그를 그룹화합니다. java.util.logging
패키지는 모든 요청 및 앱 로그에 trace ID를 자동으로 추가합니다. 로그 탐색기에서 상관관계가 지정된 로그를 보려면 상관관계가 지정된 로그 보기를 참조하세요.
Java용 단순 로깅 퍼사드(SLF4J) 사용
SLF4J는 Java 애플리케이션에서 사용되는 가장 인기 있는 로깅 인터페이스입니다. 퍼사드인 SLF4J 인터페이스는 로깅 백엔드의 플랫폼과 독립적이며 앱에 적합한 백엔드를 선택할 수 있게 해줍니다.
다음 이미지는 java.util.logging
라이브러리 및 Logback 어펜더를 포함하여 2개의 SLF4J 백엔드에 대한 통합 옵션을 보여줍니다.
java.util.logging
패키지를 사용하는 SLF4J
SLF4J를 사용하면 java.util.logging
로깅 백엔드와 함께 SLF4J를 사용할 때 앱을 Cloud Logging에 통합할 수 있습니다. 기본적으로 App Engine은 모든 요청 및 앱 로그에 trace ID를 추가합니다. 이 메커니즘을 사용하면 로그 탐색기에서 요청 및 앱 로그를 그룹화할 수 있습니다.
java.util.logging
으로 SLF4J를 구현하려면 다음 단계를 수행합니다.
slf4j-jdk14.jar
종속 항목을pom.xml
파일에 추가합니다.slf4j-jdk14.jar
파일은java.util.logging
라이브러리에 대한 백엔드 통합을 제공합니다.<!-- SLF4J interface --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>2.0.4</version> </dependency> <!-- JUL implementation for SLF4J --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-jdk14</artifactId> <version>2.0.9</version> </dependency>
WEB-INF/logging.properties
파일을 만들어 커스텀 구성을 추가합니다.com.example.appengine.java8.HelloAppEngine.level = INFO
WEB-INF/logging.properties
에 대해<property>
값을 포함하도록appengine-web.xml
파일을 업데이트합니다.<system-properties> <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/> </system-properties>
다음 이미지는 java.util.logging
과 함께 SLF4J가 앱 로그에 trace ID를 자동으로 추가하는 방법을 보여줍니다.
1세대 런타임과 같이 로그 탐색기 보기를 요청 중심의 보기로 조정하려면 상관관계가 지정된 로그 보기를 참조하세요.
Logback 어펜더와 함께 SLF4J 사용
1세대 런타임 앱에 Logback과 함께 SLF4J에 대한 기본 제공 구현이 사용되는 경우 소스 코드를 업데이트하고 요청 및 앱 로그를 그룹화하기 위한 추가 단계를 구현해야 합니다.
앱을 Cloud Logging에 통합하려면 다음 단계를 수행합니다.
pom.xml
파일에google-cloud-logging-logback
어펜더를 추가하여 Logback에 대한 로깅 어펜더를 설치합니다.<!-- SLF4J interface --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>2.0.4</version> </dependency> <!-- Logback JARs --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.3.6</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.3.5</version> </dependency> <!-- Google Cloud logging appender for Logback --> <dependency> <groupId>com.google.cloud</groupId> <artifactId>google-cloud-logging-logback</artifactId> </dependency>
각
LogEntry
필드에 trace ID를 추가하기 위해 로깅 개선 도구를 만듭니다. 다음TraceIdLoggingEnhancer
클래스는 ApiProxy API를 사용하여 요청과 연결된 trace ID를 검색합니다.import com.google.appengine.api.utils.SystemProperty; import com.google.cloud.logging.LogEntry; import com.google.cloud.logging.LoggingEnhancer; import com.google.apphosting.api.ApiProxy; import com.google.apphosting.api.ApiProxy.Environment; // Add trace ID to the log entry public class TraceIdLoggingEnhancer implements LoggingEnhancer { @Override public void enhanceLogEntry(LogEntry.Builder logEntry) { final String PROJECT_ID = SystemProperty.applicationId.get(); Environment environment = ApiProxy.getCurrentEnvironment(); if (environment instanceof ApiProxy.EnvironmentWithTrace) { ApiProxy.EnvironmentWithTrace environmentWithTrace = (ApiProxy.EnvironmentWithTrace) environment; environmentWithTrace .getTraceId() .ifPresent( id -> logEntry.setTrace(String.format("projects/%s/traces/%s", PROJECT_ID, id))); } } } // [END logging_enhancer]
logback.xml
파일의 Cloud Logging 어펜더를 추가하여 Logback을 구성합니다. Logback 프레임워크는WEB-INF/classes
에서logback.xml
파일을 통해 구성을 관리합니다.<configuration> <appender name="CLOUD" class="com.google.cloud.logging.logback.LoggingAppender"> <!-- This should be set to the new Logging Enhancer in the app code. --> <enhancer>com.example.appengine.my_app.enhancers.TraceIdLoggingEnhancer</enhancer> <resourceType>gae_app</resourceType> </appender> <root level="info"> <appender-ref ref="CLOUD" /> </root> </configuration>
다음 이미지는 최종 앱 디렉터리 구조를 보여줍니다.
상관관계가 지정된 로그 보기
로그 탐색기에서 각 로그 항목의 trace ID 필드를 사용하여 상관관계가 지정된 로그를 볼 수 있습니다. 로그 탐색기에서 상관관계가 지정된 로그를 보려면 다음 안내를 따르세요.
Google Cloud 콘솔의 탐색 패널에서 Logging을 선택한 후 로그 탐색기를 선택합니다.
리소스 유형에서 GAE 애플리케이션을 선택합니다.
요청 로그를 보고 상관관계를 지정하려면 로그 이름에서 request_log를 선택합니다. 또는 요청 로그별로 상관관계를 지정하려면 상관관계 지정 기준을 클릭하고 request_log를 선택합니다.
쿼리 결과 창에서 로그 항목을 펼치려면 펼치기를 클릭합니다. 펼치면 각 요청 로그에 연결된 앱 로그가 표시됩니다.