Skip to content

Commit 7360d6b

Browse files
committed
Add usage log in metric helper
1 parent 3561532 commit 7360d6b

File tree

7 files changed

+199
-1
lines changed

7 files changed

+199
-1
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<ApplicationInsights xmlns="http://schemas.microsoft.com/ApplicationInsights/2013/Settings" schemaVersion="2014-05-30">
3+
<!--
4+
Learn more about Application Insights configuration with ApplicationInsights.config here:
5+
http://go.microsoft.com/fwlink/?LinkID=513840
6+
7+
Note: If not present, please add <InstrumentationKey>Your Key</InstrumentationKey> to the top of this file.
8+
-->
9+
<TelemetryModules>
10+
<Add Type="Microsoft.ApplicationInsights.Extensibility.Implementation.Tracing.DiagnosticsTelemetryModule, Microsoft.ApplicationInsights"/>
11+
</TelemetryModules>
12+
<ContextInitializers>
13+
</ContextInitializers>
14+
<TelemetryInitializers>
15+
</TelemetryInitializers>
16+
<InstrumentationKey>171b81dc-a785-47a2-9e1b-d1f79b09941b</InstrumentationKey>
17+
</ApplicationInsights>

src/Common/Commands.Common/AzurePSCmdlet.cs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ public abstract class AzurePSCmdlet : PSCmdlet
3535
private DebugStreamTraceListener _adalListener;
3636
protected static AzureProfile _currentProfile = null;
3737
protected static AzurePSDataCollectionProfile _dataCollectionProfile = null;
38+
protected virtual bool IsMetricEnabled {
39+
get { return false; }
40+
}
3841

3942
[Parameter(Mandatory = false, HelpMessage = "In-memory profile.")]
4043
public AzureProfile Profile { get; set; }
@@ -305,7 +308,7 @@ protected override void BeginProcessing()
305308
{
306309
InitializeProfile();
307310
PromptForDataCollectionProfileIfNotExists();
308-
311+
LogMetricHelperUsage();
309312
if (string.IsNullOrEmpty(ParameterSetName))
310313
{
311314
WriteDebugWithTimestamp(string.Format(Resources.BeginProcessingWithoutParameterSetLog, this.GetType().Name));
@@ -352,6 +355,10 @@ protected override void EndProcessing()
352355
RecordingTracingInterceptor.RemoveFromContext(_httpTracingInterceptor);
353356
DebugStreamTraceListener.RemoveAdalTracing(_adalListener);
354357
FlushDebugMessages();
358+
if (IsMetricEnabled)
359+
{
360+
MetricHelper.FlushMetric();
361+
}
355362

356363
base.EndProcessing();
357364
}
@@ -379,6 +386,7 @@ protected bool IsVerbose()
379386
public new void WriteError(ErrorRecord errorRecord)
380387
{
381388
FlushDebugMessages();
389+
LogMetricHelperErrorEvent(errorRecord);
382390
base.WriteError(errorRecord);
383391
}
384392

@@ -506,6 +514,42 @@ private void FlushDebugMessages()
506514
}
507515
}
508516

517+
protected void LogMetricHelperUsage()
518+
{
519+
if (!IsMetricEnabled)
520+
{
521+
return;
522+
}
523+
524+
try
525+
{
526+
MetricHelper.LogUsageEvent(this.Profile.DefaultSubscription.Id.ToString(), this.GetType().Name);
527+
}
528+
catch (Exception e)
529+
{
530+
//Swallow error from Application Insights event collection.
531+
WriteErrorWithTimestamp(e.ToString());
532+
}
533+
}
534+
535+
protected void LogMetricHelperErrorEvent(ErrorRecord er)
536+
{
537+
if (!IsMetricEnabled)
538+
{
539+
return;
540+
}
541+
542+
try
543+
{
544+
MetricHelper.LogErrorEvent(er, this.Profile.DefaultSubscription.Id.ToString(), this.GetType().Name);
545+
}
546+
catch (Exception e)
547+
{
548+
//Swallow error from Application Insights event collection.
549+
WriteErrorWithTimestamp(e.ToString());
550+
}
551+
}
552+
509553
/// <summary>
510554
/// Asks for confirmation before executing the action.
511555
/// </summary>

