在 Amazon EC2 中设置 Error Reporting

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

使用 Logging 报告错误

如需将 EC2 应用连接到 Error Reporting,请将异常或其他错误发送到 Logging。

例如:

  1. 将 Amazon Web Services (AWS) 系统连接到 Google Cloud。如需了解详情,请参阅在单个虚拟机上安装 Logging 代理
  2. 根据您的环境,安装 Logging google-fluentd 代理。如需查看说明,请参阅安装 Logging 代理
  3. 修改应用,使其将异常及其堆栈轨迹记录到 Logging。

    您必须在同一日志条目中添加单个错误或异常的所有信息,包括任何堆栈轨迹的所有帧。如果所有信息没有汇总在一起,则 Error Reporting 可能无法检测到错误。您可以对日志条目载荷使用结构化 JSON 格式,从而为每个错误包含不同类型的信息。

  4. 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 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

    ASP.NET NuGet 程序包向 Error Reporting 报告 ASP.NET Web 应用中未捕获的异常。

    安装 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 应用后,您可以在 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

    Java

    请参阅设置 Java 版 Error Reporting

    Node.js

    请参阅设置 Node.js 版 Error Reporting

    Ruby

    请参阅设置 Ruby 版 Error Reporting

    Python

    请参阅设置 Python 版 Error Reporting

    PHP

    请参阅设置 PHP 版 Error Reporting

    查看错误组

    在 Google Cloud 控制台的导航面板中,选择 Error Reporting,然后选择您的 Google Cloud 项目:

    前往 Error Reporting