Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/google/cloud/logging_v2/_http.py: 32%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

118 statements  

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. 

14 

15"""Interact with Cloud Logging via JSON-over-HTTP.""" 

16 

17import functools 

18 

19from google.api_core import page_iterator 

20from google.cloud import _http 

21 

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 

26 

27 

28class Connection(_http.JSONConnection): 

29 DEFAULT_API_ENDPOINT = "https://logging.googleapis.com" 

30 

31 def __init__(self, client, *, client_info=None, api_endpoint=DEFAULT_API_ENDPOINT): 

32 """A connection to Google Cloud Logging via the JSON REST API. 

33 

34 Args: 

35 client (google.cloud.logging_v2.cliet.Client): 

36 The client that owns the current connection. 

37 client_info (Optional[google.api_core.client_info.ClientInfo]): 

38 Instance used to generate user agent. 

39 client_options (Optional[google.api_core.client_options.ClientOptions]): 

40 Client options used to set user options 

41 on the client. API Endpoint should be set through client_options. 

42 """ 

43 super(Connection, self).__init__(client, client_info) 

44 self.API_BASE_URL = api_endpoint 

45 self._client_info.gapic_version = __version__ 

46 self._client_info.client_library_version = __version__ 

47 

48 API_VERSION = "v2" 

49 """The version of the API, used in building the API call's URL.""" 

50 

51 API_URL_TEMPLATE = "{api_base_url}/{api_version}{path}" 

52 """A template for the URL of a particular API call.""" 

53 

54 

55class _LoggingAPI(object): 

56 """Helper mapping logging-related APIs. 

57 

58 See 

59 https://cloud.google.com/logging/docs/reference/v2/rest/v2/entries 

60 https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.logs 

61 

62 :type client: :class:`~google.cloud.logging.client.Client` 

63 :param client: The client used to make API requests. 

64 """ 

65 

66 def __init__(self, client): 

67 self._client = client 

68 self.api_request = client._connection.api_request 

69 

70 def list_entries( 

71 self, 

72 resource_names, 

73 *, 

74 filter_=None, 

75 order_by=None, 

76 max_results=None, 

77 page_size=None, 

78 page_token=None, 

79 ): 

80 """Return a page of log entry resources. 

81 

82 Args: 

83 resource_names (Sequence[str]): Names of one or more parent resources 

84 from which to retrieve log entries: 

85 

86 :: 

87 

88 "projects/[PROJECT_ID]" 

89 "organizations/[ORGANIZATION_ID]" 

90 "billingAccounts/[BILLING_ACCOUNT_ID]" 

91 "folders/[FOLDER_ID]" 

92 

93 filter_ (str): a filter expression. See 

94 https://cloud.google.com/logging/docs/view/advanced_filters 

95 order_by (str) One of :data:`~logging_v2.ASCENDING` 

96 or :data:`~logging_v2.DESCENDING`. 

97 max_results (Optional[int]): 

98 Optional. The maximum number of entries to return. 

99 Non-positive values are treated as 0. If None, uses API defaults. 

100 page_size (int): number of entries to fetch in each API call. Although 

101 requests are paged internally, logs are returned by the generator 

102 one at a time. If not passed, defaults to a value set by the API. 

103 page_token (str): opaque marker for the starting "page" of entries. If not 

104 passed, the API will return the first page of entries. 

105 Returns: 

106 Generator[~logging_v2.LogEntry] 

107 """ 

108 extra_params = {"resourceNames": resource_names} 

109 

110 if filter_ is not None: 

111 extra_params["filter"] = filter_ 

112 

113 if order_by is not None: 

114 extra_params["orderBy"] = order_by 

115 

116 if page_size is not None: 

117 extra_params["pageSize"] = page_size 

118 

119 path = "/entries:list" 

120 # We attach a mutable loggers dictionary so that as Logger 

121 # objects are created by entry_from_resource, they can be 

122 # re-used by other log entries from the same logger. 

123 loggers = {} 

124 item_to_value = functools.partial(_item_to_entry, loggers=loggers) 

125 iterator = page_iterator.HTTPIterator( 

126 client=self._client, 

127 api_request=self._client._connection.api_request, 

128 path=path, 

129 item_to_value=item_to_value, 

130 items_key="entries", 

131 page_token=page_token, 

132 extra_params=extra_params, 

133 ) 

134 # This method uses POST to make a read-only request. 

135 iterator._HTTP_METHOD = "POST" 

136 

137 return _entries_pager(iterator, max_results) 

138 

139 def write_entries( 

140 self, 

141 entries, 

142 *, 

143 logger_name=None, 

144 resource=None, 

145 labels=None, 

146 partial_success=True, 

147 dry_run=False, 

148 ): 

