Skip to content

Commit e590f29

Browse files
authored
Update Az.Accounts for telemetry (#17477)
* Update Az.Accounts for telemetry * Update test for az.accounts * revert test change and client request id related change * Update a parameter for OnProcessRecordAsyncEnd
1 parent 69fe9d3 commit e590f29

File tree

5 files changed

+114
-11
lines changed

5 files changed

+114
-11
lines changed

src/Accounts/Accounts/CommonModule/AzModule.cs

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
using Microsoft.Azure.Commands.Profile.CommonModule;
1818
using Microsoft.Rest.Azure;
1919
using Microsoft.Rest.Serialization;
20+
using Microsoft.WindowsAzure.Commands.Common;
2021
using Microsoft.WindowsAzure.Commands.Utilities.Common;
2122
using Newtonsoft.Json;
2223
using System;
@@ -121,31 +122,52 @@ public async Task EventListener(string id, CancellationToken cancellationToken,
121122
switch (id)
122123
{
123124
case Events.CmdletBeginProcessing:
124-
await OnCmdletBeginProcessing(id, cancellationToken, getEventData, signal, processRecordId);
125+
await OnCmdletBeginProcessing(id, cancellationToken, getEventData, signal, correlationId);
125126
break;
126127
case Events.BeforeCall:
127-
await OnBeforeCall(id, cancellationToken, getEventData, signal, processRecordId);
128+
await OnBeforeCall(id, cancellationToken, getEventData, signal, correlationId);
128129
break;
129130
case Events.CmdletProcessRecordAsyncStart:
130131
await OnProcessRecordAsyncStart(id, cancellationToken, getEventData, signal, processRecordId, invocationInfo, parameterSetName, correlationId);
131132
break;
132133
case Events.CmdletProcessRecordAsyncEnd:
133-
await OnProcessRecordAsyncEnd(id, cancellationToken, getEventData, signal, processRecordId);
134+
await OnProcessRecordAsyncEnd(id, cancellationToken, getEventData, signal, correlationId);
134135
break;
135136
case Events.CmdletException:
136-
await OnCmdletException(id, cancellationToken, getEventData, signal, processRecordId, exception);
137+
await OnCmdletException(id, cancellationToken, getEventData, signal, correlationId, exception);
137138
break;
138139
case Events.ResponseCreated:
139-
await OnResponseCreated(id, cancellationToken, getEventData, signal, processRecordId);
140+
await OnResponseCreated(id, cancellationToken, getEventData, signal, correlationId);
140141
break;
141142
case Events.Polling:
142143
await OnPolling(id, cancellationToken, getEventData, signal, processRecordId);
143144
break;
144145
case Events.Finally:
145-
await OnFinally(id, cancellationToken, getEventData, signal, processRecordId);
146+
await OnFinally(id, cancellationToken, getEventData, signal, correlationId);
146147
break;
147148
case Events.CmdletEndProcessing:
148-
await OnCmdletEndProcessing(id, cancellationToken, getEventData, signal, processRecordId);
149+
await OnCmdletEndProcessing(id, cancellationToken, getEventData, signal, correlationId);
150+
break;
151+
default:
152+
break;
153+
}
154+
}
155+
156+
/// <summary>
157+
/// The cmdlet will call this for every event during the pipeline.
158+
/// </summary>
159+
/// <param name="id">a <c>string</c> containing the name of the event being raised (well-known events are in <see cref="Microsoft.Azure.Commands.Common.Events"/></param>
160+
/// <param name="invocationInfo">The <see cref="System.Management.Automation.InvocationInfo" /> from the cmdlet</param>
161+
/// <param name="parameterSetName">The <see cref="string" /> containing the name of the parameter set for this invocation (if available></param>
162+
public void Telemetry(string id, InvocationInfo invocationInfo, string parameterSetName, PSCmdlet pscmdlet)
163+
{
164+
switch (id)
165+
{
166+
case Telemetries.Create:
167+
OnTelemetryCreated(invocationInfo, parameterSetName, pscmdlet);
168+
break;
169+
case Telemetries.Send:
170+
OnTelemetrySent(pscmdlet);
149171
break;
150172
default:
151173
break;
@@ -222,18 +244,45 @@ await signal(Events.Debug, cancellationToken,
222244
internal async Task OnProcessRecordAsyncStart(string id, CancellationToken cancellationToken, GetEventData getEventData, SignalDelegate signal, string processRecordId, InvocationInfo invocationInfo, string parameterSetName, string correlationId)
223245
{
224246
//AzVersion is null indicates no SDK based cmdlet is invoked. Below properties needs to be filled.
225-
if(_runtime != null && AzurePSCmdlet.AzVersion == null)
247+
if (_runtime != null && AzurePSCmdlet.AzVersion == null)
226248
{
227249
AzurePSCmdlet.PSHostName = _runtime.Host?.Name;
228250
AzurePSCmdlet.PSHostVersion = _runtime.Host?.Version?.ToString();
229251
}
230-
var qos = _telemetry.CreateQosEvent(invocationInfo, parameterSetName, correlationId, processRecordId);
252+
var qos = _telemetry.CreateQosEvent(invocationInfo, parameterSetName, correlationId, correlationId);
231253
qos.PreviousEndTime = _previousEndTime;
232254
await signal(Events.Debug, cancellationToken,
233255
() => EventHelper.CreateLogEvent($"[{id}]: Created new QosEvent for command '{qos?.CommandName}'"));
234256
}
235257

236-
internal async Task OnProcessRecordAsyncEnd(string id, CancellationToken cancellationToken, GetEventData getEventData, SignalDelegate signal, string processRecordId)
258+
internal void OnTelemetryCreated(InvocationInfo invocationInfo, string parameterSetName, PSCmdlet pscmdlet)
259+
{
260+
//AzVersion is null indicates no SDK based cmdlet is invoked. Below properties needs to be filled.
261+
if (_runtime != null && AzurePSCmdlet.AzVersion == null)
262+
{
263+
AzurePSCmdlet.PSHostName = _runtime.Host?.Name;
264+
AzurePSCmdlet.PSHostVersion = _runtime.Host?.Version?.ToString();
265+
}
266+
var qos = _telemetry.CreateQosEvent(invocationInfo, parameterSetName, MetricHelper.TelemetryId, MetricHelper.TelemetryId);
267+
qos.Parameters = string.Join(" ",
268+
invocationInfo.BoundParameters.Keys.Select(
269+
s => string.Format(System.Globalization.CultureInfo.InvariantCulture, "-{0} ***", s)));
270+
qos.PreviousEndTime = _previousEndTime;
271+
}
272+
273+
internal void OnTelemetrySent(PSCmdlet pscmdlet)
274+
{
275+
AzurePSQoSEvent qos;
276+
if (_telemetry.TryGetValue(MetricHelper.TelemetryId, out qos))
277+
{
278+
qos.IsSuccess = (qos.Exception == null);
279+
_telemetry.LogEvent(MetricHelper.TelemetryId);
280+
_previousEndTime = DateTimeOffset.Now;
281+
pscmdlet.WriteDebug(qos.ToString());
282+
}
283+
}
284+
285+
internal async Task OnProcessRecordAsyncEnd(string id, CancellationToken cancellationToken, GetEventData getEventData, SignalDelegate signal, string correlationId)
237286
{
238287
await signal(Events.Debug, cancellationToken,
239288
() => EventHelper.CreateLogEvent($"[{id}]: Finish HTTP process"));

src/Accounts/Accounts/CommonModule/RegisterAzModule.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
using System.Threading.Tasks;
1818
using System.Management.Automation;
1919
using System.Net.Http;
20+
using Microsoft.WindowsAzure.Commands.Common;
2021

2122
namespace Microsoft.Azure.Commands.Common
2223
{
@@ -48,6 +49,12 @@ protected override void ProcessRecord()
4849
// this gets called for every event that is signaled
4950
EventListener = module.EventListener,
5051

52+
// this gets called to get the telemetryId
53+
GetTelemetryId = () => { return MetricHelper.TelemetryId; },
54+
55+
// this gets called when a telemetry related operation is made, e.g. create/send a telemetry
56+
Telemetry = module.Telemetry,
57+
5158
// this gets called at module load time (allows you to change the http pipeline)
5259
OnModuleLoad = module.OnModuleLoad,
5360

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+
16+
using System;
17+
using System.Collections.Generic;
18+
using System.Net.Http;
19+
using System.Threading.Tasks;
20+
21+
22+
namespace Microsoft.Azure.Commands.Common
23+
{
24+
/// <summary>
25+
/// Constants for the telemetries defined in PowerShell Generated Cmdlets
26+
/// </summary>
27+
public static class Telemetries
28+
{
29+
/// <summary>
30+
/// Create a telemetry in memory
31+
/// </summary>
32+
public const string Create = nameof(Create);
33+
34+
/// <summary>
35+
/// Send a telemetry
36+
/// </summary>
37+
public const string Send = nameof(Send);
38+
}
39+
40+
}

src/Accounts/Accounts/CommonModule/TelemetryProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ public virtual AzurePSQoSEvent CreateQosEvent(InvocationInfo invocationInfo, str
142142
CommandName = invocationInfo?.MyCommand?.Name,
143143
ModuleVersion = TrimModuleVersion(invocationInfo?.MyCommand?.Module?.Version),
144144
ModuleName = TrimModuleName(invocationInfo?.MyCommand?.ModuleName),
145-
SessionId = correlationId,
145+
SessionId = MetricHelper.SessionId,
146146
ParameterSetName = parameterSetName,
147147
InvocationName = invocationInfo?.InvocationName,
148148
InputFromPipeline = invocationInfo?.PipelineLength > 0,

src/Accounts/Accounts/CommonModule/VTable.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ namespace Microsoft.Azure.Commands.Common
2121
{
2222
using EventListenerDelegate = Func<string, CancellationToken, Func<EventArgs>, Func<string, CancellationToken, Func<EventArgs>, Task>, System.Management.Automation.InvocationInfo, string, string, string, System.Exception, Task>;
2323
using GetParameterDelegate = Func<string, string, System.Management.Automation.InvocationInfo, string, string, object>;
24+
using TelemetryDelegate = Action<string, System.Management.Automation.InvocationInfo, string, System.Management.Automation.PSCmdlet>;
25+
using GetTelemetryIdDelegate = Func<string>;
2426
using ModuleLoadPipelineDelegate = Action<string, string, Action<Func<HttpRequestMessage, CancellationToken, Action, Func<string, CancellationToken, Func<EventArgs>, Task>, Func<HttpRequestMessage, CancellationToken, Action, Func<string, CancellationToken, Func<EventArgs>, Task>, Task<HttpResponseMessage>>, Task<HttpResponseMessage>>>, Action<Func<HttpRequestMessage, CancellationToken, Action, Func<string, CancellationToken, Func<EventArgs>, Task>, Func<HttpRequestMessage, CancellationToken, Action, Func<string, CancellationToken, Func<EventArgs>, Task>, Task<HttpResponseMessage>>, Task<HttpResponseMessage>>>>;
2527
using NewRequestPipelineDelegate = Action<System.Management.Automation.InvocationInfo, string, string, Action<Func<HttpRequestMessage, CancellationToken, Action, Func<string, CancellationToken, Func<EventArgs>, Task>, Func<HttpRequestMessage, CancellationToken, Action, Func<string, CancellationToken, Func<EventArgs>, Task>, Task<HttpResponseMessage>>, Task<HttpResponseMessage>>>, Action<Func<HttpRequestMessage, CancellationToken, Action, Func<string, CancellationToken, Func<EventArgs>, Task>, Func<HttpRequestMessage, CancellationToken, Action, Func<string, CancellationToken, Func<EventArgs>, Task>, Task<HttpResponseMessage>>, Task<HttpResponseMessage>>>>;
2628
using ArgumentCompleterDelegate = Func<string, System.Management.Automation.InvocationInfo, string, string[], string[], string[]>;
@@ -48,6 +50,11 @@ public class VTable
4850
/// <example>public object GetParameterValue(string resourceId, string moduleName, System.Management.Automation.InvocationInfo invocationInfo, string name)</example>
4951
public GetParameterDelegate GetParameterValue;
5052

53+
public GetTelemetryIdDelegate GetTelemetryId;
54+
55+
public TelemetryDelegate Telemetry;
56+
57+
5158
/// <summary>
5259
/// The cmdlet will call this for every event during the pipeline.
5360
/// </summary>

0 commit comments

Comments
 (0)