Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ServiceBus] Adjust user-agent following the guideline #12596

Merged
merged 4 commits into from
Jul 21, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def __init__(
self._running = False
self._handler = None # type: uamqp.AMQPClient
self._auth_uri = None
self._properties = create_properties()
self._properties = create_properties(self._config.user_agent)

def __enter__(self):
self._open_with_retry()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,24 @@

from uamqp.constants import TransportType

from .constants import MAX_USER_AGENT_LENGTH


class Configuration(object): # pylint:disable=too-many-instance-attributes
def __init__(self, **kwargs):
self.user_agent = kwargs.get("user_agent") # type: Optional[str]

if self.user_agent:
if len(self.user_agent) > MAX_USER_AGENT_LENGTH:
raise ValueError(
"The user-agent string cannot be more than {} in length."
"The length of the provided string is: {}".format(
MAX_USER_AGENT_LENGTH, len(self.user_agent)
)
)
if ' ' in self.user_agent:
KieranBrantnerMagee marked this conversation as resolved.
Show resolved Hide resolved
raise ValueError("The user-agent string must not contain a space.")

self.retry_total = kwargs.get("retry_total", 3) # type: int
self.retry_backoff_factor = kwargs.get("retry_backoff_factor", 0.8) # type: float
self.retry_backoff_max = kwargs.get("retry_backoff_max", 120) # type: int
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@
_X_OPT_LOCK_TOKEN = b'x-opt-lock-token'
_X_OPT_SCHEDULED_ENQUEUE_TIME = b'x-opt-scheduled-enqueue-time'

MAX_USER_AGENT_LENGTH = 24
USER_AGENT_PREFIX = "azsdk-python-servicebus"
KieranBrantnerMagee marked this conversation as resolved.
Show resolved Hide resolved


DEAD_LETTER_QUEUE_SUFFIX = '/$DeadLetterQueue'
TRANSFER_DEAD_LETTER_QUEUE_SUFFIX = '/$Transfer' + DEAD_LETTER_QUEUE_SUFFIX
Expand Down
40 changes: 32 additions & 8 deletions sdk/servicebus/azure-servicebus/azure/servicebus/_common/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,25 @@
import threading
import time
import functools
import platform
from typing import Optional, Dict
try:
from urlparse import urlparse
except ImportError:
from urllib.parse import urlparse
from concurrent.futures import ThreadPoolExecutor

from uamqp import authentication
from uamqp import authentication, types

from ..exceptions import AutoLockRenewFailed, AutoLockRenewTimeout, ServiceBusError
from .._version import VERSION as sdk_version
from .._version import VERSION
from .constants import (
JWT_TOKEN_SCOPE,
TOKEN_TYPE_JWT,
TOKEN_TYPE_SASTOKEN,
DEAD_LETTER_QUEUE_SUFFIX,
TRANSFER_DEAD_LETTER_QUEUE_SUFFIX
TRANSFER_DEAD_LETTER_QUEUE_SUFFIX,
USER_AGENT_PREFIX
)

_log = logging.getLogger(__name__)
Expand Down Expand Up @@ -93,12 +96,33 @@ def build_uri(address, entity):
return address


def create_properties():
def create_properties(user_agent=None):
# type: (Optional[str]) -> Dict[types.AMQPSymbol, str]
"""
Format the properties with which to instantiate the connection.
This acts like a user agent over HTTP.

:param str user_agent: If specified, this will be added in front of the built-in user agent string.

:rtype: dict
"""
properties = {}
properties["product"] = "servicebus.python"
properties["version"] = sdk_version
properties["framework"] = "Python {}.{}.{}".format(*sys.version_info[0:3])
properties["platform"] = sys.platform
properties[types.AMQPSymbol("product")] = USER_AGENT_PREFIX
properties[types.AMQPSymbol("version")] = VERSION
framework = "Python/{}.{}.{}".format(
sys.version_info[0], sys.version_info[1], sys.version_info[2]
)
properties[types.AMQPSymbol("framework")] = framework
platform_str = platform.platform()
properties[types.AMQPSymbol("platform")] = platform_str

final_user_agent = "{}/{} {} ({})".format(
USER_AGENT_PREFIX, VERSION, framework, platform_str
)
if user_agent:
final_user_agent = "{} {}".format(user_agent, final_user_agent)

properties[types.AMQPSymbol("user-agent")] = final_user_agent
return properties


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class ServiceBusClient(object):
:keyword dict http_proxy: HTTP proxy settings. This must be a dictionary with the following
keys: `'proxy_hostname'` (str value) and `'proxy_port'` (int value).
Additionally the following keys may also be present: `'username', 'password'`.
:keyword str user_agent: If specified, this will be added in front of the built-in user agent string.

.. admonition:: Example:

Expand Down Expand Up @@ -115,6 +116,7 @@ def from_connection_string(
:keyword dict http_proxy: HTTP proxy settings. This must be a dictionary with the following
keys: `'proxy_hostname'` (str value) and `'proxy_port'` (int value).
Additionally the following keys may also be present: `'username', 'password'`.
:keyword str user_agent: If specified, this will be added in front of the built-in user agent string.
:rtype: ~azure.servicebus.ServiceBusClient

.. admonition:: Example:
Expand Down Expand Up @@ -163,6 +165,7 @@ def get_queue_sender(self, queue_name, **kwargs):
transport_type=self._config.transport_type,
http_proxy=self._config.http_proxy,
connection=self._connection,
user_agent=self._config.user_agent,
**kwargs
)

Expand Down Expand Up @@ -210,6 +213,7 @@ def get_queue_receiver(self, queue_name, **kwargs):
transport_type=self._config.transport_type,
http_proxy=self._config.http_proxy,
connection=self._connection,
user_agent=self._config.user_agent,
**kwargs
)

