Amazon EC2 上の Error Reporting の設定

Error Reporting を使用すると、EC2 アプリケーションのクラッシュを集計し、ランタイム例外を診断できます。エラーデータを送信するには、Cloud Logging にログをストリーミングするか、Error Reporting API を直接呼び出します。Logging を使用する場合、ログエントリは形式の要件に準拠している必要があります。

ロギングを使用してエラーを報告する

EC2 アプリケーションを Error Reporting に接続するには、例外やその他のエラーを Logging に送信します。

次に例を示します。

  1. Amazon Web Services(AWS)システムを Google Cloudに接続します。詳細については、個々の VM に Logging エージェントをインストールするをご覧ください。
  2. ご使用の環境に適した Logging google-fluentd エージェントをインストールします。手順については、Logging エージェントをインストールするをご覧ください。
  3. 例外とスタック トレースを Logging に記録するようにアプリケーションを変更します。

    単一のエラーまたは例外に関する情報は、スタック トレースのすべてのフレームを含め、すべて同じログエントリに格納する必要があります。すべての情報が 1 つにまとめられていないと、Error Reporting でエラーを検出できない可能性があります。ログエントリのペイロードに構造化 JSON 形式を使用すると、各エラーに関するさまざまな情報を含めることができます。

Java

次のコードを 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