src/Common/Commands.Common/Commands.Common.csproj

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
1616
<RestorePackages>true</RestorePackages>
1717
<CodeAnalysisAdditionalOptions>/assemblyCompareMode:StrongNameIgnoringVersion</CodeAnalysisAdditionalOptions>
18+
<NuGetPackageImportStamp>06e19c11</NuGetPackageImportStamp>
1819
</PropertyGroup>
1920
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
2021
<DebugSymbols>true</DebugSymbols>
@@ -54,6 +55,10 @@
5455
<SpecificVersion>False</SpecificVersion>
5556
<HintPath>..\..\packages\Hyak.Common.1.0.2\lib\portable-net403+win+wpa81\Hyak.Common.dll</HintPath>
5657
</Reference>
58+
<Reference Include="Microsoft.ApplicationInsights, Version=1.1.0.1899, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
59+
<HintPath>..\..\packages\Microsoft.ApplicationInsights.1.1.1-beta\lib\net45\Microsoft.ApplicationInsights.dll</HintPath>
60+
<Private>True</Private>
61+
</Reference>
5762
<Reference Include="Microsoft.Azure.Common">
5863
<SpecificVersion>False</SpecificVersion>
5964
<HintPath>..\..\packages\Microsoft.Azure.Common.2.1.0\lib\net45\Microsoft.Azure.Common.dll</HintPath>
@@ -147,6 +152,7 @@
147152
<DesignTime>True</DesignTime>
148153
<DependentUpon>Resources.resx</DependentUpon>
149154
</Compile>
155+
<Compile Include="MetricHelper.cs" />
150156
<Compile Include="SecureStringExtensions.cs" />
151157
<Compile Include="ConversionUtilities.cs" />
152158
<Compile Include="DebugStreamTraceListener.cs" />
@@ -184,6 +190,9 @@
184190
</EmbeddedResource>
185191
</ItemGroup>
186192
<ItemGroup>
193+
<Content Include="ApplicationInsights.config">
194+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
195+
</Content>
187196
<None Include="packages.config">
188197
<SubType>Designer</SubType>
189198
</None>
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Management.Automation;
5+
using System.Security.Cryptography;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
using Microsoft.ApplicationInsights;
9+
using Microsoft.ApplicationInsights.Channel;
10+
using Microsoft.ApplicationInsights.DataContracts;
11+
using Microsoft.ApplicationInsights.Extensibility;
12+
using Microsoft.WindowsAzure.Commands.Utilities.Common;
13+
14+
namespace Microsoft.WindowsAzure.Commands.Common
15+
{
16+
public static class MetricHelper
17+
{
18+
private static readonly TelemetryClient TelemetryClient;
19+
20+
static MetricHelper()
21+
{
22+
TelemetryClient = new TelemetryClient();
23+
24+
if (!IsMetricTermAccepted())
25+
{
26+
TelemetryConfiguration.Active.DisableTelemetry = true;
27+
}
28+
29+
if (TestMockSupport.RunningMocked)
30+
{
31+
//TODO enable in final cr
32+
//TelemetryConfiguration.Active.DisableTelemetry = true;
33+
//TelemetryConfiguration.Active.TelemetryChannel.DeveloperMode = true;
34+
}
35+
}
36+
37+
public static void LogUsageEvent(string subscriptionId, string cmdletName)
38+
{
39+
if (!IsMetricTermAccepted())
40+
{
41+
return;
42+
}
43+
44+
var tcEvent = new EventTelemetry("CmdletUsage");
45+
46+
tcEvent.Context.User.Id = GenerateSha256HashString(subscriptionId);
47+
tcEvent.Context.User.UserAgent = AzurePowerShell.UserAgentValue.ToString();
48+
tcEvent.Properties.Add("CmdletType", cmdletName);
49+
50+
TelemetryClient.TrackEvent(tcEvent);
51+
}
52+
53+
public static void LogErrorEvent(ErrorRecord err, string subscriptionId, string cmdletName)
54+
{
55+
if (!IsMetricTermAccepted())
56+
{
57+
return;
58+
}
59+
60+
var tcEvent = new EventTelemetry("CmdletError");
61+
tcEvent.Properties.Add("ExceptionType", err.Exception.GetType().FullName);
62+
if (err.Exception.InnerException != null)
63+
{
64+
tcEvent.Properties.Add("InnerExceptionType", err.Exception.InnerException.GetType().FullName);
65+
}
66+
67+
tcEvent.Context.User.Id = GenerateSha256HashString(subscriptionId);
68+
tcEvent.Context.User.UserAgent = AzurePowerShell.UserAgentValue.ToString();
69+
tcEvent.Properties.Add("CmdletType", cmdletName);
70+
71+
TelemetryClient.TrackEvent(tcEvent);
72+
}
73+
74+
public static bool IsMetricTermAccepted()
75+
{
76+
//TODO check the config/preference
77+
return true;
78+
}
79+
80+
public static void FlushMetric()
81+
{
82+
if (!IsMetricTermAccepted())
83+
{
84+
return;
85+
}
86+
87+
var t = Task.Run(() => FlushAi());
88+
//TelemetryClient.Flush();
89+
}
90+
91+
private static void FlushAi()
92+
{
93+
try
94+
{
95+
TelemetryClient.Flush();
96+
97+
//return Task.FromResult(default(object));
98+
}
99+
catch
100+
{
101+
// ignored
102+
}
103+
}
104+
105+
/// <summary>
106+
/// Gereate a SHA256 Hash string from the originInput.
107+
/// </summary>
108+
/// <param name="originInput"></param>
109+
/// <returns></returns>
110+
public static string GenerateSha256HashString(string originInput)
111+
{
112+
SHA256 sha256 = SHA256.Create();
113+
var bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(originInput));
114+
return Encoding.UTF8.GetString(bytes);
115+
}
116+
}
117+
}