Expand Down Expand Up @@ -270,6 +274,7 @@ def get_queue_deadletter_receiver(self, queue_name, **kwargs):
http_proxy=self._config.http_proxy,
connection=self._connection,
is_dead_letter_receiver=True,
user_agent=self._config.user_agent,
**kwargs
)

Expand Down Expand Up @@ -303,6 +308,7 @@ def get_topic_sender(self, topic_name, **kwargs):
transport_type=self._config.transport_type,
http_proxy=self._config.http_proxy,
connection=self._connection,
user_agent=self._config.user_agent,
**kwargs
)

Expand Down Expand Up @@ -356,6 +362,7 @@ def get_subscription_receiver(self, topic_name, subscription_name, **kwargs):
transport_type=self._config.transport_type,
http_proxy=self._config.http_proxy,
connection=self._connection,
user_agent=self._config.user_agent,
**kwargs
)

Expand Down Expand Up @@ -418,6 +425,7 @@ def get_subscription_deadletter_receiver(self, topic_name, subscription_name, **
http_proxy=self._config.http_proxy,
connection=self._connection,
is_dead_letter_receiver=True,
user_agent=self._config.user_agent,
**kwargs
)

Expand Down Expand Up @@ -475,6 +483,7 @@ def get_subscription_session_receiver(self, topic_name, subscription_name, sessi
http_proxy=self._config.http_proxy,
connection=self._connection,
session_id=session_id,
user_agent=self._config.user_agent,
**kwargs
)

