// Copyright 2016 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.

syntax = "proto3";

package google.devtools.clouderrorreporting.v1beta1;

import "google/api/annotations.proto";
import "google/devtools/clouderrorreporting/v1beta1/common.proto";
import "google/protobuf/timestamp.proto";

option csharp_namespace = "Google.Cloud.ErrorReporting.V1Beta1";
option go_package = "google.golang.org/genproto/googleapis/devtools/clouderrorreporting/v1beta1;clouderrorreporting";
option java_multiple_files = true;
option java_outer_classname = "ReportErrorsServiceProto";
option java_package = "com.google.devtools.clouderrorreporting.v1beta1";


// An API for reporting error events.
service ReportErrorsService {
  // Report an individual error event.
  //
  // This endpoint accepts <strong>either</strong> an OAuth token,
  // <strong>or</strong> an
  // <a href="https://support.google.com/cloud/answer/6158862">API key</a>
  // for authentication. To use an API key, append it to the URL as the value of
  // a `key` parameter. For example:
  // <pre>POST https://clouderrorreporting.googleapis.com/v1beta1/projects/example-project/events:report?key=123ABC456</pre>
  rpc ReportErrorEvent(ReportErrorEventRequest) returns (ReportErrorEventResponse) {
    option (google.api.http) = { post: "/v1beta1/{project_name=projects/*}/events:report" body: "event" };
  }
}

// A request for reporting an individual error event.
message ReportErrorEventRequest {
  // [Required] The resource name of the Google Cloud Platform project. Written
  // as `projects/` plus the
  // [Google Cloud Platform project ID](https://support.google.com/cloud/answer/6158840).
  // Example: `projects/my-project-123`.
  string project_name = 1;

  // [Required] The error event to be reported.
  ReportedErrorEvent event = 2;
}

// Response for reporting an individual error event.
// Data may be added to this message in the future.
message ReportErrorEventResponse {

}

// An error event which is reported to the Error Reporting system.
message ReportedErrorEvent {
  // [Optional] Time when the event occurred.
  // If not provided, the time when the event was received by the
  // Error Reporting system will be used.
  google.protobuf.Timestamp event_time = 1;

  // [Required] The service context in which this error has occurred.
  ServiceContext service_context = 2;

  // [Required] A message describing the error. The message can contain an
  // exception stack in one of the supported programming languages and formats.
  // In that case, the message is parsed and detailed exception information
  // is returned when retrieving the error event again.
  string message = 3;

  // [Optional] A description of the context in which the error occurred.
  ErrorContext context = 4;
}