src/Common/Commands.Common/packages.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<packages>
33
<package id="Hyak.Common" version="1.0.2" targetFramework="net45" />
4+
<package id="Microsoft.ApplicationInsights" version="1.1.1-beta" targetFramework="net45" />
45
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.2" targetFramework="net45" />
56
<package id="Microsoft.Azure.Common" version="2.1.0" targetFramework="net45" />
67
<package id="Microsoft.Azure.Common.Authentication" version="1.1.3-preview" targetFramework="net45" />

src/ResourceManager/Compute/Commands.Compute/Common/ComputeClientBaseCmdlet.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ public abstract class ComputeClientBaseCmdlet : AzurePSCmdlet
2323
{
2424
protected const string VirtualMachineExtensionType = "Microsoft.Compute/virtualMachines/extensions";
2525

26+
protected override bool IsMetricEnabled
27+
{
28+
get { return true; }
29+
}
30+
2631
private ComputeClient computeClient;
2732

2833
public ComputeClient ComputeClient

src/ResourceManager/Compute/Commands.Compute/VirtualMachine/Config/NewAzureVMConfigCommand.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ public class NewAzureVMConfigCommand : AzurePSCmdlet
5151
[ValidateNotNullOrEmpty]
5252
public string AvailabilitySetId { get; set; }
5353

54+
protected override bool IsMetricEnabled
55+
{
56+
get { return true; }
57+
}
58+
5459
public override void ExecuteCmdlet()
5560
{
5661
var vm = new PSVirtualMachine

0 commit comments

Comments
 (0)