diff --git a/flexible/errorreporting/README.md b/flexible/errorreporting/README.md new file mode 100644 index 00000000000..089cbfb8fb3 --- /dev/null +++ b/flexible/errorreporting/README.md @@ -0,0 +1,52 @@ +# Error reporting sample for Google App Engine Flexible + +[Stackdriver Error Reporting][error-reporting] Stackdriver Error Reporting counts, analyzes and aggregates the crashes in your running cloud services. +A [centralized error management interface](https://console.cloud.google.com/errors) displays the results with sorting and filtering capabilities. + +This sample Java application demonstrates how errors are automatically sent to Error reporting in applications running in [App Engine Flex environment][ae-flex]. +It also demonstrates how to send custom error events using the Error Reporting API. + +[error-reporting]: https://cloud.google.com/error-reporting/ +[ae-flex]: https://cloud.google.com/appengine/docs/flexible/java +[google-cloud-java]: https://github.com/GoogleCloudPlatform/google-cloud-java + +## Setup + +1. Install [Maven](http://maven.apache.org/). +1. Install and initialize [GCloud SDK](https://cloud.google.com/sdk/downloads). +1. [Enable](https://console.cloud.google.com/apis/api/clouderrorreporting.googleapis.com/overview) Stack Driver Error Reporting API. +(Note : only required for logging custom events using the Error Reporting API) + +## Build +Build your project with: +``` + mvn clean package +``` + +## Local testing +1. Authorize the local environment +``` + gcloud auth application-default login +``` +For local testing, we will be using the [Jetty Maven plugin](http://www.eclipse.org/jetty/documentation/9.4.x/jetty-maven-plugin.html). +Run: +``` + mvn jetty:run +``` +Access [http://localhost:8080/error](http://localhost:8080/error) endpoint. + +After accessing the `/error` endpoint, check the [error reporting console](https://console.cloud.google.com/errors). +Confirm that you see the custom error reported using the error reporting API. + +## Deploy +Run: +``` + mvn appengine:deploy +``` +Access [https://YOUR_PROJECT_ID.appspot.com/error] endpoint. + +After accessing the `/error` endpoint, check the [error reporting console](https://console.cloud.google.com/errors). +Confirm that you see: +1. IllegalArgumentException logged via the standard logging framework. +1. Custom error reported using the error reporting API. +1. Runtime exception. diff --git a/flexible/errorreporting/pom.xml b/flexible/errorreporting/pom.xml new file mode 100644 index 00000000000..05599c4a521 --- /dev/null +++ b/flexible/errorreporting/pom.xml @@ -0,0 +1,90 @@ + + + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.flexible + flexible-error-reporting + + + doc-samples + com.google.cloud + 1.0.0 + ../.. + + + + 1.3.1 + 1.8 + 1.8 + false + 9.4.6.v20170531 + + + + + + + com.google.auth + google-auth-library-credentials + 0.6.1 + + + com.google.auth + google-auth-library-oauth2-http + 0.6.1 + + + + + + + javax.servlet + javax.servlet-api + 3.1.0 + jar + provided + + + com.google.cloud + google-cloud-errorreporting + 0.20.0-alpha + + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + com.google.cloud.tools + appengine-maven-plugin + ${appengine.maven.plugin} + + + + + + org.eclipse.jetty + jetty-maven-plugin + ${jetty.maven.plugin} + + + + + diff --git a/flexible/errorreporting/src/main/appengine/app.yaml b/flexible/errorreporting/src/main/appengine/app.yaml new file mode 100644 index 00000000000..7ce831ea623 --- /dev/null +++ b/flexible/errorreporting/src/main/appengine/app.yaml @@ -0,0 +1,20 @@ +# Copyright 2017 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# [START appyaml] +runtime: java +env: flex + +handlers: +- url: /.* + script: this field is required, but ignored +# [END appyaml] diff --git a/flexible/errorreporting/src/main/java/com/example/flexible/errorreporting/ErrorReportingExample.java b/flexible/errorreporting/src/main/java/com/example/flexible/errorreporting/ErrorReportingExample.java new file mode 100644 index 00000000000..38a7c86d666 --- /dev/null +++ b/flexible/errorreporting/src/main/java/com/example/flexible/errorreporting/ErrorReportingExample.java @@ -0,0 +1,72 @@ +/** + * Copyright 2017 Google Inc. + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.example.flexible.errorreporting; + +import com.google.cloud.ServiceOptions; +import com.google.cloud.errorreporting.v1beta1.ReportErrorsServiceClient; +import com.google.devtools.clouderrorreporting.v1beta1.ProjectName; +import com.google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +// [START flex_error_reporting] +@WebServlet(name = "Error reporting", value = "/error") +public class ErrorReportingExample extends HttpServlet { + + private Logger logger = Logger.getLogger(ErrorReportingExample.class.getName()); + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse resp) + throws IOException, ServletException { + + // errors logged to stderr / Cloud logging with exceptions are automatically reported. + logger.log(Level.SEVERE, "exception using log framework", new IllegalArgumentException()); + + // use the error-reporting client library to log custom error events + logCustomErrorEvent(); + + // runtime exceptions are also automatically picked up by error reporting. + throw new RuntimeException("this is a runtime exception"); + } + + private void logCustomErrorEvent() { + try (ReportErrorsServiceClient reportErrorsServiceClient = ReportErrorsServiceClient.create()) { + // custom exception logged using the API + Exception e = new Exception("custom event reported using the API"); + // Events reported using the API must contain a stack trace message + StringWriter stackTrace = new StringWriter(); + e.printStackTrace(new PrintWriter(stackTrace)); + ReportedErrorEvent errorEvent = + ReportedErrorEvent.getDefaultInstance() + .toBuilder() + .setMessage(stackTrace.toString()) + .build(); + // default project id + ProjectName projectName = ProjectName.create(ServiceOptions.getDefaultProjectId()); + reportErrorsServiceClient.reportErrorEvent(projectName, errorEvent); + } catch (Exception e) { + logger.log(Level.SEVERE, "Exception encountered logging custom event", e); + } + } +} +// [END flex_error_reporting] diff --git a/pom.xml b/pom.xml index 465b313e4d9..749ab2282c1 100644 --- a/pom.xml +++ b/pom.xml @@ -57,6 +57,7 @@ flexible/cron flexible/datastore flexible/disk + flexible/errorreporting flexible/extending-runtime flexible/helloworld flexible/mailgun