Compute Engine에서 설정

Error Reporting을 사용하면 Compute Engine 애플리케이션의 비정상 종료를 집계하고 런타임 예외를 진단할 수 있습니다. Cloud Logging으로 로그를 스트리밍하거나 Error Reporting API를 직접 호출하여 오류 데이터를 보낼 수 있습니다. 로깅을 사용하는 경우 로그 항목이 형식 요구사항을 따라야 합니다.

Logging을 사용한 오류 보고

Compute Engine 애플리케이션을 Error Reporting에 연결하려면 다음 에이전트 중 하나를 사용하여 예외 또는 기타 오류를 Logging에 전송합니다.

운영 에이전트

운영 에이전트를 사용하도록 Error Reporting을 설정하려면 다음 단계를 완료하세요.

  1. 사용자 환경에 적합한 운영 에이전트를 설치합니다. 자세한 내용은 운영 에이전트 설치를 참고하세요.

  2. 애플리케이션 로그를 수집하고 적절하게 형식을 지정하도록 운영 에이전트를 구성합니다.

    • 지원되는 서드 파티 애플리케이션: 운영 에이전트는 Error Reporting에서 인식하는 구조화된 형식으로 로그 항목을 자동으로 캡처하고 파싱하는 사전 구성된 로깅 수신기를 제공합니다. 지원되는 서드 파티 애플리케이션에 관한 자세한 내용은 서드 파티 애플리케이션 모니터링을 참고하세요.

    • 맞춤 애플리케이션: 로깅 수신자를 구성하여 로그 파일 위치를 지정하고 다음 프로세서 중 하나와 페어링합니다.

      • 앱이 여러 줄에 일반 텍스트 스택 트레이스를 쓰는 경우 parse_multiline 프로세서를 사용하세요.
      • 앱이 로그를 JSON 문자열로 작성하는 경우 parse_json 프로세서를 사용합니다.

      자세한 내용은 운영 에이전트 구성을 참고하세요.

  3. 애플리케이션이 표준 스택 트레이스를 생성하지 않으면 예외 및 스택 트레이스를 Cloud Logging에 로깅하도록 애플리케이션을 수정합니다.

    스택 트레이스의 모든 프레임을 포함하여 단일 오류 또는 예외에 대한 모든 정보를 동일한 로그 항목에 포함해야 합니다. 모든 정보가 함께 표시되지 않으면 Error Reporting이 오류를 감지하지 못할 수 있습니다. 로그 항목 페이로드에 대해 구조화된 JSON 형식을 사용하여 각 오류에 다양한 종류의 정보를 포함할 수 있습니다.

기존 Logging 에이전트

기존 Logging 에이전트를 사용하도록 Error Reporting을 설정하려면 다음 단계를 완료하세요.

  1. 사용자 환경에 적합한 google-fluentd 에이전트를 설치합니다. 자세한 내용은 Logging 에이전트 설치를 참고하세요.
  2. Logging에 예외 및 스택 트레이스를 로깅하도록 애플리케이션을 수정합니다.

    스택 트레이스의 모든 프레임을 포함하여 단일 오류 또는 예외에 대한 모든 정보를 동일한 로그 항목에 포함해야 합니다. 모든 정보가 함께 표시되지 않으면 Error Reporting이 오류를 감지하지 못할 수 있습니다. 로그 항목 페이로드에 대해 구조화된 JSON 형식을 사용하여 각 오류에 다양한 종류의 정보를 포함할 수 있습니다.

자바

pom.xml 파일에 다음을 추가합니다.

<dependency>
  <groupId>org.fluentd</groupId>
  <artifactId>fluent-logger</artifactId>
  <version>0.3.4</version>
</dependency>

그런 다음 다음과 같은 코드를 사용하여 예외 데이터를 보냅니다.

public class ExceptionUtil {
  private static FluentLogger ERRORS = FluentLogger.getLogger("myapp");

  public static void main(String[] args) {
    try {
      throw new Exception("Generic exception for testing Stackdriver");
    } catch (Exception e) {
      report(e);
    }
  }

  public static void report(Throwable ex) {
    StringWriter exceptionWriter = new StringWriter();
    ex.printStackTrace(new PrintWriter(exceptionWriter));
    Map<String, Object> data = new HashMap<>();
    data.put("message", exceptionWriter.toString());
    Map<String, String> serviceContextData = new HashMap<>();
    serviceContextData.put("service", "myapp");
    data.put("serviceContext", serviceContextData);
    // ... add more metadata
    ERRORS.log("errors", data);
  }
}

Python

먼저 fluent-logger-python 라이브러리를 설치합니다.

sudo pip install fluent-logger

그런 다음 다음과 같은 코드를 사용하여 예외 데이터를 보냅니다.

import traceback

import fluent.event
import fluent.sender


