Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
@@ -1,4 +1,8 @@
# Release History

## 1.0.0b4 (2019-10-09)
This release has trivial internal changes only. No feature changes.

## 1.0.0b1 (2019-09-10)

**New features**
Expand Down
16 changes: 14 additions & 2 deletions sdk/eventhub/azure-eventhubs/HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
# Release History

## 5.0.0b4 (2019-XX-XX)
## 5.0.0b4 (2019-10-08)

**New features**

- Support for tracing #7153
- Added support for tracing (issue #7153).
- Added the capability of tracking last enqueued event properties of the partition to `EventHubConsumer` .
- Added new boolean type parameter`track_last_enqueued_event_properties` in method `EventHubClient.create_consumer()`.
- Added new property `last_enqueued_event_properties` of on `EventHubConsumer` which contains sequence_number, offset, enqueued_time and retrieval_time information.
- By default the capability is disabled as it will cost extra band width for transferring more information if turned on.

**Breaking changes**

- Removed support for IoT Hub direct connection.
- [EventHubs compatible connection string](https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-messages-read-builtin) of an IotHub can be used to create `EventHubClient` and read properties or events from an IoT Hub.
- Removed support for sending EventData to IoT Hub.
- Removed parameter `exception` in method `close()` of `EventHubConsumer` and `EventHubProcuer`.
- Updated uAMQP dependency to 1.2.3.

## 5.0.0b3 (2019-09-10)

Expand Down
21 changes: 20 additions & 1 deletion sdk/eventhub/azure-eventhubs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ The Azure Event Hubs client library allows for publishing and consuming of Azure
- Observe interesting operations and interactions happening within your business or other ecosystem, allowing loosely coupled systems to interact without the need to bind them together.
- Receive events from one or more publishers, transform them to better meet the needs of your ecosystem, then publish the transformed events to a new stream for consumers to observe.

[Source code](https://github.com/Azure/azure-sdk-for-python/tree/master/sdk/eventhub/azure-eventhubs) | [Package (PyPi)](https://pypi.org/project/azure-eventhub/5.0.0b3) | [API reference documentation](https://azure.github.io/azure-sdk-for-python/ref/azure.eventhub) | [Product documentation](https://docs.microsoft.com/en-us/azure/event-hubs/)
[Source code](https://github.com/Azure/azure-sdk-for-python/tree/master/sdk/eventhub/azure-eventhubs) | [Package (PyPi)](https://pypi.org/project/azure-eventhub/5.0.0b4) | [API reference documentation](https://azure.github.io/azure-sdk-for-python/ref/azure.eventhub) | [Product documentation](https://docs.microsoft.com/en-us/azure/event-hubs/)

## Getting started

Expand Down Expand Up @@ -119,6 +119,7 @@ The following sections provide several code snippets covering some of the most c
- [Async publish events to an Event Hub](#async-publish-events-to-an-event-hub)
- [Async consume events from an Event Hub](#async-consume-events-from-an-event-hub)
- [Consume events using an Event Processor](#consume-events-using-an-event-processor)
- [Use EventHubClient to work with IoT Hub](#use-eventhubclient-to-work-with-iot-hub)

### Inspect an Event Hub

Expand Down Expand Up @@ -359,6 +360,24 @@ if __name__ == '__main__':
loop.run_until_complete(main())
```

### Use EventHubClient to work with IoT Hub

You can use `EventHubClient` to work with IoT Hub as well. This is useful for receiving telemetry data of IoT Hub from the
linked EventHub. The associated connection string will not have send claims, hence sending events is not possible.

- Please notice that the connection string needs to be for an
[Event Hub-compatible endpoint](https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-messages-read-builtin)
e.g. "Endpoint=sb://my-iothub-namespace-[uid].servicebus.windows.net/;SharedAccessKeyName=my-SA-name;SharedAccessKey=my-SA-key;EntityPath=my-iot-hub-name"

```python
from azure.eventhub import EventHubClient

connection_str = 'Endpoint=sb://my-iothub-namespace-[uid].servicebus.windows.net/;SharedAccessKeyName=my-SA-name;SharedAccessKey=my-SA-key;EntityPath=my-iot-hub-name'
client = EventHubClient.from_connection_string(connection_str)

partition_ids = client.get_partition_ids()
```

## Troubleshooting

### General
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,46 +18,34 @@ def __init__(self):
self._client = None
self._handler = None
self._name = None
self._running = False
self._closed = False

def __enter__(self):
return self

def __exit__(self, exc_type, exc_val, exc_tb):
self.close(exc_val)
self.close()

def _check_closed(self):
if self._error:
if self._closed:
raise EventHubError("{} has been closed. Please create a new one to handle event data.".format(self._name))

def _create_handler(self):
pass

def _redirect(self, redirect):
self._redirected = redirect
self._running = False
self._close_connection()

def _open(self):
"""
Open the EventHubConsumer/EventHubProducer using the supplied connection.
If the handler has previously been redirected, the redirect
context will be used to create a new handler before opening it.
"""Open the EventHubConsumer/EventHubProducer using the supplied connection.

"""
# pylint: disable=protected-access
if not self._running:
if self._handler:
self._handler.close()
if self._redirected:
alt_creds = {
"username": self._client._auth_config.get("iot_username"),
"password": self._client._auth_config.get("iot_password")}
else:
alt_creds = {}
self._create_handler()
self._handler.open(connection=self._client._conn_manager.get_connection( # pylint: disable=protected-access
self._client._address.hostname,
self._client._get_auth(**alt_creds)
self._client._create_auth()
))
while not self._handler.client_ready():
time.sleep(0.05)
Expand All @@ -66,7 +54,8 @@ def _open(self):
self._running = True

def _close_handler(self):
self._handler.close() # close the link (sharing connection) or connection (not sharing)
if self._handler:
self._handler.close() # close the link (sharing connection) or connection (not sharing)
self._running = False

def _close_connection(self):
Expand All @@ -76,8 +65,6 @@ def _close_connection(self):
def _handle_exception(self, exception):
if not self._running and isinstance(exception, compat.TimeoutException):
exception = errors.AuthenticationException("Authorization timeout.")
return _handle_exception(exception, self)

return _handle_exception(exception, self)

def _do_retryable_operation(self, operation, timeout=100000, **kwargs):
Expand All @@ -102,16 +89,11 @@ def _do_retryable_operation(self, operation, timeout=100000, **kwargs):
log.info("%r operation has exhausted retry. Last exception: %r.", self._name, last_exception)
raise last_exception

def close(self, exception=None):
# type:(Exception) -> None
def close(self):
# type:() -> None
"""
Close down the handler. If the handler has already closed,
this will be a no op. An optional exception can be passed in to
indicate that the handler was shutdown due to error.

:param exception: An optional exception if the handler is closing
due to an error.
:type exception: Exception
this will be a no op.

Example:
.. literalinclude:: ../examples/test_examples_eventhub.py
Expand All @@ -122,16 +104,7 @@ def close(self, exception=None):
:caption: Close down the handler.

"""
self._running = False
if self._error: # type: ignore
return
if isinstance(exception, errors.LinkRedirect):
self._redirected = exception
elif isinstance(exception, EventHubError):
self._error = exception
elif exception:
self._error = EventHubError(str(exception))
else:
self._error = EventHubError("{} handler is closed.".format(self._name))
if self._handler:
self._handler.close() # this will close link if sharing connection. Otherwise close connection
self._running = False
self._closed = True
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import time

from uamqp import errors, constants, compat # type: ignore
from azure.eventhub.error import EventHubError, ConnectError
from azure.eventhub.error import EventHubError
from ..aio.error_async import _handle_exception

log = logging.getLogger(__name__)
Expand All @@ -19,46 +19,35 @@ def __init__(self):
self._client = None
self._handler = None
self._name = None
self._running = False
self._closed = False

async def __aenter__(self):
return self

async def __aexit__(self, exc_type, exc_val, exc_tb):
await self.close(exc_val)
await self.close()

def _check_closed(self):
if self._error:
if self._closed:
raise EventHubError("{} has been closed. Please create a new one to handle event data.".format(self._name))

def _create_handler(self):
pass

async def _redirect(self, redirect):
self._redirected = redirect
self._running = False
await self._close_connection()

async def _open(self):
"""
Open the EventHubConsumer using the supplied connection.
If the handler has previously been redirected, the redirect
context will be used to create a new handler before opening it.

"""
# pylint: disable=protected-access
if not self._running:
if self._handler:
await self._handler.close_async()
if self._redirected:
alt_creds = {
"username": self._client._auth_config.get("iot_username"),
"password": self._client._auth_config.get("iot_password")}
else:
alt_creds = {}
self._create_handler()
await self._handler.open_async(connection=await self._client._conn_manager.get_connection(
self._client._address.hostname,
self._client._get_auth(**alt_creds)
self._client._create_auth()
))
while not await self._handler.client_ready_async():
await asyncio.sleep(0.05)
Expand All @@ -67,7 +56,8 @@ async def _open(self):
self._running = True

async def _close_handler(self):
await self._handler.close_async() # close the link (sharing connection) or connection (not sharing)
if self._handler:
await self._handler.close_async() # close the link (sharing connection) or connection (not sharing)
self._running = False

async def _close_connection(self):
Expand Down Expand Up @@ -103,16 +93,11 @@ async def _do_retryable_operation(self, operation, timeout=100000, **kwargs):
log.info("%r operation has exhausted retry. Last exception: %r.", self._name, last_exception)
raise last_exception

async def close(self, exception=None):
# type: (Exception) -> None
async def close(self):
# type: () -> None
"""
Close down the handler. If the handler has already closed,
this will be a no op. An optional exception can be passed in to
indicate that the handler was shutdown due to error.

:param exception: An optional exception if the handler is closing
due to an error.
:type exception: Exception
this will be a no op.

Example:
.. literalinclude:: ../examples/async_examples/test_examples_eventhub_async.py
Expand All @@ -123,18 +108,7 @@ async def close(self, exception=None):
:caption: Close down the handler.

"""
self._running = False
if self._error: #type: ignore
return
if isinstance(exception, errors.LinkRedirect):
self._redirected = exception
elif isinstance(exception, EventHubError):
self._error = exception
elif isinstance(exception, (errors.LinkDetach, errors.ConnectionClose)):
self._error = ConnectError(str(exception), exception)
elif exception:
self._error = EventHubError(str(exception))
else:
self._error = EventHubError("This receive handler is now closed.")
if self._handler:
await self._handler.close_async()
self._running = False
self._closed = True
Loading