Skip to content

Commit f37cc8c

Browse files
committed
Merge pull request #98 from AuxMon/insightsEvtRPCmdlets
BUG: 1933802 Create Powershell Commandlets for Event Service
2 parents 8239a52 + f9b3330 commit f37cc8c

20 files changed

+2433
-1
lines changed

src/AzurePowershell.sln

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.StreamAnalytics",
159159
EndProject
160160
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.StreamAnalytics.Test", "ResourceManager\StreamAnalytics\Commands.StreamAnalytics.Test\Commands.StreamAnalytics.Test.csproj", "{7E6683BE-ECFF-4709-89EB-1325E9E70512}"
161161
EndProject
162+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.Insights", "ResourceManager\Insights\Commands.Insights\Commands.Insights.csproj", "{DEA446A1-84E2-46CC-B780-EB4AFDE2460E}"
163+
EndProject
162164
Global
163165
GlobalSection(SolutionConfigurationPlatforms) = preSolution
164166
Debug|Any CPU = Debug|Any CPU
@@ -385,6 +387,10 @@ Global
385387
{7E6683BE-ECFF-4709-89EB-1325E9E70512}.Debug|Any CPU.Build.0 = Debug|Any CPU
386388
{7E6683BE-ECFF-4709-89EB-1325E9E70512}.Release|Any CPU.ActiveCfg = Release|Any CPU
387389
{7E6683BE-ECFF-4709-89EB-1325E9E70512}.Release|Any CPU.Build.0 = Release|Any CPU
390+
{DEA446A1-84E2-46CC-B780-EB4AFDE2460E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
391+
{DEA446A1-84E2-46CC-B780-EB4AFDE2460E}.Debug|Any CPU.Build.0 = Debug|Any CPU
392+
{DEA446A1-84E2-46CC-B780-EB4AFDE2460E}.Release|Any CPU.ActiveCfg = Release|Any CPU
393+
{DEA446A1-84E2-46CC-B780-EB4AFDE2460E}.Release|Any CPU.Build.0 = Release|Any CPU
388394
EndGlobalSection
389395
GlobalSection(SolutionProperties) = preSolution
390396
HideSolutionNode = FALSE

src/ResourceManager.sln

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Microsoft Visual Studio Solution File, Format Version 12.00
22
# Visual Studio 2013
3-
VisualStudioVersion = 12.0.30501.0
3+
VisualStudioVersion = 12.0.30723.0
44
MinimumVisualStudioVersion = 10.0.40219.1
55
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8531411A-0137-4E27-9C5E-49E07C245048}"
66
ProjectSection(SolutionItems) = preProject
@@ -47,6 +47,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.StreamAnalytics",
4747
EndProject
4848
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.StreamAnalytics.Test", "ResourceManager\StreamAnalytics\Commands.StreamAnalytics.Test\Commands.StreamAnalytics.Test.csproj", "{7E6683BE-ECFF-4709-89EB-1325E9E70512}"
4949
EndProject
50+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.Insights", "ResourceManager\Insights\Commands.Insights\Commands.Insights.csproj", "{DEA446A1-84E2-46CC-B780-EB4AFDE2460E}"
51+
EndProject
5052
Global
5153
GlobalSection(SolutionConfigurationPlatforms) = preSolution
5254
Debug|Any CPU = Debug|Any CPU
@@ -125,6 +127,10 @@ Global
125127
{7E6683BE-ECFF-4709-89EB-1325E9E70512}.Debug|Any CPU.Build.0 = Debug|Any CPU
126128
{7E6683BE-ECFF-4709-89EB-1325E9E70512}.Release|Any CPU.ActiveCfg = Release|Any CPU
127129
{7E6683BE-ECFF-4709-89EB-1325E9E70512}.Release|Any CPU.Build.0 = Release|Any CPU
130+
{DEA446A1-84E2-46CC-B780-EB4AFDE2460E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
131+
{DEA446A1-84E2-46CC-B780-EB4AFDE2460E}.Debug|Any CPU.Build.0 = Debug|Any CPU
132+
{DEA446A1-84E2-46CC-B780-EB4AFDE2460E}.Release|Any CPU.ActiveCfg = Release|Any CPU
133+
{DEA446A1-84E2-46CC-B780-EB4AFDE2460E}.Release|Any CPU.Build.0 = Release|Any CPU
128134
EndGlobalSection
129135
GlobalSection(SolutionProperties) = preSolution
130136
HideSolutionNode = FALSE
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
4+
<PropertyGroup>
5+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7+
<ProjectGuid>{DEA446A1-84E2-46CC-B780-EB4AFDE2460E}</ProjectGuid>
8+
<OutputType>Library</OutputType>
9+
<AppDesignerFolder>Properties</AppDesignerFolder>
10+
<RootNamespace>Microsoft.Azure.Commands.Insights</RootNamespace>
11+
<AssemblyName>Microsoft.Azure.Commands.Insights</AssemblyName>
12+
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
13+
<FileAlignment>512</FileAlignment>
14+
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\..\</SolutionDir>
15+
<RestorePackages>true</RestorePackages>
16+
</PropertyGroup>
17+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
18+
<PlatformTarget>AnyCPU</PlatformTarget>
19+
<DebugSymbols>true</DebugSymbols>
20+
<DebugType>full</DebugType>
21+
<Optimize>false</Optimize>
22+
<OutputPath>..\..\..\Package\Debug\ResourceManager\AzureResourceManager\Insights\</OutputPath>
23+
<DefineConstants>DEBUG;TRACE</DefineConstants>
24+
<ErrorReport>prompt</ErrorReport>
25+
<WarningLevel>4</WarningLevel>
26+
<RunCodeAnalysis>true</RunCodeAnalysis>
27+
<Prefer32Bit>false</Prefer32Bit>
28+
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
29+
</PropertyGroup>
30+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
31+
<PlatformTarget>AnyCPU</PlatformTarget>
32+
<DebugType>pdbonly</DebugType>
33+
<Optimize>true</Optimize>
34+
<OutputPath>..\..\..\Package\Release\ResourceManager\AzureResourceManager\Insights\</OutputPath>
35+
<DefineConstants>TRACE</DefineConstants>
36+
<ErrorReport>prompt</ErrorReport>
37+
<WarningLevel>4</WarningLevel>
38+
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
39+
<SignAssembly>true</SignAssembly>
40+
<AssemblyOriginatorKeyFile>MSSharedLibKey.snk</AssemblyOriginatorKeyFile>
41+
<DelaySign>true</DelaySign>
42+
<Prefer32Bit>false</Prefer32Bit>
43+
</PropertyGroup>
44+
<ItemGroup>
45+
<Reference Include="Hyak.Common">
46+
<SpecificVersion>False</SpecificVersion>
47+
<HintPath>..\..\..\packages\Hyak.Common.1.0.1\lib\portable-net403+win+wpa81\Hyak.Common.dll</HintPath>
48+
</Reference>
49+
<Reference Include="Microsoft.Azure.Insights">
50+
<HintPath>..\..\..\packages\Microsoft.Azure.Insights.0.6.0-preview\lib\net45\Microsoft.Azure.Insights.dll</HintPath>
51+
</Reference>
52+
<Reference Include="Microsoft.Azure.Common">
53+
<HintPath>..\..\..\packages\Microsoft.Azure.Common.2.0.1\lib\net45\Microsoft.Azure.Common.dll</HintPath>
54+
</Reference>
55+
<Reference Include="Microsoft.Azure.Common.NetFramework">
56+
<HintPath>..\..\..\packages\Microsoft.Azure.Common.2.0.1\lib\net45\Microsoft.Azure.Common.NetFramework.dll</HintPath>
57+
</Reference>
58+
<Reference Include="Microsoft.Azure.Common.Extensions">
59+
<SpecificVersion>False</SpecificVersion>
60+
<HintPath>..\..\..\packages\Microsoft.Azure.Common.Extensions.0.13.0-preview\lib\net45\Microsoft.Azure.Common.Extensions.dll</HintPath>
61+
</Reference>
62+
<Reference Include="System" />
63+
<Reference Include="System.Core" />
64+
<Reference Include="System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
65+
<Reference Include="System.Net.Http" />
66+
</ItemGroup>
67+
<ItemGroup>
68+
<Compile Include="EventCmdletBase.cs" />
69+
<Compile Include="GetAzureResourceGroupLogCommand.cs" />
70+
<Compile Include="GetAzureResourceLogCommand.cs" />
71+
<Compile Include="GetAzureResourceProviderLogCommand.cs" />
72+
<Compile Include="GetAzureCorrelationIdLogCommand.cs" />
73+
<Compile Include="GetAzureSubscriptionIdLogCommand.cs" />
74+
<Compile Include="InsightsCmdletBase.cs" />
75+
<Compile Include="OutputClasses\IPSEventData.cs" />
76+
<Compile Include="OutputClasses\PSDictionaryElement.cs" />
77+
<Compile Include="OutputClasses\PSEventData.cs" />
78+
<Compile Include="OutputClasses\PSEventDataAuthorization.cs" />
79+
<Compile Include="OutputClasses\PSEventDataHttpRequest.cs" />
80+
<Compile Include="OutputClasses\PSEventDataNoDetails.cs" />
81+
<Compile Include="Properties\AssemblyInfo.cs" />
82+
</ItemGroup>
83+
<ItemGroup>
84+
<None Include="MSSharedLibKey.snk" />
85+
<None Include="packages.config">
86+
<SubType>Designer</SubType>
87+
</None>
88+
</ItemGroup>
89+
<ItemGroup>
90+
<ProjectReference Include="..\..\..\Common\Commands.Common\Commands.Common.csproj">
91+
<Project>{5ee72c53-1720-4309-b54b-5fb79703195f}</Project>
92+
<Name>Commands.Common</Name>
93+
</ProjectReference>
94+
</ItemGroup>
95+
<ItemGroup>
96+
<Content Include="Microsoft.Azure.Commands.Insights.dll-Help.xml">
97+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
98+
</Content>
99+
</ItemGroup>
100+
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
101+
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
102+
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
103+
<PropertyGroup>
104+
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
105+
</PropertyGroup>
106+
<Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
107+
</Target>
108+
<Import Project="..\..\..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\..\..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" />
109+
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
110+
<Error Condition="!Exists('..\..\..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
111+
<Error Condition="Exists('..\..\..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
112+
</Target>
113+
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
114+
Other similar extension points exist, see Microsoft.Common.targets.
115+
<Target Name="BeforeBuild">
116+
</Target>
117+
<Target Name="AfterBuild">
118+
</Target>
119+
-->
120+
</Project>
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
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 System;
16+
using System.Collections.Generic;
17+
using System.Linq;
18+
using System.Management.Automation;
19+
using Microsoft.Azure.Commands.Insights.OutputClasses;
20+
using Microsoft.Azure.Insights;
21+
using Microsoft.Azure.Insights.Models;
22+
23+
namespace Microsoft.Azure.Commands.Insights
24+
{
25+
/// <summary>
26+
/// Base class for the Azure SDK EventService Cmdlets
27+
/// </summary>
28+
public abstract class EventCmdletBase : InsightsCmdletBase
29+
{
30+
internal static readonly TimeSpan DefaultQueryTimeRange = TimeSpan.FromHours(-1);
31+
32+
internal static int MaxNumberOfReturnedRecords = 100000;
33+
34+
internal const string SubscriptionLevelName = "Query at subscription level";
35+
internal const string ResourceProviderName = "Query on ResourceProvider";
36+
internal const string ResourceGroupName = "Query on ResourceGroupProvider";
37+
internal const string ResourceUriName = "Query on ResourceUriName";
38+
internal const string CorrelationIdName = "Query on CorrelationId";
39+
40+
#region Optional parameters declarations
41+
42+
/// <summary>
43+
/// Gets or sets the starttime parameter of the cmdlet
44+
/// </summary>
45+
[Parameter(ValueFromPipelineByPropertyName = true, HelpMessage = "The startTime of the query")]
46+
[ValidateNotNullOrEmpty]
47+
public string StartTime { get; set; }
48+
49+
/// <summary>
50+
/// Gets or sets the endtime parameter of the cmdlet
51+
/// </summary>
52+
[Parameter(ValueFromPipelineByPropertyName = true, HelpMessage = "The endTime of the query")]
53+
[ValidateNotNullOrEmpty]
54+
public string EndTime { get; set; }
55+
56+
/// <summary>
57+
/// Gets or sets the status parameter of the cmdlet
58+
/// </summary>
59+
[Parameter(ValueFromPipelineByPropertyName = true, HelpMessage = "The status of the records to fetch")]
60+
[ValidateNotNullOrEmpty]
61+
public string Status { get; set; }
62+
63+
/// <summary>
64+
/// Gets or sets the caller parameter of the cmdlet
65+
/// </summary>
66+
[Parameter(ValueFromPipelineByPropertyName = true, HelpMessage = "The caller of the records to fetch")]
67+
[ValidateNotNullOrEmpty]
68+
public string Caller { get; set; }
69+
70+
/// <summary>
71+
/// Gets or sets the detailedoutput parameter of the cmdlet
72+
/// </summary>
73+
[Parameter(ValueFromPipelineByPropertyName = true, HelpMessage = "Return object with all the details of the records (the default is to return only some attributes, i.e. no detail)")]
74+
public SwitchParameter DetailedOutput { get; set; }
75+
76+
#endregion
77+
78+
#region Parameters processing
79+
80+
/// <summary>
81+
/// Adds a condition to the query filter based on the give name and the value
82+
/// </summary>
83+
/// <param name="currentQueryFilter">The current query filter</param>
84+
/// <param name="name">The name to be used in the new condition</param>
85+
/// <param name="value">The value to be used in the new condition.<para>If this value is null, the currentQueryFilter is returned unmodified.</para></param>
86+
/// <returns></returns>
87+
protected string AddConditionIfPResent(string currentQueryFilter, string name, string value)
88+
{
89+
return !string.IsNullOrWhiteSpace(value) ? string.Format("{0} and {1} eq '{2}'", currentQueryFilter, name, value) : currentQueryFilter;
90+
}
91+
92+
/// <summary>
93+
/// Process the parameters defined by this class
94+
/// </summary>
95+
/// <returns>The query filter with the conditions for general parameters (i.e. defined by this class) added</returns>
96+
private string ProcessGeneralParameters()
97+
{
98+
DateTime startTime;
99+
if (string.IsNullOrWhiteSpace(this.StartTime))
100+
{
101+
// Default to one hour from Now
102+
startTime = DateTime.Now.Subtract(DefaultQueryTimeRange);
103+
}
104+
else if (!DateTime.TryParse(this.StartTime, out startTime))
105+
{
106+
throw new ArgumentException("Unable to parse startTime argument");
107+
}
108+
109+
string queryFilter;
110+
111+
// EndTime is optional
112+
if (string.IsNullOrWhiteSpace(this.EndTime))
113+
{
114+
queryFilter = string.Format("eventTimestamp ge '{0:o}'", startTime.ToUniversalTime());
115+
}
116+
else
117+
{
118+
DateTime endTime;
119+
if (!DateTime.TryParse(this.EndTime, out endTime))
120+
{
121+
throw new ArgumentException("Unable to parse endTime argument");
122+
}
123+
124+
queryFilter = string.Format("eventTimestamp ge '{0:o}' and eventTimestamp le '{1:o}'", startTime.ToUniversalTime(), endTime.ToUniversalTime());
125+
}
126+
127+
// Include the status if present
128+
queryFilter = this.AddConditionIfPResent(queryFilter, "status", this.Status);
129+
130+
// Include the caller if present
131+
queryFilter = this.AddConditionIfPResent(queryFilter, "caller", this.Caller);
132+
133+
return queryFilter;
134+
}
135+
136+
/// <summary>
137+
/// Process the general parameters (i.e. defined in this class) and the particular parameters (i.e. the parameters added by the descendants of this class).
138+
/// </summary>
139+
/// <returns>The final query filter to be used by the cmdlet</returns>
140+
protected string ProcessParameters()
141+
{
142+
string queryFilter = this.ProcessGeneralParameters();
143+
return this.ProcessParticularParameters(queryFilter);
144+
}
145+
146+
/// <summary>
147+
/// Process the parameters defined by the descendants of this class
148+
/// </summary>
149+
/// <param name="currentQueryFilter">The current query filter</param>
150+
/// <returns>The query filter with the conditions for particular parameters added</returns>
151+
protected abstract string ProcessParticularParameters(string currentQueryFilter);
152+
153+
#endregion
154+
155+
/// <summary>
156+
/// Execute the cmdlet
157+
/// </summary>
158+
public override void ExecuteCmdlet()
159+
{
160+
string queryFilter = this.ProcessParameters();
161+
162+
// Call the proper API methods to return a list of raw records. In the future this pattern can be extended to include DigestRecords
163+
Func<string, string, EventDataListResponse> initialCall = (f, s) => this.InsightsClient.EventOperations.ListEvents(filterString: f, selectedProperties: s);
164+
Func<string, EventDataListResponse> nextCall = (n) => this.InsightsClient.EventOperations.ListEventsNext(nextLink: n);
165+
166+
// Retrieve the records
167+
var fullDetails = this.DetailedOutput.IsPresent;
168+
169+
// If fullDetails is present do not select fields, if not present fetch only the SelectedFieldsForQuery
170+
EventDataListResponse response = initialCall.Invoke(queryFilter, fullDetails ? null : PSEventDataNoDetails.SelectedFieldsForQuery);
171+
var records = new List<IPSEventData>(response.EventDataCollection.Value.Select(e => fullDetails ? (IPSEventData)new PSEventData(e) : (IPSEventData)new PSEventDataNoDetails(e)));
172+
string nextLink = response.EventDataCollection.NextLink;
173+
174+
// Adding a safety check to stop returning records if too many have been read already.
175+
while (!string.IsNullOrWhiteSpace(nextLink) && records.Count < MaxNumberOfReturnedRecords)
176+
{
177+
response = nextCall.Invoke(nextLink);
178+
records.AddRange(response.EventDataCollection.Value.Select(e => fullDetails ? (IPSEventData)new PSEventData(e) : (IPSEventData)new PSEventDataNoDetails(e)));
179+
nextLink = response.EventDataCollection.NextLink;
180+
}
181+
182+
// Returns an object that contains a link to the set of subsequent records or null if not more records are available, called Next, and an array of records, called Value
183+
WriteObject(sendToPipeline: records, enumerateCollection: true);
184+
}
185+
}
186+
}

0 commit comments

Comments
 (0)