def simulate_error():
    fluent.sender.setup("myapp", host="localhost", port=24224)

    def report(ex):
        data = {}
        data["message"] = "{0}".format(ex)
        data["serviceContext"] = {"service": "myapp"}
        # ... add more metadata
        fluent.event.Event("errors", data)

    # report exception data using:
    try:
        # simulate calling a method that's not defined
        raise NameError
    except Exception:
        report(traceback.format_exc())

Node.js

먼저 fluent-logger-node 라이브러리를 설치합니다.

npm install fluent-logger

그런 다음 다음과 같은 코드를 사용하여 예외 데이터를 보냅니다.

const structuredLogger = require('fluent-logger').createFluentSender('myapp', {
  host: 'localhost',
  port: 24224,
  timeout: 3.0,
});

const report = (err, req) => {
  const payload = {
    serviceContext: {
      service: 'myapp',
    },
    message: err.stack,
    context: {
      httpRequest: {
        url: req.originalUrl,
        method: req.method,
        referrer: req.header('Referer'),
        userAgent: req.header('User-Agent'),
        remoteIp: req.ip,
        responseStatusCode: 500,
      },
    },
  };
  structuredLogger.emit('errors', payload);
};

// Handle errors (the following uses the Express framework)
// eslint-disable-next-line no-unused-vars
app.use((err, req, res, next) => {
  report(err, req);
  res.status(500).send(err.response || 'Something broke!');
});

Go

먼저 fluent-logger-golang 패키지를 설치합니다.

go get github.com/fluent/fluent-logger-golang/

그런 다음 다음과 같은 코드를 사용하여 오류 데이터를 보냅니다.


package main

import (
	"log"
	"net/http"
	"os"
	"runtime"

	"github.com/fluent/fluent-logger-golang/fluent"
)

var logger *fluent.Fluent

func main() {
	var err error
	logger, err = fluent.New(fluent.Config{
		FluentHost: "localhost",
		FluentPort: 24224,
	})
	if err != nil {
		log.Fatal(err)
	}

	http.HandleFunc("/demo", demoHandler)

	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}
	log.Printf("Listening on port %s", port)
	if err := http.ListenAndServe(":"+port, nil); err != nil {
		log.Fatal(err)
	}
}

func report(stackTrace string, r *http.Request) {
	payload := map[string]interface{}{
		"serviceContext": map[string]interface{}{
			"service": "myapp",
		},
		"message": stackTrace,
		"context": map[string]interface{}{
			"httpRequest": map[string]interface{}{
				"method":    r.Method,
				"url":       r.URL.String(),
				"userAgent": r.UserAgent(),
				"referrer":  r.Referer(),
				"remoteIp":  r.RemoteAddr,
			},
		},
	}
	if err := logger.Post("myapp.errors", payload); err != nil {
		log.Print(err)
	}
}

// Handler for the incoming requests.
func demoHandler(w http.ResponseWriter, r *http.Request) {
	// How to handle a panic.
	defer func() {
		if e := recover(); e != nil {
			stack := make([]byte, 1<<16)
			stackSize := runtime.Stack(stack, true)
			report(string(stack[:stackSize]), r)
		}
	}()

	// Panic is triggered.
	x := 0
	log.Println(100500 / x)
}

Error Reporting API를 사용하여 오류 쓰기

Error Reporting API는 서비스에 오류 정보를 작성하기 위한 report 엔드포인트를 제공합니다.

  1. Error Reporting API를 아직 사용 설정하지 않았다면 사용 설정합니다.

    API 사용 설정에 필요한 역할

    API를 사용 설정하려면 serviceusage.services.enable 권한이 필요합니다. 프로젝트를 만든 경우 소유자 역할 (roles/owner)을 통해 이 권한이 이미 있을 수 있습니다. 그렇지 않으면 서비스 사용량 관리자 역할 (roles/serviceusage.serviceUsageAdmin)을 통해 이 권한을 얻을 수 있습니다. 역할을 부여하는 방법 알아보기

    API 사용 설정하기

  2. REST API 또는 클라이언트 라이브러리를 사용하여 오류를 API로 보고합니다.

    • REST API

      API에 대한 자세한 내용은 참고 문서를 확인하세요.

    • 클라이언트 라이브러리 사용

      라이브러리는 제한된 언어에 대해 제공되며 애플리케이션에서 Error Reporting API를 호출하는 데 도움이 됩니다.

샘플

ASP.NET

ASP.NET NuGet 패키지는 ASP.NET 웹 애플리케이션에서 포착되지 않은 예외를 Error Reporting으로 보고합니다.

NuGet 패키지 설치

Visual Studio에서 Stackdriver ASP.NET NuGet 패키지를 설치하려면 다음 단계를 따르세요.

  1. 솔루션을 마우스 오른쪽 버튼으로 클릭하고 Manage NuGet packages for solution(솔루션용 NuGet 패키지 관리)를 선택합니다.
  2. Include prerelease(사전 출시 포함) 체크박스를 선택합니다.
  3. 이름이 Google.Cloud.Diagnostics.AspNet인 패키지를 검색하여 설치합니다.

