OLD | NEW |
(Empty) | |
| 1 # Copyright 2016 Google Inc. All Rights Reserved. |
| 2 # |
| 3 # Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 # you may not use this file except in compliance with the License. |
| 5 # You may obtain a copy of the License at |
| 6 # |
| 7 # http://www.apache.org/licenses/LICENSE-2.0 |
| 8 # |
| 9 # Unless required by applicable law or agreed to in writing, software |
| 10 # distributed under the License is distributed on an "AS IS" BASIS, |
| 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 # See the License for the specific language governing permissions and |
| 13 # limitations under the License. |
| 14 |
| 15 """label_descriptor provides funcs for working with `LabelDescriptor` instances. |
| 16 |
| 17 :class:`KnownLabels` is an :class:`enum.Enum` that defines the list of known |
| 18 `LabelDescriptor` instances. Each enum instance has several fields |
| 19 |
| 20 - label_name: the name used in the label |
| 21 - kind: indicates whether the label is system or user label |
| 22 - value_type: the value type used in the label |
| 23 - update_label_func: a function to update the labels |
| 24 |
| 25 """ |
| 26 |
| 27 from __future__ import absolute_import |
| 28 |
| 29 import base64 |
| 30 from enum import Enum |
| 31 from . import messages, USER_AGENT, SERVICE_AGENT |
| 32 |
| 33 ValueType = messages.LabelDescriptor.ValueTypeValueValuesEnum |
| 34 |
| 35 |
| 36 class Kind(Enum): |
| 37 """Enumerates the known labels.""" |
| 38 # pylint: disable=too-few-public-methods |
| 39 USER = 0 |
| 40 SYSTEM = 1 |
| 41 |
| 42 |
| 43 _CANONICAL_CODES = { |
| 44 200: 0, # OK |
| 45 400: 3, # INVALID_ARGUMENT |
| 46 401: 16, # UNAUTHENTICATED |
| 47 403: 7, # PERMISSION_DENIED |
| 48 404: 5, # NOT_FOUND |
| 49 409: 10, # ABORTED |
| 50 412: 9, # FAILED_PRECONDITION |
| 51 416: 11, # OUT_OF_RANGE |
| 52 429: 8, # RESOURCE_EXHAUSTED |
| 53 499: 1, # CANCELLED |
| 54 500: 13, # INTERNAL, UNKNOWN |
| 55 504: 4, # DEADLINE_EXCEEDED |
| 56 501: 12, # UNIMPLEMENTED |
| 57 503: 14, # UNAVAILABLE |
| 58 } |
| 59 |
| 60 |
| 61 def _canonical_code(http_code): |
| 62 mapped_code = _CANONICAL_CODES.get(http_code, 0) |
| 63 if mapped_code != 0: |
| 64 return mapped_code |
| 65 elif 200 <= http_code < 300: |
| 66 return 0 # OK |
| 67 elif 400 <= http_code < 500: |
| 68 return 9 # failed precondition |
| 69 elif 500 <= http_code < 600: |
| 70 return 13 # internal |
| 71 else: |
| 72 return 2 # unknown |
| 73 |
| 74 |
| 75 def set_credential_id(name, info, labels): |
| 76 # The rule to set /credential_id is: |
| 77 # 1) If api_key is available, set it as apiKey:API-KEY |
| 78 # 2) If auth issuer and audience both are available, set it as: |
| 79 # jwtAuth:issuer=base64(issuer)&audience=base64(audience) |
| 80 if info.api_key: |
| 81 labels[name] = 'apiKey:' + info.api_key |
| 82 elif info.auth_issuer: |
| 83 value = 'jwtAuth:issuer=' + base64.urlsafe_b64encode(info.auth_issuer) |
| 84 if info.auth_audience: |
| 85 value += '&audience=' + base64.urlsafe_b64encode(info.auth_audience) |
| 86 labels[name] = value |
| 87 |
| 88 |
| 89 _ERROR_TYPES = tuple('%dxx' % (x,) for x in range(10)) |
| 90 |
| 91 |
| 92 def set_error_type(name, info, labels): |
| 93 if info.response_code > 0: |
| 94 code = (info.response_code // 100) % 10 |
| 95 if code < len(_ERROR_TYPES): |
| 96 labels[name] = _ERROR_TYPES[code] |
| 97 |
| 98 |
| 99 def set_protocol(name, info, labels): |
| 100 labels[name] = info.protocol.name |
| 101 |
| 102 |
| 103 def set_referer(name, info, labels): |
| 104 if info.referer: |
| 105 labels[name] = info.referer |
| 106 |
| 107 |
| 108 def set_response_code(name, info, labels): |
| 109 labels[name] = '%d' % (info.response_code,) |
| 110 |
| 111 |
| 112 def set_response_code_class(name, info, labels): |
| 113 if info.response_code > 0: |
| 114 code = (info.response_code // 100) % 10 |
| 115 if code < len(_ERROR_TYPES): |
| 116 labels[name] = _ERROR_TYPES[code] |
| 117 |
| 118 |
| 119 def set_status_code(name, info, labels): |
| 120 if info.response_code > 0: |
| 121 labels[name] = '%d' % (_canonical_code(info.response_code),) |
| 122 |
| 123 |
| 124 def set_location(name, info, labels): |
| 125 if info.location: |
| 126 labels[name] = info.location |
| 127 |
| 128 |
| 129 def set_api_method(name, info, labels): |
| 130 if info.api_method: |
| 131 labels[name] = info.api_method |
| 132 |
| 133 |
| 134 def set_api_version(name, info, labels): |
| 135 if info.api_version: |
| 136 labels[name] = info.api_version |
| 137 |
| 138 |
| 139 def set_platform(name, info, labels): |
| 140 labels[name] = info.platform.name |
| 141 |
| 142 |
| 143 def set_service_agent(name, dummy_info, labels): |
| 144 labels[name] = SERVICE_AGENT |
| 145 |
| 146 |
| 147 def set_user_agent(name, dummy_info, labels): |
| 148 labels[name] = USER_AGENT |
| 149 |
| 150 |
| 151 class KnownLabels(Enum): |
| 152 """Enumerates the known labels.""" |
| 153 |
| 154 CREDENTIAL_ID = ( |
| 155 '/credential_id', ValueType.STRING, Kind.USER, set_credential_id) |
| 156 END_USER = ('/end_user', ValueType.STRING, Kind.USER, None) |
| 157 END_USER_COUNTRY = ('/end_user_country', ValueType.STRING, Kind.USER, None) |
| 158 ERROR_TYPE = ('/error_type', ValueType.STRING, Kind.USER, |
| 159 set_error_type) |
| 160 PROTOCOL = ('/protocol', ValueType.STRING, Kind.USER, |
| 161 set_protocol) |
| 162 REFERER = ('/referer', ValueType.STRING, Kind.USER, |
| 163 set_referer) |
| 164 RESPONSE_CODE = ('/response_code', ValueType.STRING, Kind.USER, |
| 165 set_response_code) |
| 166 RESPONSE_CODE_CLASS = ('/response_code_class', ValueType.STRING, Kind.USER, |
| 167 set_response_code_class) |
| 168 STATUS_CODE = ('/status_code', ValueType.STRING, Kind.USER, |
| 169 set_status_code) |
| 170 GAE_CLONE_ID = ( |
| 171 'appengine.googleapis.com/clone_id', ValueType.STRING, Kind.USER, None) |
| 172 GAE_MODULE_ID = ( |
| 173 'appengine.googleapis.com/module_id', ValueType.STRING, Kind.USER, None) |
| 174 GAE_REPLICA_INDEX = ( |
| 175 'appengine.googleapis.com/replica_index', ValueType.STRING, Kind.USER, |
| 176 None) |
| 177 GAE_VERSION_ID = ( |
| 178 'appengine.googleapis.com/version_id', ValueType.STRING, Kind.USER, None
) |
| 179 GCP_LOCATION = ( |
| 180 'cloud.googleapis.com/location', ValueType.STRING, Kind.SYSTEM, |
| 181 set_location) |
| 182 GCP_PROJECT = ( |
| 183 'cloud.googleapis.com/project', ValueType.STRING, Kind.SYSTEM, None) |
| 184 GCP_REGION = ( |
| 185 'cloud.googleapis.com/region', ValueType.STRING, Kind.SYSTEM, None) |
| 186 GCP_RESOURCE_ID = ( |
| 187 'cloud.googleapis.com/resource_id', ValueType.STRING, Kind.USER, None) |
| 188 GCP_RESOURCE_TYPE = ( |
| 189 'cloud.googleapis.com/resource_type', ValueType.STRING, Kind.USER, None) |
| 190 GCP_SERVICE = ( |
| 191 'cloud.googleapis.com/service', ValueType.STRING, Kind.SYSTEM, None) |
| 192 GCP_ZONE = ( |
| 193 'cloud.googleapis.com/zone', ValueType.STRING, Kind.SYSTEM, None) |
| 194 GCP_UID = ( |
| 195 'cloud.googleapis.com/uid', ValueType.STRING, Kind.SYSTEM, None) |
| 196 GCP_API_METHOD = ( |
| 197 'serviceruntime.googleapis.com/api_method', ValueType.STRING, Kind.USER, |
| 198 set_api_method) |
| 199 GCP_API_VERSION = ( |
| 200 'serviceruntime.googleapis.com/api_version', ValueType.STRING, Kind.USER
, |
| 201 set_api_version) |
| 202 SCC_CALLER_IP = ( |
| 203 'servicecontrol.googleapis.com/caller_ip', ValueType.STRING, Kind.SYSTEM
, None) |
| 204 SCC_PLATFORM = ( |
| 205 'servicecontrol.googleapis.com/platform', ValueType.STRING, Kind.SYSTEM, |
| 206 set_platform) |
| 207 SCC_REFERER = ( |
| 208 'servicecontrol.googleapis.com/referer', ValueType.STRING, Kind.SYSTEM,
None) |
| 209 SCC_SERVICE_AGENT = ( |
| 210 'servicecontrol.googleapis.com/service_agent', ValueType.STRING, Kind.SY
STEM, |
| 211 set_service_agent) |
| 212 SCC_USER_AGENT = ( |
| 213 'servicecontrol.googleapis.com/user_agent', ValueType.STRING, Kind.SYSTE
M, |
| 214 set_user_agent) |
| 215 |
| 216 def __init__(self, label_name, value_type, kind, update_label_func): |
| 217 """Constructor. |
| 218 |
| 219 update_label_func is used when updating a label in an `Operation` from a |
| 220 `ReportRequestInfo`. |
| 221 |
| 222 Args: |
| 223 label_name (str): the name of the label descriptor |
| 224 value_type (:class:`ValueType`): the `value type` of the described me
tric |
| 225 kind (:class:`Kind`): the ``kind`` of the described metric |
| 226 update_op_func (function): the func to update an operation |
| 227 |
| 228 """ |
| 229 self.label_name = label_name |
| 230 self.kind = kind |
| 231 self.update_label_func = update_label_func |
| 232 self.value_type = value_type |
| 233 |
| 234 def matches(self, desc): |
| 235 """Determines if a given label descriptor matches this enum instance |
| 236 |
| 237 Args: |
| 238 desc (:class:`google.api.gen.servicecontrol_v1_messages.LabelDescript
or`): the |
| 239 instance to test |
| 240 |
| 241 Return: |
| 242 `True` if desc is supported, otherwise `False` |
| 243 |
| 244 """ |
| 245 desc_value_type = desc.valueType or ValueType.STRING # default not pars
ed |
| 246 return (self.label_name == desc.key and |
| 247 self.value_type == desc_value_type) |
| 248 |
| 249 def do_labels_update(self, info, labels): |
| 250 """Updates a dictionary of labels using the assigned update_op_func |
| 251 |
| 252 Args: |
| 253 info (:class:`google.api.control.report_request.Info`): the |
| 254 info instance to update |
| 255 labels (dict[string[string]]): the labels dictionary |
| 256 |
| 257 Return: |
| 258 `True` if desc is supported, otherwise `False` |
| 259 |
| 260 """ |
| 261 if self.update_label_func: |
| 262 self.update_label_func(self.label_name, info, labels) |
| 263 |
| 264 @classmethod |
| 265 def is_supported(cls, desc): |
| 266 """Determines if the given label descriptor is supported. |
| 267 |
| 268 Args: |
| 269 desc (:class:`google.api.gen.servicecontrol_v1_messages.LabelDescript
or`): the |
| 270 label descriptor to test |
| 271 |
| 272 Return: |
| 273 `True` if desc is supported, otherwise `False` |
| 274 |
| 275 """ |
| 276 for l in cls: |
| 277 if l.matches(desc): |
| 278 return True |
| 279 return False |
OLD | NEW |