149 """Log an entry resource via a POST request 

150 

151 See 

152 https://cloud.google.com/logging/docs/reference/v2/rest/v2/entries/write 

153 

154 Args: 

155 entries (Sequence[Mapping[str, ...]]): sequence of mappings representing 

156 the log entry resources to log. 

157 logger_name (Optional[str]): name of default logger to which to log the entries; 

158 individual entries may override. 

159 resource(Optional[Mapping[str, ...]]): default resource to associate with entries; 

160 individual entries may override. 

161 labels (Optional[Mapping[str, ...]]): default labels to associate with entries; 

162 individual entries may override. 

163 partial_success (Optional[bool]): Whether valid entries should be written even if 

164 some other entries fail due to INVALID_ARGUMENT or 

165 PERMISSION_DENIED errors. If any entry is not written, then 

166 the response status is the error associated with one of the 

167 failed entries and the response includes error details keyed 

168 by the entries' zero-based index in the ``entries.write`` 

169 method. 

170 dry_run (Optional[bool]): 

171 If true, the request should expect normal response, 

172 but the entries won't be persisted nor exported. 

173 Useful for checking whether the logging API endpoints are working 

174 properly before sending valuable data. 

175 """ 

176 data = { 

177 "entries": list(entries), 

178 "partialSuccess": partial_success, 

179 "dry_run": dry_run, 

180 } 

181 

182 if logger_name is not None: 

183 data["logName"] = logger_name 

184 

185 if resource is not None: 

186 data["resource"] = resource 

187 

188 if labels is not None: 

189 data["labels"] = labels 

190 

191 self.api_request(method="POST", path="/entries:write", data=data) 

192 

193 def logger_delete(self, logger_name): 

194 """Delete all entries in a logger. 

195 

196 Args: 

197 logger_name (str): The resource name of the log to delete: 

198 

199 :: 

200 

201 "projects/[PROJECT_ID]/logs/[LOG_ID]" 

202 "organizations/[ORGANIZATION_ID]/logs/[LOG_ID]" 

203 "billingAccounts/[BILLING_ACCOUNT_ID]/logs/[LOG_ID]" 

204 "folders/[FOLDER_ID]/logs/[LOG_ID]" 

205 

206 ``[LOG_ID]`` must be URL-encoded. For example, 

207 ``"projects/my-project-id/logs/syslog"``, 

208 ``"organizations/1234567890/logs/cloudresourcemanager.googleapis.com%2Factivity"``. 

209 """ 

210 path = f"/{logger_name}" 

211 self.api_request(method="DELETE", path=path) 

212 

213 

214class _SinksAPI(object): 

215 """Helper mapping sink-related APIs. 

216 

217 See 

218 https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.sinks 

219 """ 

220 

221 def __init__(self, client): 

222 self._client = client 

223 self.api_request = client._connection.api_request 

224 

225 def list_sinks(self, parent, *, max_results=None, page_size=None, page_token=None): 

226 """List sinks for the parent resource. 

227 

228 See 

229 https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.sinks/list 

230 

231 Args: 

232 parent (str): The parent resource whose sinks are to be listed: 

233 

234 :: 

235 

236 "projects/[PROJECT_ID]" 

237 "organizations/[ORGANIZATION_ID]" 

238 "billingAccounts/[BILLING_ACCOUNT_ID]" 

239 "folders/[FOLDER_ID]". 

240 max_results (Optional[int]): 

241 Optional. The maximum number of entries to return. 

242 Non-positive values are treated as 0. If None, uses API defaults. 

243 page_size (int): number of entries to fetch in each API call. Although 

244 requests are paged internally, logs are returned by the generator 

245 one at a time. If not passed, defaults to a value set by the API. 

246 page_token (str): opaque marker for the starting "page" of entries. If not 

247 passed, the API will return the first page of entries. 

248 

249 Returns: 

250 Generator[~logging_v2.Sink] 

251 """ 

252 extra_params = {} 

253 

254 if page_size is not None: 

255 extra_params["pageSize"] = page_size 

256 

257 path = f"/{parent}/sinks" 

258 iterator = page_iterator.HTTPIterator( 

259 client=self._client, 

260 api_request=self._client._connection.api_request, 

261 path=path, 

262 item_to_value=_item_to_sink, 

263 items_key="sinks", 

264 page_token=page_token, 

265 extra_params=extra_params, 

266 ) 

267 

268 return _entries_pager(iterator, max_results) 

269 

270 def sink_create( 

271 self, parent, sink_name, filter_, destination, *, unique_writer_identity=False 

272 ): 

