Vehicle-Anti-Theft-Face-Rec.../venv/Lib/site-packages/gcloud/logging/_gax.py

575 lines
20 KiB
Python

# Copyright 2016 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""GAX wrapper for Logging API requests."""
import json
# pylint: disable=import-error
from google.gax import CallOptions
from google.gax import INITIAL_PAGE
from google.gax.errors import GaxError
from google.gax.grpc import exc_to_code
from google.logging.type.log_severity_pb2 import LogSeverity
from google.logging.v2.logging_config_pb2 import LogSink
from google.logging.v2.logging_metrics_pb2 import LogMetric
from google.logging.v2.log_entry_pb2 import LogEntry
from google.protobuf.json_format import Parse
from grpc.beta.interfaces import StatusCode
# pylint: enable=import-error
from gcloud.exceptions import Conflict
from gcloud.exceptions import NotFound
from gcloud._helpers import _datetime_to_pb_timestamp
from gcloud._helpers import _datetime_to_rfc3339
from gcloud._helpers import _pb_timestamp_to_datetime
class _LoggingAPI(object):
"""Helper mapping logging-related APIs.
:type gax_api:
:class:`google.logging.v2.logging_service_v2_api.LoggingServiceV2Api`
:param gax_api: API object used to make GAX requests.
"""
def __init__(self, gax_api):
self._gax_api = gax_api
def list_entries(self, projects, filter_='', order_by='',
page_size=0, page_token=None):
"""Return a page of log entry resources.
:type projects: list of strings
:param projects: project IDs to include. If not passed,
defaults to the project bound to the API's client.
:type filter_: str
:param filter_: a filter expression. See:
https://cloud.google.com/logging/docs/view/advanced_filters
:type order_by: str
:param order_by: One of :data:`gcloud.logging.ASCENDING` or
:data:`gcloud.logging.DESCENDING`.
:type page_size: int
:param page_size: maximum number of entries to return, If not passed,
defaults to a value set by the API.
:type page_token: str
:param page_token: opaque marker for the next "page" of entries. If not
passed, the API will return the first page of
entries.
:rtype: tuple, (list, str)
:returns: list of mappings, plus a "next page token" string:
if not None, indicates that more entries can be retrieved
with another call (pass that value as ``page_token``).
"""
options = _build_paging_options(page_token)
page_iter = self._gax_api.list_log_entries(
projects, filter_, order_by, page_size, options)
entries = [_log_entry_pb_to_mapping(entry_pb)
for entry_pb in page_iter.next()]
token = page_iter.page_token or None
return entries, token
def write_entries(self, entries, logger_name=None, resource=None,
labels=None):
"""API call: log an entry resource via a POST request
:type entries: sequence of mapping
:param entries: the log entry resources to log.
:type logger_name: string
:param logger_name: name of default logger to which to log the entries;
individual entries may override.
:type resource: mapping
:param resource: default resource to associate with entries;
individual entries may override.
:type labels: mapping
:param labels: default labels to associate with entries;
individual entries may override.
"""
options = None
partial_success = False
entry_pbs = [_log_entry_mapping_to_pb(entry) for entry in entries]
self._gax_api.write_log_entries(entry_pbs, logger_name, resource,
labels, partial_success, options)
def logger_delete(self, project, logger_name):
"""API call: delete all entries in a logger via a DELETE request
:type project: string
:param project: ID of project containing the log entries to delete
:type logger_name: string
:param logger_name: name of logger containing the log entries to delete
"""
options = None
path = 'projects/%s/logs/%s' % (project, logger_name)
self._gax_api.delete_log(path, options)
class _SinksAPI(object):
"""Helper mapping sink-related APIs.
:type gax_api:
:class:`google.logging.v2.config_service_v2_api.ConfigServiceV2Api`
:param gax_api: API object used to make GAX requests.
"""
def __init__(self, gax_api):
self._gax_api = gax_api
def list_sinks(self, project, page_size=0, page_token=None):
"""List sinks for the project associated with this client.
:type project: string
:param project: ID of the project whose sinks are to be listed.
:type page_size: int
:param page_size: maximum number of sinks to return, If not passed,
defaults to a value set by the API.
:type page_token: str
:param page_token: opaque marker for the next "page" of sinks. If not
passed, the API will return the first page of
sinks.
:rtype: tuple, (list, str)
:returns: list of mappings, plus a "next page token" string:
if not None, indicates that more sinks can be retrieved
with another call (pass that value as ``page_token``).
"""
options = _build_paging_options(page_token)
page_iter = self._gax_api.list_sinks(project, page_size, options)
sinks = [_log_sink_pb_to_mapping(log_sink_pb)
for log_sink_pb in page_iter.next()]
token = page_iter.page_token or None
return sinks, token
def sink_create(self, project, sink_name, filter_, destination):
"""API call: create a sink resource.
See:
https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/projects.sinks/create
:type project: string
:param project: ID of the project in which to create the sink.
:type sink_name: string
:param sink_name: the name of the sink
:type filter_: string
:param filter_: the advanced logs filter expression defining the
entries exported by the sink.
:type destination: string
:param destination: destination URI for the entries exported by
the sink.
"""
options = None
parent = 'projects/%s' % (project,)
sink_pb = LogSink(name=sink_name, filter=filter_,
destination=destination)
try:
self._gax_api.create_sink(parent, sink_pb, options)
except GaxError as exc:
if exc_to_code(exc.cause) == StatusCode.FAILED_PRECONDITION:
path = 'projects/%s/sinks/%s' % (project, sink_name)
raise Conflict(path)
raise
def sink_get(self, project, sink_name):
"""API call: retrieve a sink resource.
:type project: string
:param project: ID of the project containing the sink.
:type sink_name: string
:param sink_name: the name of the sink
"""
options = None
path = 'projects/%s/sinks/%s' % (project, sink_name)
try:
sink_pb = self._gax_api.get_sink(path, options)
except GaxError as exc:
if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
raise NotFound(path)
raise
return _log_sink_pb_to_mapping(sink_pb)
def sink_update(self, project, sink_name, filter_, destination):
"""API call: update a sink resource.
:type project: string
:param project: ID of the project containing the sink.
:type sink_name: string
:param sink_name: the name of the sink
:type filter_: string
:param filter_: the advanced logs filter expression defining the
entries exported by the sink.
:type destination: string
:param destination: destination URI for the entries exported by
the sink.
"""
options = None
path = 'projects/%s/sinks/%s' % (project, sink_name)
sink_pb = LogSink(name=path, filter=filter_, destination=destination)
try:
self._gax_api.update_sink(path, sink_pb, options)
except GaxError as exc:
if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
raise NotFound(path)
raise
return _log_sink_pb_to_mapping(sink_pb)
def sink_delete(self, project, sink_name):
"""API call: delete a sink resource.
:type project: string
:param project: ID of the project containing the sink.
:type sink_name: string
:param sink_name: the name of the sink
"""
options = None
path = 'projects/%s/sinks/%s' % (project, sink_name)
try:
self._gax_api.delete_sink(path, options)
except GaxError as exc:
if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
raise NotFound(path)
raise
class _MetricsAPI(object):
"""Helper mapping sink-related APIs.
:type gax_api:
:class:`google.logging.v2.metrics_service_v2_api.MetricsServiceV2Api`
:param gax_api: API object used to make GAX requests.
"""
def __init__(self, gax_api):
self._gax_api = gax_api
def list_metrics(self, project, page_size=0, page_token=None):
"""List metrics for the project associated with this client.
:type project: string
:param project: ID of the project whose metrics are to be listed.
:type page_size: int
:param page_size: maximum number of metrics to return, If not passed,
defaults to a value set by the API.
:type page_token: str
:param page_token: opaque marker for the next "page" of metrics. If not
passed, the API will return the first page of
metrics.
:rtype: tuple, (list, str)
:returns: list of mappings, plus a "next page token" string:
if not None, indicates that more metrics can be retrieved
with another call (pass that value as ``page_token``).
"""
options = _build_paging_options(page_token)
page_iter = self._gax_api.list_log_metrics(project, page_size, options)
metrics = [_log_metric_pb_to_mapping(log_metric_pb)
for log_metric_pb in page_iter.next()]
token = page_iter.page_token or None
return metrics, token
def metric_create(self, project, metric_name, filter_, description):
"""API call: create a metric resource.
See:
https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/projects.metrics/create
:type project: string
:param project: ID of the project in which to create the metric.
:type metric_name: string
:param metric_name: the name of the metric
:type filter_: string
:param filter_: the advanced logs filter expression defining the
entries exported by the metric.
:type description: string
:param description: description of the metric.
"""
options = None
parent = 'projects/%s' % (project,)
metric_pb = LogMetric(name=metric_name, filter=filter_,
description=description)
try:
self._gax_api.create_log_metric(parent, metric_pb, options)
except GaxError as exc:
if exc_to_code(exc.cause) == StatusCode.FAILED_PRECONDITION:
path = 'projects/%s/metrics/%s' % (project, metric_name)
raise Conflict(path)
raise
def metric_get(self, project, metric_name):
"""API call: retrieve a metric resource.
:type project: string
:param project: ID of the project containing the metric.
:type metric_name: string
:param metric_name: the name of the metric
"""
options = None
path = 'projects/%s/metrics/%s' % (project, metric_name)
try:
metric_pb = self._gax_api.get_log_metric(path, options)
except GaxError as exc:
if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
raise NotFound(path)
raise
return _log_metric_pb_to_mapping(metric_pb)
def metric_update(self, project, metric_name, filter_, description):
"""API call: update a metric resource.
:type project: string
:param project: ID of the project containing the metric.
:type metric_name: string
:param metric_name: the name of the metric
:type filter_: string
:param filter_: the advanced logs filter expression defining the
entries exported by the metric.
:type description: string
:param description: description of the metric.
"""
options = None
path = 'projects/%s/metrics/%s' % (project, metric_name)
metric_pb = LogMetric(name=path, filter=filter_,
description=description)
try:
self._gax_api.update_log_metric(path, metric_pb, options)
except GaxError as exc:
if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
raise NotFound(path)
raise
return _log_metric_pb_to_mapping(metric_pb)
def metric_delete(self, project, metric_name):
"""API call: delete a metric resource.
:type project: string
:param project: ID of the project containing the metric.
:type metric_name: string
:param metric_name: the name of the metric
"""
options = None
path = 'projects/%s/metrics/%s' % (project, metric_name)
try:
self._gax_api.delete_log_metric(path, options)
except GaxError as exc:
if exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
raise NotFound(path)
raise
def _build_paging_options(page_token=None):
"""Helper for :meth:'_PublisherAPI.list_topics' et aliae."""
if page_token is None:
page_token = INITIAL_PAGE
options = {'page_token': page_token}
return CallOptions(**options)
def _mon_resource_pb_to_mapping(resource_pb):
"""Helper for :func:_log_entry_pb_to_mapping"""
mapping = {
'type': resource_pb.type,
}
if resource_pb.labels:
mapping['labels'] = resource_pb.labels
return mapping
def _pb_timestamp_to_rfc3339(timestamp_pb):
"""Helper for :func:_log_entry_pb_to_mapping"""
timestamp = _pb_timestamp_to_datetime(timestamp_pb)
return _datetime_to_rfc3339(timestamp)
def _log_entry_pb_to_mapping(entry_pb):
"""Helper for :meth:`list_entries`, et aliae
Ideally, would use a function from :mod:`protobuf.json_format`, but
the right one isn't public. See:
https://github.com/google/protobuf/issues/1351
"""
mapping = {
'logName': entry_pb.log_name,
'resource': _mon_resource_pb_to_mapping(entry_pb.resource),
'severity': entry_pb.severity,
'insertId': entry_pb.insert_id,
'timestamp': _pb_timestamp_to_rfc3339(entry_pb.timestamp),
'labels': entry_pb.labels,
'textPayload': entry_pb.text_payload,
'jsonPayload': entry_pb.json_payload,
'protoPayload': entry_pb.proto_payload,
}
if entry_pb.http_request:
request = entry_pb.http_request
mapping['httpRequest'] = {
'request_method': request.request_method,
'request_url': request.request_url,
'status': request.status,
'referer': request.referer,
'user_agent': request.user_agent,
'cache_hit': request.cache_hit,
'request_size': request.request_size,
'response_size': request.response_size,
'remote_ip': request.remote_ip,
}
if entry_pb.operation:
operation = entry_pb.operation
mapping['operation'] = {
'producer': operation.producer,
'id': operation.id,
'first': operation.first,
'last': operation.last,
}
return mapping
def _http_request_mapping_to_pb(info, request):
"""Helper for _log_entry_mapping_to_pb"""
optional_request_keys = {
'requestMethod': 'request_method',
'requestUrl': 'request_url',
'status': 'status',
'referer': 'referer',
'userAgent': 'user_agent',
'cacheHit': 'cache_hit',
'requestSize': 'request_size',
'responseSize': 'response_size',
'remoteIp': 'remote_ip',
}
for key, pb_name in optional_request_keys.items():
if key in info:
setattr(request, pb_name, info[key])
def _log_operation_mapping_to_pb(info, operation):
"""Helper for _log_entry_mapping_to_pb"""
operation.producer = info['producer']
operation.id = info['id']
if 'first' in info:
operation.first = info['first']
if 'last' in info:
operation.last = info['last']
def _log_entry_mapping_to_pb(mapping):
"""Helper for :meth:`write_entries`, et aliae
Ideally, would use a function from :mod:`protobuf.json_format`, but
the right one isn't public. See:
https://github.com/google/protobuf/issues/1351
"""
# pylint: disable=too-many-branches
entry_pb = LogEntry()
optional_scalar_keys = {
'logName': 'log_name',
'insertId': 'insert_id',
'textPayload': 'text_payload',
}
for key, pb_name in optional_scalar_keys.items():
if key in mapping:
setattr(entry_pb, pb_name, mapping[key])
if 'resource' in mapping:
entry_pb.resource.type = mapping['resource']['type']
if 'severity' in mapping:
severity = mapping['severity']
if isinstance(severity, str):
severity = LogSeverity.Value(severity)
entry_pb.severity = severity
if 'timestamp' in mapping:
timestamp = _datetime_to_pb_timestamp(mapping['timestamp'])
entry_pb.timestamp.CopyFrom(timestamp)
if 'labels' in mapping:
for key, value in mapping['labels'].items():
entry_pb.labels[key] = value
if 'jsonPayload' in mapping:
for key, value in mapping['jsonPayload'].items():
entry_pb.json_payload[key] = value
if 'protoPayload' in mapping:
Parse(json.dumps(mapping['protoPayload']), entry_pb.proto_payload)
if 'httpRequest' in mapping:
_http_request_mapping_to_pb(
mapping['httpRequest'], entry_pb.http_request)
if 'operation' in mapping:
_log_operation_mapping_to_pb(
mapping['operation'], entry_pb.operation)
return entry_pb
# pylint: enable=too-many-branches
def _log_sink_pb_to_mapping(sink_pb):
"""Helper for :meth:`list_sinks`, et aliae
Ideally, would use a function from :mod:`protobuf.json_format`, but
the right one isn't public. See:
https://github.com/google/protobuf/issues/1351
"""
return {
'name': sink_pb.name,
'destination': sink_pb.destination,
'filter': sink_pb.filter,
}
def _log_metric_pb_to_mapping(metric_pb):
"""Helper for :meth:`list_metrics`, et aliae
Ideally, would use a function from :mod:`protobuf.json_format`, but
the right one isn't public. See:
https://github.com/google/protobuf/issues/1351
"""
return {
'name': metric_pb.name,
'description': metric_pb.description,
'filter': metric_pb.filter,
}