1# -*- coding: utf-8 -*-
2# Copyright 2025 Google LLC
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16from collections import OrderedDict
17from http import HTTPStatus
18import json
19import logging as std_logging
20import os
21import re
22from typing import (
23 Dict,
24 Callable,
25 Mapping,
26 MutableMapping,
27 MutableSequence,
28 Optional,
29 Sequence,
30 Tuple,
31 Type,
32 Union,
33 cast,
34)
35import warnings
36
37from google.cloud.errorreporting_v1beta1 import gapic_version as package_version
38
39from google.api_core import client_options as client_options_lib
40from google.api_core import exceptions as core_exceptions
41from google.api_core import gapic_v1
42from google.api_core import retry as retries
43from google.auth import credentials as ga_credentials # type: ignore
44from google.auth.transport import mtls # type: ignore
45from google.auth.transport.grpc import SslCredentials # type: ignore
46from google.auth.exceptions import MutualTLSChannelError # type: ignore
47from google.oauth2 import service_account # type: ignore
48import google.protobuf
49
50try:
51 OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None]
52except AttributeError: # pragma: NO COVER
53 OptionalRetry = Union[retries.Retry, object, None] # type: ignore
54
55try:
56 from google.api_core import client_logging # type: ignore
57
58 CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER
59except ImportError: # pragma: NO COVER
60 CLIENT_LOGGING_SUPPORTED = False
61
62_LOGGER = std_logging.getLogger(__name__)
63
64from google.cloud.errorreporting_v1beta1.types import common
65from google.cloud.errorreporting_v1beta1.types import error_group_service
66from .transports.base import ErrorGroupServiceTransport, DEFAULT_CLIENT_INFO
67from .transports.grpc import ErrorGroupServiceGrpcTransport
68from .transports.grpc_asyncio import ErrorGroupServiceGrpcAsyncIOTransport
69from .transports.rest import ErrorGroupServiceRestTransport
70
71
72class ErrorGroupServiceClientMeta(type):
73 """Metaclass for the ErrorGroupService client.
74
75 This provides class-level methods for building and retrieving
76 support objects (e.g. transport) without polluting the client instance
77 objects.
78 """
79
80 _transport_registry = (
81 OrderedDict()
82 ) # type: Dict[str, Type[ErrorGroupServiceTransport]]
83 _transport_registry["grpc"] = ErrorGroupServiceGrpcTransport
84 _transport_registry["grpc_asyncio"] = ErrorGroupServiceGrpcAsyncIOTransport
85 _transport_registry["rest"] = ErrorGroupServiceRestTransport
86
87 def get_transport_class(
88 cls,
89 label: Optional[str] = None,
90 ) -> Type[ErrorGroupServiceTransport]:
91 """Returns an appropriate transport class.
92
93 Args:
94 label: The name of the desired transport. If none is
95 provided, then the first transport in the registry is used.
96
97 Returns:
98 The transport class to use.
99 """
100 # If a specific transport is requested, return that one.
101 if label:
102 return cls._transport_registry[label]
103
104 # No transport is requested; return the default (that is, the first one
105 # in the dictionary).
106 return next(iter(cls._transport_registry.values()))
107
108
109class ErrorGroupServiceClient(metaclass=ErrorGroupServiceClientMeta):
110 """Service for retrieving and updating individual error groups."""
111
112 @staticmethod
113 def _get_default_mtls_endpoint(api_endpoint):
114 """Converts api endpoint to mTLS endpoint.
115
116 Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to
117 "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively.
118 Args:
119 api_endpoint (Optional[str]): the api endpoint to convert.
120 Returns:
121 str: converted mTLS api endpoint.
122 """
123 if not api_endpoint:
124 return api_endpoint
125
126 mtls_endpoint_re = re.compile(
127 r"(?P<name>[^.]+)(?P<mtls>\.mtls)?(?P<sandbox>\.sandbox)?(?P<googledomain>\.googleapis\.com)?"
128 )
129
130 m = mtls_endpoint_re.match(api_endpoint)
131 name, mtls, sandbox, googledomain = m.groups()
132 if mtls or not googledomain:
133 return api_endpoint
134
135 if sandbox:
136 return api_endpoint.replace(
137 "sandbox.googleapis.com", "mtls.sandbox.googleapis.com"
138 )
139
140 return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com")
141
142 # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead.
143 DEFAULT_ENDPOINT = "clouderrorreporting.googleapis.com"
144 DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore
145 DEFAULT_ENDPOINT
146 )
147
148 _DEFAULT_ENDPOINT_TEMPLATE = "clouderrorreporting.{UNIVERSE_DOMAIN}"
149 _DEFAULT_UNIVERSE = "googleapis.com"
150
151 @staticmethod
152 def _use_client_cert_effective():
153 """Returns whether client certificate should be used for mTLS if the
154 google-auth version supports should_use_client_cert automatic mTLS enablement.
155
156 Alternatively, read from the GOOGLE_API_USE_CLIENT_CERTIFICATE env var.
157
158 Returns:
159 bool: whether client certificate should be used for mTLS
160 Raises:
161 ValueError: (If using a version of google-auth without should_use_client_cert and
162 GOOGLE_API_USE_CLIENT_CERTIFICATE is set to an unexpected value.)
163 """
164 # check if google-auth version supports should_use_client_cert for automatic mTLS enablement
165 if hasattr(mtls, "should_use_client_cert"): # pragma: NO COVER
166 return mtls.should_use_client_cert()
167 else: # pragma: NO COVER
168 # if unsupported, fallback to reading from env var
169 use_client_cert_str = os.getenv(
170 "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"
171 ).lower()
172 if use_client_cert_str not in ("true", "false"):
173 raise ValueError(
174 "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be"
175 " either `true` or `false`"
176 )
177 return use_client_cert_str == "true"
178
179 @classmethod
180 def from_service_account_info(cls, info: dict, *args, **kwargs):
181 """Creates an instance of this client using the provided credentials
182 info.
183
184 Args:
185 info (dict): The service account private key info.
186 args: Additional arguments to pass to the constructor.
187 kwargs: Additional arguments to pass to the constructor.
188
189 Returns:
190 ErrorGroupServiceClient: The constructed client.
191 """
192 credentials = service_account.Credentials.from_service_account_info(info)
193 kwargs["credentials"] = credentials
194 return cls(*args, **kwargs)
195
196 @classmethod
197 def from_service_account_file(cls, filename: str, *args, **kwargs):
198 """Creates an instance of this client using the provided credentials
199 file.
200
201 Args:
202 filename (str): The path to the service account private key json
203 file.
204 args: Additional arguments to pass to the constructor.
205 kwargs: Additional arguments to pass to the constructor.
206
207 Returns:
208 ErrorGroupServiceClient: The constructed client.
209 """
210 credentials = service_account.Credentials.from_service_account_file(filename)
211 kwargs["credentials"] = credentials
212 return cls(*args, **kwargs)
213
214 from_service_account_json = from_service_account_file
215
216 @property
217 def transport(self) -> ErrorGroupServiceTransport:
218 """Returns the transport used by the client instance.
219
220 Returns:
221 ErrorGroupServiceTransport: The transport used by the client
222 instance.
223 """
224 return self._transport
225
226 @staticmethod
227 def error_group_path(
228 project: str,
229 group: str,
230 ) -> str:
231 """Returns a fully-qualified error_group string."""
232 return "projects/{project}/groups/{group}".format(
233 project=project,
234 group=group,
235 )
236
237 @staticmethod
238 def parse_error_group_path(path: str) -> Dict[str, str]:
239 """Parses a error_group path into its component segments."""
240 m = re.match(r"^projects/(?P<project>.+?)/groups/(?P<group>.+?)$", path)
241 return m.groupdict() if m else {}
242
243 @staticmethod
244 def common_billing_account_path(
245 billing_account: str,
246 ) -> str:
247 """Returns a fully-qualified billing_account string."""
248 return "billingAccounts/{billing_account}".format(
249 billing_account=billing_account,
250 )
251
252 @staticmethod
253 def parse_common_billing_account_path(path: str) -> Dict[str, str]:
254 """Parse a billing_account path into its component segments."""
255 m = re.match(r"^billingAccounts/(?P<billing_account>.+?)$", path)
256 return m.groupdict() if m else {}
257
258 @staticmethod
259 def common_folder_path(
260 folder: str,
261 ) -> str:
262 """Returns a fully-qualified folder string."""
263 return "folders/{folder}".format(
264 folder=folder,
265 )
266
267 @staticmethod
268 def parse_common_folder_path(path: str) -> Dict[str, str]:
269 """Parse a folder path into its component segments."""
270 m = re.match(r"^folders/(?P<folder>.+?)$", path)
271 return m.groupdict() if m else {}
272
273 @staticmethod
274 def common_organization_path(
275 organization: str,
276 ) -> str:
277 """Returns a fully-qualified organization string."""
278 return "organizations/{organization}".format(
279 organization=organization,
280 )
281
282 @staticmethod
283 def parse_common_organization_path(path: str) -> Dict[str, str]:
284 """Parse a organization path into its component segments."""
285 m = re.match(r"^organizations/(?P<organization>.+?)$", path)
286 return m.groupdict() if m else {}
287
288 @staticmethod
289 def common_project_path(
290 project: str,
291 ) -> str:
292 """Returns a fully-qualified project string."""
293 return "projects/{project}".format(
294 project=project,
295 )
296
297 @staticmethod
298 def parse_common_project_path(path: str) -> Dict[str, str]:
299 """Parse a project path into its component segments."""
300 m = re.match(r"^projects/(?P<project>.+?)$", path)
301 return m.groupdict() if m else {}
302
303 @staticmethod
304 def common_location_path(
305 project: str,
306 location: str,
307 ) -> str:
308 """Returns a fully-qualified location string."""
309 return "projects/{project}/locations/{location}".format(
310 project=project,
311 location=location,
312 )
313
314 @staticmethod
315 def parse_common_location_path(path: str) -> Dict[str, str]:
316 """Parse a location path into its component segments."""
317 m = re.match(r"^projects/(?P<project>.+?)/locations/(?P<location>.+?)$", path)
318 return m.groupdict() if m else {}
319
320 @classmethod
321 def get_mtls_endpoint_and_cert_source(
322 cls, client_options: Optional[client_options_lib.ClientOptions] = None
323 ):
324 """Deprecated. Return the API endpoint and client cert source for mutual TLS.
325
326 The client cert source is determined in the following order:
327 (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the
328 client cert source is None.
329 (2) if `client_options.client_cert_source` is provided, use the provided one; if the
330 default client cert source exists, use the default one; otherwise the client cert
331 source is None.
332
333 The API endpoint is determined in the following order:
334 (1) if `client_options.api_endpoint` if provided, use the provided one.
335 (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the
336 default mTLS endpoint; if the environment variable is "never", use the default API
337 endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise
338 use the default API endpoint.
339
340 More details can be found at https://google.aip.dev/auth/4114.
341
342 Args:
343 client_options (google.api_core.client_options.ClientOptions): Custom options for the
344 client. Only the `api_endpoint` and `client_cert_source` properties may be used
345 in this method.
346
347 Returns:
348 Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the
349 client cert source to use.
350
351 Raises:
352 google.auth.exceptions.MutualTLSChannelError: If any errors happen.
353 """
354
355 warnings.warn(
356 "get_mtls_endpoint_and_cert_source is deprecated. Use the api_endpoint property instead.",
357 DeprecationWarning,
358 )
359 if client_options is None:
360 client_options = client_options_lib.ClientOptions()
361 use_client_cert = ErrorGroupServiceClient._use_client_cert_effective()
362 use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto")
363 if use_mtls_endpoint not in ("auto", "never", "always"):
364 raise MutualTLSChannelError(
365 "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
366 )
367
368 # Figure out the client cert source to use.
369 client_cert_source = None
370 if use_client_cert:
371 if client_options.client_cert_source:
372 client_cert_source = client_options.client_cert_source
373 elif mtls.has_default_client_cert_source():
374 client_cert_source = mtls.default_client_cert_source()
375
376 # Figure out which api endpoint to use.
377 if client_options.api_endpoint is not None:
378 api_endpoint = client_options.api_endpoint
379 elif use_mtls_endpoint == "always" or (
380 use_mtls_endpoint == "auto" and client_cert_source
381 ):
382 api_endpoint = cls.DEFAULT_MTLS_ENDPOINT
383 else:
384 api_endpoint = cls.DEFAULT_ENDPOINT
385
386 return api_endpoint, client_cert_source
387
388 @staticmethod
389 def _read_environment_variables():
390 """Returns the environment variables used by the client.
391
392 Returns:
393 Tuple[bool, str, str]: returns the GOOGLE_API_USE_CLIENT_CERTIFICATE,
394 GOOGLE_API_USE_MTLS_ENDPOINT, and GOOGLE_CLOUD_UNIVERSE_DOMAIN environment variables.
395
396 Raises:
397 ValueError: If GOOGLE_API_USE_CLIENT_CERTIFICATE is not
398 any of ["true", "false"].
399 google.auth.exceptions.MutualTLSChannelError: If GOOGLE_API_USE_MTLS_ENDPOINT
400 is not any of ["auto", "never", "always"].
401 """
402 use_client_cert = ErrorGroupServiceClient._use_client_cert_effective()
403 use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto").lower()
404 universe_domain_env = os.getenv("GOOGLE_CLOUD_UNIVERSE_DOMAIN")
405 if use_mtls_endpoint not in ("auto", "never", "always"):
406 raise MutualTLSChannelError(
407 "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
408 )
409 return use_client_cert, use_mtls_endpoint, universe_domain_env
410
411 @staticmethod
412 def _get_client_cert_source(provided_cert_source, use_cert_flag):
413 """Return the client cert source to be used by the client.
414
415 Args:
416 provided_cert_source (bytes): The client certificate source provided.
417 use_cert_flag (bool): A flag indicating whether to use the client certificate.
418
419 Returns:
420 bytes or None: The client cert source to be used by the client.
421 """
422 client_cert_source = None
423 if use_cert_flag:
424 if provided_cert_source:
425 client_cert_source = provided_cert_source
426 elif mtls.has_default_client_cert_source():
427 client_cert_source = mtls.default_client_cert_source()
428 return client_cert_source
429
430 @staticmethod
431 def _get_api_endpoint(
432 api_override, client_cert_source, universe_domain, use_mtls_endpoint
433 ):
434 """Return the API endpoint used by the client.
435
436 Args:
437 api_override (str): The API endpoint override. If specified, this is always
438 the return value of this function and the other arguments are not used.
439 client_cert_source (bytes): The client certificate source used by the client.
440 universe_domain (str): The universe domain used by the client.
441 use_mtls_endpoint (str): How to use the mTLS endpoint, which depends also on the other parameters.
442 Possible values are "always", "auto", or "never".
443
444 Returns:
445 str: The API endpoint to be used by the client.
446 """
447 if api_override is not None:
448 api_endpoint = api_override
449 elif use_mtls_endpoint == "always" or (
450 use_mtls_endpoint == "auto" and client_cert_source
451 ):
452 _default_universe = ErrorGroupServiceClient._DEFAULT_UNIVERSE
453 if universe_domain != _default_universe:
454 raise MutualTLSChannelError(
455 f"mTLS is not supported in any universe other than {_default_universe}."
456 )
457 api_endpoint = ErrorGroupServiceClient.DEFAULT_MTLS_ENDPOINT
458 else:
459 api_endpoint = ErrorGroupServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format(
460 UNIVERSE_DOMAIN=universe_domain
461 )
462 return api_endpoint
463
464 @staticmethod
465 def _get_universe_domain(
466 client_universe_domain: Optional[str], universe_domain_env: Optional[str]
467 ) -> str:
468 """Return the universe domain used by the client.
469
470 Args:
471 client_universe_domain (Optional[str]): The universe domain configured via the client options.
472 universe_domain_env (Optional[str]): The universe domain configured via the "GOOGLE_CLOUD_UNIVERSE_DOMAIN" environment variable.
473
474 Returns:
475 str: The universe domain to be used by the client.
476
477 Raises:
478 ValueError: If the universe domain is an empty string.
479 """
480 universe_domain = ErrorGroupServiceClient._DEFAULT_UNIVERSE
481 if client_universe_domain is not None:
482 universe_domain = client_universe_domain
483 elif universe_domain_env is not None:
484 universe_domain = universe_domain_env
485 if len(universe_domain.strip()) == 0:
486 raise ValueError("Universe Domain cannot be an empty string.")
487 return universe_domain
488
489 def _validate_universe_domain(self):
490 """Validates client's and credentials' universe domains are consistent.
491
492 Returns:
493 bool: True iff the configured universe domain is valid.
494
495 Raises:
496 ValueError: If the configured universe domain is not valid.
497 """
498
499 # NOTE (b/349488459): universe validation is disabled until further notice.
500 return True
501
502 def _add_cred_info_for_auth_errors(
503 self, error: core_exceptions.GoogleAPICallError
504 ) -> None:
505 """Adds credential info string to error details for 401/403/404 errors.
506
507 Args:
508 error (google.api_core.exceptions.GoogleAPICallError): The error to add the cred info.
509 """
510 if error.code not in [
511 HTTPStatus.UNAUTHORIZED,
512 HTTPStatus.FORBIDDEN,
513 HTTPStatus.NOT_FOUND,
514 ]:
515 return
516
517 cred = self._transport._credentials
518
519 # get_cred_info is only available in google-auth>=2.35.0
520 if not hasattr(cred, "get_cred_info"):
521 return
522
523 # ignore the type check since pypy test fails when get_cred_info
524 # is not available
525 cred_info = cred.get_cred_info() # type: ignore
526 if cred_info and hasattr(error._details, "append"):
527 error._details.append(json.dumps(cred_info))
528
529 @property
530 def api_endpoint(self):
531 """Return the API endpoint used by the client instance.
532
533 Returns:
534 str: The API endpoint used by the client instance.
535 """
536 return self._api_endpoint
537
538 @property
539 def universe_domain(self) -> str:
540 """Return the universe domain used by the client instance.
541
542 Returns:
543 str: The universe domain used by the client instance.
544 """
545 return self._universe_domain
546
547 def __init__(
548 self,
549 *,
550 credentials: Optional[ga_credentials.Credentials] = None,
551 transport: Optional[
552 Union[
553 str,
554 ErrorGroupServiceTransport,
555 Callable[..., ErrorGroupServiceTransport],
556 ]
557 ] = None,
558 client_options: Optional[Union[client_options_lib.ClientOptions, dict]] = None,
559 client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
560 ) -> None:
561 """Instantiates the error group service client.
562
563 Args:
564 credentials (Optional[google.auth.credentials.Credentials]): The
565 authorization credentials to attach to requests. These
566 credentials identify the application to the service; if none
567 are specified, the client will attempt to ascertain the
568 credentials from the environment.
569 transport (Optional[Union[str,ErrorGroupServiceTransport,Callable[..., ErrorGroupServiceTransport]]]):
570 The transport to use, or a Callable that constructs and returns a new transport.
571 If a Callable is given, it will be called with the same set of initialization
572 arguments as used in the ErrorGroupServiceTransport constructor.
573 If set to None, a transport is chosen automatically.
574 client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]):
575 Custom options for the client.
576
577 1. The ``api_endpoint`` property can be used to override the
578 default endpoint provided by the client when ``transport`` is
579 not explicitly provided. Only if this property is not set and
580 ``transport`` was not explicitly provided, the endpoint is
581 determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment
582 variable, which have one of the following values:
583 "always" (always use the default mTLS endpoint), "never" (always
584 use the default regular endpoint) and "auto" (auto-switch to the
585 default mTLS endpoint if client certificate is present; this is
586 the default value).
587
588 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable
589 is "true", then the ``client_cert_source`` property can be used
590 to provide a client certificate for mTLS transport. If
591 not provided, the default SSL client certificate will be used if
592 present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not
593 set, no client certificate will be used.
594
595 3. The ``universe_domain`` property can be used to override the
596 default "googleapis.com" universe. Note that the ``api_endpoint``
597 property still takes precedence; and ``universe_domain`` is
598 currently not supported for mTLS.
599
600 client_info (google.api_core.gapic_v1.client_info.ClientInfo):
601 The client info used to send a user-agent string along with
602 API requests. If ``None``, then default info will be used.
603 Generally, you only need to set this if you're developing
604 your own client library.
605
606 Raises:
607 google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport
608 creation failed for any reason.
609 """
610 self._client_options = client_options
611 if isinstance(self._client_options, dict):
612 self._client_options = client_options_lib.from_dict(self._client_options)
613 if self._client_options is None:
614 self._client_options = client_options_lib.ClientOptions()
615 self._client_options = cast(
616 client_options_lib.ClientOptions, self._client_options
617 )
618
619 universe_domain_opt = getattr(self._client_options, "universe_domain", None)
620
621 (
622 self._use_client_cert,
623 self._use_mtls_endpoint,
624 self._universe_domain_env,
625 ) = ErrorGroupServiceClient._read_environment_variables()
626 self._client_cert_source = ErrorGroupServiceClient._get_client_cert_source(
627 self._client_options.client_cert_source, self._use_client_cert
628 )
629 self._universe_domain = ErrorGroupServiceClient._get_universe_domain(
630 universe_domain_opt, self._universe_domain_env
631 )
632 self._api_endpoint = None # updated below, depending on `transport`
633
634 # Initialize the universe domain validation.
635 self._is_universe_domain_valid = False
636
637 if CLIENT_LOGGING_SUPPORTED: # pragma: NO COVER
638 # Setup logging.
639 client_logging.initialize_logging()
640
641 api_key_value = getattr(self._client_options, "api_key", None)
642 if api_key_value and credentials:
643 raise ValueError(
644 "client_options.api_key and credentials are mutually exclusive"
645 )
646
647 # Save or instantiate the transport.
648 # Ordinarily, we provide the transport, but allowing a custom transport
649 # instance provides an extensibility point for unusual situations.
650 transport_provided = isinstance(transport, ErrorGroupServiceTransport)
651 if transport_provided:
652 # transport is a ErrorGroupServiceTransport instance.
653 if credentials or self._client_options.credentials_file or api_key_value:
654 raise ValueError(
655 "When providing a transport instance, "
656 "provide its credentials directly."
657 )
658 if self._client_options.scopes:
659 raise ValueError(
660 "When providing a transport instance, provide its scopes "
661 "directly."
662 )
663 self._transport = cast(ErrorGroupServiceTransport, transport)
664 self._api_endpoint = self._transport.host
665
666 self._api_endpoint = (
667 self._api_endpoint
668 or ErrorGroupServiceClient._get_api_endpoint(
669 self._client_options.api_endpoint,
670 self._client_cert_source,
671 self._universe_domain,
672 self._use_mtls_endpoint,
673 )
674 )
675
676 if not transport_provided:
677 import google.auth._default # type: ignore
678
679 if api_key_value and hasattr(
680 google.auth._default, "get_api_key_credentials"
681 ):
682 credentials = google.auth._default.get_api_key_credentials(
683 api_key_value
684 )
685
686 transport_init: Union[
687 Type[ErrorGroupServiceTransport],
688 Callable[..., ErrorGroupServiceTransport],
689 ] = (
690 ErrorGroupServiceClient.get_transport_class(transport)
691 if isinstance(transport, str) or transport is None
692 else cast(Callable[..., ErrorGroupServiceTransport], transport)
693 )
694 # initialize with the provided callable or the passed in class
695 self._transport = transport_init(
696 credentials=credentials,
697 credentials_file=self._client_options.credentials_file,
698 host=self._api_endpoint,
699 scopes=self._client_options.scopes,
700 client_cert_source_for_mtls=self._client_cert_source,
701 quota_project_id=self._client_options.quota_project_id,
702 client_info=client_info,
703 always_use_jwt_access=True,
704 api_audience=self._client_options.api_audience,
705 )
706
707 if "async" not in str(self._transport):
708 if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
709 std_logging.DEBUG
710 ): # pragma: NO COVER
711 _LOGGER.debug(
712 "Created client `google.devtools.clouderrorreporting_v1beta1.ErrorGroupServiceClient`.",
713 extra={
714 "serviceName": "google.devtools.clouderrorreporting.v1beta1.ErrorGroupService",
715 "universeDomain": getattr(
716 self._transport._credentials, "universe_domain", ""
717 ),
718 "credentialsType": f"{type(self._transport._credentials).__module__}.{type(self._transport._credentials).__qualname__}",
719 "credentialsInfo": getattr(
720 self.transport._credentials, "get_cred_info", lambda: None
721 )(),
722 }
723 if hasattr(self._transport, "_credentials")
724 else {
725 "serviceName": "google.devtools.clouderrorreporting.v1beta1.ErrorGroupService",
726 "credentialsType": None,
727 },
728 )
729
730 def get_group(
731 self,
732 request: Optional[Union[error_group_service.GetGroupRequest, dict]] = None,
733 *,
734 group_name: Optional[str] = None,
735 retry: OptionalRetry = gapic_v1.method.DEFAULT,
736 timeout: Union[float, object] = gapic_v1.method.DEFAULT,
737 metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
738 ) -> common.ErrorGroup:
739 r"""Get the specified group.
740
741 .. code-block:: python
742
743 # This snippet has been automatically generated and should be regarded as a
744 # code template only.
745 # It will require modifications to work:
746 # - It may require correct/in-range values for request initialization.
747 # - It may require specifying regional endpoints when creating the service
748 # client as shown in:
749 # https://googleapis.dev/python/google-api-core/latest/client_options.html
750 from google.cloud import errorreporting_v1beta1
751
752 def sample_get_group():
753 # Create a client
754 client = errorreporting_v1beta1.ErrorGroupServiceClient()
755
756 # Initialize request argument(s)
757 request = errorreporting_v1beta1.GetGroupRequest(
758 group_name="group_name_value",
759 )
760
761 # Make the request
762 response = client.get_group(request=request)
763
764 # Handle the response
765 print(response)
766
767 Args:
768 request (Union[google.cloud.errorreporting_v1beta1.types.GetGroupRequest, dict]):
769 The request object. A request to return an individual
770 group.
771 group_name (str):
772 Required. The group resource name. Written as either
773 ``projects/{projectID}/groups/{group_id}`` or
774 ``projects/{projectID}/locations/{location}/groups/{group_id}``.
775 Call [groupStats.list]
776 [google.devtools.clouderrorreporting.v1beta1.ErrorStatsService.ListGroupStats]
777 to return a list of groups belonging to this project.
778
779 Examples: ``projects/my-project-123/groups/my-group``,
780 ``projects/my-project-123/locations/global/groups/my-group``
781
782 In the group resource name, the ``group_id`` is a unique
783 identifier for a particular error group. The identifier
784 is derived from key parts of the error-log content and
785 is treated as Service Data. For information about how
786 Service Data is handled, see `Google Cloud Privacy
787 Notice <https://cloud.google.com/terms/cloud-privacy-notice>`__.
788
789 For a list of supported locations, see `Supported
790 Regions <https://cloud.google.com/logging/docs/region-support>`__.
791 ``global`` is the default when unspecified.
792
793 This corresponds to the ``group_name`` field
794 on the ``request`` instance; if ``request`` is provided, this
795 should not be set.
796 retry (google.api_core.retry.Retry): Designation of what errors, if any,
797 should be retried.
798 timeout (float): The timeout for this request.
799 metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
800 sent along with the request as metadata. Normally, each value must be of type `str`,
801 but for metadata keys ending with the suffix `-bin`, the corresponding values must
802 be of type `bytes`.
803
804 Returns:
805 google.cloud.errorreporting_v1beta1.types.ErrorGroup:
806 Description of a group of similar
807 error events.
808
809 """
810 # Create or coerce a protobuf request object.
811 # - Quick check: If we got a request object, we should *not* have
812 # gotten any keyword arguments that map to the request.
813 flattened_params = [group_name]
814 has_flattened_params = (
815 len([param for param in flattened_params if param is not None]) > 0
816 )
817 if request is not None and has_flattened_params:
818 raise ValueError(
819 "If the `request` argument is set, then none of "
820 "the individual field arguments should be set."
821 )
822
823 # - Use the request object if provided (there's no risk of modifying the input as
824 # there are no flattened fields), or create one.
825 if not isinstance(request, error_group_service.GetGroupRequest):
826 request = error_group_service.GetGroupRequest(request)
827 # If we have keyword arguments corresponding to fields on the
828 # request, apply these.
829 if group_name is not None:
830 request.group_name = group_name
831
832 # Wrap the RPC method; this adds retry and timeout information,
833 # and friendly error handling.
834 rpc = self._transport._wrapped_methods[self._transport.get_group]
835
836 # Certain fields should be provided within the metadata header;
837 # add these here.
838 metadata = tuple(metadata) + (
839 gapic_v1.routing_header.to_grpc_metadata(
840 (("group_name", request.group_name),)
841 ),
842 )
843
844 # Validate the universe domain.
845 self._validate_universe_domain()
846
847 # Send the request.
848 response = rpc(
849 request,
850 retry=retry,
851 timeout=timeout,
852 metadata=metadata,
853 )
854
855 # Done; return the response.
856 return response
857
858 def update_group(
859 self,
860 request: Optional[Union[error_group_service.UpdateGroupRequest, dict]] = None,
861 *,
862 group: Optional[common.ErrorGroup] = None,
863 retry: OptionalRetry = gapic_v1.method.DEFAULT,
864 timeout: Union[float, object] = gapic_v1.method.DEFAULT,
865 metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
866 ) -> common.ErrorGroup:
867 r"""Replace the data for the specified group.
868 Fails if the group does not exist.
869
870 .. code-block:: python
871
872 # This snippet has been automatically generated and should be regarded as a
873 # code template only.
874 # It will require modifications to work:
875 # - It may require correct/in-range values for request initialization.
876 # - It may require specifying regional endpoints when creating the service
877 # client as shown in:
878 # https://googleapis.dev/python/google-api-core/latest/client_options.html
879 from google.cloud import errorreporting_v1beta1
880
881 def sample_update_group():
882 # Create a client
883 client = errorreporting_v1beta1.ErrorGroupServiceClient()
884
885 # Initialize request argument(s)
886 request = errorreporting_v1beta1.UpdateGroupRequest(
887 )
888
889 # Make the request
890 response = client.update_group(request=request)
891
892 # Handle the response
893 print(response)
894
895 Args:
896 request (Union[google.cloud.errorreporting_v1beta1.types.UpdateGroupRequest, dict]):
897 The request object. A request to replace the existing
898 data for the given group.
899 group (google.cloud.errorreporting_v1beta1.types.ErrorGroup):
900 Required. The group which replaces
901 the resource on the server.
902
903 This corresponds to the ``group`` field
904 on the ``request`` instance; if ``request`` is provided, this
905 should not be set.
906 retry (google.api_core.retry.Retry): Designation of what errors, if any,
907 should be retried.
908 timeout (float): The timeout for this request.
909 metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
910 sent along with the request as metadata. Normally, each value must be of type `str`,
911 but for metadata keys ending with the suffix `-bin`, the corresponding values must
912 be of type `bytes`.
913
914 Returns:
915 google.cloud.errorreporting_v1beta1.types.ErrorGroup:
916 Description of a group of similar
917 error events.
918
919 """
920 # Create or coerce a protobuf request object.
921 # - Quick check: If we got a request object, we should *not* have
922 # gotten any keyword arguments that map to the request.
923 flattened_params = [group]
924 has_flattened_params = (
925 len([param for param in flattened_params if param is not None]) > 0
926 )
927 if request is not None and has_flattened_params:
928 raise ValueError(
929 "If the `request` argument is set, then none of "
930 "the individual field arguments should be set."
931 )
932
933 # - Use the request object if provided (there's no risk of modifying the input as
934 # there are no flattened fields), or create one.
935 if not isinstance(request, error_group_service.UpdateGroupRequest):
936 request = error_group_service.UpdateGroupRequest(request)
937 # If we have keyword arguments corresponding to fields on the
938 # request, apply these.
939 if group is not None:
940 request.group = group
941
942 # Wrap the RPC method; this adds retry and timeout information,
943 # and friendly error handling.
944 rpc = self._transport._wrapped_methods[self._transport.update_group]
945
946 # Certain fields should be provided within the metadata header;
947 # add these here.
948 metadata = tuple(metadata) + (
949 gapic_v1.routing_header.to_grpc_metadata(
950 (("group.name", request.group.name),)
951 ),
952 )
953
954 # Validate the universe domain.
955 self._validate_universe_domain()
956
957 # Send the request.
958 response = rpc(
959 request,
960 retry=retry,
961 timeout=timeout,
962 metadata=metadata,
963 )
964
965 # Done; return the response.
966 return response
967
968 def __enter__(self) -> "ErrorGroupServiceClient":
969 return self
970
971 def __exit__(self, type, value, traceback):
972 """Releases underlying transport's resources.
973
974 .. warning::
975 ONLY use as a context manager if the transport is NOT shared
976 with other clients! Exiting the with block will CLOSE the transport
977 and may cause errors in other clients!
978 """
979 self.transport.close()
980
981
982DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
983 gapic_version=package_version.__version__
984)
985
986if hasattr(DEFAULT_CLIENT_INFO, "protobuf_runtime_version"): # pragma: NO COVER
987 DEFAULT_CLIENT_INFO.protobuf_runtime_version = google.protobuf.__version__
988
989__all__ = ("ErrorGroupServiceClient",)