Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1206)

Unified Diff: third_party/google-endpoints/google/api/control/operation.py

Issue 2666783008: Add google-endpoints to third_party/. (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/google-endpoints/google/api/control/operation.py
diff --git a/third_party/google-endpoints/google/api/control/operation.py b/third_party/google-endpoints/google/api/control/operation.py
new file mode 100644
index 0000000000000000000000000000000000000000..a3c25fea0377e99f64e0b4eb71d3efeb7b55f549
--- /dev/null
+++ b/third_party/google-endpoints/google/api/control/operation.py
@@ -0,0 +1,200 @@
+# 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.
+
+"""operation provides support for working with `Operation` instances.
+
+:class:`~google.api.gen.servicecontrol_v1_message.Operation` represents
+information regarding an operation, and is a key constituent of
+:class:`~google.api.gen.servicecontrol_v1_message.CheckRequest` and
+:class:`~google.api.gen.servicecontrol_v1_message.ReportRequests.
+
+The :class:`.Aggregator` support this.
+
+"""
+
+from __future__ import absolute_import
+
+import collections
+import logging
+from datetime import datetime
+
+from apitools.base.py import encoding
+
+from . import messages, metric_value, timestamp, MetricKind
+
+logger = logging.getLogger(__name__)
+
+
+class Info(
+ collections.namedtuple(
+ 'Info', [
+ 'api_key',
+ 'api_key_valid',
+ 'consumer_project_id',
+ 'operation_id',
+ 'operation_name',
+ 'referer',
+ 'service_name',
+ ])):
+ """Holds basic information about an api call.
+
+ This class is one of several used to mediate between the raw service
+ control api surface and python frameworks. Client code can construct
+ operations using this surface
+
+ Attributes:
+ api_key (string): the api key
+ api_key_valid (bool): it the request has a valid api key. By default
+ it is true, it will only be set to false if the api key cannot
+ be validated by the service controller
+ consumer_project_id (string): the project id of the api consumer
+ operation_id (string): identity of the operation, which must be unique
+ within the scope of the service. Calls to report and check on the
+ same operation should carry the same operation id
+ operation_name (string): the fully-qualified name of the operation
+ referer (string): the referer header, or if not present the origin
+ service_name(string): the name of service
+
+ """
+ # pylint: disable=too-many-arguments
+
+ def __new__(cls,
+ api_key='',
+ api_key_valid=False,
+ consumer_project_id='',
+ operation_id='',
+ operation_name='',
+ referer='',
+ service_name=''):
+ """Invokes the base constructor with default values."""
+ return super(cls, Info).__new__(
+ cls,
+ api_key,
+ api_key_valid,
+ consumer_project_id,
+ operation_id,
+ operation_name,
+ referer,
+ service_name)
+
+ def as_operation(self, timer=datetime.utcnow):
+ """Makes an ``Operation`` from this instance.
+
+ Returns:
+ an ``Operation``
+
+ """
+ now = timer()
+ op = messages.Operation(
+ endTime=timestamp.to_rfc3339(now),
+ startTime=timestamp.to_rfc3339(now),
+ importance=messages.Operation.ImportanceValueValuesEnum.LOW)
+ if self.operation_id:
+ op.operationId = self.operation_id
+ if self.operation_name:
+ op.operationName = self.operation_name
+ if self.api_key and self.api_key_valid:
+ op.consumerId = 'api_key:' + self.api_key
+ elif self.consumer_project_id:
+ op.consumerId = 'project:' + self.consumer_project_id
+ return op
+
+
+class Aggregator(object):
+ """Container that implements operation aggregation.
+
+ Thread compatible.
+ """
+ DEFAULT_KIND = MetricKind.DELTA
+ """Used when kinds are not specified, or are missing a metric name"""
+
+ def __init__(self, initial_op, kinds=None):
+ """Constructor.
+
+ If kinds is not specifed, all operations will be merged assuming
+ they are of Kind ``DEFAULT_KIND``
+
+ Args:
+ initial_op (
+ :class:`google.api.gen.servicecontrol_v1_messages.Operation`): the
+ initial version of the operation
+ kinds (dict[string,[string]]): specifies the metric kind for
+ each metric name
+
+ """
+ assert isinstance(initial_op, messages.Operation)
+ if kinds is None:
+ kinds = {}
+ self._kinds = kinds
+ self._metric_values_by_name_then_sign = collections.defaultdict(dict)
+ our_op = encoding.CopyProtoMessage(initial_op)
+ self._merge_metric_values(our_op)
+ our_op.metricValueSets = []
+ self._op = our_op
+
+ def as_operation(self):
+ """Obtains a single `Operation` representing this instances contents.
+
+ Returns:
+ :class:`google.api.gen.servicecontrol_v1_messages.Operation`
+ """
+ result = encoding.CopyProtoMessage(self._op)
+ names = sorted(self._metric_values_by_name_then_sign.keys())
+ for name in names:
+ mvs = self._metric_values_by_name_then_sign[name]
+ result.metricValueSets.append(
+ messages.MetricValueSet(
+ metricName=name, metricValues=mvs.values()))
+ return result
+
+ def add(self, other_op):
+ """Combines `other_op` with the operation held by this aggregator.
+
+ N.B. It merges the operations log entries and metric values, but makes
+ the assumption the operation is consistent. It's the callers
+ responsibility to ensure consistency
+
+ Args:
+ other_op (
+ class:`google.api.gen.servicecontrol_v1_messages.Operation`):
+ an operation merge into this one
+
+ """
+ self._op.logEntries.extend(other_op.logEntries)
+ self._merge_timestamps(other_op)
+ self._merge_metric_values(other_op)
+
+ def _merge_metric_values(self, other_op):
+ for value_set in other_op.metricValueSets:
+ name = value_set.metricName
+ kind = self._kinds.get(name, self.DEFAULT_KIND)
+ by_signature = self._metric_values_by_name_then_sign[name]
+ for mv in value_set.metricValues:
+ signature = metric_value.sign(mv)
+ prior = by_signature.get(signature)
+ if prior is not None:
+ metric_value.merge(kind, prior, mv)
+ by_signature[signature] = mv
+
+ def _merge_timestamps(self, other_op):
+ # Update the start time and end time in self._op as needed
+ if (other_op.startTime and
+ (self._op.startTime is None or
+ timestamp.compare(other_op.startTime, self._op.startTime) == -1)):
+ self._op.startTime = other_op.startTime
+
+ if (other_op.endTime and
+ (self._op.endTime is None or timestamp.compare(
+ self._op.endTime, other_op.endTime) == -1)):
+ self._op.endTime = other_op.endTime

Powered by Google App Engine
This is Rietveld 408576698