273 """Create a sink resource. 

274 

275 See 

276 https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.sinks/create 

277 

278 Args: 

279 parent(str): The resource in which to create the sink: 

280 

281 :: 

282 

283 "projects/[PROJECT_ID]" 

284 "organizations/[ORGANIZATION_ID]" 

285 "billingAccounts/[BILLING_ACCOUNT_ID]" 

286 "folders/[FOLDER_ID]". 

287 sink_name (str): The name of the sink. 

288 filter_ (str): The advanced logs filter expression defining the 

289 entries exported by the sink. 

290 destination (str): Destination URI for the entries exported by 

291 the sink. 

292 unique_writer_identity (Optional[bool]): determines the kind of 

293 IAM identity returned as writer_identity in the new sink. 

294 

295 Returns: 

296 dict: The sink resource returned from the API. 

297 """ 

298 target = f"/{parent}/sinks" 

299 data = {"name": sink_name, "filter": filter_, "destination": destination} 

300 query_params = {"uniqueWriterIdentity": unique_writer_identity} 

301 return self.api_request( 

302 method="POST", path=target, data=data, query_params=query_params 

303 ) 

304 

305 def sink_get(self, sink_name): 

306 """Retrieve a sink resource. 

307 

308 Args: 

309 sink_name (str): The resource name of the sink: 

310 

311 :: 

312 

313 "projects/[PROJECT_ID]/sinks/[SINK_ID]" 

314 "organizations/[ORGANIZATION_ID]/sinks/[SINK_ID]" 

315 "billingAccounts/[BILLING_ACCOUNT_ID]/sinks/[SINK_ID]" 

316 "folders/[FOLDER_ID]/sinks/[SINK_ID]" 

317 

318 Returns: 

319 dict: The JSON sink object returned from the API. 

320 """ 

321 target = f"/{sink_name}" 

322 return self.api_request(method="GET", path=target) 

323 

324 def sink_update( 

325 self, sink_name, filter_, destination, *, unique_writer_identity=False 

326 ): 

327 """Update a sink resource. 

328 

329 Args: 

330 sink_name (str): Required. The resource name of the sink: 

331 

332 :: 

333 

334 "projects/[PROJECT_ID]/sinks/[SINK_ID]" 

335 "organizations/[ORGANIZATION_ID]/sinks/[SINK_ID]" 

336 "billingAccounts/[BILLING_ACCOUNT_ID]/sinks/[SINK_ID]" 

337 "folders/[FOLDER_ID]/sinks/[SINK_ID]" 

338 filter_ (str): The advanced logs filter expression defining the 

339 entries exported by the sink. 

340 destination (str): destination URI for the entries exported by 

341 the sink. 

342 unique_writer_identity (Optional[bool]): determines the kind of 

343 IAM identity returned as writer_identity in the new sink. 

344 

345 

346 Returns: 

347 dict: The returned (updated) resource. 

348 """ 

349 target = f"/{sink_name}" 

350 name = sink_name.split("/")[-1] # parse name out of full resource name 

351 data = {"name": name, "filter": filter_, "destination": destination} 

352 query_params = {"uniqueWriterIdentity": unique_writer_identity} 

353 return self.api_request( 

354 method="PUT", path=target, query_params=query_params, data=data 

355 ) 

356 

357 def sink_delete(self, sink_name): 

358 """Delete a sink resource. 

359 

360 Args: 

361 sink_name (str): Required. The full resource name of the sink to delete, 

362 including the parent resource and the sink identifier: 

363 

364 :: 

365 

366 "projects/[PROJECT_ID]/sinks/[SINK_ID]" 

367 "organizations/[ORGANIZATION_ID]/sinks/[SINK_ID]" 

368 "billingAccounts/[BILLING_ACCOUNT_ID]/sinks/[SINK_ID]" 

369 "folders/[FOLDER_ID]/sinks/[SINK_ID]" 

370 

371 Example: ``"projects/my-project-id/sinks/my-sink-id"``. 

372 """ 

373 target = f"/{sink_name}" 

374 self.api_request(method="DELETE", path=target) 

375 

376 

377class _MetricsAPI(object): 

378 """Helper mapping sink-related APIs.""" 

379 

380 def __init__(self, client): 

381 self._client = client 

382 self.api_request = client._connection.api_request 

383 

384 def list_metrics( 

385 self, project, *, max_results=None, page_size=None, page_token=None 

386 ): 

387 """List metrics for the project associated with this client. 

388 

389 See 

390 https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.metrics/list 

391 

392 Args: 

393 max_results (Optional[int]): 

394 Optional. The maximum number of entries to return. 

395 Non-positive values are treated as 0. If None, uses API defaults. 

396 page_size (int): number of entries to fetch in each API call. Although 

397 requests are paged internally, logs are returned by the generator 

398 one at a time. If not passed, defaults to a value set by the API. 

399 page_token (str): opaque marker for the starting "page" of entries. If not 

400 passed, the API will return the first page of entries. 

401 

402 Returns: 

403 Generator[logging_v2.Metric] 

404 

405 """ 

406 extra_params = {} 

407 

408 if page_size is not None: 

409 extra_params["pageSize"] = page_size 

410 

