Skip to content

Commit cbbd122

Browse files
authored
Merge pull request #11226 from anusapan/iot-distributed-tracing
[IotHub] Manage distributed settings per-device
2 parents a680401 + 2ddfc10 commit cbbd122

File tree

19 files changed

+1930
-17
lines changed

19 files changed

+1930
-17
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// ----------------------------------------------------------------------------------
2+
//
3+
// Copyright Microsoft Corporation
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
// ----------------------------------------------------------------------------------
14+
15+
using Microsoft.Azure.ServiceManagement.Common.Models;
16+
using Microsoft.WindowsAzure.Commands.ScenarioTest;
17+
using Microsoft.WindowsAzure.Commands.Test.Utilities.Common;
18+
using Xunit;
19+
using Xunit.Abstractions;
20+
21+
namespace Microsoft.Azure.Commands.IotHub.Test.ScenarioTests
22+
{
23+
public class IotHubDPTracingTests : RMTestBase
24+
{
25+
public XunitTracingInterceptor _logger;
26+
27+
public IotHubDPTracingTests(ITestOutputHelper output)
28+
{
29+
_logger = new XunitTracingInterceptor(output);
30+
XunitTracingInterceptor.AddToContext(_logger);
31+
}
32+
33+
[Fact]
34+
[Trait(Category.AcceptanceType, Category.LiveOnly)]
35+
public void TestAzureIotHubTracing()
36+
{
37+
IotHubController.NewInstance.RunPsTest(_logger, "Test-AzureRmIotHubTracing");
38+
}
39+
}
40+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# ----------------------------------------------------------------------------------
2+
#
3+
# Copyright Microsoft Corporation
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS,
10+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
# See the License for the specific language governing permissions and
12+
# limitations under the License.
13+
# ----------------------------------------------------------------------------------
14+
15+
16+
#################################
17+
## IotHub Tracing Cmdlets ##
18+
#################################
19+
20+
<#
21+
.SYNOPSIS
22+
Test all iothub device tracing cmdlets
23+
#>
24+
function Test-AzureRmIotHubTracing
25+
{
26+
$Location = Get-Location "Microsoft.Devices" "IotHubs" "WEST US 2"
27+
$IotHubName = getAssetName
28+
$ResourceGroupName = getAssetName
29+
$Sku = "S1"
30+
$device1 = getAssetName
31+
32+
# Create Resource Group
33+
$resourceGroup = New-AzResourceGroup -Name $ResourceGroupName -Location $Location
34+
35+
# Create Iot Hub
36+
$iothub = New-AzIotHub -Name $IotHubName -ResourceGroupName $ResourceGroupName -Location $Location -SkuName $Sku -Units 1
37+
38+
# Add iot device
39+
$newDevice1 = Add-AzIotHubDevice -ResourceGroupName $ResourceGroupName -IotHubName $IotHubName -DeviceId $device1 -AuthMethod 'shared_private_key'
40+
Assert-True { $newDevice1.Id -eq $device1 }
41+
Assert-False { $newDevice1.Capabilities.IotEdge }
42+
43+
# Get device tracing detail
44+
$deviceTracing = Get-AzIotHubDistributedTracing -ResourceGroupName $ResourceGroupName -IotHubName $IotHubName -DeviceId $device1
45+
Assert-True { $deviceTracing.DeviceId -eq $device1}
46+
Assert-True { $deviceTracing.TracingOption.SamplingMode -eq 'Disabled'}
47+
Assert-True { $deviceTracing.TracingOption.SamplingRate -eq ''}
48+
Assert-False { $deviceTracing.IsSynced}
49+
50+
# Set device tracing option
51+
$updatedDeviceTracing = Set-AzIotHubDistributedTracing -ResourceGroupName $ResourceGroupName -IotHubName $IotHubName -DeviceId $device1 -mode 'Enabled' -rate 45
52+
Assert-True { $updatedDeviceTracing.DeviceId -eq $device1}
53+
Assert-True { $updatedDeviceTracing.TracingOption.SamplingMode -eq 'Enabled'}
54+
Assert-True { $updatedDeviceTracing.TracingOption.SamplingRate -eq 45}
55+
Assert-False { $updatedDeviceTracing.IsSynced}
56+
57+
# Delete all devices
58+
$result = Remove-AzIotHubDevice -ResourceGroupName $ResourceGroupName -IotHubName $IotHubName -Passthru
59+
Assert-True { $result }
60+
}

src/IotHub/IotHub.Test/SessionRecords/Microsoft.Azure.Commands.IotHub.Test.ScenarioTests.IotHubDPTracingTests/TestAzureIotHubTracing.json

Lines changed: 1008 additions & 0 deletions
Large diffs are not rendered by default.

src/IotHub/IotHub/Az.IotHub.psd1

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,8 @@ CmdletsToExport = 'Add-AzIotHubKey', 'Get-AzIotHubEventHubConsumerGroup',
9999
'Set-AzIotHubModule', 'Get-AzIotHubDeviceConnectionString',
100100
'Get-AzIotHubModuleConnectionString', 'Get-AzIotHubDeviceParent',
101101
'Set-AzIotHubDeviceParent', 'Add-AzIotHubDeviceChildren',
102-
'Remove-AzIotHubDeviceChildren', 'Get-AzIotHubDeviceChildren'
103-
102+
'Remove-AzIotHubDeviceChildren', 'Get-AzIotHubDeviceChildren',
103+
'Get-AzIotHubDistributedTracing', 'Set-AzIotHubDistributedTracing'
104104
# Variables to export from this module
105105
# VariablesToExport = @()
106106

@@ -109,7 +109,8 @@ AliasesToExport = 'Get-AzIotHubEHCG', 'Add-AzIotHubEHCG', 'Remove-AzIotHubEHCG',
109109
'Set-AzIotHubVC', 'Get-AzIotHubCVC', 'Add-AzIotHubMsgEnrich',
110110
'Get-AzIotHubMsgEnrich', 'Remove-AzIotHubMsgEnrich',
111111
'Set-AzIotHubMsgEnrich', 'Get-AzIotHubDCS', 'Get-AzIotHubMCS',
112-
'Add-AzIotHubDCL', 'Remove-AzIotHubDCL', 'Get-AzIotHubDCL'
112+
'Add-AzIotHubDCL', 'Remove-AzIotHubDCL', 'Get-AzIotHubDCL',
113+
'Get-AzIotHubTracing', 'Set-AzIotHubTracing'
113114

114115
# DSC resources to export from this module
115116
# DscResourcesToExport = @()

src/IotHub/IotHub/ChangeLog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
- `Get-AzIotHubDeviceParent`
3737
- `Set-AzIotHubDeviceParent`
3838
* Added support to manage device parent-child relationship.
39+
* Added support to manage distributed settings per-device. New Cmdlets are:
40+
- `Get-AzIotHubDistributedTracing`
41+
- `Set-AzIotHubDistributedTracing`
3942

4043
## Version 2.1.0
4144
* Added support to manage devices in an Iot Hub. New Cmdlets are:

src/IotHub/IotHub/Common/IotHubDataPlaneUtils.cs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,22 @@
1414

1515
namespace Microsoft.Azure.Commands.Management.IotHub.Common
1616
{
17+
using System;
1718
using System.Collections.Generic;
1819
using System.Linq;
1920
using Microsoft.Azure.Commands.Management.IotHub.Models;
2021
using Microsoft.Azure.Devices;
22+
using Microsoft.Azure.Devices.Shared;
23+
using Newtonsoft.Json;
2124

2225
public static class IotHubDataPlaneUtils
2326
{
27+
public const string DeviceScopePrefix = "ms-azure-iot-edge://";
28+
public const string TracingAllowedForSku = "standard";
29+
public const string TracingProperty = "azureiot*com^dtracing^1";
30+
31+
public static readonly string[] TracingAllowedForLocation = { "northeurope", "westus2", "west us 2", "southeastasia" };
32+
2433
public static string GetEdgeDevices()
2534
{
2635
return "select * from devices where capabilities.iotEdge=true";
@@ -60,5 +69,47 @@ public static IEnumerable<PSModules> ToPSModules(IEnumerable<Module> modules)
6069
{
6170
return IotHubUtils.ConvertObject<IEnumerable<Module>, IEnumerable<PSModules>>(modules.ToList());
6271
}
72+
73+
public static void ValidateDeviceTracing(string DeviceId, string Sku, string Location, bool IsEdgeDevice)
74+
{
75+
if (!TracingAllowedForLocation.Any(location => location.Equals(Location, StringComparison.OrdinalIgnoreCase)))
76+
{
77+
throw new ArgumentException($"Distributed tracing isn\'t supported for the hub located at \"{Location}\"");
78+
}
79+
if (!TracingAllowedForSku.Equals(Sku, StringComparison.OrdinalIgnoreCase))
80+
{
81+
throw new ArgumentException($"Distributed tracing isn\'t supported for the hub belongs to \"{Sku}\" sku tier.");
82+
}
83+
if (IsEdgeDevice)
84+
{
85+
throw new ArgumentException($"The device \"{DeviceId}\" should be non-edge device.");
86+
}
87+
}
88+
89+
public static PSDeviceTracing GetDeviceTracing(string DeviceId, Twin deviceTwin)
90+
{
91+
PSDeviceTracing psDeviceTracing = new PSDeviceTracing
92+
{
93+
DeviceId = DeviceId,
94+
TracingOption = new PSDistributedTracing() { SamplingMode = PSDistributedTracingSamplingMode.Disabled, SamplingRate = 0 },
95+
IsSynced = false
96+
};
97+
98+
if (deviceTwin.Properties.Desired.Contains(TracingProperty))
99+
{
100+
psDeviceTracing.TracingOption = JsonConvert.DeserializeObject<PSDistributedTracing>(deviceTwin.Properties.Desired[TracingProperty].ToString());
101+
}
102+
103+
if (deviceTwin.Properties.Reported.Contains(TracingProperty))
104+
{
105+
PSDistributedTracing psReportedDistributedTracing = JsonConvert.DeserializeObject<PSDistributedTracing>(deviceTwin.Properties.Reported[TracingProperty].ToString());
106+
if (psReportedDistributedTracing != null)
107+
{
108+
psDeviceTracing.IsSynced = (psDeviceTracing.TracingOption.SamplingMode.Equals(psReportedDistributedTracing.SamplingMode) && psDeviceTracing.TracingOption.SamplingRate.Equals(psReportedDistributedTracing.SamplingRate));
109+
}
110+
}
111+
112+
return psDeviceTracing;
113+
}
63114
}
64115
}

src/IotHub/IotHub/IotHub.format.ps1xml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,5 +898,35 @@
898898
</TableRowEntries>
899899
</TableControl>
900900
</View>
901+
<View>
902+
<Name>
903+
Microsoft.Azure.Commands.Management.IotHub.Models.PSDeviceTracing
904+
</Name>
905+
<ViewSelectedBy>
906+
<TypeName>Microsoft.Azure.Commands.Management.IotHub.Models.PSDeviceTracing</TypeName>
907+
</ViewSelectedBy>
908+
<ListControl>
909+
<ListEntries>
910+
<ListEntry>
911+
<ListItems>
912+
<ListItem>
913+
<PropertyName>DeviceId</PropertyName>
914+
</ListItem>
915+
<ListItem>
916+
<Label>Sampling Mode</Label>
917+
<ScriptBlock>$_.TracingOption.SamplingMode</ScriptBlock>
918+
</ListItem>
919+
<ListItem>
920+
<Label>Sampling Rate</Label>
921+
<ScriptBlock>if($_.TracingOption.SamplingMode.value__ -eq 1) { "$($_.TracingOption.SamplingRate)%" } else { "" }</ScriptBlock>
922+
</ListItem>
923+
<ListItem>
924+
<PropertyName>IsSynced</PropertyName>
925+
</ListItem>
926+
</ListItems>
927+
</ListEntry>
928+
</ListEntries>
929+
</ListControl>
930+
</View>
901931
</ViewDefinitions>
902932
</Configuration>

src/IotHub/IotHub/IotHub/DataPlane/Device/GetAzIotHubDeviceParent.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ public override void ExecuteCmdlet()
9292
{
9393
throw new ArgumentException($"The entered device \"{this.DeviceId}\" doesn\'t support parent device functionality.");
9494
}
95-
96-
string parentDeviceId = childDevice.Scope.Substring(Properties.Resources.DEVICE_DEVICESCOPE_PREFIX.Length, childDevice.Scope.LastIndexOf("-") - Properties.Resources.DEVICE_DEVICESCOPE_PREFIX.Length);
95+
96+
string parentDeviceId = childDevice.Scope.Substring(IotHubDataPlaneUtils.DeviceScopePrefix.Length, childDevice.Scope.LastIndexOf("-") - IotHubDataPlaneUtils.DeviceScopePrefix.Length);
9797

9898
this.WriteObject(IotHubDataPlaneUtils.ToPSDevice(registryManager.GetDeviceAsync(parentDeviceId).GetAwaiter().GetResult()));
9999
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// ----------------------------------------------------------------------------------
2+
//
3+
// Copyright Microsoft Corporation
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
// ----------------------------------------------------------------------------------
14+
15+
namespace Microsoft.Azure.Commands.Management.IotHub
16+
{
17+
using System;
18+
using System.Collections.Generic;
19+
using System.Management.Automation;
20+
using Microsoft.Azure.Commands.Management.IotHub.Common;
21+
using Microsoft.Azure.Commands.Management.IotHub.Models;
22+
using Microsoft.Azure.Devices;
23+
using Microsoft.Azure.Devices.Shared;
24+
using Microsoft.Azure.Management.IotHub;
25+
using Microsoft.Azure.Management.IotHub.Models;
26+
using ResourceManager.Common.ArgumentCompleters;
27+
28+
[Cmdlet("Get", ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "IotHubDistributedTracing", DefaultParameterSetName = ResourceParameterSet)]
29+
[Alias("Get-" + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "IotHubTracing")]
30+
[OutputType(typeof(PSDeviceTracing))]
31+
public class GetAzIotHubDistributedTracing : IotHubBaseCmdlet
32+
{
33+
private const string ResourceIdParameterSet = "ResourceIdSet";
34+
private const string ResourceParameterSet = "ResourceSet";
35+
private const string InputObjectParameterSet = "InputObjectSet";
36+
37+
[Parameter(Position = 0, Mandatory = true, ParameterSetName = InputObjectParameterSet, ValueFromPipeline = true, HelpMessage = "IotHub object")]
38+
[ValidateNotNullOrEmpty]
39+
public PSIotHub InputObject { get; set; }
40+
41+
[Parameter(Position = 0, Mandatory = true, ParameterSetName = ResourceParameterSet, HelpMessage = "Name of the Resource Group")]
42+
[ValidateNotNullOrEmpty]
43+
[ResourceGroupCompleter]
44+
public string ResourceGroupName { get; set; }
45+
46+
[Parameter(Position = 0, Mandatory = true, ParameterSetName = ResourceIdParameterSet, ValueFromPipelineByPropertyName = true, HelpMessage = "IotHub Resource Id")]
47+
[ValidateNotNullOrEmpty]
48+
[ResourceIdCompleter("Microsoft.Devices/IotHubs")]
49+
public string ResourceId { get; set; }
50+
51+
[Parameter(Position = 1, Mandatory = true, ParameterSetName = ResourceParameterSet, HelpMessage = "Name of the Iot Hub")]
52+
[ValidateNotNullOrEmpty]
53+
public string IotHubName { get; set; }
54+
55+
[Parameter(Position = 1, Mandatory = true, ParameterSetName = InputObjectParameterSet, HelpMessage = "Target Device Id.")]
56+
[Parameter(Position = 1, Mandatory = true, ParameterSetName = ResourceIdParameterSet, HelpMessage = "Target Device Id.")]
57+
[Parameter(Position = 2, Mandatory = true, ParameterSetName = ResourceParameterSet, HelpMessage = "Target Device Id.")]
58+
[ValidateNotNullOrEmpty]
59+
public string DeviceId { get; set; }
60+
61+
public override void ExecuteCmdlet()
62+
{
63+
IotHubDescription iotHubDescription;
64+
if (ParameterSetName.Equals(InputObjectParameterSet))
65+
{
66+
this.ResourceGroupName = this.InputObject.Resourcegroup;
67+
this.IotHubName = this.InputObject.Name;
68+
iotHubDescription = IotHubUtils.ConvertObject<PSIotHub, IotHubDescription>(this.InputObject);
69+
}
70+
else
71+
{
72+
if (ParameterSetName.Equals(ResourceIdParameterSet))
73+
{
74+
this.ResourceGroupName = IotHubUtils.GetResourceGroupName(this.ResourceId);
75+
this.IotHubName = IotHubUtils.GetIotHubName(this.ResourceId);
76+
}
77+
78+
iotHubDescription = this.IotHubClient.IotHubResource.Get(this.ResourceGroupName, this.IotHubName);
79+
}
80+
81+
IEnumerable<SharedAccessSignatureAuthorizationRule> authPolicies = this.IotHubClient.IotHubResource.ListKeys(this.ResourceGroupName, this.IotHubName);
82+
SharedAccessSignatureAuthorizationRule policy = IotHubUtils.GetPolicy(authPolicies, PSAccessRights.RegistryWrite);
83+
PSIotHubConnectionString psIotHubConnectionString = IotHubUtils.ToPSIotHubConnectionString(policy, iotHubDescription.Properties.HostName);
84+
RegistryManager registryManager = RegistryManager.CreateFromConnectionString(psIotHubConnectionString.PrimaryConnectionString);
85+
86+
Twin deviceTwin = registryManager.GetTwinAsync(this.DeviceId).GetAwaiter().GetResult();
87+
88+
if (deviceTwin == null)
89+
{
90+
throw new ArgumentException($"The entered non-edge device \"{this.DeviceId}\" doesn't exist.");
91+
}
92+
93+
IotHubDataPlaneUtils.ValidateDeviceTracing(this.DeviceId, iotHubDescription.Sku.Tier.Value.ToString(), iotHubDescription.Location, deviceTwin.Capabilities.IotEdge);
94+
95+
this.WriteObject(IotHubDataPlaneUtils.GetDeviceTracing(this.DeviceId, deviceTwin));
96+
}
97+
}
98+
}

0 commit comments

Comments
 (0)