diff --git a/composer.json b/composer.json index 2c0ac8f0251..cae3c958cb4 100644 --- a/composer.json +++ b/composer.json @@ -54,7 +54,7 @@ "james-heinrich/getid3": "^1.9", "erusev/parsedown": "^1.6", "vierbergenlars/php-semver": "^3.0", - "google/proto-client-php": "^0.4", + "google/proto-client-php": "^0.5", "google/gax": "^0.3" }, "suggest": { diff --git a/src/ArrayTrait.php b/src/ArrayTrait.php new file mode 100644 index 00000000000..1b7800ebf36 --- /dev/null +++ b/src/ArrayTrait.php @@ -0,0 +1,74 @@ +pluck($key, $arr); + } + + return $values; + } + + /** + * Determine whether given array is associative. + * + * @param array $arr + * @return bool + */ + private function isAssoc(array $arr) + { + return array_keys($arr) !== range(0, count($arr) - 1); + } +} diff --git a/src/Datastore/DatastoreTrait.php b/src/Datastore/DatastoreTrait.php index 01bae5bd6c8..c78a727e504 100644 --- a/src/Datastore/DatastoreTrait.php +++ b/src/Datastore/DatastoreTrait.php @@ -17,9 +17,6 @@ namespace Google\Cloud\Datastore; -use InvalidArgumentException; -use Psr\Http\Message\StreamInterface; - /** * Utility methods for data formatting. */ @@ -39,15 +36,4 @@ private function partitionId($projectId, $namespaceId) 'namespaceId' => $namespaceId ]); } - - /** - * Determine whether given array is associative - * - * @param array $value - * @return bool - */ - private function isAssoc(array $value) - { - return array_keys($value) !== range(0, count($value) - 1); - } } diff --git a/src/Datastore/EntityMapper.php b/src/Datastore/EntityMapper.php index 4e2b8a7c774..6b7cabc9924 100644 --- a/src/Datastore/EntityMapper.php +++ b/src/Datastore/EntityMapper.php @@ -17,6 +17,7 @@ namespace Google\Cloud\Datastore; +use Google\Cloud\ArrayTrait; use Google\Cloud\Datastore\Entity; use Google\Cloud\Datastore\GeoPoint; use Google\Cloud\Datastore\Key; @@ -28,6 +29,7 @@ */ class EntityMapper { + use ArrayTrait; use DatastoreTrait; /** diff --git a/src/Datastore/Key.php b/src/Datastore/Key.php index 3fd42168c34..2e3f82dfc5c 100644 --- a/src/Datastore/Key.php +++ b/src/Datastore/Key.php @@ -17,6 +17,7 @@ namespace Google\Cloud\Datastore; +use Google\Cloud\ArrayTrait; use InvalidArgumentException; use JsonSerializable; @@ -75,6 +76,7 @@ */ class Key implements JsonSerializable { + use ArrayTrait; use DatastoreTrait; const TYPE_NAME = 'name'; diff --git a/src/Datastore/Query/GqlQuery.php b/src/Datastore/Query/GqlQuery.php index ece5119aa4b..7088ff80b3b 100644 --- a/src/Datastore/Query/GqlQuery.php +++ b/src/Datastore/Query/GqlQuery.php @@ -17,6 +17,7 @@ namespace Google\Cloud\Datastore\Query; +use Google\Cloud\ArrayTrait; use Google\Cloud\Datastore\DatastoreTrait; use Google\Cloud\Datastore\EntityMapper; use InvalidArgumentException; @@ -72,6 +73,7 @@ */ class GqlQuery implements QueryInterface { + use ArrayTrait; use DatastoreTrait; const BINDING_NAMED = 'namedBindings'; diff --git a/src/GrpcRequestWrapper.php b/src/GrpcRequestWrapper.php index b86451ec415..a76ea808d57 100644 --- a/src/GrpcRequestWrapper.php +++ b/src/GrpcRequestWrapper.php @@ -17,6 +17,7 @@ namespace Google\Cloud; +use DrSlump\Protobuf\Codec\CodecInterface; use DrSlump\Protobuf\Message; use Google\Auth\FetchAuthTokenInterface; use Google\Auth\HttpHandler\HttpHandlerFactory; @@ -41,6 +42,11 @@ class GrpcRequestWrapper */ private $authHttpHandler; + /** + * @var CodecInterface A codec used to encode responses. + */ + private $codec; + /** * @var array gRPC specific configuration options passed off to the GAX * library. @@ -65,6 +71,7 @@ class GrpcRequestWrapper * * @type callable $authHttpHandler A handler used to deliver Psr7 * requests specifically for authentication. + * @type CodecInterface $codec A codec used to encode responses. * @type array $grpcOptions gRPC specific configuration options passed * off to the GAX library. * } @@ -74,10 +81,12 @@ public function __construct(array $config = []) $this->setCommonDefaults($config); $config += [ 'authHttpHandler' => null, + 'codec' => new PhpArray(), 'grpcOptions' => [] ]; $this->authHttpHandler = $config['authHttpHandler'] ?: HttpHandlerFactory::build(); + $this->codec = $config['codec']; $this->grpcOptions = $config['grpcOptions']; } @@ -132,13 +141,11 @@ public function send(callable $request, array $args, array $options = []) private function handleResponse($response) { if ($response instanceof PagedListResponse) { - return $response->getPage() - ->getResponseObject() - ->serialize(new PhpArray()); + $response = $response->getPage()->getResponseObject(); } if ($response instanceof Message) { - return $response->serialize(new PhpArray()); + return $response->serialize($this->codec); } return null; diff --git a/src/GrpcTrait.php b/src/GrpcTrait.php index 19e47f5f9f5..b2f400d19a7 100644 --- a/src/GrpcTrait.php +++ b/src/GrpcTrait.php @@ -17,13 +17,21 @@ namespace Google\Cloud; +use DateTime; +use DateTimeZone; +use Google\Auth\FetchAuthTokenCache; +use Google\Auth\Cache\MemoryCacheItemPool; +use Google\Cloud\ArrayTrait; use Google\Cloud\GrpcRequestWrapper; +use Google\Cloud\ServiceBuilder; /** * Provides shared functionality for gRPC service implementations. */ trait GrpcTrait { + use ArrayTrait; + /** * @var GrpcRequestWrapper Wrapper used to handle sending requests to the * gRPC API. @@ -58,22 +66,120 @@ public function send(callable $request, array $args) } /** - * Pluck a value out of an array. + * Gets the default configuration for generated GAX clients. * - * @param string $key - * @param array $args + * @return array + */ + private function getGaxConfig() + { + return [ + 'credentialsLoader' => new FetchAuthTokenCache( + $this->requestWrapper->getCredentialsFetcher(), + null, + new MemoryCacheItemPool() + ), + 'enableCaching' => false, + 'appName' => 'gcloud-php', + 'version' => ServiceBuilder::VERSION + ]; + } + + /** + * Format a gRPC timestamp to match the format returned by the REST API. + * + * @param array $timestamp * @return string */ - public function pluck($key, array &$args) + private function formatTimestampFromApi(array $timestamp) + { + $formattedTime = (new DateTime()) + ->setTimeZone(new DateTimeZone('UTC')) + ->setTimestamp($timestamp['seconds']) + ->format('Y-m-d\TH:i:s'); + return $formattedTime .= sprintf('.%sZ', rtrim($timestamp['nanos'], '0')); + } + + /** + * Format a set of labels for the API. + * + * @param array $labels + * @return array + */ + private function formatLabelsForApi(array $labels) { - if (!isset($args[$key])) { - throw new \InvalidArgumentException( - "Key $key does not exist in the provided array." - ); + $fLabels = []; + + foreach ($labels as $key => $value) { + $fLabels[] = [ + 'key' => $key, + 'value' => $value + ]; } - $value = $args[$key]; - unset($args[$key]); - return $value; + return $fLabels; + } + + /** + * Format a struct for the API. + * + * @param array $fields + * @return array + */ + private function formatStructForApi(array $fields) + { + $fFields = []; + + foreach ($fields as $key => $value) { + $fFields[] = [ + 'key' => $key, + 'value' => $this->formatValueForApi($value) + ]; + } + + return ['fields' => $fFields]; + } + + /** + * Format a list for the API. + * + * @param array $list + * @return array + */ + private function formatListForApi(array $list) + { + $values = []; + + foreach ($list as $value) { + $values[] = $this->formatValueForApi($value); + } + + return ['values' => $values]; + } + + /** + * Format a value for the API. + * + * @param array $value + * @return array + */ + private function formatValueForApi($value) + { + $type = gettype($value); + + switch ($type) { + case 'string': + return ['string_value' => $value]; + case 'double': + case 'integer': + return ['number_value' => $value]; + case 'boolean': + return ['bool_value' => $value]; + case 'array': + if ($this->isAssoc($value)) { + return ['struct_value' => $this->formatStructForApi($value)]; + } + + return ['list_value' => $this->formatListForApi($value)]; + } } } diff --git a/src/Logging/Connection/Grpc.php b/src/Logging/Connection/Grpc.php new file mode 100644 index 00000000000..6dac6fed942 --- /dev/null +++ b/src/Logging/Connection/Grpc.php @@ -0,0 +1,326 @@ + 'VERSION_FORMAT_UNSPECIFIED', + VersionFormat::V1 => 'V1', + VersionFormat::V2 => 'V2' + ]; + + /** + * @var ConfigServiceV2API + */ + private $configApi; + + /** + * @var LoggingServiceV2Api + */ + private $loggingApi; + + /** + * @var MetricsServiceV2Api + */ + private $metricsApi; + + /** + * @var CodecInterface + */ + private $codec; + + /** + * @var array + */ + private $sinkKeys = [ + 'name', + 'destination', + 'filter', + 'outputVersionFormat' + ]; + + /** + * @var array + */ + private $metricKeys = [ + 'name', + 'description', + 'filter' + ]; + + /** + * @param array $config + */ + public function __construct(array $config = []) + { + $this->codec = new PhpArray([ + 'timestamp' => function ($v) { + return $this->formatTimestampFromApi($v); + }, + 'severity' => function ($v) { + return Logger::getLogLevelMap()[$v]; + }, + 'outputVersionFormat' => function ($v) { + return self::$versionFormatMap[$v]; + } + ]); + $config['codec'] = $this->codec; + $this->setRequestWrapper(new GrpcRequestWrapper($config)); + $gaxConfig = $this->getGaxConfig(); + + $this->configApi = new ConfigServiceV2Api($gaxConfig); + $this->loggingApi = new LoggingServiceV2Api($gaxConfig); + $this->metricsApi = new MetricsServiceV2Api($gaxConfig); + } + + /** + * @param array $args + * @return array + */ + public function writeEntries(array $args = []) + { + $pbEntries = []; + $entries = $this->pluck('entries', $args); + + foreach ($entries as $entry) { + $pbEntries[] = $this->buildEntry($entry); + } + + return $this->send([$this->loggingApi, 'writeLogEntries'], [ + $pbEntries, + $args + ]); + } + + /** + * @param array $args + * @return array + */ + public function listEntries(array $args = []) + { + return $this->send([$this->loggingApi, 'listLogEntries'], [ + $this->pluck('projectIds', $args), + $args + ]); + } + + /** + * @param array $args + * @return array + */ + public function createSink(array $args = []) + { + if (isset($args['outputVersionFormat'])) { + $args['outputVersionFormat'] = array_flip(self::$versionFormatMap)[$args['outputVersionFormat']]; + } + + $pbSink = (new LogSink())->deserialize( + $this->pluckArray($this->sinkKeys, $args), + $this->codec + ); + + return $this->send([$this->configApi, 'createSink'], [ + $this->pluck('parent', $args), + $pbSink, + $args + ]); + } + + /** + * @param array $args + * @return array + */ + public function getSink(array $args = []) + { + return $this->send([$this->configApi, 'getSink'], [ + $this->pluck('sinkName', $args), + $args + ]); + } + + /** + * @param array $args + * @return array + */ + public function listSinks(array $args = []) + { + return $this->send([$this->configApi, 'listSinks'], [ + $this->pluck('parent', $args), + $args + ]); + } + + /** + * @param array $args + * @return array + */ + public function updateSink(array $args = []) + { + if (isset($args['outputVersionFormat'])) { + $args['outputVersionFormat'] = array_flip(self::$versionFormatMap)[$args['outputVersionFormat']]; + } + + $pbSink = (new LogSink())->deserialize( + $this->pluckArray($this->sinkKeys, $args), + $this->codec + ); + + return $this->send([$this->configApi, 'updateSink'], [ + $this->pluck('sinkName', $args), + $pbSink, + $args + ]); + } + + /** + * @param array $args + * @return array + */ + public function deleteSink(array $args = []) + { + return $this->send([$this->configApi, 'deleteSink'], [ + $this->pluck('sinkName', $args), + $args + ]); + } + + /** + * @param array $args + * @return array + */ + public function createMetric(array $args = []) + { + $pbMetric = (new LogMetric())->deserialize( + $this->pluckArray($this->metricKeys, $args), + $this->codec + ); + + return $this->send([$this->metricsApi, 'createLogMetric'], [ + $this->pluck('parent', $args), + $pbMetric, + $args + ]); + } + + /** + * @param array $args + * @return array + */ + public function getMetric(array $args = []) + { + return $this->send([$this->metricsApi, 'getLogMetric'], [ + $this->pluck('metricName', $args), + $args + ]); + } + + /** + * @param array $args + * @return array + */ + public function listMetrics(array $args = []) + { + return $this->send([$this->metricsApi, 'getLogMetric'], [ + $this->pluck('parent', $args), + $args + ]); + } + + /** + * @param array $args + * @return array + */ + public function updateMetric(array $args = []) + { + $pbMetric = (new LogMetric())->deserialize( + $this->pluckArray($this->metricKeys, $args), + $this->codec + ); + + return $this->send([$this->metricsApi, 'updateLogMetric'], [ + $this->pluck('metricName', $args), + $pbMetric, + $args + ]); + } + + /** + * @param array $args + * @return array + */ + public function deleteMetric(array $args = []) + { + return $this->send([$this->metricsApi, 'deleteLogMetric'], [ + $this->pluck('metricName', $args), + $args + ]); + } + + /** + * @param array $args + * @return array + */ + public function deleteLog(array $args = []) + { + return $this->send([$this->loggingApi, 'deleteLog'], [ + $this->pluck('logName', $args), + $args + ]); + } + + /** + * @param array $entry + * @return array + */ + private function buildEntry(array $entry) + { + if (isset($entry['jsonPayload'])) { + $entry['jsonPayload'] = $this->formatStructForApi($entry['jsonPayload']); + } + + if (isset($entry['labels'])) { + $entry['labels'] = $this->formatLabelsForApi($entry['labels']); + } + + if (isset($entry['resource']['labels'])) { + $entry['resource']['labels'] = $this->formatLabelsForApi($entry['resource']['labels']); + } + + return (new LogEntry)->deserialize($entry, $this->codec); + } +} diff --git a/src/Logging/Connection/Rest.php b/src/Logging/Connection/Rest.php index 997a0bf74e5..686de946393 100644 --- a/src/Logging/Connection/Rest.php +++ b/src/Logging/Connection/Rest.php @@ -40,7 +40,7 @@ public function __construct(array $config = []) { $this->setRequestWrapper(new RequestWrapper($config)); $this->setRequestBuilder(new RequestBuilder( - __DIR__ . '/ServiceDefinition/logging-v2-beta1.json', + __DIR__ . '/ServiceDefinition/logging-v2.json', self::BASE_URI )); } diff --git a/src/Logging/Connection/ServiceDefinition/logging-v2-beta1.json b/src/Logging/Connection/ServiceDefinition/logging-v2-beta1.json deleted file mode 100644 index b3895e2c3f7..00000000000 --- a/src/Logging/Connection/ServiceDefinition/logging-v2-beta1.json +++ /dev/null @@ -1,1209 +0,0 @@ -{ - "kind": "discovery#restDescription", - "etag": "\"C5oy1hgQsABtYOYIOXWcR3BgYqU/AGY2FGWaHRZwgyAazem2sSX20dM\"", - "discoveryVersion": "v1", - "id": "logging:v2beta1", - "name": "logging", - "version": "v2beta1", - "revision": "20160322", - "title": "Stackdriver Logging API", - "description": "Writes log entries and manages your logs, log sinks, and logs-based metrics.", - "ownerDomain": "google.com", - "ownerName": "Google", - "icons": { - "x16": "http://www.google.com/images/icons/product/search-16.gif", - "x32": "http://www.google.com/images/icons/product/search-32.gif" - }, - "documentationLink": "https://cloud.google.com/logging/docs/", - "protocol": "rest", - "baseUrl": "https://logging.googleapis.com/", - "basePath": "", - "rootUrl": "https://logging.googleapis.com/", - "servicePath": "", - "batchPath": "batch", - "version_module": true, - "parameters": { - "access_token": { - "type": "string", - "description": "OAuth access token.", - "location": "query" - }, - "alt": { - "type": "string", - "description": "Data format for response.", - "default": "json", - "enumDescriptions": [ - "Responses with Content-Type of application/json", - "Media download with context-dependent Content-Type", - "Responses with Content-Type of application/x-protobuf" - ], - "location": "query" - }, - "bearer_token": { - "type": "string", - "description": "OAuth bearer token.", - "location": "query" - }, - "callback": { - "type": "string", - "description": "JSONP", - "location": "query" - }, - "fields": { - "type": "string", - "description": "Selector specifying which fields to include in a partial response.", - "location": "query" - }, - "key": { - "type": "string", - "description": "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.", - "location": "query" - }, - "oauth_token": { - "type": "string", - "description": "OAuth 2.0 token for the current user.", - "location": "query" - }, - "pp": { - "type": "boolean", - "description": "Pretty-print response.", - "default": "true", - "location": "query" - }, - "prettyPrint": { - "type": "boolean", - "description": "Returns response with indentations and line breaks.", - "default": "true", - "location": "query" - }, - "quotaUser": { - "type": "string", - "description": "Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters.", - "location": "query" - }, - "upload_protocol": { - "type": "string", - "description": "Upload protocol for media (e.g. \"raw\", \"multipart\").", - "location": "query" - }, - "uploadType": { - "type": "string", - "description": "Legacy upload protocol for media (e.g. \"media\", \"multipart\").", - "location": "query" - }, - "$.xgafv": { - "type": "string", - "description": "V1 error format.", - "enumDescriptions": [ - "v1 error format", - "v2 error format" - ], - "location": "query" - } - }, - "auth": { - "oauth2": { - "scopes": { - "https://www.googleapis.com/auth/cloud-platform": { - "description": "View and manage your data across Google Cloud Platform services" - }, - "https://www.googleapis.com/auth/cloud-platform.read-only": { - "description": "View your data across Google Cloud Platform services" - }, - "https://www.googleapis.com/auth/logging.admin": { - "description": "Administrate log data for your projects" - }, - "https://www.googleapis.com/auth/logging.read": { - "description": "View log data for your projects" - }, - "https://www.googleapis.com/auth/logging.write": { - "description": "Submit log data for your projects" - } - } - } - }, - "schemas": { - "Empty": { - "id": "Empty", - "type": "object", - "description": "A generic empty message that you can re-use to avoid defining duplicated empty messages in your APIs. A typical example is to use it as the request or the response type of an API method. For instance: service Foo { rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); } The JSON representation for `Empty` is empty JSON object `{}`." - }, - "WriteLogEntriesRequest": { - "id": "WriteLogEntriesRequest", - "type": "object", - "description": "The parameters to WriteLogEntries.", - "properties": { - "logName": { - "type": "string", - "description": "Optional. A default log resource name for those log entries in `entries` that do not specify their own `logName`. Example: `\"projects/my-project/logs/syslog\"`. See LogEntry." - }, - "resource": { - "$ref": "MonitoredResource", - "description": "Optional. A default monitored resource for those log entries in `entries` that do not specify their own `resource`." - }, - "labels": { - "type": "object", - "description": "Optional. User-defined `key:value` items that are added to the `labels` field of each log entry in `entries`, except when a log entry specifies its own `key:value` item with the same key. Example: `{ \"size\": \"large\", \"color\":\"red\" }`", - "additionalProperties": { - "type": "string" - } - }, - "entries": { - "type": "array", - "description": "Required. The log entries to write. The log entries must have values for all required fields.", - "items": { - "$ref": "LogEntry" - } - }, - "partialSuccess": { - "type": "boolean", - "description": "Optional. Whether valid entries should be written even if some other entries fail due to INVALID_ARGUMENT or PERMISSION_DENIED errors. If any entry is not written, the response status will be the error associated with one of the failed entries and include error details in the form of WriteLogEntriesPartialErrors." - } - } - }, - "MonitoredResource": { - "id": "MonitoredResource", - "type": "object", - "description": "An object representing a resource that can be used for monitoring, logging, billing, or other purposes. Examples include virtual machine instances, databases, and storage devices such as disks. The `type` field identifies a MonitoredResourceDescriptor object that describes the resource's schema. Information in the `labels` field identifies the actual resource and its attributes according to the schema. For example, a particular Compute Engine VM instance could be represented by the following object, because the MonitoredResourceDescriptor for `\"gce_instance\"` has labels `\"instance_id\"` and `\"zone\"`: { \"type\": \"gce_instance\", \"labels\": { \"instance_id\": \"my-instance\", \"zone\": \"us-central1-a\" }}", - "properties": { - "type": { - "type": "string", - "description": "Required. The monitored resource type. This field must match the `type` field of a MonitoredResourceDescriptor object. For example, the type of a Cloud SQL database is `\"cloudsql_database\"`." - }, - "labels": { - "type": "object", - "description": "Required. Values for all of the labels listed in the associated monitored resource descriptor. For example, Cloud SQL databases use the labels `\"database_id\"` and `\"zone\"`.", - "additionalProperties": { - "type": "string" - } - } - } - }, - "LogEntry": { - "id": "LogEntry", - "type": "object", - "description": "An individual entry in a log.", - "properties": { - "logName": { - "type": "string", - "description": "Required. The resource name of the log to which this log entry belongs. The format of the name is `\"projects/\n/logs/\"`. Examples: `\"projects/my-projectid/logs/syslog\"`, `\"projects/1234567890/logs/library.googleapis.com%2Fbook_log\"`. The log ID part of resource name must be less than 512 characters long and can only include the following characters: upper and lower case alphanumeric characters: [A-Za-z0-9]; and punctuation characters: forward-slash, underscore, hyphen, and period. Forward-slash (`/`) characters in the log ID must be URL-encoded." - }, - "resource": { - "$ref": "MonitoredResource", - "description": "Required. The monitored resource associated with this log entry. Example: a log entry that reports a database error would be associated with the monitored resource designating the particular database that reported the error." - }, - "protoPayload": { - "type": "object", - "description": "The log entry payload, represented as a protocol buffer. You can only use `protoPayload` values that belong to a set of approved types.", - "additionalProperties": { - "type": "any", - "description": "Properties of the object. Contains field @ype with type URL." - } - }, - "textPayload": { - "type": "string", - "description": "The log entry payload, represented as a Unicode string (UTF-8)." - }, - "jsonPayload": { - "type": "object", - "description": "The log entry payload, represented as a structure that is expressed as a JSON object.", - "additionalProperties": { - "type": "any", - "description": "Properties of the object." - } - }, - "timestamp": { - "type": "string", - "description": "Optional. The time the event described by the log entry occurred. If omitted, Cloud Logging will use the time the log entry is written." - }, - "severity": { - "type": "string", - "description": "Optional. The severity of the log entry. The default value is `LogSeverity.DEFAULT`.", - "enum": [ - "DEFAULT", - "DEBUG", - "INFO", - "NOTICE", - "WARNING", - "ERROR", - "CRITICAL", - "ALERT", - "EMERGENCY" - ] - }, - "insertId": { - "type": "string", - "description": "Optional. A unique ID for the log entry. If you provide this field, the logging service considers other log entries in the same log with the same ID as duplicates which can be removed. If omitted, Cloud Logging will generate a unique ID for this log entry." - }, - "httpRequest": { - "$ref": "HttpRequest", - "description": "Optional. Information about the HTTP request associated with this log entry, if applicable." - }, - "labels": { - "type": "object", - "description": "Optional. A set of user-defined (key, value) data that provides additional information about the log entry.", - "additionalProperties": { - "type": "string" - } - }, - "operation": { - "$ref": "LogEntryOperation", - "description": "Optional. Information about an operation associated with the log entry, if applicable." - } - } - }, - "HttpRequest": { - "id": "HttpRequest", - "type": "object", - "description": "A common proto for logging HTTP requests.", - "properties": { - "requestMethod": { - "type": "string", - "description": "The request method. Examples: `\"GET\"`, `\"HEAD\"`, `\"PUT\"`, `\"POST\"`." - }, - "requestUrl": { - "type": "string", - "description": "The scheme (http, https), the host name, the path and the query portion of the URL that was requested. Example: `\"http://example.com/some/info?color=red\"`." - }, - "requestSize": { - "type": "string", - "description": "The size of the HTTP request message in bytes, including the request headers and the request body.", - "format": "int64" - }, - "status": { - "type": "integer", - "description": "The response code indicating the status of response. Examples: 200, 404.", - "format": "int32" - }, - "responseSize": { - "type": "string", - "description": "The size of the HTTP response message sent back to the client, in bytes, including the response headers and the response body.", - "format": "int64" - }, - "userAgent": { - "type": "string", - "description": "The user agent sent by the client. Example: `\"Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Q312461; .NET CLR 1.0.3705)\"`." - }, - "remoteIp": { - "type": "string", - "description": "The IP address (IPv4 or IPv6) of the client that issued the HTTP request. Examples: `\"192.168.1.1\"`, `\"FE80::0202:B3FF:FE1E:8329\"`." - }, - "referer": { - "type": "string", - "description": "The referer URL of the request, as defined in [HTTP/1.1 Header Field Definitions](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html)." - }, - "cacheLookup": { - "type": "boolean", - "description": "Whether or not a cache lookup was attempted." - }, - "cacheHit": { - "type": "boolean", - "description": "Whether or not an entity was served from cache (with or without validation)." - }, - "cacheValidatedWithOriginServer": { - "type": "boolean", - "description": "Whether or not the response was validated with the origin server before being served from cache. This field is only meaningful if `cache_hit` is True." - }, - "cacheFillBytes": { - "type": "string", - "description": "The number of HTTP response bytes inserted into cache. Set only when a cache fill was attempted.", - "format": "int64" - } - } - }, - "LogEntryOperation": { - "id": "LogEntryOperation", - "type": "object", - "description": "Additional information about a potentially long-running operation with which a log entry is associated.", - "properties": { - "id": { - "type": "string", - "description": "Required. An arbitrary operation identifier. Log entries with the same identifier are assumed to be part of the same operation." - }, - "producer": { - "type": "string", - "description": "Required. An arbitrary producer identifier. The combination of `id` and `producer` must be globally unique. Examples for `producer`: `\"MyDivision.MyBigCompany.com\"`, \"github.com/MyProject/MyApplication\"`." - }, - "first": { - "type": "boolean", - "description": "Optional. Set this to True if this is the first log entry in the operation." - }, - "last": { - "type": "boolean", - "description": "Optional. Set this to True if this is the last log entry in the operation." - } - } - }, - "WriteLogEntriesResponse": { - "id": "WriteLogEntriesResponse", - "type": "object", - "description": "Result returned from WriteLogEntries. empty" - }, - "ListLogEntriesRequest": { - "id": "ListLogEntriesRequest", - "type": "object", - "description": "The parameters to `ListLogEntries`.", - "properties": { - "projectIds": { - "type": "array", - "description": "Required. One or more project IDs or project numbers from which to retrieve log entries. Examples of a project ID: `\"my-project-1A\"`, `\"1234567890\"`.", - "items": { - "type": "string" - } - }, - "filter": { - "type": "string", - "description": "Optional. An [advanced logs filter](/logging/docs/view/advanced_filters). The filter is compared against all log entries in the projects specified by `projectIds`. Only entries that match the filter are retrieved. An empty filter matches all log entries." - }, - "orderBy": { - "type": "string", - "description": "Optional. How the results should be sorted. Presently, the only permitted values are `\"timestamp asc\"` (default) and `\"timestamp desc\"`. The first option returns entries in order of increasing values of `LogEntry.timestamp` (oldest first), and the second option returns entries in order of decreasing timestamps (newest first). Entries with equal timestamps are returned in order of `LogEntry.insertId`." - }, - "pageSize": { - "type": "integer", - "description": "Optional. The maximum number of results to return from this request. You must check for presence of `nextPageToken` to determine if additional results are available, which you can retrieve by passing the `nextPageToken` value as the `pageToken` parameter in the next request.", - "format": "int32" - }, - "pageToken": { - "type": "string", - "description": "Optional. If the `pageToken` parameter is supplied, then the next page of results is retrieved. The `pageToken` parameter must be set to the value of the `nextPageToken` from the previous response. The values of `projectIds`, `filter`, and `orderBy` must be the same as in the previous request." - }, - "partialSuccess": { - "type": "boolean", - "description": "Optional. If true, read access to all projects is not required and results will be returned for the subset of projects for which read access is permitted (empty subset is permitted)." - } - } - }, - "ListLogEntriesResponse": { - "id": "ListLogEntriesResponse", - "type": "object", - "description": "Result returned from `ListLogEntries`.", - "properties": { - "entries": { - "type": "array", - "description": "A list of log entries.", - "items": { - "$ref": "LogEntry" - } - }, - "nextPageToken": { - "type": "string", - "description": "If there are more results than were returned, then `nextPageToken` is included in the response. To get the next set of results, call this method again using the value of `nextPageToken` as `pageToken`." - }, - "projectIdErrors": { - "type": "object", - "description": "If partial_success is true, contains the project ids that had errors and the associated errors.", - "additionalProperties": { - "$ref": "Status" - } - } - } - }, - "Status": { - "id": "Status", - "type": "object", - "description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). The error model is designed to be: - Simple to use and understand for most users - Flexible enough to meet unexpected needs # Overview The `Status` message contains three pieces of data: error code, error message, and error details. The error code should be an enum value of google.rpc.Code, but it may accept additional error codes if needed. The error message should be a developer-facing English message that helps developers *understand* and *resolve* the error. If a localized user-facing error message is needed, put the localized message in the error details or localize it in the client. The optional error details may contain arbitrary information about the error. There is a predefined set of error detail types in the package `google.rpc` which can be used for common error conditions. # Language mapping The `Status` message is the logical representation of the error model, but it is not necessarily the actual wire format. When the `Status` message is exposed in different client libraries and different wire protocols, it can be mapped differently. For example, it will likely be mapped to some exceptions in Java, but more likely mapped to some error codes in C. # Other uses The error model and the `Status` message can be used in a variety of environments, either with or without APIs, to provide a consistent developer experience across different environments. Example uses of this error model include: - Partial errors. If a service needs to return partial errors to the client, it may embed the `Status` in the normal response to indicate the partial errors. - Workflow errors. A typical workflow has multiple steps. Each step may have a `Status` message for error reporting purpose. - Batch operations. If a client uses batch request and batch response, the `Status` message should be used directly inside batch response, one for each error sub-response. - Asynchronous operations. If an API call embeds asynchronous operation results in its response, the status of those operations should be represented directly using the `Status` message. - Logging. If some API errors are stored in logs, the message `Status` could be used directly after any stripping needed for security/privacy reasons.", - "properties": { - "code": { - "type": "integer", - "description": "The status code, which should be an enum value of google.rpc.Code.", - "format": "int32" - }, - "message": { - "type": "string", - "description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the google.rpc.Status.details field, or localized by the client." - }, - "details": { - "type": "array", - "description": "A list of messages that carry the error details. There will be a common set of message types for APIs to use.", - "items": { - "type": "object", - "additionalProperties": { - "type": "any", - "description": "Properties of the object. Contains field @ype with type URL." - } - } - } - } - }, - "ListMonitoredResourceDescriptorsResponse": { - "id": "ListMonitoredResourceDescriptorsResponse", - "type": "object", - "description": "Result returned from ListMonitoredResourceDescriptors.", - "properties": { - "resourceDescriptors": { - "type": "array", - "description": "A list of resource descriptors.", - "items": { - "$ref": "MonitoredResourceDescriptor" - } - }, - "nextPageToken": { - "type": "string", - "description": "If there are more results than were returned, then `nextPageToken` is included in the response. To get the next set of results, call this method again using the value of `nextPageToken` as `pageToken`." - } - } - }, - "MonitoredResourceDescriptor": { - "id": "MonitoredResourceDescriptor", - "type": "object", - "description": "An object that describes the schema of a MonitoredResource object using a type name and a set of labels. For example, the monitored resource descriptor for Google Compute Engine VM instances has a type of `\"gce_instance\"` and specifies the use of the labels `\"instance_id\"` and `\"zone\"` to identify particular VM instances. Different APIs can support different monitored resource types. APIs generally provide a `list` method that returns the monitored resource descriptors used by the API.", - "properties": { - "name": { - "type": "string", - "description": "Optional. The resource name of the monitored resource descriptor: `\"projects/{project_id}/monitoredResourceDescriptors/{type}\"` where {type} is the value of the `type` field in this object and {project_id} is a project ID that provides API-specific context for accessing the type. APIs that do not use project information can use the resource name format `\"monitoredResourceDescriptors/{type}\"`." - }, - "type": { - "type": "string", - "description": "Required. The monitored resource type. For example, the type `\"cloudsql_database\"` represents databases in Google Cloud SQL." - }, - "displayName": { - "type": "string", - "description": "Optional. A concise name for the monitored resource type that might be displayed in user interfaces. For example, `\"Google Cloud SQL Database\"`." - }, - "description": { - "type": "string", - "description": "Optional. A detailed description of the monitored resource type that might be used in documentation." - }, - "labels": { - "type": "array", - "description": "Required. A set of labels used to describe instances of this monitored resource type. For example, an individual Google Cloud SQL database is identified by values for the labels `\"database_id\"` and `\"zone\"`.", - "items": { - "$ref": "LabelDescriptor" - } - } - } - }, - "LabelDescriptor": { - "id": "LabelDescriptor", - "type": "object", - "description": "A description of a label.", - "properties": { - "key": { - "type": "string", - "description": "The label key." - }, - "valueType": { - "type": "string", - "description": "The type of data that can be assigned to the label.", - "enum": [ - "STRING", - "BOOL", - "INT64" - ] - }, - "description": { - "type": "string", - "description": "A human-readable description for the label." - } - } - }, - "ListSinksResponse": { - "id": "ListSinksResponse", - "type": "object", - "description": "Result returned from `ListSinks`.", - "properties": { - "sinks": { - "type": "array", - "description": "A list of sinks.", - "items": { - "$ref": "LogSink" - } - }, - "nextPageToken": { - "type": "string", - "description": "If there are more results than were returned, then `nextPageToken` is included in the response. To get the next set of results, call this method again using the value of `nextPageToken` as `pageToken`." - } - } - }, - "LogSink": { - "id": "LogSink", - "type": "object", - "description": "Describes a sink used to export log entries outside Cloud Logging.", - "properties": { - "name": { - "type": "string", - "description": "Required. The client-assigned sink identifier. Example: `\"my-severe-errors-to-pubsub\"`. Sink identifiers are limited to 1000 characters and can include only the following characters: `A-Z`, `a-z`, `0-9`, and the special characters `_-.`." - }, - "destination": { - "type": "string", - "description": "The export destination. See [Exporting Logs With Sinks](/logging/docs/api/tasks/exporting-logs). Examples: `\"storage.googleapis.com/a-bucket\"`, `\"bigquery.googleapis.com/projects/a-project-id/datasets/a-dataset\"`." - }, - "filter": { - "type": "string", - "description": "An [advanced logs filter](/logging/docs/view/advanced_filters). Only log entries matching that filter are exported. The filter must be consistent with the log entry format specified by the `outputVersionFormat` parameter, regardless of the format of the log entry that was originally written to Cloud Logging. Example (V2 format): `\"logName=projects/my-projectid/logs/syslog AND severity\u003e=ERROR\"`." - }, - "outputVersionFormat": { - "type": "string", - "description": "The log entry version to use for this sink's exported log entries. This version does not have to correspond to the version of the log entry when it was written to Cloud Logging.", - "enum": [ - "VERSION_FORMAT_UNSPECIFIED", - "V2", - "V1" - ] - } - } - }, - "ListLogMetricsResponse": { - "id": "ListLogMetricsResponse", - "type": "object", - "description": "Result returned from ListLogMetrics.", - "properties": { - "metrics": { - "type": "array", - "description": "A list of logs-based metrics.", - "items": { - "$ref": "LogMetric" - } - }, - "nextPageToken": { - "type": "string", - "description": "If there are more results than were returned, then `nextPageToken` is included in the response. To get the next set of results, call this method again using the value of `nextPageToken` as `pageToken`." - } - } - }, - "LogMetric": { - "id": "LogMetric", - "type": "object", - "description": "Describes a logs-based metric. The value of the metric is the number of log entries that match a logs filter.", - "properties": { - "name": { - "type": "string", - "description": "Required. The client-assigned metric identifier. Example: `\"severe_errors\"`. Metric identifiers are limited to 1000 characters and can include only the following characters: `A-Z`, `a-z`, `0-9`, and the special characters `_-.,+!*',()%/\\`. The forward-slash character (`/`) denotes a hierarchy of name pieces, and it cannot be the first character of the name." - }, - "description": { - "type": "string", - "description": "A description of this metric, which is used in documentation." - }, - "filter": { - "type": "string", - "description": "An [advanced logs filter](/logging/docs/view/advanced_filters). Example: `\"logName:syslog AND severity\u003e=ERROR\"`." - } - } - }, - "RequestLog": { - "id": "RequestLog", - "type": "object", - "description": "Complete log information about a single HTTP request to an App Engine application.", - "properties": { - "appId": { - "type": "string", - "description": "Application that handled this request." - }, - "moduleId": { - "type": "string", - "description": "Module of the application that handled this request." - }, - "versionId": { - "type": "string", - "description": "Version of the application that handled this request." - }, - "requestId": { - "type": "string", - "description": "Globally unique identifier for a request, which is based on the request start time. Request IDs for requests which started later will compare greater as strings than those for requests which started earlier." - }, - "ip": { - "type": "string", - "description": "Origin IP address." - }, - "startTime": { - "type": "string", - "description": "Time when the request started." - }, - "endTime": { - "type": "string", - "description": "Time when the request finished." - }, - "latency": { - "type": "string", - "description": "Latency of the request." - }, - "megaCycles": { - "type": "string", - "description": "Number of CPU megacycles used to process request.", - "format": "int64" - }, - "method": { - "type": "string", - "description": "Request method. Example: `\"GET\"`, `\"HEAD\"`, `\"PUT\"`, `\"POST\"`, `\"DELETE\"`." - }, - "resource": { - "type": "string", - "description": "Contains the path and query portion of the URL that was requested. For example, if the URL was \"http://example.com/app?name=val\", the resource would be \"/app?name=val\". The fragment identifier, which is identified by the `#` character, is not included." - }, - "httpVersion": { - "type": "string", - "description": "HTTP version of request. Example: `\"HTTP/1.1\"`." - }, - "status": { - "type": "integer", - "description": "HTTP response status code. Example: 200, 404.", - "format": "int32" - }, - "responseSize": { - "type": "string", - "description": "Size in bytes sent back to client by request.", - "format": "int64" - }, - "referrer": { - "type": "string", - "description": "Referrer URL of request." - }, - "userAgent": { - "type": "string", - "description": "User agent that made the request." - }, - "nickname": { - "type": "string", - "description": "The logged-in user who made the request. Most likely, this is the part of the user's email before the `@` sign. The field value is the same for different requests from the same user, but different users can have similar names. This information is also available to the application via the App Engine Users API. This field will be populated starting with App Engine 1.9.21." - }, - "urlMapEntry": { - "type": "string", - "description": "File or class that handled the request." - }, - "host": { - "type": "string", - "description": "Internet host and port number of the resource being requested." - }, - "cost": { - "type": "number", - "description": "An indication of the relative cost of serving this request.", - "format": "double" - }, - "taskQueueName": { - "type": "string", - "description": "Queue name of the request, in the case of an offline request." - }, - "taskName": { - "type": "string", - "description": "Task name of the request, in the case of an offline request." - }, - "wasLoadingRequest": { - "type": "boolean", - "description": "Whether this was a loading request for the instance." - }, - "pendingTime": { - "type": "string", - "description": "Time this request spent in the pending request queue." - }, - "instanceIndex": { - "type": "integer", - "description": "If the instance processing this request belongs to a manually scaled module, then this is the 0-based index of the instance. Otherwise, this value is -1.", - "format": "int32" - }, - "finished": { - "type": "boolean", - "description": "Whether this request is finished or active." - }, - "first": { - "type": "boolean", - "description": "Whether this is the first RequestLog entry for this request. If an active request has several RequestLog entries written to Cloud Logging, this field will be set for one of them." - }, - "instanceId": { - "type": "string", - "description": "An identifier for the instance that handled the request." - }, - "line": { - "type": "array", - "description": "A list of log lines emitted by the application while serving this request.", - "items": { - "$ref": "LogLine" - } - }, - "appEngineRelease": { - "type": "string", - "description": "App Engine release version." - }, - "traceId": { - "type": "string", - "description": "Cloud Trace identifier for this request." - }, - "sourceReference": { - "type": "array", - "description": "Source code for the application that handled this request. There can be more than one source reference per deployed application if source code is distributed among multiple repositories.", - "items": { - "$ref": "SourceReference" - } - } - } - }, - "LogLine": { - "id": "LogLine", - "type": "object", - "description": "Application log line emitted while processing a request.", - "properties": { - "time": { - "type": "string", - "description": "Approximate time when this log entry was made." - }, - "severity": { - "type": "string", - "description": "Severity of this log entry.", - "enum": [ - "DEFAULT", - "DEBUG", - "INFO", - "NOTICE", - "WARNING", - "ERROR", - "CRITICAL", - "ALERT", - "EMERGENCY" - ] - }, - "logMessage": { - "type": "string", - "description": "App-provided log message." - }, - "sourceLocation": { - "$ref": "SourceLocation", - "description": "Where in the source code this log message was written." - } - } - }, - "SourceLocation": { - "id": "SourceLocation", - "type": "object", - "description": "Specifies a location in a source code file.", - "properties": { - "file": { - "type": "string", - "description": "Source file name. Depending on the runtime environment, this might be a simple name or a fully-qualified name." - }, - "line": { - "type": "string", - "description": "Line within the source file.", - "format": "int64" - }, - "functionName": { - "type": "string", - "description": "Human-readable name of the function or method being invoked, with optional context such as the class or package name. This information is used in contexts such as the logs viewer, where a file and line number are less meaningful. The format can vary by language. For example: `qual.if.ied.Class.method` (Java), `dir/package.func` (Go), `function` (Python)." - } - } - }, - "SourceReference": { - "id": "SourceReference", - "type": "object", - "description": "A reference to a particular snapshot of the source tree used to build and deploy an application.", - "properties": { - "repository": { - "type": "string", - "description": "Optional. A URI string identifying the repository. Example: \"https://github.com/GoogleCloudPlatform/kubernetes.git\"" - }, - "revisionId": { - "type": "string", - "description": "The canonical and persistent identifier of the deployed revision. Example (git): \"0035781c50ec7aa23385dc841529ce8a4b70db1b\"" - } - } - } - }, - "resources": { - "projects": { - "resources": { - "logs": { - "methods": { - "delete": { - "id": "logging.projects.logs.delete", - "path": "v2beta1/{+logName}", - "httpMethod": "DELETE", - "description": "Deletes a log and all its log entries. The log will reappear if it receives new entries.", - "parameters": { - "logName": { - "type": "string", - "description": "Required. The resource name of the log to delete. Example: `\"projects/my-project/logs/syslog\"`.", - "required": true, - "pattern": "^projects/[^/]*/logs/[^/]*$", - "location": "path" - } - }, - "parameterOrder": [ - "logName" - ], - "response": { - "$ref": "Empty" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/logging.admin" - ] - } - } - }, - "sinks": { - "methods": { - "list": { - "id": "logging.projects.sinks.list", - "path": "v2beta1/{+projectName}/sinks", - "httpMethod": "GET", - "description": "Lists sinks.", - "parameters": { - "projectName": { - "type": "string", - "description": "Required. The resource name of the project containing the sinks. Example: `\"projects/my-logging-project\"`.", - "required": true, - "pattern": "^projects/[^/]*$", - "location": "path" - }, - "pageToken": { - "type": "string", - "description": "Optional. If the `pageToken` parameter is supplied, then the next page of results is retrieved. The `pageToken` parameter must be set to the value of the `nextPageToken` from the previous response. The value of `projectName` must be the same as in the previous request.", - "location": "query" - }, - "pageSize": { - "type": "integer", - "description": "Optional. The maximum number of results to return from this request. You must check for presence of `nextPageToken` to determine if additional results are available, which you can retrieve by passing the `nextPageToken` value as the `pageToken` parameter in the next request.", - "format": "int32", - "location": "query" - } - }, - "parameterOrder": [ - "projectName" - ], - "response": { - "$ref": "ListSinksResponse" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/cloud-platform.read-only", - "https://www.googleapis.com/auth/logging.admin", - "https://www.googleapis.com/auth/logging.read" - ] - }, - "get": { - "id": "logging.projects.sinks.get", - "path": "v2beta1/{+sinkName}", - "httpMethod": "GET", - "description": "Gets a sink.", - "parameters": { - "sinkName": { - "type": "string", - "description": "The resource name of the sink to return. Example: `\"projects/my-project-id/sinks/my-sink-id\"`.", - "required": true, - "pattern": "^projects/[^/]*/sinks/[^/]*$", - "location": "path" - } - }, - "parameterOrder": [ - "sinkName" - ], - "response": { - "$ref": "LogSink" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/cloud-platform.read-only", - "https://www.googleapis.com/auth/logging.admin", - "https://www.googleapis.com/auth/logging.read" - ] - }, - "create": { - "id": "logging.projects.sinks.create", - "path": "v2beta1/{+projectName}/sinks", - "httpMethod": "POST", - "description": "Creates a sink.", - "parameters": { - "projectName": { - "type": "string", - "description": "The resource name of the project in which to create the sink. Example: `\"projects/my-project-id\"`. The new sink must be provided in the request.", - "required": true, - "pattern": "^projects/[^/]*$", - "location": "path" - } - }, - "parameterOrder": [ - "projectName" - ], - "request": { - "$ref": "LogSink" - }, - "response": { - "$ref": "LogSink" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/logging.admin" - ] - }, - "update": { - "id": "logging.projects.sinks.update", - "path": "v2beta1/{+sinkName}", - "httpMethod": "PUT", - "description": "Creates or updates a sink.", - "parameters": { - "sinkName": { - "type": "string", - "description": "The resource name of the sink to update. Example: `\"projects/my-project-id/sinks/my-sink-id\"`. The updated sink must be provided in the request and have the same name that is specified in `sinkName`. If the sink does not exist, it is created.", - "required": true, - "pattern": "^projects/[^/]*/sinks/[^/]*$", - "location": "path" - } - }, - "parameterOrder": [ - "sinkName" - ], - "request": { - "$ref": "LogSink" - }, - "response": { - "$ref": "LogSink" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/logging.admin" - ] - }, - "delete": { - "id": "logging.projects.sinks.delete", - "path": "v2beta1/{+sinkName}", - "httpMethod": "DELETE", - "description": "Deletes a sink.", - "parameters": { - "sinkName": { - "type": "string", - "description": "The resource name of the sink to delete. Example: `\"projects/my-project-id/sinks/my-sink-id\"`.", - "required": true, - "pattern": "^projects/[^/]*/sinks/[^/]*$", - "location": "path" - } - }, - "parameterOrder": [ - "sinkName" - ], - "response": { - "$ref": "Empty" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/logging.admin" - ] - } - } - }, - "metrics": { - "methods": { - "list": { - "id": "logging.projects.metrics.list", - "path": "v2beta1/{+projectName}/metrics", - "httpMethod": "GET", - "description": "Lists logs-based metrics.", - "parameters": { - "projectName": { - "type": "string", - "description": "Required. The resource name of the project containing the metrics. Example: `\"projects/my-project-id\"`.", - "required": true, - "pattern": "^projects/[^/]*$", - "location": "path" - }, - "pageToken": { - "type": "string", - "description": "Optional. If the `pageToken` parameter is supplied, then the next page of results is retrieved. The `pageToken` parameter must be set to the value of the `nextPageToken` from the previous response. The value of `projectName` must be the same as in the previous request.", - "location": "query" - }, - "pageSize": { - "type": "integer", - "description": "Optional. The maximum number of results to return from this request. You must check for presence of `nextPageToken` to determine if additional results are available, which you can retrieve by passing the `nextPageToken` value as the `pageToken` parameter in the next request.", - "format": "int32", - "location": "query" - } - }, - "parameterOrder": [ - "projectName" - ], - "response": { - "$ref": "ListLogMetricsResponse" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/cloud-platform.read-only", - "https://www.googleapis.com/auth/logging.admin", - "https://www.googleapis.com/auth/logging.read" - ] - }, - "get": { - "id": "logging.projects.metrics.get", - "path": "v2beta1/{+metricName}", - "httpMethod": "GET", - "description": "Gets a logs-based metric.", - "parameters": { - "metricName": { - "type": "string", - "description": "The resource name of the desired metric. Example: `\"projects/my-project-id/metrics/my-metric-id\"`.", - "required": true, - "pattern": "^projects/[^/]*/metrics/[^/]*$", - "location": "path" - } - }, - "parameterOrder": [ - "metricName" - ], - "response": { - "$ref": "LogMetric" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/cloud-platform.read-only", - "https://www.googleapis.com/auth/logging.admin", - "https://www.googleapis.com/auth/logging.read" - ] - }, - "create": { - "id": "logging.projects.metrics.create", - "path": "v2beta1/{+projectName}/metrics", - "httpMethod": "POST", - "description": "Creates a logs-based metric.", - "parameters": { - "projectName": { - "type": "string", - "description": "The resource name of the project in which to create the metric. Example: `\"projects/my-project-id\"`. The new metric must be provided in the request.", - "required": true, - "pattern": "^projects/[^/]*$", - "location": "path" - } - }, - "parameterOrder": [ - "projectName" - ], - "request": { - "$ref": "LogMetric" - }, - "response": { - "$ref": "LogMetric" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/logging.admin", - "https://www.googleapis.com/auth/logging.write" - ] - }, - "update": { - "id": "logging.projects.metrics.update", - "path": "v2beta1/{+metricName}", - "httpMethod": "PUT", - "description": "Creates or updates a logs-based metric.", - "parameters": { - "metricName": { - "type": "string", - "description": "The resource name of the metric to update. Example: `\"projects/my-project-id/metrics/my-metric-id\"`. The updated metric must be provided in the request and have the same identifier that is specified in `metricName`. If the metric does not exist, it is created.", - "required": true, - "pattern": "^projects/[^/]*/metrics/[^/]*$", - "location": "path" - } - }, - "parameterOrder": [ - "metricName" - ], - "request": { - "$ref": "LogMetric" - }, - "response": { - "$ref": "LogMetric" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/logging.admin", - "https://www.googleapis.com/auth/logging.write" - ] - }, - "delete": { - "id": "logging.projects.metrics.delete", - "path": "v2beta1/{+metricName}", - "httpMethod": "DELETE", - "description": "Deletes a logs-based metric.", - "parameters": { - "metricName": { - "type": "string", - "description": "The resource name of the metric to delete. Example: `\"projects/my-project-id/metrics/my-metric-id\"`.", - "required": true, - "pattern": "^projects/[^/]*/metrics/[^/]*$", - "location": "path" - } - }, - "parameterOrder": [ - "metricName" - ], - "response": { - "$ref": "Empty" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/logging.admin", - "https://www.googleapis.com/auth/logging.write" - ] - } - } - } - } - }, - "entries": { - "methods": { - "write": { - "id": "logging.entries.write", - "path": "v2beta1/entries:write", - "httpMethod": "POST", - "description": "Writes log entries to Cloud Logging. All log entries in Cloud Logging are written by this method.", - "request": { - "$ref": "WriteLogEntriesRequest" - }, - "response": { - "$ref": "WriteLogEntriesResponse" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/logging.admin", - "https://www.googleapis.com/auth/logging.write" - ] - }, - "list": { - "id": "logging.entries.list", - "path": "v2beta1/entries:list", - "httpMethod": "POST", - "description": "Lists log entries. Use this method to retrieve log entries from Cloud Logging. For ways to export log entries, see [Exporting Logs](/logging/docs/export).", - "request": { - "$ref": "ListLogEntriesRequest" - }, - "response": { - "$ref": "ListLogEntriesResponse" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/cloud-platform.read-only", - "https://www.googleapis.com/auth/logging.admin", - "https://www.googleapis.com/auth/logging.read" - ] - } - } - }, - "monitoredResourceDescriptors": { - "methods": { - "list": { - "id": "logging.monitoredResourceDescriptors.list", - "path": "v2beta1/monitoredResourceDescriptors", - "httpMethod": "GET", - "description": "Lists monitored resource descriptors that are used by Cloud Logging.", - "parameters": { - "pageSize": { - "type": "integer", - "description": "Optional. The maximum number of results to return from this request. You must check for presence of `nextPageToken` to determine if additional results are available, which you can retrieve by passing the `nextPageToken` value as the `pageToken` parameter in the next request.", - "format": "int32", - "location": "query" - }, - "pageToken": { - "type": "string", - "description": "Optional. If the `pageToken` parameter is supplied, then the next page of results is retrieved. The `pageToken` parameter must be set to the value of the `nextPageToken` from the previous response.", - "location": "query" - } - }, - "response": { - "$ref": "ListMonitoredResourceDescriptorsResponse" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/cloud-platform.read-only", - "https://www.googleapis.com/auth/logging.admin", - "https://www.googleapis.com/auth/logging.read" - ] - } - } - } - } -} diff --git a/src/Logging/Connection/ServiceDefinition/logging-v2.json b/src/Logging/Connection/ServiceDefinition/logging-v2.json new file mode 100644 index 00000000000..c673e291670 --- /dev/null +++ b/src/Logging/Connection/ServiceDefinition/logging-v2.json @@ -0,0 +1,1504 @@ +{ + "id": "logging:v2", + "auth": { + "oauth2": { + "scopes": { + "https://www.googleapis.com/auth/cloud-platform": { + "description": "View and manage your data across Google Cloud Platform services" + }, + "https://www.googleapis.com/auth/cloud-platform.read-only": { + "description": "View your data across Google Cloud Platform services" + }, + "https://www.googleapis.com/auth/logging.read": { + "description": "View log data for your projects" + }, + "https://www.googleapis.com/auth/logging.write": { + "description": "Submit log data for your projects" + }, + "https://www.googleapis.com/auth/logging.admin": { + "description": "Administrate log data for your projects" + } + } + } + }, + "description": "Writes log entries and manages your Stackdriver Logging configuration.", + "protocol": "rest", + "title": "Stackdriver Logging API", + "resources": { + "projects": { + "resources": { + "metrics": { + "methods": { + "update": { + "id": "logging.projects.metrics.update", + "response": { + "$ref": "LogMetric" + }, + "parameterOrder": [ + "metricName" + ], + "description": "Creates or updates a logs-based metric.", + "request": { + "$ref": "LogMetric" + }, + "flatPath": "v2/projects/{projectsId}/metrics/{metricsId}", + "httpMethod": "PUT", + "parameters": { + "metricName": { + "description": "The resource name of the metric to update.\nExample: `\"projects/my-project-id/metrics/my-metric-id\"`.\n\nThe updated metric must be provided in the request and have the\nsame identifier that is specified in `metricName`.\nIf the metric does not exist, it is created.", + "required": true, + "pattern": "^projects/[^/]+/metrics/[^/]+$", + "location": "path", + "type": "string" + } + }, + "path": "v2/{+metricName}", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/logging.admin", + "https://www.googleapis.com/auth/logging.write" + ] + }, + "get": { + "id": "logging.projects.metrics.get", + "response": { + "$ref": "LogMetric" + }, + "parameterOrder": [ + "metricName" + ], + "description": "Gets a logs-based metric.", + "flatPath": "v2/projects/{projectsId}/metrics/{metricsId}", + "httpMethod": "GET", + "parameters": { + "metricName": { + "description": "The resource name of the desired metric.\nExample: `\"projects/my-project-id/metrics/my-metric-id\"`.", + "required": true, + "pattern": "^projects/[^/]+/metrics/[^/]+$", + "location": "path", + "type": "string" + } + }, + "path": "v2/{+metricName}", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/cloud-platform.read-only", + "https://www.googleapis.com/auth/logging.admin", + "https://www.googleapis.com/auth/logging.read" + ] + }, + "create": { + "id": "logging.projects.metrics.create", + "response": { + "$ref": "LogMetric" + }, + "parameterOrder": [ + "parent" + ], + "description": "Creates a logs-based metric.", + "request": { + "$ref": "LogMetric" + }, + "flatPath": "v2/projects/{projectsId}/metrics", + "httpMethod": "POST", + "parameters": { + "parent": { + "description": "The resource name of the project in which to create the metric.\nExample: `\"projects/my-project-id\"`.\n\nThe new metric must be provided in the request.", + "required": true, + "pattern": "^projects/[^/]+$", + "location": "path", + "type": "string" + } + }, + "path": "v2/{+parent}/metrics", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/logging.admin", + "https://www.googleapis.com/auth/logging.write" + ] + }, + "list": { + "id": "logging.projects.metrics.list", + "response": { + "$ref": "ListLogMetricsResponse" + }, + "parameterOrder": [ + "parent" + ], + "description": "Lists logs-based metrics.", + "flatPath": "v2/projects/{projectsId}/metrics", + "httpMethod": "GET", + "parameters": { + "pageSize": { + "description": "Optional. The maximum number of results to return from this request.\nNon-positive values are ignored. The presence of `nextPageToken` in the\nresponse indicates that more results might be available.", + "location": "query", + "type": "integer", + "format": "int32" + }, + "parent": { + "description": "Required. The resource name containing the metrics.\nExample: `\"projects/my-project-id\"`.", + "required": true, + "pattern": "^projects/[^/]+$", + "location": "path", + "type": "string" + }, + "pageToken": { + "description": "Optional. If present, then retrieve the next batch of results from the\npreceding call to this method. `pageToken` must be the value of\n`nextPageToken` from the previous response. The values of other method\nparameters should be identical to those in the previous call.", + "location": "query", + "type": "string" + } + }, + "path": "v2/{+parent}/metrics", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/cloud-platform.read-only", + "https://www.googleapis.com/auth/logging.admin", + "https://www.googleapis.com/auth/logging.read" + ] + }, + "delete": { + "id": "logging.projects.metrics.delete", + "response": { + "$ref": "Empty" + }, + "parameterOrder": [ + "metricName" + ], + "description": "Deletes a logs-based metric.", + "flatPath": "v2/projects/{projectsId}/metrics/{metricsId}", + "httpMethod": "DELETE", + "parameters": { + "metricName": { + "description": "The resource name of the metric to delete.\nExample: `\"projects/my-project-id/metrics/my-metric-id\"`.", + "required": true, + "pattern": "^projects/[^/]+/metrics/[^/]+$", + "location": "path", + "type": "string" + } + }, + "path": "v2/{+metricName}", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/logging.admin", + "https://www.googleapis.com/auth/logging.write" + ] + } + } + }, + "logs": { + "methods": { + "delete": { + "id": "logging.projects.logs.delete", + "response": { + "$ref": "Empty" + }, + "parameterOrder": [ + "logName" + ], + "description": "Deletes a log and all its log entries.\nThe log will reappear if it receives new entries.", + "flatPath": "v2/projects/{projectsId}/logs/{logsId}", + "httpMethod": "DELETE", + "parameters": { + "logName": { + "description": "Required. The resource name of the log to delete. Example:\n`\"projects/my-project/logs/syslog\"`.", + "required": true, + "pattern": "^projects/[^/]+/logs/[^/]+$", + "location": "path", + "type": "string" + } + }, + "path": "v2/{+logName}", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/logging.admin" + ] + } + } + }, + "sinks": { + "methods": { + "update": { + "id": "logging.projects.sinks.update", + "response": { + "$ref": "LogSink" + }, + "parameterOrder": [ + "sinkName" + ], + "description": "Updates or creates a sink.", + "request": { + "$ref": "LogSink" + }, + "flatPath": "v2/projects/{projectsId}/sinks/{sinksId}", + "httpMethod": "PUT", + "parameters": { + "sinkName": { + "description": "Required. The resource name of the sink to update, including the parent\nresource and the sink identifier. If the sink does not exist, this method\ncreates the sink. Example: `\"projects/my-project-id/sinks/my-sink-id\"`.", + "required": true, + "pattern": "^projects/[^/]+/sinks/[^/]+$", + "location": "path", + "type": "string" + } + }, + "path": "v2/{+sinkName}", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/logging.admin" + ] + }, + "get": { + "id": "logging.projects.sinks.get", + "response": { + "$ref": "LogSink" + }, + "parameterOrder": [ + "sinkName" + ], + "description": "Gets a sink.", + "flatPath": "v2/projects/{projectsId}/sinks/{sinksId}", + "httpMethod": "GET", + "parameters": { + "sinkName": { + "description": "Required. The resource name of the sink to return.\nExample: `\"projects/my-project-id/sinks/my-sink-id\"`.", + "required": true, + "pattern": "^projects/[^/]+/sinks/[^/]+$", + "location": "path", + "type": "string" + } + }, + "path": "v2/{+sinkName}", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/cloud-platform.read-only", + "https://www.googleapis.com/auth/logging.admin", + "https://www.googleapis.com/auth/logging.read" + ] + }, + "create": { + "id": "logging.projects.sinks.create", + "response": { + "$ref": "LogSink" + }, + "parameterOrder": [ + "parent" + ], + "description": "Creates a sink.", + "request": { + "$ref": "LogSink" + }, + "flatPath": "v2/projects/{projectsId}/sinks", + "httpMethod": "POST", + "parameters": { + "parent": { + "description": "Required. The resource in which to create the sink.\nExample: `\"projects/my-project-id\"`.\nThe new sink must be provided in the request.", + "required": true, + "pattern": "^projects/[^/]+$", + "location": "path", + "type": "string" + } + }, + "path": "v2/{+parent}/sinks", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/logging.admin" + ] + }, + "list": { + "id": "logging.projects.sinks.list", + "response": { + "$ref": "ListSinksResponse" + }, + "parameterOrder": [ + "parent" + ], + "description": "Lists sinks.", + "flatPath": "v2/projects/{projectsId}/sinks", + "httpMethod": "GET", + "parameters": { + "pageSize": { + "description": "Optional. The maximum number of results to return from this request.\nNon-positive values are ignored. The presence of `nextPageToken` in the\nresponse indicates that more results might be available.", + "location": "query", + "type": "integer", + "format": "int32" + }, + "parent": { + "description": "Required. The cloud resource containing the sinks.\nExample: `\"projects/my-logging-project\"`.", + "required": true, + "pattern": "^projects/[^/]+$", + "location": "path", + "type": "string" + }, + "pageToken": { + "description": "Optional. If present, then retrieve the next batch of results from the\npreceding call to this method. `pageToken` must be the value of\n`nextPageToken` from the previous response. The values of other method\nparameters should be identical to those in the previous call.", + "location": "query", + "type": "string" + } + }, + "path": "v2/{+parent}/sinks", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/cloud-platform.read-only", + "https://www.googleapis.com/auth/logging.admin", + "https://www.googleapis.com/auth/logging.read" + ] + }, + "delete": { + "id": "logging.projects.sinks.delete", + "response": { + "$ref": "Empty" + }, + "parameterOrder": [ + "sinkName" + ], + "description": "Deletes a sink.", + "flatPath": "v2/projects/{projectsId}/sinks/{sinksId}", + "httpMethod": "DELETE", + "parameters": { + "sinkName": { + "description": "Required. The resource name of the sink to delete, including the parent\nresource and the sink identifier. Example:\n`\"projects/my-project-id/sinks/my-sink-id\"`. It is an error if the sink\ndoes not exist.", + "required": true, + "pattern": "^projects/[^/]+/sinks/[^/]+$", + "location": "path", + "type": "string" + } + }, + "path": "v2/{+sinkName}", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/logging.admin" + ] + } + } + } + } + }, + "organizations": { + "resources": { + "logs": { + "methods": { + "delete": { + "id": "logging.organizations.logs.delete", + "response": { + "$ref": "Empty" + }, + "parameterOrder": [ + "logName" + ], + "description": "Deletes a log and all its log entries.\nThe log will reappear if it receives new entries.", + "flatPath": "v2/organizations/{organizationsId}/logs/{logsId}", + "httpMethod": "DELETE", + "parameters": { + "logName": { + "description": "Required. The resource name of the log to delete. Example:\n`\"projects/my-project/logs/syslog\"`.", + "required": true, + "pattern": "^organizations/[^/]+/logs/[^/]+$", + "location": "path", + "type": "string" + } + }, + "path": "v2/{+logName}", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/logging.admin" + ] + } + } + }, + "sinks": { + "methods": { + "update": { + "id": "logging.organizations.sinks.update", + "response": { + "$ref": "LogSink" + }, + "parameterOrder": [ + "sinkName" + ], + "description": "Updates or creates a sink.", + "request": { + "$ref": "LogSink" + }, + "flatPath": "v2/organizations/{organizationsId}/sinks/{sinksId}", + "httpMethod": "PUT", + "parameters": { + "sinkName": { + "description": "Required. The resource name of the sink to update, including the parent\nresource and the sink identifier. If the sink does not exist, this method\ncreates the sink. Example: `\"projects/my-project-id/sinks/my-sink-id\"`.", + "required": true, + "pattern": "^organizations/[^/]+/sinks/[^/]+$", + "location": "path", + "type": "string" + } + }, + "path": "v2/{+sinkName}", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/logging.admin" + ] + }, + "get": { + "id": "logging.organizations.sinks.get", + "response": { + "$ref": "LogSink" + }, + "parameterOrder": [ + "sinkName" + ], + "description": "Gets a sink.", + "flatPath": "v2/organizations/{organizationsId}/sinks/{sinksId}", + "httpMethod": "GET", + "parameters": { + "sinkName": { + "description": "Required. The resource name of the sink to return.\nExample: `\"projects/my-project-id/sinks/my-sink-id\"`.", + "required": true, + "pattern": "^organizations/[^/]+/sinks/[^/]+$", + "location": "path", + "type": "string" + } + }, + "path": "v2/{+sinkName}", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/cloud-platform.read-only", + "https://www.googleapis.com/auth/logging.admin", + "https://www.googleapis.com/auth/logging.read" + ] + }, + "create": { + "id": "logging.organizations.sinks.create", + "response": { + "$ref": "LogSink" + }, + "parameterOrder": [ + "parent" + ], + "description": "Creates a sink.", + "request": { + "$ref": "LogSink" + }, + "flatPath": "v2/organizations/{organizationsId}/sinks", + "httpMethod": "POST", + "parameters": { + "parent": { + "description": "Required. The resource in which to create the sink.\nExample: `\"projects/my-project-id\"`.\nThe new sink must be provided in the request.", + "required": true, + "pattern": "^organizations/[^/]+$", + "location": "path", + "type": "string" + } + }, + "path": "v2/{+parent}/sinks", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/logging.admin" + ] + }, + "list": { + "id": "logging.organizations.sinks.list", + "response": { + "$ref": "ListSinksResponse" + }, + "parameterOrder": [ + "parent" + ], + "description": "Lists sinks.", + "flatPath": "v2/organizations/{organizationsId}/sinks", + "httpMethod": "GET", + "parameters": { + "pageSize": { + "description": "Optional. The maximum number of results to return from this request.\nNon-positive values are ignored. The presence of `nextPageToken` in the\nresponse indicates that more results might be available.", + "location": "query", + "type": "integer", + "format": "int32" + }, + "parent": { + "description": "Required. The cloud resource containing the sinks.\nExample: `\"projects/my-logging-project\"`.", + "required": true, + "pattern": "^organizations/[^/]+$", + "location": "path", + "type": "string" + }, + "pageToken": { + "description": "Optional. If present, then retrieve the next batch of results from the\npreceding call to this method. `pageToken` must be the value of\n`nextPageToken` from the previous response. The values of other method\nparameters should be identical to those in the previous call.", + "location": "query", + "type": "string" + } + }, + "path": "v2/{+parent}/sinks", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/cloud-platform.read-only", + "https://www.googleapis.com/auth/logging.admin", + "https://www.googleapis.com/auth/logging.read" + ] + }, + "delete": { + "id": "logging.organizations.sinks.delete", + "response": { + "$ref": "Empty" + }, + "parameterOrder": [ + "sinkName" + ], + "description": "Deletes a sink.", + "flatPath": "v2/organizations/{organizationsId}/sinks/{sinksId}", + "httpMethod": "DELETE", + "parameters": { + "sinkName": { + "description": "Required. The resource name of the sink to delete, including the parent\nresource and the sink identifier. Example:\n`\"projects/my-project-id/sinks/my-sink-id\"`. It is an error if the sink\ndoes not exist.", + "required": true, + "pattern": "^organizations/[^/]+/sinks/[^/]+$", + "location": "path", + "type": "string" + } + }, + "path": "v2/{+sinkName}", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/logging.admin" + ] + } + } + } + } + }, + "entries": { + "methods": { + "write": { + "id": "logging.entries.write", + "response": { + "$ref": "WriteLogEntriesResponse" + }, + "parameterOrder": [], + "description": "Writes log entries to Stackdriver Logging. All log entries are\nwritten by this method.", + "request": { + "$ref": "WriteLogEntriesRequest" + }, + "flatPath": "v2/entries:write", + "httpMethod": "POST", + "parameters": {}, + "path": "v2/entries:write", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/logging.admin", + "https://www.googleapis.com/auth/logging.write" + ] + }, + "list": { + "id": "logging.entries.list", + "response": { + "$ref": "ListLogEntriesResponse" + }, + "parameterOrder": [], + "description": "Lists log entries. Use this method to retrieve log entries from Cloud\nLogging. For ways to export log entries, see\n[Exporting Logs](/logging/docs/export).", + "request": { + "$ref": "ListLogEntriesRequest" + }, + "flatPath": "v2/entries:list", + "httpMethod": "POST", + "parameters": {}, + "path": "v2/entries:list", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/cloud-platform.read-only", + "https://www.googleapis.com/auth/logging.admin", + "https://www.googleapis.com/auth/logging.read" + ] + } + } + }, + "monitoredResourceDescriptors": { + "methods": { + "list": { + "id": "logging.monitoredResourceDescriptors.list", + "response": { + "$ref": "ListMonitoredResourceDescriptorsResponse" + }, + "parameterOrder": [], + "description": "Lists the monitored resource descriptors used by Stackdriver Logging.", + "flatPath": "v2/monitoredResourceDescriptors", + "httpMethod": "GET", + "parameters": { + "pageSize": { + "description": "Optional. The maximum number of results to return from this request.\nNon-positive values are ignored. The presence of `nextPageToken` in the\nresponse indicates that more results might be available.", + "location": "query", + "type": "integer", + "format": "int32" + }, + "pageToken": { + "description": "Optional. If present, then retrieve the next batch of results from the\npreceding call to this method. `pageToken` must be the value of\n`nextPageToken` from the previous response. The values of other method\nparameters should be identical to those in the previous call.", + "location": "query", + "type": "string" + } + }, + "path": "v2/monitoredResourceDescriptors", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/cloud-platform.read-only", + "https://www.googleapis.com/auth/logging.admin", + "https://www.googleapis.com/auth/logging.read" + ] + } + } + }, + "billingAccounts": { + "resources": { + "logs": { + "methods": { + "delete": { + "id": "logging.billingAccounts.logs.delete", + "response": { + "$ref": "Empty" + }, + "parameterOrder": [ + "logName" + ], + "description": "Deletes a log and all its log entries.\nThe log will reappear if it receives new entries.", + "flatPath": "v2/billingAccounts/{billingAccountsId}/logs/{logsId}", + "httpMethod": "DELETE", + "parameters": { + "logName": { + "description": "Required. The resource name of the log to delete. Example:\n`\"projects/my-project/logs/syslog\"`.", + "required": true, + "pattern": "^billingAccounts/[^/]+/logs/[^/]+$", + "location": "path", + "type": "string" + } + }, + "path": "v2/{+logName}", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/logging.admin" + ] + } + } + } + } + } + }, + "schemas": { + "ListLogEntriesResponse": { + "description": "Result returned from `ListLogEntries`.", + "type": "object", + "properties": { + "entries": { + "description": "A list of log entries.", + "type": "array", + "items": { + "$ref": "LogEntry" + } + }, + "nextPageToken": { + "description": "If there might be more results than appear in this response, then\n`nextPageToken` is included. To get the next set of results, call this\nmethod again using the value of `nextPageToken` as `pageToken`.", + "type": "string" + } + }, + "id": "ListLogEntriesResponse" + }, + "ListSinksResponse": { + "description": "Result returned from `ListSinks`.", + "type": "object", + "properties": { + "nextPageToken": { + "description": "If there might be more results than appear in this response, then\n`nextPageToken` is included. To get the next set of results, call the same\nmethod again using the value of `nextPageToken` as `pageToken`.", + "type": "string" + }, + "sinks": { + "description": "A list of sinks.", + "type": "array", + "items": { + "$ref": "LogSink" + } + } + }, + "id": "ListSinksResponse" + }, + "SourceLocation": { + "description": "Specifies a location in a source code file.", + "type": "object", + "properties": { + "file": { + "description": "Source file name. Depending on the runtime environment, this might be a\nsimple name or a fully-qualified name.", + "type": "string" + }, + "functionName": { + "description": "Human-readable name of the function or method being invoked, with optional\ncontext such as the class or package name. This information is used in\ncontexts such as the logs viewer, where a file and line number are less\nmeaningful. The format can vary by language. For example:\n`qual.if.ied.Class.method` (Java), `dir/package.func` (Go), `function`\n(Python).", + "type": "string" + }, + "line": { + "description": "Line within the source file.", + "type": "string", + "format": "int64" + } + }, + "id": "SourceLocation" + }, + "LogSink": { + "description": "Describes a sink used to export log entries outside of Stackdriver Logging.", + "type": "object", + "properties": { + "destination": { + "description": "Required. The export destination. See\n[Exporting Logs With Sinks](/logging/docs/api/tasks/exporting-logs).\nExamples:\n\n \"storage.googleapis.com/my-gcs-bucket\"\n \"bigquery.googleapis.com/projects/my-project-id/datasets/my-dataset\"\n \"pubsub.googleapis.com/projects/my-project/topics/my-topic\"", + "type": "string" + }, + "filter": { + "description": "Optional. An [advanced logs filter](/logging/docs/view/advanced_filters).\nOnly log entries matching the filter are exported. The filter\nmust be consistent with the log entry format specified by the\n`outputVersionFormat` parameter, regardless of the format of the\nlog entry that was originally written to Stackdriver Logging.\nExample filter (V2 format):\n\n logName=projects/my-projectid/logs/syslog AND severity>=ERROR", + "type": "string" + }, + "endTime": { + "description": "Optional. Time at which this sink expires.", + "type": "string", + "format": "google-datetime" + }, + "name": { + "description": "Required. The client-assigned sink identifier, unique within the\nproject. Example: `\"my-syslog-errors-to-pubsub\"`. Sink identifiers are\nlimited to 1000 characters and can include only the following characters:\n`A-Z`, `a-z`, `0-9`, and the special characters `_-.`. The maximum length\nof the name is 100 characters.", + "type": "string" + }, + "startTime": { + "description": "Optional. Time range for which this sink is active.\nLogs are exported only if start_time <= entry.timestamp < end_time\nBoth start_time and end_time may be omitted to specify\n(half) infinite ranges. The start_time must be less than the end_time.", + "type": "string", + "format": "google-datetime" + }, + "outputVersionFormat": { + "description": "Optional. The log entry version to use for this sink's exported log\nentries. This version does not have to correspond to the version of the\nlog entry that was written to Stackdriver Logging. If omitted, the\nv2 format is used.", + "enum": [ + "VERSION_FORMAT_UNSPECIFIED", + "V2", + "V1" + ], + "enumDescriptions": [ + "An unspecified version format will default to V2.", + "`LogEntry` version 2 format.", + "`LogEntry` version 1 format." + ], + "type": "string" + }, + "writerIdentity": { + "description": "Output only. The IAM identity to which the destination needs to grant write\naccess. This may be a service account or a group.\nExamples (Do not assume these specific values):\n \"serviceAccount:cloud-logs@system.gserviceaccount.com\"\n \"group:cloud-logs@google.com\"\n\n For GCS destinations, the role \"roles/owner\" is required on the bucket\n For Cloud Pubsub destinations, the role \"roles/pubsub.publisher\" is\n required on the topic\n For BigQuery, the role \"roles/editor\" is required on the dataset", + "type": "string" + } + }, + "id": "LogSink" + }, + "LogMetric": { + "description": "Describes a logs-based metric. The value of the metric is the\nnumber of log entries that match a logs filter.", + "type": "object", + "properties": { + "description": { + "description": "Optional. A description of this metric, which is used in documentation.", + "type": "string" + }, + "filter": { + "description": "Required. An [advanced logs filter](/logging/docs/view/advanced_filters).\nExample: `\"resource.type=gae_app AND severity>=ERROR\"`.", + "type": "string" + }, + "name": { + "description": "Required. The client-assigned metric identifier. Example:\n`\"severe_errors\"`. Metric identifiers are limited to 100\ncharacters and can include only the following characters: `A-Z`,\n`a-z`, `0-9`, and the special characters `_-.,+!*',()%/`. The\nforward-slash character (`/`) denotes a hierarchy of name pieces,\nand it cannot be the first character of the name. The '%' character\nis used to URL encode unsafe and reserved characters and must be\nfollowed by two hexadecimal digits according to RFC 1738.", + "type": "string" + }, + "version": { + "description": "Output only. The API version that created or updated this metric.\nThe version also dictates the syntax of the filter expression. When a value\nfor this field is missing, the default value of V2 should be assumed.", + "enum": [ + "V2", + "V1" + ], + "enumDescriptions": [ + "Stackdriver Logging API v2.", + "Stackdriver Logging API v1." + ], + "type": "string" + } + }, + "id": "LogMetric" + }, + "LogEntry": { + "description": "An individual entry in a log.", + "type": "object", + "properties": { + "textPayload": { + "description": "The log entry payload, represented as a Unicode string (UTF-8).", + "type": "string" + }, + "httpRequest": { + "description": "Optional. Information about the HTTP request associated with this\nlog entry, if applicable.", + "$ref": "HttpRequest" + }, + "jsonPayload": { + "description": "The log entry payload, represented as a structure that\nis expressed as a JSON object.", + "additionalProperties": { + "description": "Properties of the object.", + "type": "any" + }, + "type": "object" + }, + "labels": { + "description": "Optional. A set of user-defined (key, value) data that provides additional\ninformation about the log entry.", + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "logName": { + "description": "Required. The resource name of the log to which this log entry\nbelongs. The format of the name is\n`\"projects//logs/\"`. Examples:\n`\"projects/my-projectid/logs/syslog\"`,\n`\"projects/my-projectid/logs/library.googleapis.com%2Fbook_log\"`.\n\nThe log ID part of resource name must be less than 512 characters\nlong and can only include the following characters: upper and\nlower case alphanumeric characters: [A-Za-z0-9]; and punctuation\ncharacters: forward-slash, underscore, hyphen, and period.\nForward-slash (`/`) characters in the log ID must be URL-encoded.", + "type": "string" + }, + "severity": { + "description": "Optional. The severity of the log entry. The default value is\n`LogSeverity.DEFAULT`.", + "enum": [ + "DEFAULT", + "DEBUG", + "INFO", + "NOTICE", + "WARNING", + "ERROR", + "CRITICAL", + "ALERT", + "EMERGENCY" + ], + "enumDescriptions": [ + "(0) The log entry has no assigned severity level.", + "(100) Debug or trace information.", + "(200) Routine information, such as ongoing status or performance.", + "(300) Normal but significant events, such as start up, shut down, or\na configuration change.", + "(400) Warning events might cause problems.", + "(500) Error events are likely to cause problems.", + "(600) Critical events cause more severe problems or outages.", + "(700) A person must take an action immediately.", + "(800) One or more systems are unusable." + ], + "type": "string" + }, + "resource": { + "description": "Required. The monitored resource associated with this log entry.\nExample: a log entry that reports a database error would be\nassociated with the monitored resource designating the particular\ndatabase that reported the error.", + "$ref": "MonitoredResource" + }, + "protoPayload": { + "description": "The log entry payload, represented as a protocol buffer. Some\nGoogle Cloud Platform services use this field for their log\nentry payloads.", + "additionalProperties": { + "description": "Properties of the object. Contains field @type with type URL.", + "type": "any" + }, + "type": "object" + }, + "timestamp": { + "description": "Optional. The time the event described by the log entry occurred. If\nomitted, Stackdriver Logging will use the time the log entry is received.", + "type": "string", + "format": "google-datetime" + }, + "insertId": { + "description": "Optional. A unique ID for the log entry. If you provide this\nfield, the logging service considers other log entries in the\nsame project with the same ID as duplicates which can be removed. If\nomitted, Stackdriver Logging will generate a unique ID for this\nlog entry.", + "type": "string" + }, + "operation": { + "description": "Optional. Information about an operation associated with the log entry, if\napplicable.", + "$ref": "LogEntryOperation" + } + }, + "id": "LogEntry" + }, + "LogLine": { + "description": "Application log line emitted while processing a request.", + "type": "object", + "properties": { + "time": { + "description": "Approximate time when this log entry was made.", + "type": "string", + "format": "google-datetime" + }, + "severity": { + "description": "Severity of this log entry.", + "enum": [ + "DEFAULT", + "DEBUG", + "INFO", + "NOTICE", + "WARNING", + "ERROR", + "CRITICAL", + "ALERT", + "EMERGENCY" + ], + "enumDescriptions": [ + "(0) The log entry has no assigned severity level.", + "(100) Debug or trace information.", + "(200) Routine information, such as ongoing status or performance.", + "(300) Normal but significant events, such as start up, shut down, or\na configuration change.", + "(400) Warning events might cause problems.", + "(500) Error events are likely to cause problems.", + "(600) Critical events cause more severe problems or outages.", + "(700) A person must take an action immediately.", + "(800) One or more systems are unusable." + ], + "type": "string" + }, + "sourceLocation": { + "description": "Where in the source code this log message was written.", + "$ref": "SourceLocation" + }, + "logMessage": { + "description": "App-provided log message.", + "type": "string" + } + }, + "id": "LogLine" + }, + "SourceReference": { + "description": "A reference to a particular snapshot of the source tree used to build and\ndeploy an application.", + "type": "object", + "properties": { + "repository": { + "description": "Optional. A URI string identifying the repository.\nExample: \"https://github.com/GoogleCloudPlatform/kubernetes.git\"", + "type": "string" + }, + "revisionId": { + "description": "The canonical and persistent identifier of the deployed revision.\nExample (git): \"0035781c50ec7aa23385dc841529ce8a4b70db1b\"", + "type": "string" + } + }, + "id": "SourceReference" + }, + "MonitoredResource": { + "description": "An object representing a resource that can be used for monitoring, logging,\nbilling, or other purposes. Examples include virtual machine instances,\ndatabases, and storage devices such as disks. The `type` field identifies a\nMonitoredResourceDescriptor object that describes the resource's\nschema. Information in the `labels` field identifies the actual resource and\nits attributes according to the schema. For example, a particular Compute\nEngine VM instance could be represented by the following object, because the\nMonitoredResourceDescriptor for `\"gce_instance\"` has labels\n`\"instance_id\"` and `\"zone\"`:\n\n { \"type\": \"gce_instance\",\n \"labels\": { \"instance_id\": \"12345678901234\",\n \"zone\": \"us-central1-a\" }}", + "type": "object", + "properties": { + "labels": { + "description": "Required. Values for all of the labels listed in the associated monitored\nresource descriptor. For example, Cloud SQL databases use the labels\n`\"database_id\"` and `\"zone\"`.", + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "type": { + "description": "Required. The monitored resource type. This field must match\nthe `type` field of a MonitoredResourceDescriptor object. For\nexample, the type of a Cloud SQL database is `\"cloudsql_database\"`.", + "type": "string" + } + }, + "id": "MonitoredResource" + }, + "WriteLogEntriesRequest": { + "description": "The parameters to WriteLogEntries.", + "type": "object", + "properties": { + "labels": { + "description": "Optional. Default labels that are added to the `labels` field of all log\nentries in `entries`. If a log entry already has a label with the same key\nas a label in this parameter, then the log entry's label is not changed.\nSee LogEntry.", + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "entries": { + "description": "Required. The log entries to write. Values supplied for the fields\n`log_name`, `resource`, and `labels` in this `entries.write` request are\nadded to those log entries that do not provide their own values for the\nfields.\n\nTo improve throughput and to avoid exceeding the\n[quota limit](/logging/quota-policy) for calls to `entries.write`,\nyou should write multiple log entries at once rather than\ncalling this method for each individual log entry.", + "type": "array", + "items": { + "$ref": "LogEntry" + } + }, + "logName": { + "description": "Optional. A default log resource name that is assigned to all log entries\nin `entries` that do not specify a value for `log_name`. Example:\n`\"projects/my-project/logs/syslog\"`. See\nLogEntry.", + "type": "string" + }, + "partialSuccess": { + "description": "Optional. Whether valid entries should be written even if some other\nentries fail due to INVALID_ARGUMENT or PERMISSION_DENIED errors. If any\nentry is not written, the response status will be the error associated\nwith one of the failed entries and include error details in the form of\nWriteLogEntriesPartialErrors.", + "type": "boolean" + }, + "resource": { + "description": "Optional. A default monitored resource object that is assigned to all log\nentries in `entries` that do not specify a value for `resource`. Example:\n\n { \"type\": \"gce_instance\",\n \"labels\": {\n \"zone\": \"us-central1-a\", \"instance_id\": \"00000000000000000000\" }}\n\nSee LogEntry.", + "$ref": "MonitoredResource" + } + }, + "id": "WriteLogEntriesRequest" + }, + "LabelDescriptor": { + "description": "A description of a label.", + "type": "object", + "properties": { + "description": { + "description": "A human-readable description for the label.", + "type": "string" + }, + "valueType": { + "description": "The type of data that can be assigned to the label.", + "enum": [ + "STRING", + "BOOL", + "INT64" + ], + "enumDescriptions": [ + "A variable-length string. This is the default.", + "Boolean; true or false.", + "A 64-bit signed integer." + ], + "type": "string" + }, + "key": { + "description": "The label key.", + "type": "string" + } + }, + "id": "LabelDescriptor" + }, + "ListLogMetricsResponse": { + "description": "Result returned from ListLogMetrics.", + "type": "object", + "properties": { + "metrics": { + "description": "A list of logs-based metrics.", + "type": "array", + "items": { + "$ref": "LogMetric" + } + }, + "nextPageToken": { + "description": "If there might be more results than appear in this response, then\n`nextPageToken` is included. To get the next set of results, call this\nmethod again using the value of `nextPageToken` as `pageToken`.", + "type": "string" + } + }, + "id": "ListLogMetricsResponse" + }, + "MonitoredResourceDescriptor": { + "description": "An object that describes the schema of a MonitoredResource object using a\ntype name and a set of labels. For example, the monitored resource\ndescriptor for Google Compute Engine VM instances has a type of\n`\"gce_instance\"` and specifies the use of the labels `\"instance_id\"` and\n`\"zone\"` to identify particular VM instances.\n\nDifferent APIs can support different monitored resource types. APIs generally\nprovide a `list` method that returns the monitored resource descriptors used\nby the API.", + "type": "object", + "properties": { + "displayName": { + "description": "Optional. A concise name for the monitored resource type that might be\ndisplayed in user interfaces. It should be a Title Cased Noun Phrase,\nwithout any article or other determiners. For example,\n`\"Google Cloud SQL Database\"`.", + "type": "string" + }, + "description": { + "description": "Optional. A detailed description of the monitored resource type that might\nbe used in documentation.", + "type": "string" + }, + "labels": { + "description": "Required. A set of labels used to describe instances of this monitored\nresource type. For example, an individual Google Cloud SQL database is\nidentified by values for the labels `\"database_id\"` and `\"zone\"`.", + "type": "array", + "items": { + "$ref": "LabelDescriptor" + } + }, + "type": { + "description": "Required. The monitored resource type. For example, the type\n`\"cloudsql_database\"` represents databases in Google Cloud SQL.\nThe maximum length of this value is 256 characters.", + "type": "string" + }, + "name": { + "description": "Optional. The resource name of the monitored resource descriptor:\n`\"projects/{project_id}/monitoredResourceDescriptors/{type}\"` where\n{type} is the value of the `type` field in this object and\n{project_id} is a project ID that provides API-specific context for\naccessing the type. APIs that do not use project information can use the\nresource name format `\"monitoredResourceDescriptors/{type}\"`.", + "type": "string" + } + }, + "id": "MonitoredResourceDescriptor" + }, + "ListMonitoredResourceDescriptorsResponse": { + "description": "Result returned from ListMonitoredResourceDescriptors.", + "type": "object", + "properties": { + "nextPageToken": { + "description": "If there might be more results than appear in this response, then\n`nextPageToken` is included. To get the next set of results, call this\nmethod again using the value of `nextPageToken` as `pageToken`.", + "type": "string" + }, + "resourceDescriptors": { + "description": "A list of resource descriptors.", + "type": "array", + "items": { + "$ref": "MonitoredResourceDescriptor" + } + } + }, + "id": "ListMonitoredResourceDescriptorsResponse" + }, + "LogEntryOperation": { + "description": "Additional information about a potentially long-running operation with which\na log entry is associated.", + "type": "object", + "properties": { + "producer": { + "description": "Optional. An arbitrary producer identifier. The combination of\n`id` and `producer` must be globally unique. Examples for `producer`:\n`\"MyDivision.MyBigCompany.com\"`, `\"github.com/MyProject/MyApplication\"`.", + "type": "string" + }, + "last": { + "description": "Optional. Set this to True if this is the last log entry in the operation.", + "type": "boolean" + }, + "first": { + "description": "Optional. Set this to True if this is the first log entry in the operation.", + "type": "boolean" + }, + "id": { + "description": "Optional. An arbitrary operation identifier. Log entries with the\nsame identifier are assumed to be part of the same operation.", + "type": "string" + } + }, + "id": "LogEntryOperation" + }, + "Empty": { + "description": "A generic empty message that you can re-use to avoid defining duplicated\nempty messages in your APIs. A typical example is to use it as the request\nor the response type of an API method. For instance:\n\n service Foo {\n rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);\n }\n\nThe JSON representation for `Empty` is empty JSON object `{}`.", + "type": "object", + "properties": {}, + "id": "Empty" + }, + "HttpRequest": { + "description": "A common proto for logging HTTP requests. Only contains semantics\ndefined by the HTTP specification. Product-specific logging\ninformation MUST be defined in a separate message.", + "type": "object", + "properties": { + "cacheLookup": { + "description": "Whether or not a cache lookup was attempted.", + "type": "boolean" + }, + "responseSize": { + "description": "The size of the HTTP response message sent back to the client, in bytes,\nincluding the response headers and the response body.", + "type": "string", + "format": "int64" + }, + "status": { + "description": "The response code indicating the status of response.\nExamples: 200, 404.", + "type": "integer", + "format": "int32" + }, + "cacheValidatedWithOriginServer": { + "description": "Whether or not the response was validated with the origin server before\nbeing served from cache. This field is only meaningful if `cache_hit` is\nTrue.", + "type": "boolean" + }, + "referer": { + "description": "The referer URL of the request, as defined in\n[HTTP/1.1 Header Field Definitions](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html).", + "type": "string" + }, + "cacheHit": { + "description": "Whether or not an entity was served from cache\n(with or without validation).", + "type": "boolean" + }, + "requestUrl": { + "description": "The scheme (http, https), the host name, the path and the query\nportion of the URL that was requested.\nExample: `\"http://example.com/some/info?color=red\"`.", + "type": "string" + }, + "latency": { + "description": "The request processing latency on the server, from the time the request was\nreceived until the response was sent.", + "type": "string", + "format": "google-duration" + }, + "cacheFillBytes": { + "description": "The number of HTTP response bytes inserted into cache. Set only when a\ncache fill was attempted.", + "type": "string", + "format": "int64" + }, + "requestMethod": { + "description": "The request method. Examples: `\"GET\"`, `\"HEAD\"`, `\"PUT\"`, `\"POST\"`.", + "type": "string" + }, + "remoteIp": { + "description": "The IP address (IPv4 or IPv6) of the client that issued the HTTP\nrequest. Examples: `\"192.168.1.1\"`, `\"FE80::0202:B3FF:FE1E:8329\"`.", + "type": "string" + }, + "serverIp": { + "description": "The IP address (IPv4 or IPv6) of the origin server that the request was\nsent to.", + "type": "string" + }, + "userAgent": { + "description": "The user agent sent by the client. Example:\n`\"Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Q312461; .NET CLR 1.0.3705)\"`.", + "type": "string" + }, + "requestSize": { + "description": "The size of the HTTP request message in bytes, including the request\nheaders and the request body.", + "type": "string", + "format": "int64" + } + }, + "id": "HttpRequest" + }, + "RequestLog": { + "description": "Complete log information about a single HTTP request to an App Engine\napplication.", + "type": "object", + "properties": { + "responseSize": { + "description": "Size in bytes sent back to client by request.", + "type": "string", + "format": "int64" + }, + "requestId": { + "description": "Globally unique identifier for a request, which is based on the request\nstart time. Request IDs for requests which started later will compare\ngreater as strings than those for requests which started earlier.", + "type": "string" + }, + "first": { + "description": "Whether this is the first RequestLog entry for this request. If an active\nrequest has several RequestLog entries written to Cloud Logging, this field\nwill be set for one of them.", + "type": "boolean" + }, + "method": { + "description": "Request method. Example: `\"GET\"`, `\"HEAD\"`, `\"PUT\"`, `\"POST\"`, `\"DELETE\"`.", + "type": "string" + }, + "versionId": { + "description": "Version of the application that handled this request.", + "type": "string" + }, + "status": { + "description": "HTTP response status code. Example: 200, 404.", + "type": "integer", + "format": "int32" + }, + "wasLoadingRequest": { + "description": "Whether this was a loading request for the instance.", + "type": "boolean" + }, + "ip": { + "description": "Origin IP address.", + "type": "string" + }, + "nickname": { + "description": "The logged-in user who made the request.\n\nMost likely, this is the part of the user's email before the `@` sign. The\nfield value is the same for different requests from the same user, but\ndifferent users can have similar names. This information is also\navailable to the application via the App Engine Users API.\n\nThis field will be populated starting with App Engine 1.9.21.", + "type": "string" + }, + "taskQueueName": { + "description": "Queue name of the request, in the case of an offline request.", + "type": "string" + }, + "pendingTime": { + "description": "Time this request spent in the pending request queue.", + "type": "string", + "format": "google-duration" + }, + "instanceIndex": { + "description": "If the instance processing this request belongs to a manually scaled\nmodule, then this is the 0-based index of the instance. Otherwise, this\nvalue is -1.", + "type": "integer", + "format": "int32" + }, + "sourceReference": { + "description": "Source code for the application that handled this request. There can be\nmore than one source reference per deployed application if source code is\ndistributed among multiple repositories.", + "type": "array", + "items": { + "$ref": "SourceReference" + } + }, + "moduleId": { + "description": "Module of the application that handled this request.", + "type": "string" + }, + "host": { + "description": "Internet host and port number of the resource being requested.", + "type": "string" + }, + "latency": { + "description": "Latency of the request.", + "type": "string", + "format": "google-duration" + }, + "urlMapEntry": { + "description": "File or class that handled the request.", + "type": "string" + }, + "endTime": { + "description": "Time when the request finished.", + "type": "string", + "format": "google-datetime" + }, + "line": { + "description": "A list of log lines emitted by the application while serving this request.", + "type": "array", + "items": { + "$ref": "LogLine" + } + }, + "megaCycles": { + "description": "Number of CPU megacycles used to process request.", + "type": "string", + "format": "int64" + }, + "appId": { + "description": "Application that handled this request.", + "type": "string" + }, + "traceId": { + "description": "Cloud Trace identifier for this request.", + "type": "string" + }, + "taskName": { + "description": "Task name of the request, in the case of an offline request.", + "type": "string" + }, + "cost": { + "description": "An indication of the relative cost of serving this request.", + "type": "number", + "format": "double" + }, + "instanceId": { + "description": "An identifier for the instance that handled the request.", + "type": "string" + }, + "startTime": { + "description": "Time when the request started.", + "type": "string", + "format": "google-datetime" + }, + "appEngineRelease": { + "description": "App Engine release version.", + "type": "string" + }, + "resource": { + "description": "Contains the path and query portion of the URL that was requested. For\nexample, if the URL was \"http://example.com/app?name=val\", the resource\nwould be \"/app?name=val\". The fragment identifier, which is identified by\nthe `#` character, is not included.", + "type": "string" + }, + "httpVersion": { + "description": "HTTP version of request. Example: `\"HTTP/1.1\"`.", + "type": "string" + }, + "referrer": { + "description": "Referrer URL of request.", + "type": "string" + }, + "userAgent": { + "description": "User agent that made the request.", + "type": "string" + }, + "finished": { + "description": "Whether this request is finished or active.", + "type": "boolean" + } + }, + "id": "RequestLog" + }, + "WriteLogEntriesResponse": { + "description": "Result returned from WriteLogEntries.\nempty", + "type": "object", + "properties": {}, + "id": "WriteLogEntriesResponse" + }, + "ListLogEntriesRequest": { + "description": "The parameters to `ListLogEntries`.", + "type": "object", + "properties": { + "filter": { + "description": "Optional. A filter that chooses which log entries to return. See [Advanced\nLogs Filters](/logging/docs/view/advanced_filters). Only log entries that\nmatch the filter are returned. An empty filter matches all log entries.", + "type": "string" + }, + "projectIds": { + "description": "Deprecated. One or more project identifiers or project numbers from which\nto retrieve log entries. Examples: `\"my-project-1A\"`, `\"1234567890\"`. If\npresent, these project identifiers are converted to resource format and\nadded to the list of resources in `resourceNames`. Callers should use\n`resourceNames` rather than this parameter.", + "type": "array", + "items": { + "type": "string" + } + }, + "resourceNames": { + "description": "Required. One or more cloud resources from which to retrieve log entries.\nExample: `\"projects/my-project-1A\"`, `\"projects/1234567890\"`. Projects\nlisted in `projectIds` are added to this list.", + "type": "array", + "items": { + "type": "string" + } + }, + "pageSize": { + "description": "Optional. The maximum number of results to return from this request.\nNon-positive values are ignored. The presence of `nextPageToken` in the\nresponse indicates that more results might be available.", + "type": "integer", + "format": "int32" + }, + "orderBy": { + "description": "Optional. How the results should be sorted. Presently, the only permitted\nvalues are `\"timestamp asc\"` (default) and `\"timestamp desc\"`. The first\noption returns entries in order of increasing values of\n`LogEntry.timestamp` (oldest first), and the second option returns entries\nin order of decreasing timestamps (newest first). Entries with equal\ntimestamps are returned in order of `LogEntry.insertId`.", + "type": "string" + }, + "pageToken": { + "description": "Optional. If present, then retrieve the next batch of results from the\npreceding call to this method. `pageToken` must be the value of\n`nextPageToken` from the previous response. The values of other method\nparameters should be identical to those in the previous call.", + "type": "string" + } + }, + "id": "ListLogEntriesRequest" + } + }, + "revision": "20161017", + "basePath": "", + "icons": { + "x32": "http://www.google.com/images/icons/product/search-32.gif", + "x16": "http://www.google.com/images/icons/product/search-16.gif" + }, + "version_module": "True", + "canonicalName": "Logging", + "discoveryVersion": "v1", + "baseUrl": "https://logging.googleapis.com/", + "name": "logging", + "parameters": { + "access_token": { + "description": "OAuth access token.", + "type": "string", + "location": "query" + }, + "prettyPrint": { + "description": "Returns response with indentations and line breaks.", + "default": "true", + "type": "boolean", + "location": "query" + }, + "key": { + "description": "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.", + "type": "string", + "location": "query" + }, + "quotaUser": { + "description": "Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters.", + "type": "string", + "location": "query" + }, + "pp": { + "description": "Pretty-print response.", + "default": "true", + "type": "boolean", + "location": "query" + }, + "fields": { + "description": "Selector specifying which fields to include in a partial response.", + "type": "string", + "location": "query" + }, + "alt": { + "description": "Data format for response.", + "location": "query", + "enum": [ + "json", + "media", + "proto" + ], + "default": "json", + "enumDescriptions": [ + "Responses with Content-Type of application/json", + "Media download with context-dependent Content-Type", + "Responses with Content-Type of application/x-protobuf" + ], + "type": "string" + }, + "$.xgafv": { + "description": "V1 error format.", + "enum": [ + "1", + "2" + ], + "enumDescriptions": [ + "v1 error format", + "v2 error format" + ], + "type": "string", + "location": "query" + }, + "callback": { + "description": "JSONP", + "type": "string", + "location": "query" + }, + "oauth_token": { + "description": "OAuth 2.0 token for the current user.", + "type": "string", + "location": "query" + }, + "uploadType": { + "description": "Legacy upload protocol for media (e.g. \"media\", \"multipart\").", + "type": "string", + "location": "query" + }, + "bearer_token": { + "description": "OAuth bearer token.", + "type": "string", + "location": "query" + }, + "upload_protocol": { + "description": "Upload protocol for media (e.g. \"raw\", \"multipart\").", + "type": "string", + "location": "query" + } + }, + "documentationLink": "https://cloud.google.com/logging/docs/", + "ownerDomain": "google.com", + "batchPath": "batch", + "servicePath": "", + "ownerName": "Google", + "version": "v2", + "rootUrl": "https://logging.googleapis.com/", + "kind": "discovery#restDescription" +} diff --git a/src/Logging/Logger.php b/src/Logging/Logger.php index 0836c98a5a2..b3bf177565c 100644 --- a/src/Logging/Logger.php +++ b/src/Logging/Logger.php @@ -34,14 +34,28 @@ */ class Logger { - const EMERGENCY = 'EMERGENCY'; - const ALERT = 'ALERT'; - const CRITICAL = 'CRITICAL'; - const ERROR = 'ERROR'; - const WARNING = 'WARNING'; - const NOTICE = 'NOTICE'; - const INFO = 'INFO'; - const DEBUG = 'DEBUG'; + const EMERGENCY = 800; + const ALERT = 700; + const CRITICAL = 600; + const ERROR = 500; + const WARNING = 400; + const NOTICE = 300; + const INFO = 200; + const DEBUG = 100; + // DEFAULT is a reserved keyword. + const DEFAULT_LEVEL = 0; + + private static $logLevelMap = [ + self::EMERGENCY => 'EMERGENCY', + self::ALERT => 'ALERT', + self::CRITICAL => 'CRITICAL', + self::ERROR => 'ERROR', + self::WARNING => 'WARNING', + self::NOTICE => 'NOTICE', + self::INFO => 'INFO', + self::DEBUG => 'DEBUG', + self::DEFAULT_LEVEL => 'DEFAULT' + ]; /** * @var ConnectionInterface Represents a connection to Stackdriver Logging. @@ -81,7 +95,7 @@ public function __construct(ConnectionInterface $connection, $name, $projectId) * ``` * * @codingStandardsIgnoreStart - * @see https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/projects.logs/delete projects.logs delete API documentation. + * @see https://cloud.google.com/logging/docs/api/reference/rest/v2/projects.logs/delete projects.logs delete API documentation. * @codingStandardsIgnoreEnd * * @param array $options [optional] Configuration Options. @@ -118,7 +132,7 @@ public function delete(array $options = []) * ``` * * @codingStandardsIgnoreStart - * @see https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/entries/list Entries list API documentation. + * @see https://cloud.google.com/logging/docs/api/reference/rest/v2/entries/list Entries list API documentation. * @codingStandardsIgnoreEnd * * @param array $options [optional] { @@ -201,10 +215,9 @@ public function entries(array $options = []) * ['severity' => Logger::EMERGENCY] * ); * ``` - * - * @see https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/LogEntry LogEntry resource documentation. - * * @codingStandardsIgnoreStart + * @see https://cloud.google.com/logging/docs/api/reference/rest/Shared.Types/LogEntry LogEntry resource documentation. + * * @param array|string $data The data to log. When providing a string the * data will be stored as a `textPayload` type. When providing an * array the data will be stored as a `jsonPayload` type. @@ -224,7 +237,7 @@ public function entries(array $options = []) * long-running operation with which a log entry is associated. * Please see [the API docs](https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/LogEntry#logentryoperation) * for more information. - * @type string $severity The severity of the log entry. **Defaults to** + * @type string|int $severity The severity of the log entry. **Defaults to** * `"DEFAULT"`. * } * @return Entry @@ -257,7 +270,7 @@ public function entry($data, array $resource, array $options = []) * ``` * * @codingStandardsIgnoreStart - * @see https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/entries/write Entries write API documentation. + * @see https://cloud.google.com/logging/docs/api/reference/rest/v2/entries/write Entries write API documentation. * @codingStandardsIgnoreEnd * * @param Entry $entry The entry to write to the log. @@ -289,7 +302,7 @@ public function write(Entry $entry, array $options = []) * ``` * * @codingStandardsIgnoreStart - * @see https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/entries/write Entries write API documentation. + * @see https://cloud.google.com/logging/docs/api/reference/rest/v2/entries/write Entries write API documentation. * @codingStandardsIgnoreEnd * * @param Entry[] $entries Entries to write to the log. @@ -303,4 +316,15 @@ public function writeBatch(array $entries, array $options = []) $this->connection->writeEntries($options + ['entries' => $entries]); } + + /** + * Returns the log level map. + * + * @param array + * @access private + */ + public static function getLogLevelMap() + { + return self::$logLevelMap; + } } diff --git a/src/Logging/LoggingClient.php b/src/Logging/LoggingClient.php index 0c3e9ff9f7a..bc1bfc93479 100644 --- a/src/Logging/LoggingClient.php +++ b/src/Logging/LoggingClient.php @@ -19,6 +19,7 @@ use Google\Cloud\ClientTrait; use Google\Cloud\Logging\Connection\ConnectionInterface; +use Google\Cloud\Logging\Connection\Grpc; use Google\Cloud\Logging\Connection\Rest; /** @@ -27,6 +28,26 @@ * Amazon Web Services. Find more information at * [Google Stackdriver Logging docs](https://cloud.google.com/logging/docs/). * + * This client supports transport over + * [REST](https://cloud.google.com/logging/docs/api/reference/rest/) or + * gRPC. + * + * In order to enable gRPC support please make sure to install and enable + * the gRPC extension through PECL: + * + * ```sh + * $ pecl install grpc + * ``` + * + * Afterwards, please install the following dependencies through composer: + * + * ```sh + * $ composer require google/gax && composer require google/proto-client-php + * ``` + * + * Please take care in installing the same version of these libraries that are + * outlined in the project's composer.json require-dev keyword. + * * Example: * ``` * use Google\Cloud\ServiceBuilder; @@ -81,15 +102,22 @@ class LoggingClient * @type int $retries Number of retries for a failed request. * **Defaults to** `3`. * @type array $scopes Scopes to be used for the request. + * @type string $transport The transport type used for requests. May be + * either `grpc` or `rest`. **Defaults to** `grpc` if gRPC support + * is detected on the system. * } */ public function __construct(array $config = []) { + $connectionType = $this->getConnectionType($config); if (!isset($config['scopes'])) { $config['scopes'] = [self::FULL_CONTROL_SCOPE]; } - $this->connection = new Rest($this->configureAuthentication($config)); + $this->connection = $connectionType === 'grpc' + ? new Grpc($this->configureAuthentication($config)) + : new Rest($this->configureAuthentication($config)); + $this->formattedProjectName = "projects/$this->projectId"; } @@ -102,7 +130,7 @@ public function __construct(array $config = []) * ``` * * @codingStandardsIgnoreStart - * @see https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/projects.sinks/create projects.sinks create API documentation. + * @see https://cloud.google.com/logging/docs/api/reference/rest/v2/projects.sinks/create projects.sinks create API documentation. * @codingStandardsIgnoreEnd * * @param string $name The name of the sink. @@ -116,16 +144,18 @@ public function __construct(array $config = []) * @type string $outputVersionFormat The log entry version to use for * this sink's exported log entries. This version does not have * to correspond to the version of the log entry when it was - * written to Stackdriver Logging. + * written to Stackdriver Logging. May be either `V1` or `V2`. + * **Defaults to** `V2`. * } * @return Sink */ public function createSink($name, $destination, array $options = []) { $response = $this->connection->createSink($options + [ - 'projectName' => $this->formattedProjectName, + 'parent' => $this->formattedProjectName, 'name' => $name, - 'destination' => $destination + 'destination' => $destination, + 'outputVersionFormat' => 'VERSION_FORMAT_UNSPECIFIED' ]); return new Sink($this->connection, $name, $this->projectId, $response); @@ -163,7 +193,7 @@ public function sink($name) * ``` * * @codingStandardsIgnoreStart - * @see https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/projects.sinks/list projects.sinks list API documentation. + * @see https://cloud.google.com/logging/docs/api/reference/rest/v2/projects.sinks/list projects.sinks list API documentation. * @codingStandardsIgnoreEnd * * @param array $options [optional] { @@ -178,7 +208,7 @@ public function sinks(array $options = []) $options['pageToken'] = null; do { - $response = $this->connection->listSinks($options + ['projectName' => $this->formattedProjectName]); + $response = $this->connection->listSinks($options + ['parent' => $this->formattedProjectName]); if (!isset($response['sinks'])) { return; @@ -201,18 +231,22 @@ public function sinks(array $options = []) * ``` * * @codingStandardsIgnoreStart - * @see https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/projects.metrics/create projects.metrics create API documentation. + * @see https://cloud.google.com/logging/docs/api/reference/rest/v2/projects.metrics/create projects.metrics create API documentation. * @codingStandardsIgnoreEnd * * @param string $name The name of the metric. * @param string $filter An [advanced logs filter](https://cloud.google.com/logging/docs/view/advanced_filters). - * @param array $options [optional] Configuration Options. + * @param array $options [optional] { + * Configuration Options. + * + * @type string $description A description of the metric. + * } * @return Metric */ public function createMetric($name, $filter, array $options = []) { $response = $this->connection->createMetric($options + [ - 'projectName' => $this->formattedProjectName, + 'parent' => $this->formattedProjectName, 'name' => $name, 'filter' => $filter ]); @@ -252,7 +286,7 @@ public function metric($name) * ``` * * @codingStandardsIgnoreStart - * @see https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/projects.metrics/list projects.metrics list API documentation. + * @see https://cloud.google.com/logging/docs/api/reference/rest/v2/projects.metrics/list projects.metrics list API documentation. * @codingStandardsIgnoreEnd * * @param array $options [optional] { @@ -267,7 +301,7 @@ public function metrics(array $options = []) $options['pageToken'] = null; do { - $response = $this->connection->listMetrics($options + ['projectName' => $this->formattedProjectName]); + $response = $this->connection->listMetrics($options + ['parent' => $this->formattedProjectName]); if (!isset($response['metrics'])) { return; @@ -305,15 +339,15 @@ public function metrics(array $options = []) * ``` * * @codingStandardsIgnoreStart - * @see https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/entries/list Entries list API documentation. + * @see https://cloud.google.com/logging/docs/api/reference/rest/v2/entries/list Entries list API documentation. * @codingStandardsIgnoreEnd * * @param array $options [optional] { * Configuration options. * - * @type string[] $projectIds A list of projectIds to fetch entries from - * in addition to entries found in the project bound to this - * client. + * @type string[] $projectIds A list of projectIds to fetch + * entries from in addition to entries found in the project bound + * to this client. * @type string $filter An [advanced logs filter](https://cloud.google.com/logging/docs/view/advanced_filters). * @type string $orderBy How the results should be sorted. Presently, * the only permitted values are `timestamp asc` and @@ -355,10 +389,10 @@ public function entries(array $options = []) * Example: * ``` * $psrLogger = $logging->psrLogger('my-log', [ - * 'type' => 'gcs_bucket', - * 'labels' => [ - * 'bucket_name' => 'my-bucket' - * ] + * 'type' => 'gcs_bucket', + * 'labels' => [ + * 'bucket_name' => 'my-bucket' + * ] * ]); * $psrLogger->alert('an alert!'); * ``` @@ -381,10 +415,10 @@ public function psrLogger($name, array $resource) * ``` * $logger = $logging->logger('my-log'); * $entry = $logger->entry('my-data', [ - * 'type' => 'gcs_bucket', - * 'labels' => [ - * 'bucket_name' => 'my-bucket' - * ] + * 'type' => 'gcs_bucket', + * 'labels' => [ + * 'bucket_name' => 'my-bucket' + * ] * ]); * $logger->write($entry); * ``` diff --git a/src/Logging/Metric.php b/src/Logging/Metric.php index ed095e7a406..0dd755b1b91 100644 --- a/src/Logging/Metric.php +++ b/src/Logging/Metric.php @@ -98,7 +98,7 @@ public function exists(array $options = []) * ``` * * @codingStandardsIgnoreStart - * @see https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/projects.metrics/delete projects.metrics delete API documentation. + * @see https://cloud.google.com/logging/docs/api/reference/rest/v2/projects.metrics/delete projects.metrics delete API documentation. * @codingStandardsIgnoreEnd * * @param array $options [optional] Configuration Options. @@ -122,7 +122,7 @@ public function delete(array $options = []) * ``` * * @codingStandardsIgnoreStart - * @see https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/projects.metrics/update projects.metrics update API documentation. + * @see https://cloud.google.com/logging/docs/api/reference/rest/v2/projects.metrics/update projects.metrics update API documentation. * @codingStandardsIgnoreEnd * * @param array $metadata { @@ -155,7 +155,7 @@ public function update(array $metadata, array $options = []) * ``` * * @codingStandardsIgnoreStart - * @see https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/projects.metrics#resource-logmetric LogMetric resource API documentation. + * @see https://cloud.google.com/logging/docs/api/reference/rest/v2/projects.metrics#resource-logmetric LogMetric resource API documentation. * @codingStandardsIgnoreEnd * * @param array $options [optional] Configuration Options. @@ -181,7 +181,7 @@ public function info(array $options = []) * ``` * * @codingStandardsIgnoreStart - * @see https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/projects.metrics/get projects.metrics get API documentation. + * @see https://cloud.google.com/logging/docs/api/reference/rest/v2/projects.metrics/get projects.metrics get API documentation. * @codingStandardsIgnoreEnd * * @param array $options [optional] Configuration Options. diff --git a/src/Logging/PsrLogger.php b/src/Logging/PsrLogger.php index 893ac55970a..d9422aa7995 100644 --- a/src/Logging/PsrLogger.php +++ b/src/Logging/PsrLogger.php @@ -210,7 +210,7 @@ public function debug($message, array $context = []) * ``` * * @codingStandardsIgnoreStart - * @param string $level The severity of the log entry. + * @param string|int $level The severity of the log entry. * @param string $message The message to log. * @param array $context { * @type array $httpRequest Information about the HTTP request @@ -224,15 +224,13 @@ public function debug($message, array $context = []) * Please see [the API docs](https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/LogEntry#logentryoperation) * for more information. * } + * @throws InvalidArgumentException * @codingStandardsIgnoreEnd */ public function log($level, $message, array $context = []) { $message = (string) $message; - - if (!defined(Logger::class . '::' . strtoupper($level))) { - throw new InvalidArgumentException("Severity level '$level' is not defined."); - } + $this->validateLogLevel($level); if (isset($context['exception']) && $context['exception'] instanceof \Exception) { $message .= ' : ' . (string) $context['exception']; @@ -247,4 +245,23 @@ public function log($level, $message, array $context = []) $this->logger->write($entry); } + + /** + * Validates whether or not the provided log level exists. + * + * @param string|int $level The severity of the log entry. + * @return bool + * @throws InvalidArgumentException + */ + private function validateLogLevel($level) + { + $map = $this->logger->getLogLevelMap(); + $level = (string) $level; + + if (isset($map[$level]) || isset(array_flip($map)[strtoupper($level)])) { + return true; + } + + throw new InvalidArgumentException("Severity level '$level' is not defined."); + } } diff --git a/src/Logging/Sink.php b/src/Logging/Sink.php index d425a61b142..0695e1fea08 100644 --- a/src/Logging/Sink.php +++ b/src/Logging/Sink.php @@ -101,7 +101,7 @@ public function exists(array $options = []) * ``` * * @codingStandardsIgnoreStart - * @see https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/projects.sinks/delete projects.sinks delete API documentation. + * @see https://cloud.google.com/logging/docs/api/reference/rest/v2/projects.sinks/delete projects.sinks delete API documentation. * @codingStandardsIgnoreEnd * * @param array $options [optional] Configuration Options. @@ -125,7 +125,7 @@ public function delete(array $options = []) * ``` * * @codingStandardsIgnoreStart - * @see https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/projects.sinks/update projects.sinks update API documentation. + * @see https://cloud.google.com/logging/docs/api/reference/rest/v2/projects.sinks/update projects.sinks update API documentation. * @codingStandardsIgnoreEnd * * @param array $metadata { @@ -138,7 +138,7 @@ public function delete(array $options = []) * @type string $outputVersionFormat The log entry version to use for * this sink's exported log entries. This version does not have * to correspond to the version of the log entry when it was - * written to Stackdriver Logging. + * written to Stackdriver Logging. May be either `V1` or `V2`. * } * @param array $options [optional] Configuration Options. * @return array @@ -164,7 +164,7 @@ public function update(array $metadata, array $options = []) * ``` * * @codingStandardsIgnoreStart - * @see https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/projects.sinks#resource-logsink LogSink resource API documentation. + * @see https://cloud.google.com/logging/docs/api/reference/rest/v2/projects.sinks#resource-logsink LogSink resource API documentation. * @codingStandardsIgnoreEnd * * @param array $options [optional] Configuration Options. @@ -190,7 +190,7 @@ public function info(array $options = []) * ``` * * @codingStandardsIgnoreStart - * @see https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/projects.sinks/get projects.sinks get API documentation. + * @see https://cloud.google.com/logging/docs/api/reference/rest/v2/projects.sinks/get projects.sinks get API documentation. * @codingStandardsIgnoreEnd * * @param array $options [optional] Configuration Options. diff --git a/src/Logging/V2/ConfigServiceV2Api.php b/src/Logging/V2/ConfigServiceV2Api.php index 5b8c20fbdc9..b140213a4ac 100644 --- a/src/Logging/V2/ConfigServiceV2Api.php +++ b/src/Logging/V2/ConfigServiceV2Api.php @@ -227,8 +227,7 @@ public function __construct($options = []) 'retryingOverride' => null, 'timeoutMillis' => self::DEFAULT_TIMEOUT_MILLIS, 'appName' => 'gax', - 'appVersion' => self::_GAX_VERSION, - 'credentialsLoader' => null, + 'appVersion' => self::_GAX_VERSION ]; $options = array_merge($defaultOptions, $options); diff --git a/src/Logging/V2/LoggingServiceV2Api.php b/src/Logging/V2/LoggingServiceV2Api.php index 6041c241e5c..b63ff820d23 100644 --- a/src/Logging/V2/LoggingServiceV2Api.php +++ b/src/Logging/V2/LoggingServiceV2Api.php @@ -233,8 +233,7 @@ public function __construct($options = []) 'retryingOverride' => null, 'timeoutMillis' => self::DEFAULT_TIMEOUT_MILLIS, 'appName' => 'gax', - 'appVersion' => self::_GAX_VERSION, - 'credentialsLoader' => null, + 'appVersion' => self::_GAX_VERSION ]; $options = array_merge($defaultOptions, $options); diff --git a/src/Logging/V2/MetricsServiceV2Api.php b/src/Logging/V2/MetricsServiceV2Api.php index 9a6f1f723ea..7725abfc259 100644 --- a/src/Logging/V2/MetricsServiceV2Api.php +++ b/src/Logging/V2/MetricsServiceV2Api.php @@ -226,8 +226,7 @@ public function __construct($options = []) 'retryingOverride' => null, 'timeoutMillis' => self::DEFAULT_TIMEOUT_MILLIS, 'appName' => 'gax', - 'appVersion' => self::_GAX_VERSION, - 'credentialsLoader' => null, + 'appVersion' => self::_GAX_VERSION ]; $options = array_merge($defaultOptions, $options); diff --git a/src/PhpArray.php b/src/PhpArray.php index ba301aaaeed..984061bbbe3 100644 --- a/src/PhpArray.php +++ b/src/PhpArray.php @@ -18,33 +18,187 @@ namespace Google\Cloud; use DrSlump\Protobuf; +use google\protobuf\Struct; +use google\protobuf\ListValue; /** - * Extend the Protobuf-PHP array codec to convert underscore keys - * to the camelcase type expected by the library. + * Extend the Protobuf-PHP array codec to allow messages to match the format + * used for REST. */ class PhpArray extends Protobuf\Codec\PhpArray { + /** + * @var array + */ + private $customFilters; + + /** + * @param array $customFilters A set of callbacks to apply to properties in + * a gRPC response. + */ + public function __construct(array $customFilters = []) + { + $this->customFilters = $customFilters; + } + + /** + * Borrowed heavily from {@see DrSlump\Protobuf\Codec\PhpArray::encodeMessage()}. + * With this approach we are able to transform the response with minimal + * overhead. + */ protected function encodeMessage(Protobuf\Message $message) { - $res = parent::encodeMessage($message); + $descriptor = Protobuf::getRegistry()->getDescriptor($message); + $data = []; + + foreach ($descriptor->getFields() as $tag => $field) { + $empty = !$message->_has($tag); + if ($field->isRequired() && $empty) { + throw new \UnexpectedValueException( + sprintf( + 'Message %s\'s field tag %s(%s) is required but has no value', + get_class($message), + $tag, + $field->getName() + ) + ); + } + + if ($empty) { + continue; + } + + $key = $this->useTagNumber ? $field->getNumber() : $field->getName(); + $v = $message->_get($tag); + + if ($field->isRepeated()) { + // Make sure the value is an array of values + $v = is_array($v) ? $v : array($v); + $arr = []; + + foreach ($v as $k => $vv) { + // Skip nullified repeated values + if (null === $vv) { + continue; + } + + $filteredValue = $this->filterValue($vv, $field); - return $this->transformKeys($res); + if ($this->isKeyValueMessage($vv)) { + $arr[key($filteredValue)] = current($filteredValue); + } else { + $arr[$k] = $filteredValue; + } + + $v = $arr; + } + } else { + $v = $this->filterValue($v, $field); + } + + $key = $this->toCamelCase($key); + + if (isset($this->customFilters[$key])) { + $v = call_user_func($this->customFilters[$key], $v); + } + + $data[$key] = $v; + } + + return $data; } - private function transformKeys(array $res) + /** + * Borrowed heavily from {@see DrSlump\Protobuf\Codec\PhpArray::decodeMessage()}. + * The only addition here is converting camel case field names to snake case. + */ + protected function decodeMessage(Protobuf\Message $message, $data) { - $out = []; - foreach ($res as $key => $val) { - $newKey = lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $key)))); + // Get message descriptor + $descriptor = Protobuf::getRegistry()->getDescriptor($message); + + foreach ($data as $key => $v) { + // Get the field by tag number or name + $field = $this->useTagNumber + ? $descriptor->getField($key) + : $descriptor->getFieldByName($this->toSnakeCase($key)); - if (is_array($val)) { - $val = $this->transformKeys($val); + // Unknown field found + if (!$field) { + $unknown = new Protobuf\Codec\PhpArray\Unknown($key, gettype($v), $v); + $message->addUnknown($unknown); + continue; } - $out[$newKey] = $val; + if ($field->isRepeated()) { + // Make sure the value is an array of values + $v = is_array($v) && is_int(key($v)) ? $v : array($v); + foreach ($v as $k => $vv) { + $v[$k] = $this->filterValue($vv, $field); + } + } else { + $v = $this->filterValue($v, $field); + } + + $message->_set($field->getNumber(), $v); } - return $out; + return $message; + } + + protected function filterValue($value, Protobuf\Field $field) + { + if ($value instanceof Protobuf\Message) { + if ($this->isKeyValueMessage($value)) { + $v = $value->getValue(); + + return [ + $value->getKey() => $v instanceof Protobuf\Message + ? $this->encodeMessage($v) + : $v + ]; + } + + if ($value instanceof Struct) { + $vals = []; + + foreach ($value->getFields() as $field) { + $val = $this->filterValue( + $field->getValue(), + $field->descriptor()->getFieldByName('value') + ); + $vals[$field->getKey()] = current($val); + } + + return $vals; + } + + if ($value instanceof ListValue) { + $vals = []; + + foreach ($value->getValuesList() as $val) { + $vals[] = current($this->encodeMessage($val)); + } + + return $vals; + } + } + + return parent::filterValue($value, $field); + } + + private function toSnakeCase($key) + { + return strtolower(preg_replace(['/([a-z\d])([A-Z])/', '/([^_])([A-Z][a-z])/'], '$1_$2', $key)); + } + + private function toCamelCase($key) + { + return lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $key)))); + } + + private function isKeyValueMessage($value) + { + return property_exists($value, 'key') && property_exists($value, 'value'); } } diff --git a/src/PubSub/Connection/Grpc.php b/src/PubSub/Connection/Grpc.php index e1f743f1342..c099eff4299 100644 --- a/src/PubSub/Connection/Grpc.php +++ b/src/PubSub/Connection/Grpc.php @@ -17,19 +17,15 @@ namespace Google\Cloud\PubSub\Connection; -use Google\Auth\FetchAuthTokenCache; -use Google\Auth\Cache\MemoryCacheItemPool; +use DrSlump\Protobuf\Codec\CodecInterface; use Google\Cloud\EmulatorTrait; use Google\Cloud\PhpArray; use Google\Cloud\PubSub\V1\PublisherApi; use Google\Cloud\PubSub\V1\SubscriberApi; use Google\Cloud\GrpcRequestWrapper; use Google\Cloud\GrpcTrait; -use Google\Cloud\ServiceBuilder; use Grpc\ChannelCredentials; use google\pubsub\v1\PubsubMessage; -use google\pubsub\v1\PubsubMessage\AttributesEntry as MessageAttributesEntry; -use google\pubsub\v1\PushConfig\AttributesEntry as PushConfigAttributesEntry; use google\pubsub\v1\PushConfig; /** @@ -53,22 +49,22 @@ class Grpc implements ConnectionInterface */ private $subscriberApi; + /** + * @var CodecInterface + */ + private $codec; + /** * @param array $config */ public function __construct(array $config = []) { + $this->codec = new PhpArray(['publishTime' => function ($v) { + return $this->formatTimestampFromApi($v); + }]); + $config['codec'] = $this->codec; $this->setRequestWrapper(new GrpcRequestWrapper($config)); - $grpcConfig = [ - 'credentialsLoader' => new FetchAuthTokenCache( - $this->requestWrapper->getCredentialsFetcher(), - null, - new MemoryCacheItemPool() - ), - 'enableCaching' => false, - 'appName' => 'gcloud-php', - 'version' => ServiceBuilder::VERSION - ]; + $grpcConfig = $this->getGaxConfig(); $emulatorHost = getenv('PUBSUB_EMULATOR_HOST'); $baseUri = $this->getEmulatorBaseUri(self::BASE_URI, $emulatorHost); @@ -137,20 +133,7 @@ public function publishMessage(array $args) $messages = $this->pluck('messages', $args); foreach ($messages as $message) { - $pbMessage = new PubsubMessage(); - $pbMessage->setData($message['data']); - - if (isset($message['attributes'])) { - foreach ($message['attributes'] as $attributeKey => $attributeValue) { - $pbAttribute = new MessageAttributesEntry(); - $pbAttribute->setKey($attributeKey); - $pbAttribute->setValue($attributeValue); - - $pbMessage->addAttributes($pbAttribute); - } - } - - $pbMessages[] = $pbMessage; + $pbMessages[] = $this->buildMessage($message); } return $this->send([$this->publisherApi, 'publish'], [ @@ -177,20 +160,7 @@ public function listSubscriptionsByTopic(array $args) public function createSubscription(array $args) { if (isset($args['pushConfig'])) { - $pbPushConfig = new PushConfig(); - $pbPushConfig->setPushEndpoint($args['pushConfig']['pushEndpoint']); - - if (isset($args['pushConfig']['attributes'])) { - foreach ($args['pushConfig']['attributes'] as $attributeKey => $attributeValue) { - $pbAttribute = new PushConfigAttributesEntry(); - $pbAttribute->setKey($attributeKey); - $pbAttribute->setValue($attributeValue); - - $pbPushConfig->addAttributes($pbAttribute); - } - } - - $args['pushConfig'] = $pbPushConfig; + $args['pushConfig'] = $this->buildPushConfig($args['pushConfig']); } return $this->send([$this->subscriberApi, 'createSubscription'], [ @@ -238,23 +208,9 @@ public function deleteSubscription(array $args) */ public function modifyPushConfig(array $args) { - $pushConfig = $this->pluck('pushConfig', $args); - $pbPushConfig = new PushConfig(); - $pbPushConfig->setPushEndpoint($pushConfig['pushEndpoint']); - - if (isset($pushConfig['attributes'])) { - foreach ($pushConfig['attributes'] as $attributeKey => $attributeValue) { - $pbAttribute = new PushConfigAttributesEntry(); - $pbAttribute->setKey($attributeKey); - $pbAttribute->setValue($attributeValue); - - $pbPushConfig->addAttributes($pbAttribute); - } - } - return $this->send([$this->subscriberApi, 'modifyPushConfig'], [ $this->pluck('subscription', $args), - $pbPushConfig, + $this->buildPushConfig($this->pluck('pushConfig', $args)), $args ]); } @@ -365,4 +321,30 @@ public function testSubscriptionIamPermissions(array $args) $args ]); } + + /** + * @param array $message + * @return array + */ + private function buildMessage(array $message) + { + if (isset($message['attributes'])) { + $message['attributes'] = $this->formatLabelsForApi($message['attributes']); + } + + return (new PubsubMessage())->deserialize($message, $this->codec); + } + + /** + * @param array $pushConfig + * @return array + */ + private function buildPushConfig(array $pushConfig) + { + if (isset($pushConfig['attributes'])) { + $pushConfig['attributes'] = $this->formatLabelsForApi($pushConfig['attributes']); + } + + return (new PushConfig())->deserialize($pushConfig, $this->codec); + } } diff --git a/src/PubSub/PubSubClient.php b/src/PubSub/PubSubClient.php index 99bd864c161..26d3d14355c 100644 --- a/src/PubSub/PubSubClient.php +++ b/src/PubSub/PubSubClient.php @@ -49,7 +49,7 @@ * ``` * * Please take care in installing the same version of these libraries that are - * outlined in the project's composer.json suggest keyword. + * outlined in the project's composer.json require-dev keyword. * * Example: * ``` diff --git a/src/RequestWrapper.php b/src/RequestWrapper.php index 2486e329e9f..3d1309a3d12 100644 --- a/src/RequestWrapper.php +++ b/src/RequestWrapper.php @@ -190,7 +190,7 @@ private function fetchCredentials() throw $this->convertToGoogleException($ex); } - $credentials['expiry'] = time() + $this->credentials['expires_in']; + $credentials['expiry'] = time() + $credentials['expires_in']; return $credentials; } diff --git a/tests/ArrayTraitTest.php b/tests/ArrayTraitTest.php new file mode 100644 index 00000000000..53dc3866791 --- /dev/null +++ b/tests/ArrayTraitTest.php @@ -0,0 +1,96 @@ +implementation = new ArrayTraitStub(); + } + + public function testPluck() + { + $value = '123'; + $key = 'key'; + $array = [$key => $value]; + $actualValue = $this->implementation->call('pluck', [$key, &$array]); + + $this->assertEquals($value, $actualValue); + $this->assertEquals([], $array); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testPluckThrowsExceptionWithInvalidKey() + { + $array = []; + $this->implementation->call('pluck', ['not_here', &$array]); + } + + public function testPluckArray() + { + $keys = ['key1', 'key2']; + $array = [ + 'key1' => 'test', + 'key2' => 'test' + ]; + $expectedArray = $array; + + $actualValues = $this->implementation->call('pluckArray', [$keys, &$array]); + + $this->assertEquals($expectedArray, $actualValues); + $this->assertEquals([], $array); + } + + public function testIsAssocTrue() + { + $actual = $this->implementation->call('isAssoc', [[ + 'test' => 1, + 'test' => 2 + ]]); + + $this->assertTrue($actual); + } + + public function testIsAssocFalse() + { + $actual = $this->implementation->call('isAssoc', [[1, 2, 3]]); + + $this->assertFalse($actual); + } +} + +class ArrayTraitStub +{ + use ArrayTrait; + + public function call($fn, array $args) + { + return call_user_func_array([$this, $fn], $args); + } +} diff --git a/tests/GrpcRequestWrapperTest.php b/tests/GrpcRequestWrapperTest.php index b386a254038..e8dc9014246 100644 --- a/tests/GrpcRequestWrapperTest.php +++ b/tests/GrpcRequestWrapperTest.php @@ -169,6 +169,7 @@ public function exceptionProvider() [3, Exception\BadRequestException::class], [5, Exception\NotFoundException::class], [6, Exception\ConflictException::class], + [2, Exception\ServerException::class], [13, Exception\ServerException::class], [15, Exception\ServiceException::class] ]; diff --git a/tests/GrpcTraitTest.php b/tests/GrpcTraitTest.php index 35593229cfe..ce1194ef62a 100644 --- a/tests/GrpcTraitTest.php +++ b/tests/GrpcTraitTest.php @@ -17,8 +17,12 @@ namespace Google\Cloud\Tests; +use Google\Auth\Cache\MemoryCacheItemPool; +use Google\Auth\FetchAuthTokenCache; +use Google\Auth\FetchAuthTokenInterface; use Google\Cloud\GrpcRequestWrapper; use Google\Cloud\GrpcTrait; +use Google\Cloud\ServiceBuilder; use Prophecy\Argument; /** @@ -35,7 +39,7 @@ public function setUp() $this->markTestSkipped('Must have the grpc extension installed to run this test.'); } - $this->implementation = $this->getObjectForTrait(GrpcTrait::class); + $this->implementation = new GrpcTraitStub(); $this->requestWrapper = $this->prophesize(GrpcRequestWrapper::class); } @@ -59,23 +63,152 @@ public function testSendsRequest() $this->assertEquals($message, $actualResponse); } - public function testPluck() + public function testGetsGaxConfig() { - $value = '123'; - $key = 'key'; - $array = [$key => $value]; - $actualValue = $this->implementation->pluck($key, $array); + $fetcher = $this->prophesize(FetchAuthTokenInterface::class)->reveal(); + $this->requestWrapper->getCredentialsFetcher()->willReturn($fetcher); + $this->implementation->setRequestWrapper($this->requestWrapper->reveal()); + $expected = [ + 'credentialsLoader' => new FetchAuthTokenCache( + $fetcher, + null, + new MemoryCacheItemPool() + ), + 'enableCaching' => false, + 'appName' => 'gcloud-php', + 'version' => ServiceBuilder::VERSION + ]; + + $this->assertEquals($expected, $this->implementation->call('getGaxConfig')); + } + + public function testFormatsTimestamp() + { + $timestamp = [ + 'seconds' => '1471242909', + 'nanos' => '1' + ]; + + $this->assertEquals('2016-08-15T06:35:09.1Z', $this->implementation->call('formatTimestampFromApi', [$timestamp])); + } - $this->assertEquals($value, $actualValue); - $this->assertEquals([], $array); + public function testFormatsLabels() + { + $labels = ['test' => 'label']; + $expected = [ + [ + 'key' => key($labels), + 'value' => current($labels) + ] + ]; + + $this->assertEquals($expected, $this->implementation->call('formatLabelsForApi', [$labels])); + } + + public function testFormatsStruct() + { + $value = 'test'; + $struct = [ + $value => [ + $value => $value + ] + ]; + + $expected = [ + 'fields' => [ + [ + 'key' => $value, + 'value' => [ + 'struct_value' => [ + 'fields' => [ + [ + 'key' => $value, + 'value' => [ + 'string_value' => $value + ] + ] + ] + ] + ] + ] + ] + ]; + + $this->assertEquals($expected, $this->implementation->call('formatStructForApi', [$struct])); + } + + public function testFormatsList() + { + $value = 'test'; + $list = [ + $value, + $value + ]; + $expected = [ + 'values' => [ + [ + 'string_value' => $value, + ], + [ + 'string_value' => $value + ] + ] + ]; + + $this->assertEquals($expected, $this->implementation->call('formatListForApi', [$list])); } /** - * @expectedException \InvalidArgumentException + * @dataProvider valueProvider */ - public function testPluckThrowsExceptionWithInvalidKey() + public function testFormatsValue($value, $expected) + { + $this->assertEquals($expected, $this->implementation->call('formatValueForApi', [$value])); + } + + public function valueProvider() + { + return [ + ['string', ['string_value' => 'string']], + [true, ['bool_value' => true]], + [1, ['number_value' => 1]], + [ + ['1'], + [ + 'list_value' => [ + 'values' => [ + [ + 'string_value' => '1' + ] + ] + ] + ] + ], + [ + ['test' => 'test'], + [ + 'struct_value' => [ + 'fields' => [ + [ + 'key' => 'test', + 'value' => [ + 'string_value' => 'test' + ] + ] + ] + ] + ] + ] + ]; + } +} + +class GrpcTraitStub +{ + use GrpcTrait; + + public function call($fn, array $args = []) { - $array = []; - $actualValue = $this->implementation->pluck('not_here', $array); + return call_user_func_array([$this, $fn], $args); } } diff --git a/tests/Logging/Connection/GrpcTest.php b/tests/Logging/Connection/GrpcTest.php new file mode 100644 index 00000000000..a037e7529b6 --- /dev/null +++ b/tests/Logging/Connection/GrpcTest.php @@ -0,0 +1,195 @@ +markTestSkipped('Must have the grpc extension installed to run this test.'); + } + + $this->requestWrapper = $this->prophesize(GrpcRequestWrapper::class); + $this->successMessage = 'success'; + } + + /** + * @dataProvider methodProvider + */ + public function testCallBasicMethods($method, $args, $expectedArgs) + { + $this->requestWrapper->send( + Argument::type('callable'), + $expectedArgs, + Argument::type('array') + )->willReturn($this->successMessage); + + $grpc = new Grpc(); + $grpc->setRequestWrapper($this->requestWrapper->reveal()); + + $this->assertEquals($this->successMessage, $grpc->$method($args)); + } + + public function methodProvider() + { + $value = 'value'; + $entryData = [ + 'logName' => $value, + 'resource' => [ + 'type' => $value, + 'labels' => [ + [ + 'key' => $value, + 'value' => $value + ] + ] + ], + 'jsonPayload' => [ + 'fields' => [ + 'key' => $value, + 'value' => [ + 'string_value' => $value + ] + ] + ], + 'labels' => [ + [ + 'key' => $value, + 'value' => $value + ] + ] + ]; + $sinkData = [ + 'name' => $value, + 'destination' => $value, + 'filter' => $value, + 'outputVersionFormat' => 'V2' + ]; + $metricData = [ + 'name' => $value, + 'description' => $value, + 'filter' => $value + ]; + $pbEntry = (new LogEntry())->deserialize($entryData, new PhpArray()); + $pbSink = (new LogSink())->deserialize(['outputVersionFormat' => 1] + $sinkData, new PhpArray()); + $pbMetric = (new LogMetric())->deserialize($metricData, new PhpArray()); + $projectIds = ['id']; + $pageSizeSetting = ['pageSize' => 2]; + + return [ + [ + 'writeEntries', + [ + 'entries' => [ + [ + 'logName' => $value, + 'resource' => [ + 'type' => $value, + 'labels' => [ + $value => $value + ] + ], + 'jsonPayload' => [ + $value => $value + ], + 'labels' => [ + $value => $value + ] + ] + ] + ], + [[$pbEntry], []] + ], + [ + 'listEntries', + ['projectIds' => $projectIds], + [$projectIds, []] + ], + [ + 'createSink', + ['parent' => $value] + $sinkData, + [$value, $pbSink, []] + ], + [ + 'getSink', + ['sinkName' => $value], + [$value, []] + ], + [ + 'listSinks', + ['parent' => $value] + $pageSizeSetting, + [$value, $pageSizeSetting] + ], + [ + 'updateSink', + ['sinkName' => $value] + $sinkData, + [$value, $pbSink, []] + ], + [ + 'deleteSink', + ['sinkName' => $value], + [$value, []] + ], + [ + 'createMetric', + ['parent' => $value] + $metricData, + [$value, $pbMetric, []] + ], + [ + 'getMetric', + ['metricName' => $value], + [$value, []] + ], + [ + 'listMetrics', + ['parent' => $value] + $pageSizeSetting, + [$value, $pageSizeSetting] + ], + [ + 'updateMetric', + ['metricName' => $value] + $metricData, + [$value, $pbMetric, []] + ], + [ + 'deleteMetric', + ['metricName' => $value], + [$value, []] + ], + [ + 'deleteLog', + ['logName' => $value], + [$value, []] + ] + ]; + } +} diff --git a/tests/Logging/LoggingClientTest.php b/tests/Logging/LoggingClientTest.php index dee79f035cf..deb206549ef 100644 --- a/tests/Logging/LoggingClientTest.php +++ b/tests/Logging/LoggingClientTest.php @@ -49,9 +49,10 @@ public function testCreatesSink() { $destination = 'storage.googleapis.com/my-bucket'; $this->connection->createSink([ - 'projectName' => $this->formattedProjectId, + 'parent' => $this->formattedProjectId, 'name' => $this->sinkName, - 'destination' => $destination + 'destination' => $destination, + 'outputVersionFormat' => 'VERSION_FORMAT_UNSPECIFIED' ]) ->willReturn([ 'name' => $this->sinkName, @@ -128,7 +129,7 @@ public function testCreatesMetric() { $filter = 'logName = myLog'; $this->connection->createMetric([ - 'projectName' => $this->formattedProjectId, + 'parent' => $this->formattedProjectId, 'name' => $this->metricName, 'filter' => $filter ]) diff --git a/tests/Logging/PsrLoggerTest.php b/tests/Logging/PsrLoggerTest.php index 191ad9a806a..7fec2679538 100644 --- a/tests/Logging/PsrLoggerTest.php +++ b/tests/Logging/PsrLoggerTest.php @@ -56,7 +56,7 @@ public function testWritesEntryWithDefinedLevels($level) $this->connection->writeEntries([ 'entries' => [ [ - 'severity' => $level, + 'severity' => array_flip(Logger::getLogLevelMap())[$level], 'textPayload' => $this->textPayload, 'logName' => $this->formattedName, 'resource' => $this->resource diff --git a/tests/PhpArrayTest.php b/tests/PhpArrayTest.php index 0a8b5b05de4..4df80c57192 100644 --- a/tests/PhpArrayTest.php +++ b/tests/PhpArrayTest.php @@ -26,62 +26,146 @@ */ class PhpArrayTest extends \PHPUnit_Framework_TestCase { - private $phpArray; - - public function setUp() + private function getCodec($customFilters = []) { - $this->phpArray = new PhpArray(); + return new PhpArray($customFilters); } - public function testProperlyTransformsKeys() + /** + * @expectedException \UnexpectedValueException + */ + public function testThrowsExceptionWithoutRequiredField() { - $value = 'testing123'; $message = new TestMessage(); - $message->setTestField($value); - $serializedMessage = $message->serialize(new PhpArray()); + $serializedMessage = $message->serialize($this->getCodec()); + } - $this->assertEquals(['testField' => $value], $serializedMessage); + public function testProperlyHandlesMessage() + { + $value = 'test'; + $message = new TestMessage(); + $message = $message->deserialize([ + 'testStruct' => [ + 'fields' => [ + 'key' => $value, + 'value' => [ + 'list_value' => [ + 'values' => [ + 'string_value' => $value + ] + ] + ] + ] + ], + 'testLabels' => [ + [ + 'key' => strtoupper($value), + 'value' => strtoupper($value) + ], + [ + 'key' => $value, + 'value' => $value + ] + ], + 'testStrings' => [ + $value, + $value + ] + ], $this->getCodec()); + $serializedMessage = $message->serialize($this->getCodec()); + + $expected = [ + 'testStruct' => [ + $value => [ + $value + ] + ], + 'testLabels' => [ + strtoupper($value) => strtoupper($value), + $value => $value + ], + 'testStrings' => [ + $value, + $value + ] + ]; + + $this->assertEquals($expected, $serializedMessage); } } class TestMessage extends Message { - public $test_field = null; + public $test_struct = null; + public $test_labels = []; + public $test_stings = []; protected static $__extensions = array(); public static function descriptor() { - $descriptor = new \DrSlump\Protobuf\Descriptor(__CLASS__, 'Google.Cloud.Tests.TestMessage'); - - $f = new \DrSlump\Protobuf\Field(); - $f->number = 1; - $f->name = "test_field"; - $f->type = \DrSlump\Protobuf::TYPE_STRING; - $f->rule = \DrSlump\Protobuf::RULE_OPTIONAL; - $descriptor->addField($f); - - - foreach (self::$__extensions as $cb) { - $descriptor->addField($cb(), true); - } - - return $descriptor; + $descriptor = new \DrSlump\Protobuf\Descriptor(__CLASS__, 'Google.Cloud.Tests.TestMessage'); + + $f = new \DrSlump\Protobuf\Field(); + $f->number = 1; + $f->name = "test_struct"; + $f->type = \DrSlump\Protobuf::TYPE_MESSAGE; + $f->rule = \DrSlump\Protobuf::RULE_REQUIRED; + $f->reference = '\google\protobuf\Struct'; + $descriptor->addField($f); + + $f = new \DrSlump\Protobuf\Field(); + $f->number = 2; + $f->name = "test_labels"; + $f->type = \DrSlump\Protobuf::TYPE_MESSAGE; + $f->rule = \DrSlump\Protobuf::RULE_REPEATED; + $f->reference = '\Google\Cloud\Tests\TestLabelsEntry'; + $descriptor->addField($f); + + $f = new \DrSlump\Protobuf\Field(); + $f->number = 3; + $f->name = "test_strings"; + $f->type = \DrSlump\Protobuf::TYPE_STRING; + $f->rule = \DrSlump\Protobuf::RULE_REPEATED; + $descriptor->addField($f); + + return $descriptor; } +} - public function hasTestField(){ - return $this->_has(1); - } +class TestLabelsEntry extends Message +{ + public $key = null; + public $value = null; - public function clearTestField(){ - return $this->_clear(1); + protected static $__extensions = array(); + + public static function descriptor() + { + $descriptor = new \DrSlump\Protobuf\Descriptor(__CLASS__, 'Google.Cloud.Tests.TestLabelsEntry'); + + $f = new \DrSlump\Protobuf\Field(); + $f->number = 1; + $f->name = "key"; + $f->type = \DrSlump\Protobuf::TYPE_STRING; + $f->rule = \DrSlump\Protobuf::RULE_OPTIONAL; + $descriptor->addField($f); + + $f = new \DrSlump\Protobuf\Field(); + $f->number = 2; + $f->name = "value"; + $f->type = \DrSlump\Protobuf::TYPE_STRING; + $f->rule = \DrSlump\Protobuf::RULE_OPTIONAL; + $descriptor->addField($f); + + return $descriptor; } - public function getTestField(){ - return $this->_get(1); + public function getKey(){ + return $this->_get(1); } - public function setTestField( $value){ - return $this->_set(1, $value); + public function getValue(){ + return $this->_get(2); } } diff --git a/tests/PubSub/Connection/GrpcTest.php b/tests/PubSub/Connection/GrpcTest.php index 4c0dd2edc0c..08f1866f46c 100644 --- a/tests/PubSub/Connection/GrpcTest.php +++ b/tests/PubSub/Connection/GrpcTest.php @@ -32,8 +32,6 @@ class GrpcTest extends \PHPUnit_Framework_TestCase { private $requestWrapper; private $successMessage; - private $publisherApi; - private $subscriberApi; public function setUp() {