411 path = f"/projects/{project}/metrics" 

412 iterator = page_iterator.HTTPIterator( 

413 client=self._client, 

414 api_request=self._client._connection.api_request, 

415 path=path, 

416 item_to_value=_item_to_metric, 

417 items_key="metrics", 

418 page_token=page_token, 

419 extra_params=extra_params, 

420 ) 

421 return _entries_pager(iterator, max_results) 

422 

423 def metric_create(self, project, metric_name, filter_, description): 

424 """Create a metric resource. 

425 

426 See 

427 https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.metrics/create 

428 

429 Args: 

430 project (str): ID of the project in which to create the metric. 

431 metric_name (str): The name of the metric 

432 filter_ (str): The advanced logs filter expression defining the 

433 entries exported by the metric. 

434 description (str): description of the metric. 

435 """ 

436 target = f"/projects/{project}/metrics" 

437 data = {"name": metric_name, "filter": filter_, "description": description} 

438 self.api_request(method="POST", path=target, data=data) 

439 

440 def metric_get(self, project, metric_name): 

441 """Retrieve a metric resource. 

442 

443 Args: 

444 project (str): ID of the project containing the metric. 

445 metric_name (str): The name of the metric 

446 

447 Returns: 

448 dict: The JSON metric object returned from the API. 

449 """ 

450 target = f"/projects/{project}/metrics/{metric_name}" 

451 return self.api_request(method="GET", path=target) 

452 

453 def metric_update(self, project, metric_name, filter_, description): 

454 """Update a metric resource. 

455 

456 See 

457 https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.metrics/update 

458 

459 Args: 

460 project (str): ID of the project containing the metric. 

461 metric_name (str): the name of the metric 

462 filter_ (str): the advanced logs filter expression defining the 

463 entries exported by the metric. 

464 description (str): description of the metric. 

465 

466 Returns: 

467 dict: The returned (updated) resource. 

468 """ 

469 target = f"/projects/{project}/metrics/{metric_name}" 

470 data = {"name": metric_name, "filter": filter_, "description": description} 

471 return self.api_request(method="PUT", path=target, data=data) 

472 

473 def metric_delete(self, project, metric_name): 

474 """Delete a metric resource. 

475 

476 Args: 

477 project (str): ID of the project containing the metric. 

478 metric_name (str): The name of the metric 

479 """ 

480 target = f"/projects/{project}/metrics/{metric_name}" 

481 self.api_request(method="DELETE", path=target) 

482 

483 

484def _entries_pager(page_iter, max_results=None): 

485 if max_results is not None and max_results < 0: 

486 raise ValueError("max_results must be positive") 

487 

488 i = 0 

489 for page in page_iter: 

490 if max_results is not None and i >= max_results: 

491 break 

492 yield page 

493 i += 1 

494 

495 

496def _item_to_entry(iterator, resource, loggers): 

497 """Convert a log entry resource to the native object. 

498 

499 .. note:: 

500 

501 This method does not have the correct signature to be used as 

502 the ``item_to_value`` argument to 

503 :class:`~google.api_core.page_iterator.Iterator`. It is intended to be 

504 patched with a mutable ``loggers`` argument that can be updated 

505 on subsequent calls. For an example, see how the method is 

506 used above in :meth:`_LoggingAPI.list_entries`. 

507 

508 Args: 

509 iterator (google.api_core.page_iterator.Iterator): The iterator that 

510 is currently in use. 

511 resource (dict): Log entry JSON resource returned from the API. 

512 loggers (Mapping[str, logging_v2.logger.Logger]): 

513 A mapping of logger fullnames -> loggers. If the logger 

514 that owns the entry is not in ``loggers``, the entry 

515 will have a newly-created logger. 

516 

517 Returns: 

518 ~logging_v2.entries._BaseEntry: The next log entry in the page. 

519 """ 

520 return entry_from_resource(resource, iterator.client, loggers) 

521 

522 

523def _item_to_sink(iterator, resource): 

524 """Convert a sink resource to the native object. 

525 

526 Args: 

527 iterator (google.api_core.page_iterator.Iterator): The iterator that 

528 is currently in use. 

529 resource (dict): Sink JSON resource returned from the API. 

530 

531 Returns: 

532 ~logging_v2.sink.Sink: The next sink in the page. 

533 """ 

534 return Sink.from_api_repr(resource, iterator.client) 

535 

536 

537def _item_to_metric(iterator, resource): 

538 """Convert a metric resource to the native object. 

539 

540 Args: 

541 iterator (google.api_core.page_iterator.Iterator): The iterator that 

542 is currently in use. 

543 resource (dict): Sink JSON resource returned from the API. 

544 

545 Returns: 

546 ~logging_v2.metric.Metric: 

547 The next metric in the page. 

548 """ 

549 return Metric.from_api_repr(resource, iterator.client)