在 Amazon EC2 中设置 Error Reporting

您可以通过下列任一方式将 EC2 应用的错误发送到 Error Reporting:

使用 Logging 报告错误

如需将 EC2 应用连接到 Error Reporting,请使用专用的日志名称将异常或其他错误发送到 Logging,以使错误与其他日志分开。

例如:

  1. 启用 Cloud Logging API。

    启用 API

  2. 安装适用于您的环境的 Logging 代理。如需查看说明,请转到安装 Logging 代理 google-fluentd

  3. 修改您的应用,使其将异常及其堆栈轨迹记录到 Logging 中。为您的错误信息选择日志名称,使其与其他已记录的信息分开。

    您必须在同一日志条目中添加单个错误或异常的所有信息,包括任何堆栈轨迹的所有帧。如果所有信息没有收集在一起,则 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 --save 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 -u 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

  2. 使用 REST API 或客户端库向 API 报告错误。

示例

ASP.NET

Stackdriver ASP.NET NuGet 软件包将 ASP.NET Web 应用中未捕获的异常报告给 Error Reporting。

安装 NuGet 程序包

要在 Visual Studio 中安装 Stackdriver ASP.NET NuGet 程序包,请执行以下操作:

  1. 右键点击您的解决方案,然后选择管理解决方案的 NuGet 程序包
  2. 选中包括预发行版复选框。
  3. 搜索并安装名为 Google.Cloud.Diagnostics.AspNet 的软件包。

用量

安装 Stackdriver ASP.NET NuGet 程序包之后,请将下列语句添加到应用代码中,以开始向 Stackdriver 发送错误:

using Google.Cloud.Diagnostics.AspNet;

将以下 HttpConfiguration 代码添加到您的.NET Web 应用的 Register 方法中(用您的实际项目 ID 替换 your-project-id),以便启用异常报告功能:

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 应用之后,即可在 Cloud Console 的 Error Reporting 部分中查看报告到 Google Cloud 的任何未捕获异常。

C#

有关以下示例,可查看 GoogleCloudPlatform/dotnet-docs-samples 代码库。若要使用该示例,请在构建项目后指定您的项目 ID

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

请务必将 [YOUR_PROJECT_ID] 替换为 Cloud Console 中的正确值。

然后,使用类似下面的代码发送异常数据:

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

Java

请参阅设置 Java 版 Error Reporting

Node.js

请参阅设置 Node.js 版 Error Reporting

Ruby

请参阅设置 Ruby 版 Error Reporting

Python

请参阅设置 Python 版 Error Reporting