사용

Stackdriver ASP.NET NuGet 패키지를 설치했으면 애플리케이션 코드에 다음 문을 추가하여 Stackdriver로 오류 보내기를 시작합니다.

using Google.Cloud.Diagnostics.AspNet;

다음 HttpConfiguration 코드를 .NET 웹 앱(your-project-id를 실제 프로젝트 ID로 바꿈)의 Register 메서드에 추가하여 예외 보고를 사용 설정합니다.

public static void Register(HttpConfiguration config)
{
    string projectId = "YOUR-PROJECT-ID";
    string serviceName = "NAME-OF-YOUR-SERVICE";
    string version = "VERSION-OF-YOUR-SERVCICE";
    // ...
    // Add a catch all for the uncaught exceptions.
    config.Services.Add(typeof(IExceptionLogger),
        ErrorReportingExceptionLogger.Create(projectId, serviceName, version));
    // ...
}

이 메서드를 ASP.NET 애플리케이션에 추가하면 Google Cloud 콘솔의 Error Reporting 섹션에서 Google Cloud에 보고될 때 발생하는 포착되지 않은 예외를 볼 수 있습니다.

C#

다음 예시는 GoogleCloudPlatform/dotnet-docs-samples 저장소에서 찾을 수 있습니다. 사용하려면 프로젝트를 빌드한 후 프로젝트 ID를 지정합니다.

C:\...\bin\Debug> set GOOGLE_PROJECT_ID=[YOUR_PROJECT_ID]

[YOUR_PROJECT_ID]를Google Cloud 콘솔의 올바른 값으로 바꿉니다.

그런 다음 다음과 유사한 코드로 예외 데이터를 보냅니다.

public class ErrorReportingSample
{
    public static void Main(string[] args)
    {
        try
        {
            throw new Exception("Generic exception for testing Stackdriver Error Reporting");
        }
        catch (Exception e)
        {
            report(e);
            Console.WriteLine("Stackdriver Error Report Sent");
        }
    }

    /// <summary>
    /// Create the Error Reporting service (<seealso cref="ClouderrorreportingService"/>)
    /// with the Application Default Credentials and the proper scopes.
    /// See: https://developers.google.com/identity/protocols/application-default-credentials.
    /// </summary>
    private static ClouderrorreportingService CreateErrorReportingClient()
    {
        // Get the Application Default Credentials.
        GoogleCredential credential = GoogleCredential.GetApplicationDefaultAsync().Result;

        // Add the needed scope to the credentials.
        credential.CreateScoped(ClouderrorreportingService.Scope.CloudPlatform);

        // Create the Error Reporting Service.
        ClouderrorreportingService service = new ClouderrorreportingService(new BaseClientService.Initializer
        {
            HttpClientInitializer = credential,
        });
        return service;
    }

    /// <summary>
    /// Creates a <seealso cref="ReportRequest"/> from a given exception.
    /// </summary>
    private static ReportRequest CreateReportRequest(Exception e)
    {
        // Create the service.
        ClouderrorreportingService service = CreateErrorReportingClient();

        // Get the project ID from the environement variables.
        string projectId = Environment.GetEnvironmentVariable("GOOGLE_PROJECT_ID");

        // Format the project id to the format Error Reporting expects. See:
        // https://cloud.google.com/error-reporting/reference/rest/v1beta1/projects.events/report
        string formattedProjectId = string.Format("projects/{0}", projectId);

        // Add a service context to the report.  For more details see:
        // https://cloud.google.com/error-reporting/reference/rest/v1beta1/projects.events#ServiceContext
        ServiceContext serviceContext = new ServiceContext()
        {
            Service = "myapp",
            Version = "8c1917a9eca3475b5a3686d1d44b52908463b989",
        };
        ReportedErrorEvent errorEvent = new ReportedErrorEvent()
        {
            Message = e.ToString(),
            ServiceContext = serviceContext,
        };
        return new ReportRequest(service, errorEvent, formattedProjectId);
    }

    /// <summary>
    /// Report an exception to the Error Reporting service.
    /// </summary>
    private static void report(Exception e)
    {
        // Create the report and execute the request.
        ReportRequest request = CreateReportRequest(e);
        request.Execute();
    }
}

Go

Go용 Error Reporting 설정을 참조하세요.

자바

자바용 Error Reporting 설정을 참조하세요.

Node.js

Node.js용 Error Reporting 설정을 참조하세요.

Ruby

Ruby용 Error Reporting 설정을 참조하세요.

Python

Python용 Error Reporting 설정을 참조하세요.

PHP

PHP용 Error Reporting 설정을 참조하세요.

오류 그룹 보기

Google Cloud 콘솔에서 Error Reporting 페이지로 이동합니다.

Error Reporting으로 이동

검색창을 사용하여 이 페이지를 찾을 수도 있습니다.