google-cloud-pubsub 2.30.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. google/cloud/pubsub/__init__.py +31 -0
  2. google/cloud/pubsub_v1/__init__.py +35 -0
  3. google/cloud/pubsub_v1/exceptions.py +20 -0
  4. google/cloud/pubsub_v1/futures.py +56 -0
  5. google/cloud/pubsub_v1/open_telemetry/__init__.py +13 -0
  6. google/cloud/pubsub_v1/open_telemetry/context_propagation.py +55 -0
  7. google/cloud/pubsub_v1/open_telemetry/publish_message_wrapper.py +142 -0
  8. google/cloud/pubsub_v1/open_telemetry/subscribe_opentelemetry.py +280 -0
  9. google/cloud/pubsub_v1/proto/pubsub.proto +1344 -0
  10. google/cloud/pubsub_v1/proto/schema.proto +286 -0
  11. google/cloud/pubsub_v1/publisher/__init__.py +20 -0
  12. google/cloud/pubsub_v1/publisher/_batch/__init__.py +0 -0
  13. google/cloud/pubsub_v1/publisher/_batch/base.py +174 -0
  14. google/cloud/pubsub_v1/publisher/_batch/thread.py +492 -0
  15. google/cloud/pubsub_v1/publisher/_sequencer/__init__.py +0 -0
  16. google/cloud/pubsub_v1/publisher/_sequencer/base.py +82 -0
  17. google/cloud/pubsub_v1/publisher/_sequencer/ordered_sequencer.py +340 -0
  18. google/cloud/pubsub_v1/publisher/_sequencer/unordered_sequencer.py +167 -0
  19. google/cloud/pubsub_v1/publisher/client.py +614 -0
  20. google/cloud/pubsub_v1/publisher/exceptions.py +51 -0
  21. google/cloud/pubsub_v1/publisher/flow_controller.py +313 -0
  22. google/cloud/pubsub_v1/publisher/futures.py +83 -0
  23. google/cloud/pubsub_v1/subscriber/__init__.py +20 -0
  24. google/cloud/pubsub_v1/subscriber/_protocol/__init__.py +0 -0
  25. google/cloud/pubsub_v1/subscriber/_protocol/dispatcher.py +658 -0
  26. google/cloud/pubsub_v1/subscriber/_protocol/heartbeater.py +77 -0
  27. google/cloud/pubsub_v1/subscriber/_protocol/helper_threads.py +122 -0
  28. google/cloud/pubsub_v1/subscriber/_protocol/histogram.py +159 -0
  29. google/cloud/pubsub_v1/subscriber/_protocol/leaser.py +292 -0
  30. google/cloud/pubsub_v1/subscriber/_protocol/messages_on_hold.py +182 -0
  31. google/cloud/pubsub_v1/subscriber/_protocol/requests.py +62 -0
  32. google/cloud/pubsub_v1/subscriber/_protocol/streaming_pull_manager.py +1309 -0
  33. google/cloud/pubsub_v1/subscriber/client.py +323 -0
  34. google/cloud/pubsub_v1/subscriber/exceptions.py +44 -0
  35. google/cloud/pubsub_v1/subscriber/futures.py +125 -0
  36. google/cloud/pubsub_v1/subscriber/message.py +532 -0
  37. google/cloud/pubsub_v1/subscriber/scheduler.py +170 -0
  38. google/cloud/pubsub_v1/types.py +336 -0
  39. google/pubsub/__init__.py +174 -0
  40. google/pubsub/gapic_version.py +16 -0
  41. google/pubsub/py.typed +2 -0
  42. google/pubsub_v1/__init__.py +172 -0
  43. google/pubsub_v1/gapic_metadata.json +591 -0
  44. google/pubsub_v1/gapic_version.py +16 -0
  45. google/pubsub_v1/py.typed +2 -0
  46. google/pubsub_v1/services/__init__.py +15 -0
  47. google/pubsub_v1/services/publisher/__init__.py +22 -0
  48. google/pubsub_v1/services/publisher/async_client.py +1670 -0
  49. google/pubsub_v1/services/publisher/client.py +2136 -0
  50. google/pubsub_v1/services/publisher/pagers.py +508 -0
  51. google/pubsub_v1/services/publisher/transports/__init__.py +38 -0
  52. google/pubsub_v1/services/publisher/transports/base.py +427 -0
  53. google/pubsub_v1/services/publisher/transports/grpc.py +667 -0
  54. google/pubsub_v1/services/publisher/transports/grpc_asyncio.py +847 -0
  55. google/pubsub_v1/services/publisher/transports/rest.py +2511 -0
  56. google/pubsub_v1/services/publisher/transports/rest_base.py +678 -0
  57. google/pubsub_v1/services/schema_service/__init__.py +22 -0
  58. google/pubsub_v1/services/schema_service/async_client.py +1783 -0
  59. google/pubsub_v1/services/schema_service/client.py +2197 -0
  60. google/pubsub_v1/services/schema_service/pagers.py +352 -0
  61. google/pubsub_v1/services/schema_service/transports/__init__.py +38 -0
  62. google/pubsub_v1/services/schema_service/transports/base.py +439 -0
  63. google/pubsub_v1/services/schema_service/transports/grpc.py +676 -0
  64. google/pubsub_v1/services/schema_service/transports/grpc_asyncio.py +858 -0
  65. google/pubsub_v1/services/schema_service/transports/rest.py +2718 -0
  66. google/pubsub_v1/services/schema_service/transports/rest_base.py +746 -0
  67. google/pubsub_v1/services/subscriber/__init__.py +22 -0
  68. google/pubsub_v1/services/subscriber/async_client.py +2643 -0
  69. google/pubsub_v1/services/subscriber/client.py +3094 -0
  70. google/pubsub_v1/services/subscriber/pagers.py +352 -0
  71. google/pubsub_v1/services/subscriber/transports/__init__.py +38 -0
  72. google/pubsub_v1/services/subscriber/transports/base.py +589 -0
  73. google/pubsub_v1/services/subscriber/transports/grpc.py +921 -0
  74. google/pubsub_v1/services/subscriber/transports/grpc_asyncio.py +1207 -0
  75. google/pubsub_v1/services/subscriber/transports/rest.py +3561 -0
  76. google/pubsub_v1/services/subscriber/transports/rest_base.py +1024 -0
  77. google/pubsub_v1/types/__init__.py +169 -0
  78. google/pubsub_v1/types/pubsub.py +3478 -0
  79. google/pubsub_v1/types/schema.py +511 -0
  80. google_cloud_pubsub-2.30.0.data/scripts/fixup_pubsub_v1_keywords.py +210 -0
  81. google_cloud_pubsub-2.30.0.dist-info/METADATA +283 -0
  82. google_cloud_pubsub-2.30.0.dist-info/RECORD +85 -0
  83. google_cloud_pubsub-2.30.0.dist-info/WHEEL +5 -0
  84. google_cloud_pubsub-2.30.0.dist-info/licenses/LICENSE +202 -0
  85. google_cloud_pubsub-2.30.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,31 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright 2020 Google LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+