Expand Down Expand Up @@ -526,5 +535,6 @@ def get_queue_session_receiver(self, queue_name, session_id=None, **kwargs):
session_id=session_id,
transport_type=self._config.transport_type,
http_proxy=self._config.http_proxy,
user_agent=self._config.user_agent,
**kwargs
)
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class ServiceBusReceiver(BaseHandler, ReceiverMixin): # pylint: disable=too-man
:keyword dict http_proxy: HTTP proxy settings. This must be a dictionary with the following
keys: `'proxy_hostname'` (str value) and `'proxy_port'` (int value).
Additionally the following keys may also be present: `'username', 'password'`.
:keyword str user_agent: If specified, this will be added in front of the built-in user agent string.
:keyword int prefetch: The maximum number of messages to cache with each request to the service.
This setting is only for advanced performance tuning. Increasing this value will improve message throughput
performance but increase the chance that messages will expire while they are cached if they're not
Expand Down Expand Up @@ -290,6 +291,7 @@ def from_connection_string(
:keyword dict http_proxy: HTTP proxy settings. This must be a dictionary with the following
keys: `'proxy_hostname'` (str value) and `'proxy_port'` (int value).
Additionally the following keys may also be present: `'username', 'password'`.
:keyword str user_agent: If specified, this will be added in front of the built-in user agent string.
:keyword int prefetch: The maximum number of messages to cache with each request to the service.
This setting is only for advanced performance tuning. Increasing this value will improve message throughput
performance but increase the chance that messages will expire while they are cached if they're not
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ class ServiceBusSender(BaseHandler, SenderMixin):
:keyword dict http_proxy: HTTP proxy settings. This must be a dictionary with the following
keys: `'proxy_hostname'` (str value) and `'proxy_port'` (int value).
Additionally the following keys may also be present: `'username', 'password'`.
:keyword str user_agent: If specified, this will be added in front of the built-in user agent string.

.. admonition:: Example:

Expand Down Expand Up @@ -276,6 +277,7 @@ def from_connection_string(
:keyword dict http_proxy: HTTP proxy settings. This must be a dictionary with the following
keys: `'proxy_hostname'` (str value) and `'proxy_port'` (int value).
Additionally the following keys may also be present: `'username', 'password'`.
:keyword str user_agent: If specified, this will be added in front of the built-in user agent string.
:rtype: ~azure.servicebus.ServiceBusSenderClient

.. admonition:: Example:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ class ServiceBusSessionReceiver(ServiceBusReceiver, SessionReceiverMixin):
the client connects to.
:keyword str subscription_name: The path of specific Service Bus Subscription under the
specified Topic the client connects to.
:keyword int prefetch: The maximum number of messages to cache with each request to the service.
The default value is 0, meaning messages will be received from the service and processed
one at a time. Increasing this value will improve message throughput performance but increase
the change that messages will expire while they are cached if they're not processed fast enough.
:keyword float idle_timeout: The timeout in seconds between received messages after which the receiver will
automatically shutdown. The default value is 0, meaning no timeout.
:keyword mode: The mode with which messages will be retrieved from the entity. The two options
Expand All @@ -66,6 +62,14 @@ class ServiceBusSessionReceiver(ServiceBusReceiver, SessionReceiverMixin):
:keyword dict http_proxy: HTTP proxy settings. This must be a dictionary with the following
keys: `'proxy_hostname'` (str value) and `'proxy_port'` (int value).
Additionally the following keys may also be present: `'username', 'password'`.
:keyword str user_agent: If specified, this will be added in front of the built-in user agent string.
:keyword int prefetch: The maximum number of messages to cache with each request to the service.
This setting is only for advanced performance tuning. Increasing this value will improve message throughput
performance but increase the chance that messages will expire while they are cached if they're not
processed fast enough.
The default value is 0, meaning messages will be received from the service and processed one at a time.
In the case of prefetch being 0, `ServiceBusReceiver.receive` would try to cache `max_batch_size` (if provided)
within its request to the service.

.. admonition:: Example:

Expand Down Expand Up @@ -128,10 +132,6 @@ def from_connection_string(
sessionful entity, otherwise it must be None. In order to receive messages from the next available
session, set this to None. The default is None.
:paramtype session_id: str
:keyword int prefetch: The maximum number of messages to cache with each request to the service.
The default value is 0, meaning messages will be received from the service and processed
one at a time. Increasing this value will improve message throughput performance but increase
the change that messages will expire while they are cached if they're not processed fast enough.
:keyword float idle_timeout: The timeout in seconds between received messages after which the receiver will
automatically shutdown. The default value is 0, meaning no timeout.
:keyword bool logging_enable: Whether to output network trace logs to the logger. Default is `False`.
Expand All @@ -143,6 +143,14 @@ def from_connection_string(
:keyword dict http_proxy: HTTP proxy settings. This must be a dictionary with the following
keys: `'proxy_hostname'` (str value) and `'proxy_port'` (int value).
Additionally the following keys may also be present: `'username', 'password'`.
:keyword str user_agent: If specified, this will be added in front of the built-in user agent string.
:keyword int prefetch: The maximum number of messages to cache with each request to the service.
This setting is only for advanced performance tuning. Increasing this value will improve message throughput
performance but increase the chance that messages will expire while they are cached if they're not
processed fast enough.
The default value is 0, meaning messages will be received from the service and processed one at a time.
In the case of prefetch being 0, `ServiceBusReceiver.receive` would try to cache `max_batch_size` (if provided)
within its request to the service.
:rtype: ~azure.servicebus.ServiceBusSessionReceiver

.. admonition:: Example:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def __init__(
self._running = False
self._handler = None # type: uamqp.AMQPClient
self._auth_uri = None
self._properties = create_properties()
self._properties = create_properties(self._config.user_agent)

async def __aenter__(self):
await self._open_with_retry()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class ServiceBusClient(object):
:keyword dict http_proxy: HTTP proxy settings. This must be a dictionary with the following
keys: `'proxy_hostname'` (str value) and `'proxy_port'` (int value).
Additionally the following keys may also be present: `'username', 'password'`.
:keyword str user_agent: If specified, this will be added in front of the built-in user agent string.

.. admonition:: Example:

Expand Down Expand Up @@ -107,6 +108,7 @@ def from_connection_string(
:keyword dict http_proxy: HTTP proxy settings. This must be a dictionary with the following
keys: `'proxy_hostname'` (str value) and `'proxy_port'` (int value).
Additionally the following keys may also be present: `'username', 'password'`.
:keyword str user_agent: If specified, this will be added in front of the built-in user agent string.
:rtype: ~azure.servicebus.aio.ServiceBusClient

.. admonition:: Example:
Expand Down Expand Up @@ -165,6 +167,7 @@ def get_queue_sender(self, queue_name, **kwargs):
transport_type=self._config.transport_type,
http_proxy=self._config.http_proxy,
connection=self._connection,
user_agent=self._config.user_agent,
**kwargs
)

Expand Down Expand Up @@ -211,6 +214,7 @@ def get_queue_receiver(self, queue_name, **kwargs):
transport_type=self._config.transport_type,
http_proxy=self._config.http_proxy,
connection=self._connection,
user_agent=self._config.user_agent,
**kwargs
)

Expand Down Expand Up @@ -271,6 +275,7 @@ def get_queue_deadletter_receiver(self, queue_name, **kwargs):
http_proxy=self._config.http_proxy,
connection=self._connection,
is_dead_letter_receiver=True,
user_agent=self._config.user_agent,
**kwargs
)

Expand Down Expand Up @@ -304,6 +309,7 @@ def get_topic_sender(self, topic_name, **kwargs):
transport_type=self._config.transport_type,
http_proxy=self._config.http_proxy,
connection=self._connection,
user_agent=self._config.user_agent,
**kwargs
)

Expand Down Expand Up @@ -357,6 +363,7 @@ def get_subscription_receiver(self, topic_name, subscription_name, **kwargs):
transport_type=self._config.transport_type,
http_proxy=self._config.http_proxy,
connection=self._connection,
user_agent=self._config.user_agent,
**kwargs
)

Expand Down Expand Up @@ -419,6 +426,7 @@ def get_subscription_deadletter_receiver(self, topic_name, subscription_name, **
http_proxy=self._config.http_proxy,
connection=self._connection,
is_dead_letter_receiver=True,
user_agent=self._config.user_agent,
**kwargs
)

Expand Down Expand Up @@ -476,6 +484,7 @@ def get_subscription_session_receiver(self, topic_name, subscription_name, sessi
http_proxy=self._config.http_proxy,
connection=self._connection,
session_id=session_id,
user_agent=self._config.user_agent,
**kwargs
)

Expand Down Expand Up @@ -526,5 +535,6 @@ def get_queue_session_receiver(self, queue_name, session_id=None, **kwargs):
session_id=session_id,
transport_type=self._config.transport_type,
http_proxy=self._config.http_proxy,
user_agent=self._config.user_agent,
**kwargs
)
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class ServiceBusReceiver(collections.abc.AsyncIterator, BaseHandler, ReceiverMix
:keyword dict http_proxy: HTTP proxy settings. This must be a dictionary with the following
keys: `'proxy_hostname'` (str value) and `'proxy_port'` (int value).
Additionally the following keys may also be present: `'username', 'password'`.
:keyword str user_agent: If specified, this will be added in front of the built-in user agent string.
:keyword int prefetch: The maximum number of messages to cache with each request to the service.
This setting is only for advanced performance tuning. Increasing this value will improve message throughput
performance but increase the chance that messages will expire while they are cached if they're not
Expand Down Expand Up @@ -279,6 +280,7 @@ def from_connection_string(
:keyword dict http_proxy: HTTP proxy settings. This must be a dictionary with the following
keys: `'proxy_hostname'` (str value) and `'proxy_port'` (int value).
Additionally the following keys may also be present: `'username', 'password'`.
:keyword str user_agent: If specified, this will be added in front of the built-in user agent string.
:keyword int prefetch: The maximum number of messages to cache with each request to the service.
This setting is only for advanced performance tuning. Increasing this value will improve message throughput
performance but increase the chance that messages will expire while they are cached if they're not
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class ServiceBusSender(BaseHandler, SenderMixin):
:keyword dict http_proxy: HTTP proxy settings. This must be a dictionary with the following
keys: `'proxy_hostname'` (str value) and `'proxy_port'` (int value).
Additionally the following keys may also be present: `'username', 'password'`.
:keyword str user_agent: If specified, this will be added in front of the built-in user agent string.

.. admonition:: Example:

Expand Down Expand Up @@ -217,6 +218,7 @@ def from_connection_string(
:keyword dict http_proxy: HTTP proxy settings. This must be a dictionary with the following
keys: `'proxy_hostname'` (str value) and `'proxy_port'` (int value).
Additionally the following keys may also be present: `'username', 'password'`.
:keyword str user_agent: If specified, this will be added in front of the built-in user agent string.
:rtype: ~azure.servicebus.aio.ServiceBusSender

.. admonition:: Example:
Expand Down
Loading