-
Notifications
You must be signed in to change notification settings - Fork 462
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Metrics Collector: Roll back configurable
TransportType
+ bug fix (#…
…6665) Three conceptual changes: 1. Rolling support back for configurable `TransportType` as MetricsCollector is a mature product not expected to take on new features like this. Configurable transport type will not be supported in our future products for collecting metrics, so don't want to mislead customers. That change was in this PR: #6656 2. Keeping the bug fix from that PR though. Bug description from changelog: > "Fix bug where failing connection to EdgeHub blocks independent AzureMonitor upload path". 3. Fixing bug where module won't shutdown if UploadTarget is IoTMessage and client cannot be recreated. Now it will shutdown in this case to be restarted by EdgeHub. If UploadTarget is AzureMonitor and client cannot be created, this is ignored and won't effect MetricsCollector operation as no metrics will be sent. In order to achieve this I have created a composition pattern around ModuleClientWrapper where there are separate implementations for AzureMonitor and IoTMessage upload paths. ## Azure IoT Edge PR checklist:
- Loading branch information
1 parent
e171a1f
commit 14c78fe
Showing
10 changed files
with
255 additions
and
144 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
102 changes: 0 additions & 102 deletions
102
edge-modules/metrics-collector/src/ModuleClientWrapper.cs
This file was deleted.
Oops, something went wrong.
66 changes: 66 additions & 0 deletions
66
edge-modules/metrics-collector/src/ModuleClientWrapper/AzureMonitorModuleClientWrapper.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
using System; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.Azure.Devices.Client; | ||
using Microsoft.Azure.Devices.Edge.Util; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace Microsoft.Azure.Devices.Edge.Azure.Monitor.ModuleClientWrapper | ||
{ | ||
public class AzureMonitorClientWrapper : IDisposable, IModuleClientWrapper | ||
{ | ||
Option<BasicModuleClientWrapper> inner; | ||
|
||
public AzureMonitorClientWrapper(Option<BasicModuleClientWrapper> basicModuleClientWrapper) | ||
{ | ||
this.inner = basicModuleClientWrapper; | ||
} | ||
|
||
public static Task<AzureMonitorClientWrapper> BuildModuleClientWrapperAsync() | ||
{ | ||
// Don't try to initialize client so this call won't block. | ||
return Task.FromResult(new AzureMonitorClientWrapper(Option.None<BasicModuleClientWrapper>())); | ||
} | ||
|
||
public async Task RecreateClientAsync() | ||
{ | ||
await this.inner.Match(async (BasicModuleClientWrapper) => | ||
{ | ||
try | ||
{ | ||
await BasicModuleClientWrapper.RecreateClientAsync(); | ||
} | ||
catch (Exception) | ||
{ | ||
this.inner = Option.None<BasicModuleClientWrapper>(); | ||
} | ||
}, async () => | ||
{ | ||
try | ||
{ | ||
this.inner = Option.Some(await BasicModuleClientWrapper.BuildModuleClientWrapperAsync()); | ||
} | ||
catch (Exception) | ||
{ | ||
this.inner = Option.None<BasicModuleClientWrapper>(); | ||
} | ||
}); | ||
} | ||
|
||
public Task SendMessageAsync(string outputName, Message message) | ||
{ | ||
throw new Exception("Not expected to send metrics to IoT Hub when upload target is AzureMonitor"); | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
this.inner.ForEach((basicModuleClientWrapper) => | ||
{ | ||
basicModuleClientWrapper.Dispose(); | ||
}); | ||
} | ||
} | ||
} | ||
|
||
|
||
|
87 changes: 87 additions & 0 deletions
87
edge-modules/metrics-collector/src/ModuleClientWrapper/BasicModuleClientWrapper.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
using System; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.Azure.Devices.Client; | ||
using Microsoft.Azure.Devices.Edge.Util; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace Microsoft.Azure.Devices.Edge.Azure.Monitor.ModuleClientWrapper | ||
{ | ||
public class BasicModuleClientWrapper : IDisposable, IModuleClientWrapper | ||
{ | ||
ModuleClient inner; | ||
SemaphoreSlim moduleClientLock; | ||
|
||
public BasicModuleClientWrapper(ModuleClient moduleClient, SemaphoreSlim moduleClientLock) | ||
{ | ||
this.inner = moduleClient; | ||
this.moduleClientLock = Preconditions.CheckNotNull(moduleClientLock); | ||
} | ||
|
||
public static async Task<BasicModuleClientWrapper> BuildModuleClientWrapperAsync() | ||
{ | ||
SemaphoreSlim moduleClientLock = new SemaphoreSlim(1, 1); | ||
ModuleClient moduleClient = await InitializeModuleClientAsync(); | ||
return new BasicModuleClientWrapper(moduleClient, moduleClientLock); | ||
} | ||
|
||
public async Task RecreateClientAsync() | ||
{ | ||
|
||
await this.moduleClientLock.WaitAsync(); | ||
|
||
try | ||
{ | ||
this.inner.Dispose(); | ||
this.inner = await InitializeModuleClientAsync(); | ||
LoggerUtil.Writer.LogInformation("Closed and re-established connection to IoT Hub"); | ||
} | ||
catch (Exception) | ||
{ | ||
this.moduleClientLock.Release(); | ||
throw; | ||
} | ||
|
||
this.moduleClientLock.Release(); | ||
} | ||
|
||
public async Task SendMessageAsync(string outputName, Message message) | ||
{ | ||
await this.moduleClientLock.WaitAsync(); | ||
|
||
try | ||
{ | ||
await this.inner.SendEventAsync(outputName, message); | ||
LoggerUtil.Writer.LogInformation("Successfully sent metrics via IoT message"); | ||
} | ||
catch (Exception) | ||
{ | ||
this.moduleClientLock.Release(); | ||
throw; | ||
} | ||
|
||
this.moduleClientLock.Release(); | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
this.inner.Dispose(); | ||
this.moduleClientLock.Dispose(); | ||
} | ||
|
||
static async Task<ModuleClient> InitializeModuleClientAsync() | ||
{ | ||
TransportType transportType = TransportType.Amqp_Tcp_Only; | ||
LoggerUtil.Writer.LogInformation($"Trying to initialize module client using transport type [{transportType}]"); | ||
|
||
ITransportSettings[] settings = new ITransportSettings[] { new AmqpTransportSettings(transportType) }; | ||
ModuleClient moduleClient = await ModuleClient.CreateFromEnvironmentAsync(settings); | ||
moduleClient.ProductInfo = Constants.ProductInfo; | ||
|
||
await moduleClient.OpenAsync(); | ||
LoggerUtil.Writer.LogInformation($"Successfully initialized module client using transport type [{transportType}]"); | ||
return moduleClient; | ||
} | ||
} | ||
} | ||
|
60 changes: 60 additions & 0 deletions
60
edge-modules/metrics-collector/src/ModuleClientWrapper/IotMessageModuleClientWrapper.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
using System; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.Azure.Devices.Client; | ||
using Microsoft.Azure.Devices.Edge.Util; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace Microsoft.Azure.Devices.Edge.Azure.Monitor.ModuleClientWrapper | ||
{ | ||
public class IotMessageModuleClientWrapper : IDisposable, IModuleClientWrapper | ||
{ | ||
BasicModuleClientWrapper inner; | ||
CancellationTokenSource cancellationTokenSource; | ||
|
||
public IotMessageModuleClientWrapper(BasicModuleClientWrapper basicModuleClientWrapper, CancellationTokenSource cts) | ||
{ | ||
this.inner = basicModuleClientWrapper; | ||
this.cancellationTokenSource = cts; | ||
} | ||
|
||
public static async Task<IModuleClientWrapper> BuildModuleClientWrapperAsync(CancellationTokenSource cts) | ||
{ | ||
BasicModuleClientWrapper basicModuleClientWrapper = await BasicModuleClientWrapper.BuildModuleClientWrapperAsync(); | ||
return new IotMessageModuleClientWrapper(basicModuleClientWrapper, cts); | ||
} | ||
|
||
public async Task RecreateClientAsync() | ||
{ | ||
try | ||
{ | ||
await this.inner.RecreateClientAsync(); | ||
} | ||
catch (Exception e) | ||
{ | ||
LoggerUtil.Writer.LogError($"Failed closing and re-establishing connection to IoT Hub: {e.ToString()}"); | ||
this.cancellationTokenSource.Cancel(); | ||
} | ||
} | ||
|
||
public async Task SendMessageAsync(string outputName, Message message) | ||
{ | ||
try | ||
{ | ||
await this.inner.SendMessageAsync(outputName, message); | ||
} | ||
catch (Exception e) | ||
{ | ||
LoggerUtil.Writer.LogError($"Failed sending metrics as IoT message: {e.ToString()}"); | ||
} | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
this.inner.Dispose(); | ||
} | ||
} | ||
} | ||
|
||
|
||
|
16 changes: 16 additions & 0 deletions
16
edge-modules/metrics-collector/src/ModuleClientWrapper/ModuleClientWrapper.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using System; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.Azure.Devices.Client; | ||
using Microsoft.Azure.Devices.Edge.Util; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace Microsoft.Azure.Devices.Edge.Azure.Monitor.ModuleClientWrapper | ||
{ | ||
public interface IModuleClientWrapper | ||
{ | ||
Task RecreateClientAsync(); | ||
Task SendMessageAsync(string outputName, Message message); | ||
|
||
} | ||
} |
Oops, something went wrong.