Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/google/cloud/logging_v2/_http.py: 32%
116 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 06:45 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 06:45 +0000
1# Copyright 2016 Google LLC
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.
15"""Interact with Cloud Logging via JSON-over-HTTP."""
17import functools
19from google.api_core import page_iterator
20from google.cloud import _http
22from google.cloud.logging_v2 import __version__
23from google.cloud.logging_v2._helpers import entry_from_resource
24from google.cloud.logging_v2.sink import Sink
25from google.cloud.logging_v2.metric import Metric
28class Connection(_http.JSONConnection):
30 DEFAULT_API_ENDPOINT = "https://logging.googleapis.com"
32 def __init__(self, client, *, client_info=None, api_endpoint=DEFAULT_API_ENDPOINT):
33 """A connection to Google Cloud Logging via the JSON REST API.
35 Args:
36 client (google.cloud.logging_v2.cliet.Client):
37 The client that owns the current connection.
38 client_info (Optional[google.api_core.client_info.ClientInfo]):
39 Instance used to generate user agent.
40 client_options (Optional[google.api_core.client_options.ClientOptions]):
41 Client options used to set user options
42 on the client. API Endpoint should be set through client_options.
43 """
44 super(Connection, self).__init__(client, client_info)
45 self.API_BASE_URL = api_endpoint
46 self._client_info.gapic_version = __version__
47 self._client_info.client_library_version = __version__
49 API_VERSION = "v2"
50 """The version of the API, used in building the API call's URL."""
52 API_URL_TEMPLATE = "{api_base_url}/{api_version}{path}"
53 """A template for the URL of a particular API call."""
56class _LoggingAPI(object):
57 """Helper mapping logging-related APIs.
59 See
60 https://cloud.google.com/logging/docs/reference/v2/rest/v2/entries
61 https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.logs
63 :type client: :class:`~google.cloud.logging.client.Client`
64 :param client: The client used to make API requests.
65 """
67 def __init__(self, client):
68 self._client = client
69 self.api_request = client._connection.api_request
71 def list_entries(
72 self,
73 resource_names,
74 *,
75 filter_=None,
76 order_by=None,
77 max_results=None,
78 page_size=None,
79 page_token=None,
80 ):
81 """Return a page of log entry resources.
83 Args:
84 resource_names (Sequence[str]): Names of one or more parent resources
85 from which to retrieve log entries:
87 ::
89 "projects/[PROJECT_ID]"
90 "organizations/[ORGANIZATION_ID]"
91 "billingAccounts/[BILLING_ACCOUNT_ID]"
92 "folders/[FOLDER_ID]"
94 filter_ (str): a filter expression. See
95 https://cloud.google.com/logging/docs/view/advanced_filters
96 order_by (str) One of :data:`~logging_v2.ASCENDING`
97 or :data:`~logging_v2.DESCENDING`.
98 max_results (Optional[int]):
99 Optional. The maximum number of entries to return.
100 Non-positive values are treated as 0. If None, uses API defaults.
101 page_size (int): number of entries to fetch in each API call. Although
102 requests are paged internally, logs are returned by the generator
103 one at a time. If not passed, defaults to a value set by the API.
104 page_token (str): opaque marker for the starting "page" of entries. If not
105 passed, the API will return the first page of entries.
106 Returns:
107 Generator[~logging_v2.LogEntry]
108 """
109 extra_params = {"resourceNames": resource_names}
111 if filter_ is not None:
112 extra_params["filter"] = filter_
114 if order_by is not None:
115 extra_params["orderBy"] = order_by
117 if page_size is not None:
118 extra_params["pageSize"] = page_size
120 path = "/entries:list"
121 # We attach a mutable loggers dictionary so that as Logger
122 # objects are created by entry_from_resource, they can be
123 # re-used by other log entries from the same logger.
124 loggers = {}
125 item_to_value = functools.partial(_item_to_entry, loggers=loggers)
126 iterator = page_iterator.HTTPIterator(
127 client=self._client,
128 api_request=self._client._connection.api_request,
129 path=path,
130 item_to_value=item_to_value,
131 items_key="entries",
132 page_token=page_token,
133 extra_params=extra_params,
134 )
135 # This method uses POST to make a read-only request.
136 iterator._HTTP_METHOD = "POST"
138 return _entries_pager(iterator, max_results)
140 def write_entries(
141 self,
142 entries,
143 *,
144 logger_name=None,
145 resource=None,
146 labels=None,
147 partial_success=True,
148 dry_run=False,
149 ):
150 """Log an entry resource via a POST request
152 See
153 https://cloud.google.com/logging/docs/reference/v2/rest/v2/entries/write
155 Args:
156 entries (Sequence[Mapping[str, ...]]): sequence of mappings representing
157 the log entry resources to log.
158 logger_name (Optional[str]): name of default logger to which to log the entries;
159 individual entries may override.
160 resource(Optional[Mapping[str, ...]]): default resource to associate with entries;
161 individual entries may override.
162 labels (Optional[Mapping[str, ...]]): default labels to associate with entries;
163 individual entries may override.
164 partial_success (Optional[bool]): Whether valid entries should be written even if
165 some other entries fail due to INVALID_ARGUMENT or
166 PERMISSION_DENIED errors. If any entry is not written, then
167 the response status is the error associated with one of the
168 failed entries and the response includes error details keyed
169 by the entries' zero-based index in the ``entries.write``
170 method.
171 dry_run (Optional[bool]):
172 If true, the request should expect normal response,
173 but the entries won't be persisted nor exported.
174 Useful for checking whether the logging API endpoints are working
175 properly before sending valuable data.
176 """
177 data = {
178 "entries": list(entries),
179 "partialSuccess": partial_success,
180 "dry_run": dry_run,
181 }
183 if logger_name is not None:
184 data["logName"] = logger_name
186 if resource is not None:
187 data["resource"] = resource
189 if labels is not None:
190 data["labels"] = labels
192 self.api_request(method="POST", path="/entries:write", data=data)
194 def logger_delete(self, logger_name):
195 """Delete all entries in a logger.
197 Args:
198 logger_name (str): The resource name of the log to delete:
200 ::
202 "projects/[PROJECT_ID]/logs/[LOG_ID]"
203 "organizations/[ORGANIZATION_ID]/logs/[LOG_ID]"
204 "billingAccounts/[BILLING_ACCOUNT_ID]/logs/[LOG_ID]"
205 "folders/[FOLDER_ID]/logs/[LOG_ID]"
207 ``[LOG_ID]`` must be URL-encoded. For example,
208 ``"projects/my-project-id/logs/syslog"``,
209 ``"organizations/1234567890/logs/cloudresourcemanager.googleapis.com%2Factivity"``.
210 """
211 path = f"/{logger_name}"
212 self.api_request(method="DELETE", path=path)
215class _SinksAPI(object):
216 """Helper mapping sink-related APIs.
218 See
219 https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.sinks
220 """
222 def __init__(self, client):
223 self._client = client
224 self.api_request = client._connection.api_request
226 def list_sinks(self, parent, *, max_results=None, page_size=None, page_token=None):
227 """List sinks for the parent resource.
229 See
230 https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.sinks/list
232 Args:
233 parent (str): The parent resource whose sinks are to be listed:
235 ::
237 "projects/[PROJECT_ID]"
238 "organizations/[ORGANIZATION_ID]"
239 "billingAccounts/[BILLING_ACCOUNT_ID]"
240 "folders/[FOLDER_ID]".
241 max_results (Optional[int]):
242 Optional. The maximum number of entries to return.
243 Non-positive values are treated as 0. If None, uses API defaults.
244 page_size (int): number of entries to fetch in each API call. Although
245 requests are paged internally, logs are returned by the generator
246 one at a time. If not passed, defaults to a value set by the API.
247 page_token (str): opaque marker for the starting "page" of entries. If not
248 passed, the API will return the first page of entries.
250 Returns:
251 Generator[~logging_v2.Sink]
252 """
253 extra_params = {}
255 if page_size is not None:
256 extra_params["pageSize"] = page_size
258 path = f"/{parent}/sinks"
259 iterator = page_iterator.HTTPIterator(
260 client=self._client,
261 api_request=self._client._connection.api_request,
262 path=path,
263 item_to_value=_item_to_sink,
264 items_key="sinks",
265 page_token=page_token,
266 extra_params=extra_params,
267 )
269 return _entries_pager(iterator, max_results)
271 def sink_create(
272 self, parent, sink_name, filter_, destination, *, unique_writer_identity=False
273 ):
274 """Create a sink resource.
276 See
277 https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.sinks/create
279 Args:
280 parent(str): The resource in which to create the sink:
282 ::
284 "projects/[PROJECT_ID]"
285 "organizations/[ORGANIZATION_ID]"
286 "billingAccounts/[BILLING_ACCOUNT_ID]"
287 "folders/[FOLDER_ID]".
288 sink_name (str): The name of the sink.
289 filter_ (str): The advanced logs filter expression defining the
290 entries exported by the sink.
291 destination (str): Destination URI for the entries exported by
292 the sink.
293 unique_writer_identity (Optional[bool]): determines the kind of
294 IAM identity returned as writer_identity in the new sink.
296 Returns:
297 dict: The sink resource returned from the API.
298 """
299 target = f"/{parent}/sinks"
300 data = {"name": sink_name, "filter": filter_, "destination": destination}
301 query_params = {"uniqueWriterIdentity": unique_writer_identity}
302 return self.api_request(
303 method="POST", path=target, data=data, query_params=query_params
304 )
306 def sink_get(self, sink_name):
307 """Retrieve a sink resource.
309 Args:
310 sink_name (str): The resource name of the sink:
312 ::
314 "projects/[PROJECT_ID]/sinks/[SINK_ID]"
315 "organizations/[ORGANIZATION_ID]/sinks/[SINK_ID]"
316 "billingAccounts/[BILLING_ACCOUNT_ID]/sinks/[SINK_ID]"
317 "folders/[FOLDER_ID]/sinks/[SINK_ID]"
319 Returns:
320 dict: The JSON sink object returned from the API.
321 """
322 target = f"/{sink_name}"
323 return self.api_request(method="GET", path=target)
325 def sink_update(
326 self, sink_name, filter_, destination, *, unique_writer_identity=False
327 ):
328 """Update a sink resource.
330 Args:
331 sink_name (str): Required. The resource name of the sink:
333 ::
335 "projects/[PROJECT_ID]/sinks/[SINK_ID]"
336 "organizations/[ORGANIZATION_ID]/sinks/[SINK_ID]"
337 "billingAccounts/[BILLING_ACCOUNT_ID]/sinks/[SINK_ID]"
338 "folders/[FOLDER_ID]/sinks/[SINK_ID]"
339 filter_ (str): The advanced logs filter expression defining the
340 entries exported by the sink.
341 destination (str): destination URI for the entries exported by
342 the sink.
343 unique_writer_identity (Optional[bool]): determines the kind of
344 IAM identity returned as writer_identity in the new sink.
347 Returns:
348 dict: The returned (updated) resource.
349 """
350 target = f"/{sink_name}"
351 name = sink_name.split("/")[-1] # parse name out of full resoure name
352 data = {"name": name, "filter": filter_, "destination": destination}
353 query_params = {"uniqueWriterIdentity": unique_writer_identity}
354 return self.api_request(
355 method="PUT", path=target, query_params=query_params, data=data
356 )
358 def sink_delete(self, sink_name):
359 """Delete a sink resource.
361 Args:
362 sink_name (str): Required. The full resource name of the sink to delete,
363 including the parent resource and the sink identifier:
365 ::
367 "projects/[PROJECT_ID]/sinks/[SINK_ID]"
368 "organizations/[ORGANIZATION_ID]/sinks/[SINK_ID]"
369 "billingAccounts/[BILLING_ACCOUNT_ID]/sinks/[SINK_ID]"
370 "folders/[FOLDER_ID]/sinks/[SINK_ID]"
372 Example: ``"projects/my-project-id/sinks/my-sink-id"``.
373 """
374 target = f"/{sink_name}"
375 self.api_request(method="DELETE", path=target)
378class _MetricsAPI(object):
379 """Helper mapping sink-related APIs."""
381 def __init__(self, client):
382 self._client = client
383 self.api_request = client._connection.api_request
385 def list_metrics(
386 self, project, *, max_results=None, page_size=None, page_token=None
387 ):
388 """List metrics for the project associated with this client.
390 See
391 https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.metrics/list
393 Args:
394 max_results (Optional[int]):
395 Optional. The maximum number of entries to return.
396 Non-positive values are treated as 0. If None, uses API defaults.
397 page_size (int): number of entries to fetch in each API call. Although
398 requests are paged internally, logs are returned by the generator
399 one at a time. If not passed, defaults to a value set by the API.
400 page_token (str): opaque marker for the starting "page" of entries. If not
401 passed, the API will return the first page of entries.
403 Returns:
404 Generator[logging_v2.Metric]
406 """
407 extra_params = {}
409 if page_size is not None:
410 extra_params["pageSize"] = page_size
412 path = f"/projects/{project}/metrics"
413 iterator = page_iterator.HTTPIterator(
414 client=self._client,
415 api_request=self._client._connection.api_request,
416 path=path,
417 item_to_value=_item_to_metric,
418 items_key="metrics",
419 page_token=page_token,
420 extra_params=extra_params,
421 )
422 return _entries_pager(iterator, max_results)
424 def metric_create(self, project, metric_name, filter_, description):
425 """Create a metric resource.
427 See
428 https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.metrics/create
430 Args:
431 project (str): ID of the project in which to create the metric.
432 metric_name (str): The name of the metric
433 filter_ (str): The advanced logs filter expression defining the
434 entries exported by the metric.
435 description (str): description of the metric.
436 """
437 target = f"/projects/{project}/metrics"
438 data = {"name": metric_name, "filter": filter_, "description": description}
439 self.api_request(method="POST", path=target, data=data)
441 def metric_get(self, project, metric_name):
442 """Retrieve a metric resource.
444 Args:
445 project (str): ID of the project containing the metric.
446 metric_name (str): The name of the metric
448 Returns:
449 dict: The JSON metric object returned from the API.
450 """
451 target = f"/projects/{project}/metrics/{metric_name}"
452 return self.api_request(method="GET", path=target)
454 def metric_update(self, project, metric_name, filter_, description):
455 """Update a metric resource.
457 See
458 https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.metrics/update
460 Args:
461 project (str): ID of the project containing the metric.
462 metric_name (str): the name of the metric
463 filter_ (str): the advanced logs filter expression defining the
464 entries exported by the metric.
465 description (str): description of the metric.
467 Returns:
468 dict: The returned (updated) resource.
469 """
470 target = f"/projects/{project}/metrics/{metric_name}"
471 data = {"name": metric_name, "filter": filter_, "description": description}
472 return self.api_request(method="PUT", path=target, data=data)
474 def metric_delete(self, project, metric_name):
475 """Delete a metric resource.
477 Args:
478 project (str): ID of the project containing the metric.
479 metric_name (str): The name of the metric
480 """
481 target = f"/projects/{project}/metrics/{metric_name}"
482 self.api_request(method="DELETE", path=target)
485def _entries_pager(page_iter, max_results=None):
486 if max_results is not None and max_results < 0:
487 raise ValueError("max_results must be positive")
489 i = 0
490 for page in page_iter:
491 if max_results is not None and i >= max_results:
492 break
493 yield page
494 i += 1
497def _item_to_entry(iterator, resource, loggers):
498 """Convert a log entry resource to the native object.
500 .. note::
502 This method does not have the correct signature to be used as
503 the ``item_to_value`` argument to
504 :class:`~google.api_core.page_iterator.Iterator`. It is intended to be
505 patched with a mutable ``loggers`` argument that can be updated
506 on subsequent calls. For an example, see how the method is
507 used above in :meth:`_LoggingAPI.list_entries`.
509 Args:
510 iterator (google.api_core.page_iterator.Iterator): The iterator that
511 is currently in use.
512 resource (dict): Log entry JSON resource returned from the API.
513 loggers (Mapping[str, logging_v2.logger.Logger]):
514 A mapping of logger fullnames -> loggers. If the logger
515 that owns the entry is not in ``loggers``, the entry
516 will have a newly-created logger.
518 Returns:
519 ~logging_v2.entries._BaseEntry: The next log entry in the page.
520 """
521 return entry_from_resource(resource, iterator.client, loggers)
524def _item_to_sink(iterator, resource):
525 """Convert a sink resource to the native object.
527 Args:
528 iterator (google.api_core.page_iterator.Iterator): The iterator that
529 is currently in use.
530 resource (dict): Sink JSON resource returned from the API.
532 Returns:
533 ~logging_v2.sink.Sink: The next sink in the page.
534 """
535 return Sink.from_api_repr(resource, iterator.client)
538def _item_to_metric(iterator, resource):
539 """Convert a metric resource to the native object.
541 Args:
542 iterator (google.api_core.page_iterator.Iterator): The iterator that
543 is currently in use.
544 resource (dict): Sink JSON resource returned from the API.
546 Returns:
547 ~logging_v2.metric.Metric:
548 The next metric in the page.
549 """
550 return Metric.from_api_repr(resource, iterator.client)