18
+ from __future__ import absolute_import
19
+
20
+ from google.cloud.pubsub_v1 import PublisherClient
21
+ from google.cloud.pubsub_v1 import SubscriberClient
22
+ from google.cloud.pubsub_v1 import SchemaServiceClient
23
+ from google.cloud.pubsub_v1 import types
24
+
25
+
26
+ __all__ = (
27
+ "types",
28
+ "PublisherClient",
29
+ "SubscriberClient",
30
+ "SchemaServiceClient",
31
+ )
@@ -0,0 +1,35 @@
1
+ # Copyright 2017, Google LLC 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
+ from __future__ import absolute_import
16
+
17
+ from google.cloud.pubsub_v1 import types
18
+ from google.cloud.pubsub_v1 import publisher
19
+ from google.cloud.pubsub_v1 import subscriber
20
+ from google.pubsub_v1.services import schema_service
21
+
22
+
23
+ class PublisherClient(publisher.Client):
24
+ __doc__ = publisher.Client.__doc__
25
+
26
+
27
+ class SubscriberClient(subscriber.Client):
28
+ __doc__ = subscriber.Client.__doc__
29
+
30
+
31
+ class SchemaServiceClient(schema_service.client.SchemaServiceClient):
32
+ __doc__ = schema_service.client.SchemaServiceClient.__doc__
33
+
34
+
35
+ __all__ = ("types", "PublisherClient", "SubscriberClient", "SchemaServiceClient")
@@ -0,0 +1,20 @@
1
+ # Copyright 2017, Google LLC 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
+ from __future__ import absolute_import
16
+
17
+ from concurrent.futures import TimeoutError
18
+
19
+
20
+ __all__ = ("TimeoutError",)
@@ -0,0 +1,56 @@
1
+ # Copyright 2017, Google LLC 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
+ from __future__ import absolute_import
16
+
17
+ import concurrent.futures
18
+ from typing import Any, NoReturn, Optional
19
+
20
+ import google.api_core.future
21
+
22
+
23
+ class Future(concurrent.futures.Future, google.api_core.future.Future):
24
+ """Encapsulation of the asynchronous execution of an action.
25
+
26
+ This object is returned from asychronous Pub/Sub calls, and is the
27
+ interface to determine the status of those calls.
28
+
29
+ This object should not be created directly, but is returned by other
30
+ methods in this library.
31
+ """
32
+
33
+ def running(self) -> bool:
34
+ """Return ``True`` if the associated Pub/Sub action has not yet completed."""
35
+ return not self.done()
36
+
37
+ def set_running_or_notify_cancel(self) -> NoReturn:
38
+ raise NotImplementedError(
39
+ "Only used by executors from `concurrent.futures` package."
40
+ )
41
+
42
+ def set_result(self, result: Any):
43
+ """Set the return value of work associated with the future.
44
+
45
+ Do not use this method, it should only be used internally by the library and its
46
+ unit tests.
47
+ """
48
+ return super().set_result(result=result)
49
+
50
+ def set_exception(self, exception: Optional[BaseException]):
51
+ """Set the result of the future as being the given exception.
52
+
53
+ Do not use this method, it should only be used internally by the library and its
54
+ unit tests.
55
+ """
56
+ return super().set_exception(exception=exception)
@@ -0,0 +1,13 @@
1
+ # Copyright 2024, Google LLC 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.
@@ -0,0 +1,55 @@
1
+ # Copyright 2024, Google LLC 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
+ from typing import Optional, List
16
+
17
+ from opentelemetry.propagators.textmap import Setter, Getter
18
+
19
+ from google.pubsub_v1 import PubsubMessage
20
+
21
+
22
+ class OpenTelemetryContextSetter(Setter):
23
+ """
24
+ Used by Open Telemetry for context propagation.
25
+ """
26
+
27
+ def set(self, carrier: PubsubMessage, key: str, value: str) -> None:
28
+ """
29
+ Injects trace context into Pub/Sub message attributes with
30
+ "googclient_" prefix.
31
+
32
+ Args:
33
+ carrier(PubsubMessage): The Pub/Sub message which is the carrier of Open Telemetry
34
+ data.
35
+ key(str): The key for which the Open Telemetry context data needs to be set.
36
+ value(str): The Open Telemetry context value to be set.
37
+
38
+ Returns:
39
+ None
40
+ """
41
+ carrier.attributes["googclient_" + key] = value
42
+
43
+
44
+ class OpenTelemetryContextGetter(Getter):
45
+ """
46
+ Used by Open Telemetry for context propagation.
47
+ """
48
+
49
+ def get(self, carrier: PubsubMessage, key: str) -> Optional[List[str]]:
50
+ if ("googclient_" + key) not in carrier.attributes:
51
+ return None
52
+ return [carrier.attributes["googclient_" + key]]
53
+
54
+ def keys(self, carrier: PubsubMessage) -> List[str]:
55
+ return list(map(str, carrier.attributes.keys()))
@@ -0,0 +1,142 @@
1
+ # Copyright 2017, Google LLC 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
+ import sys
16
+ from datetime import datetime
17
+ from typing import Optional
18
+
19
+ from opentelemetry import trace
20
+ from opentelemetry.trace.propagation import set_span_in_context
21
+ from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator
22
+
23
+ from google.pubsub_v1 import types as gapic_types
24
+ from google.cloud.pubsub_v1.open_telemetry.context_propagation import (
25
+ OpenTelemetryContextSetter,
26
+ )
27
+
28
+
29
+ class PublishMessageWrapper:
30
+ _OPEN_TELEMETRY_TRACER_NAME: str = "google.cloud.pubsub_v1"
31
+ _OPEN_TELEMETRY_MESSAGING_SYSTEM: str = "gcp_pubsub"
32
+ _OPEN_TELEMETRY_PUBLISHER_BATCHING = "publisher batching"
33
+
34
+ _PUBLISH_START_EVENT: str = "publish start"
35
+ _PUBLISH_FLOW_CONTROL: str = "publisher flow control"
36
+
37
+ def __init__(self, message: gapic_types.PubsubMessage):
38
+ self._message: gapic_types.PubsubMessage = message
39
+ self._create_span: Optional[trace.Span] = None
40
+ self._flow_control_span: Optional[trace.Span] = None
41
+ self._batching_span: Optional[trace.Span] = None
42
+
43
+ @property
44
+ def message(self):
45
+ return self._message
46
+
47
+ @message.setter # type: ignore[no-redef] # resetting message value is intentional here
48
+ def message(self, message: gapic_types.PubsubMessage):
49
+ self._message = message
50
+
51
+ @property
52
+ def create_span(self):
53
+ return self._create_span
54
+
55
+ def __eq__(self, other): # pragma: NO COVER
56
+ """Used for pytest asserts to compare two PublishMessageWrapper objects with the same message"""
57
+ if isinstance(self, other.__class__):
58
+ return self.message == other.message
59
+ return False
60
+
61
+ def start_create_span(self, topic: str, ordering_key: str) -> None:
62
+ tracer = trace.get_tracer(self._OPEN_TELEMETRY_TRACER_NAME)
63
+ assert len(topic.split("/")) == 4
64
+ topic_short_name = topic.split("/")[3]
65
+ with tracer.start_as_current_span(
66
+ name=f"{topic_short_name} create",
67
+ attributes={
68
+ "messaging.system": self._OPEN_TELEMETRY_MESSAGING_SYSTEM,
69
+ "messaging.destination.name": topic_short_name,
70
+ "code.function": "publish",
71
+ "messaging.gcp_pubsub.message.ordering_key": ordering_key,
72
+ "messaging.operation": "create",
73
+ "gcp.project_id": topic.split("/")[1],
74
+ "messaging.message.body.size": sys.getsizeof(
75
+ self._message.data
76
+ ), # sys.getsizeof() used since the attribute expects size of message body in bytes
77
+ },
78
+ kind=trace.SpanKind.PRODUCER,
79
+ end_on_exit=False,
80
+ ) as create_span:
81
+ create_span.add_event(
82
+ name=self._PUBLISH_START_EVENT,
83
+ attributes={
84
+ "timestamp": str(datetime.now()),
85
+ },
86
+ )
87
+ self._create_span = create_span
88
+ TraceContextTextMapPropagator().inject(
89
+ carrier=self._message,
90
+ setter=OpenTelemetryContextSetter(),
91
+ )
92
+
93
+ def end_create_span(self, exc: Optional[BaseException] = None) -> None:
94
+ assert self._create_span is not None
95
+ if exc:
96
+ self._create_span.record_exception(exception=exc)
97
+ self._create_span.set_status(
98
+ trace.Status(status_code=trace.StatusCode.ERROR)
99
+ )
100
+ self._create_span.end()
101
+
102
+ def start_publisher_flow_control_span(self) -> None:
103
+ tracer = trace.get_tracer(self._OPEN_TELEMETRY_TRACER_NAME)
104
+ assert self._create_span is not None
105
+ with tracer.start_as_current_span(
106
+ name=self._PUBLISH_FLOW_CONTROL,
107
+ kind=trace.SpanKind.INTERNAL,
108
+ context=set_span_in_context(self._create_span),
109
+ end_on_exit=False,
110
+ ) as flow_control_span:
111
+ self._flow_control_span = flow_control_span
112
+
113
+ def end_publisher_flow_control_span(
114
+ self, exc: Optional[BaseException] = None
115
+ ) -> None:
116
+ assert self._flow_control_span is not None
117
+ if exc:
118
+ self._flow_control_span.record_exception(exception=exc)
119
+ self._flow_control_span.set_status(
120
+ trace.Status(status_code=trace.StatusCode.ERROR)
121
+ )
122
+ self._flow_control_span.end()
123
+
124
+ def start_publisher_batching_span(self) -> None:
125
+ assert self._create_span is not None
126
+ tracer = trace.get_tracer(self._OPEN_TELEMETRY_TRACER_NAME)
127
+ with tracer.start_as_current_span(
128
+ name=self._OPEN_TELEMETRY_PUBLISHER_BATCHING,
129
+ kind=trace.SpanKind.INTERNAL,
130
+ context=set_span_in_context(self._create_span),
131
+ end_on_exit=False,
132
+ ) as batching_span:
133
+ self._batching_span = batching_span
134
+
135
+ def end_publisher_batching_span(self, exc: Optional[BaseException] = None) -> None:
136
+ assert self._batching_span is not None
137
+ if exc:
138
+ self._batching_span.record_exception(exception=exc)
139
+ self._batching_span.set_status(
140
+ trace.Status(status_code=trace.StatusCode.ERROR)
141
+ )
142
+ self._batching_span.end()
@@ -0,0 +1,280 @@
1
+ # Copyright 2024, Google LLC 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
+ from typing import Optional, List
16
+ from datetime import datetime
17
+
18
+ from opentelemetry import trace, context
19
+ from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator
20
+ from opentelemetry.trace.propagation import set_span_in_context
21
+
22
+ from google.cloud.pubsub_v1.open_telemetry.context_propagation import (
23
+ OpenTelemetryContextGetter,
24
+ )
25
+ from google.pubsub_v1.types import PubsubMessage
26
+
27
+ _OPEN_TELEMETRY_TRACER_NAME: str = "google.cloud.pubsub_v1"
28
+ _OPEN_TELEMETRY_MESSAGING_SYSTEM: str = "gcp_pubsub"
29
+
30
+
31
+ class SubscribeOpenTelemetry:
32
+ def __init__(self, message: PubsubMessage):
33
+ self._message: PubsubMessage = message
34
+
35
+ # subscribe span will be initialized by the `start_subscribe_span`
36
+ # method.
37
+ self._subscribe_span: Optional[trace.Span] = None
38
+
39
+ # subscriber concurrency control span will be initialized by the
40
+ # `start_subscribe_concurrency_control_span` method.
41
+ self._concurrency_control_span: Optional[trace.Span] = None
42
+
43
+ # scheduler span will be initialized by the
44
+ # `start_subscribe_scheduler_span` method.
45
+ self._scheduler_span: Optional[trace.Span] = None
46
+
47
+ # This will be set by `start_subscribe_span` method and will be used
48
+ # for other spans, such as process span.
49
+ self._subscription_id: Optional[str] = None
50
+
51
+ # This will be set by `start_process_span` method.
52
+ self._process_span: Optional[trace.Span] = None
53
+
54
+ # This will be set by `start_subscribe_span` method, if a publisher create span
55
+ # context was extracted from trace propagation. And will be used by spans like
56
+ # proces span to add links to the publisher create span.
57
+ self._publisher_create_span_context: Optional[context.Context] = None
58
+
59
+ # This will be set by `start_subscribe_span` method and will be used
60
+ # for other spans, such as modack span.
61
+ self._project_id: Optional[str] = None
62
+
63
+ @property
64
+ def subscription_id(self) -> Optional[str]:
65
+ return self._subscription_id
66
+
67
+ @property
68
+ def project_id(self) -> Optional[str]:
69
+ return self._project_id
70
+
71
+ @property
72
+ def subscribe_span(self) -> Optional[trace.Span]:
73
+ return self._subscribe_span
74
+
75
+ def start_subscribe_span(
76
+ self,
77
+ subscription: str,
78
+ exactly_once_enabled: bool,
79
+ ack_id: str,
80
+ delivery_attempt: int,
81
+ ) -> None:
82
+ tracer = trace.get_tracer(_OPEN_TELEMETRY_TRACER_NAME)
83
+ parent_span_context = TraceContextTextMapPropagator().extract(
84
+ carrier=self._message,
85
+ getter=OpenTelemetryContextGetter(),
86
+ )
87
+ self._publisher_create_span_context = parent_span_context
88
+ split_subscription: List[str] = subscription.split("/")
89
+ assert len(split_subscription) == 4
90
+ subscription_short_name = split_subscription[3]
91
+ self._project_id = split_subscription[1]
92
+ self._subscription_id = subscription_short_name
93
+ with tracer.start_as_current_span(
94
+ name=f"{subscription_short_name} subscribe",
95
+ context=parent_span_context if parent_span_context else None,
96
+ kind=trace.SpanKind.CONSUMER,
97
+ attributes={
98
+ "messaging.system": _OPEN_TELEMETRY_MESSAGING_SYSTEM,
99
+ "messaging.destination.name": subscription_short_name,
100
+ "gcp.project_id": subscription.split("/")[1],
101
+ "messaging.message.id": self._message.message_id,
102
+ "messaging.message.body.size": len(self._message.data),
103
+ "messaging.gcp_pubsub.message.ack_id": ack_id,
104
+ "messaging.gcp_pubsub.message.ordering_key": self._message.ordering_key,
105
+ "messaging.gcp_pubsub.message.exactly_once_delivery": exactly_once_enabled,
106
+ "code.function": "_on_response",
107
+ "messaging.gcp_pubsub.message.delivery_attempt": delivery_attempt,
108
+ },
109
+ end_on_exit=False,
110
+ ) as subscribe_span:
111
+ self._subscribe_span = subscribe_span
112
+
113
+ def add_subscribe_span_event(self, event: str) -> None:
114
+ assert self._subscribe_span is not None
115
+ self._subscribe_span.add_event(
116
+ name=event,
117
+ attributes={
118
+ "timestamp": str(datetime.now()),
119
+ },
120
+ )
121
+
122
+ def end_subscribe_span(self) -> None:
123
+ assert self._subscribe_span is not None
124
+ self._subscribe_span.end()
125
+
126
+ def set_subscribe_span_result(self, result: str) -> None:
127
+ assert self._subscribe_span is not None
128
+ self._subscribe_span.set_attribute(
129
+ key="messaging.gcp_pubsub.result",
130
+ value=result,
131
+ )
132
+
133
+ def start_subscribe_concurrency_control_span(self) -> None:
134
+ assert self._subscribe_span is not None
135
+ tracer = trace.get_tracer(_OPEN_TELEMETRY_TRACER_NAME)
136
+ with tracer.start_as_current_span(
137
+ name="subscriber concurrency control",
138
+ kind=trace.SpanKind.INTERNAL,
139
+ context=set_span_in_context(self._subscribe_span),
140
+ end_on_exit=False,
141
+ ) as concurrency_control_span:
142
+ self._concurrency_control_span = concurrency_control_span
143
+
144
+ def end_subscribe_concurrency_control_span(self) -> None:
145
+ assert self._concurrency_control_span is not None
146
+ self._concurrency_control_span.end()
147
+
148
+ def start_subscribe_scheduler_span(self) -> None:
149
+ assert self._subscribe_span is not None
150
+ tracer = trace.get_tracer(_OPEN_TELEMETRY_TRACER_NAME)
151
+ with tracer.start_as_current_span(
152
+ name="subscriber scheduler",
153
+ kind=trace.SpanKind.INTERNAL,
154
+ context=set_span_in_context(self._subscribe_span),
155
+ end_on_exit=False,
156
+ ) as scheduler_span:
157
+ self._scheduler_span = scheduler_span
158
+
159
+ def end_subscribe_scheduler_span(self) -> None:
160
+ assert self._scheduler_span is not None
161
+ self._scheduler_span.end()
162
+
163
+ def start_process_span(self) -> None:
164
+ assert self._subscribe_span is not None
165
+ tracer = trace.get_tracer(_OPEN_TELEMETRY_TRACER_NAME)
166
+ publish_create_span_link: Optional[trace.Link] = None
167
+ if self._publisher_create_span_context:
168
+ publish_create_span: trace.Span = trace.get_current_span(
169
+ self._publisher_create_span_context
170
+ )
171
+ span_context: Optional[
172
+ trace.SpanContext
173
+ ] = publish_create_span.get_span_context()
174
+ publish_create_span_link = (
175
+ trace.Link(span_context) if span_context else None
176
+ )
177
+
178
+ with tracer.start_as_current_span(
179
+ name=f"{self._subscription_id} process",
180
+ attributes={
181
+ "messaging.system": _OPEN_TELEMETRY_MESSAGING_SYSTEM,
182
+ },
183
+ kind=trace.SpanKind.INTERNAL,
184
+ context=set_span_in_context(self._subscribe_span),
185
+ links=[publish_create_span_link] if publish_create_span_link else None,
186
+ end_on_exit=False,
187
+ ) as process_span:
188
+ self._process_span = process_span
189
+
190
+ def end_process_span(self) -> None:
191
+ assert self._process_span is not None
192
+ self._process_span.end()
193
+
194
+ def add_process_span_event(self, event: str) -> None:
195
+ assert self._process_span is not None
196
+ self._process_span.add_event(
197
+ name=event,
198
+ attributes={
199
+ "timestamp": str(datetime.now()),
200
+ },
201
+ )
202
+
203
+
204
+ def start_modack_span(
205
+ subscribe_span_links: List[trace.Link],
206
+ subscription_id: Optional[str],
207
+ message_count: int,
208
+ deadline: float,
209
+ project_id: Optional[str],
210
+ code_function: str,
211
+ receipt_modack: bool,
212
+ ) -> trace.Span:
213
+ assert subscription_id is not None
214
+ assert project_id is not None
215
+ tracer = trace.get_tracer(_OPEN_TELEMETRY_TRACER_NAME)
216
+ with tracer.start_as_current_span(
217
+ name=f"{subscription_id} modack",
218
+ attributes={
219
+ "messaging.system": _OPEN_TELEMETRY_MESSAGING_SYSTEM,
220
+ "messaging.batch.message_count": message_count,
221
+ "messaging.gcp_pubsub.message.ack_deadline": deadline,
222
+ "messaging.destination.name": subscription_id,
223
+ "gcp.project_id": project_id,
224
+ "messaging.operation.name": "modack",
225
+ "code.function": code_function,
226
+ "messaging.gcp_pubsub.is_receipt_modack": receipt_modack,
227
+ },
228
+ links=subscribe_span_links,
229
+ kind=trace.SpanKind.CLIENT,
230
+ end_on_exit=False,
231
+ ) as modack_span:
232
+ return modack_span
233
+
234
+
235
+ def start_ack_span(
236
+ subscription_id: str,
237
+ message_count: int,
238
+ project_id: str,
239
+ links: List[trace.Link],
240
+ ) -> trace.Span:
241
+ tracer = trace.get_tracer(_OPEN_TELEMETRY_TRACER_NAME)
242
+ with tracer.start_as_current_span(
243
+ name=f"{subscription_id} ack",
244
+ attributes={
245
+ "messaging.system": _OPEN_TELEMETRY_MESSAGING_SYSTEM,
246
+ "messaging.batch.message_count": message_count,
247
+ "messaging.operation": "ack",
248
+ "gcp.project_id": project_id,
249
+ "messaging.destination.name": subscription_id,
250
+ "code.function": "ack",
251
+ },
252
+ kind=trace.SpanKind.CLIENT,
253
+ links=links,
254
+ end_on_exit=False,
255
+ ) as ack_span:
256
+ return ack_span
257
+
258
+
259
+ def start_nack_span(
260
+ subscription_id: str,
261
+ message_count: int,
262
+ project_id: str,
263
+ links: List[trace.Link],
264
+ ) -> trace.Span:
265
+ tracer = trace.get_tracer(_OPEN_TELEMETRY_TRACER_NAME)
266
+ with tracer.start_as_current_span(
267
+ name=f"{subscription_id} nack",
268
+ attributes={
269
+ "messaging.system": _OPEN_TELEMETRY_MESSAGING_SYSTEM,
270
+ "messaging.batch.message_count": message_count,
271
+ "messaging.operation": "nack",
272
+ "gcp.project_id": project_id,
273
+ "messaging.destination.name": subscription_id,
274
+ "code.function": "modify_ack_deadline",
275
+ },
276
+ kind=trace.SpanKind.CLIENT,
277
+ links=links,
278
+ end_on_exit=False,
279
+ ) as nack_span:
280
+ return nack_span