├── .gitattributes
├── .gitignore
├── .nuget
├── NuGet.Config
└── NuGet.targets
├── .vs
└── config
│ └── applicationhost.config
├── LICENSE
├── NuGet.Services.Dashboard.Common
├── AlertThresholds.cs
├── App_Readme
│ └── Elmah.txt
├── ConfigurationProcessor.cs
├── DatabaseEvent.cs
├── DatabaseIndex.cs
├── DatabaseRequest.cs
├── DatabaseSize.cs
├── ElmahError.cs
├── IISIPDetails.cs
├── IISRequestDetails.cs
├── IISResponseTimeDetails.cs
├── IISUserAgentDetails.cs
├── NuGet.Services.Dashboard.Common.csproj
├── Properties
│ └── AssemblyInfo.cs
├── RefreshDB.cs
├── RefreshElmahError.cs
├── SearchResult.cs
├── SecretReaderFactory.cs
├── VsTrending.cs
├── WorkJobInstanceDetails.cs
├── WorkJobInvocation.cs
├── app.config
└── packages.config
├── NuGet.Services.Dashboard.Operations.Tools
├── DebugHelper.cs
├── ExceptionUtility.cs
├── NuGet.Services.Dashboard.Operations.Tools.csproj
├── NuGet.Services.Dashboard.Operations.Tools.nuspec
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
├── SnazzyConsoleTarget.cs
├── app.config
└── packages.config
├── NuGet.Services.Dashboard.Operations
├── App.config
├── App_Readme
│ └── Elmah.txt
├── Attributes
│ ├── CommandAttribute.cs
│ └── OptionAttribute.cs
├── Commands
│ └── HelpCommand.cs
├── Common
│ ├── ArgCheck.cs
│ ├── CloudStorageAccountConverter.cs
│ ├── CommandHelp.Designer.cs
│ ├── CommandHelp.resx
│ ├── CommandLineConstants.cs
│ ├── CommandLineException.cs
│ ├── CommonResources.Designer.cs
│ ├── CommonResources.resx
│ ├── LocalizedResourceManager.cs
│ ├── ReportHelpers.cs
│ ├── ResourceHelper.cs
│ ├── SqlConnectionStringConverter.cs
│ ├── SqlHelper.cs
│ ├── StreamConverter.cs
│ ├── TaskResources.Designer.cs
│ ├── TaskResources.resx
│ └── TypeHelper.cs
├── DeploymentEnvironment.cs
├── Infrastructure
│ ├── CommandLineParser.cs
│ ├── CommandManager.cs
│ ├── ICommand.cs
│ ├── ICommandManager.cs
│ └── Verbosity.cs
├── NuGet.Services.Dashboard.Operations.csproj
├── Properties
│ └── AssemblyInfo.cs
├── Scripts
│ └── Highcharts-4.0.1
│ │ └── js
│ │ ├── adapters
│ │ ├── standalone-framework.js
│ │ └── standalone-framework.src.js
│ │ ├── highcharts-3d.js
│ │ ├── highcharts-3d.src.js
│ │ ├── highcharts-all.js
│ │ ├── highcharts-more.js
│ │ ├── highcharts-more.src.js
│ │ ├── highcharts.js
│ │ ├── highcharts.src.js
│ │ ├── modules
│ │ ├── canvas-tools.js
│ │ ├── canvas-tools.src.js
│ │ ├── data.js
│ │ ├── data.src.js
│ │ ├── drilldown.js
│ │ ├── drilldown.src.js
│ │ ├── exporting.js
│ │ ├── exporting.src.js
│ │ ├── funnel.js
│ │ ├── funnel.src.js
│ │ ├── heatmap.js
│ │ ├── heatmap.src.js
│ │ ├── no-data-to-display.js
│ │ ├── no-data-to-display.src.js
│ │ ├── solid-gauge.js
│ │ └── solid-gauge.src.js
│ │ └── themes
│ │ ├── dark-blue.js
│ │ ├── dark-green.js
│ │ ├── dark-unica.js
│ │ ├── gray.js
│ │ ├── grid-light.js
│ │ ├── grid.js
│ │ ├── sand-signika.js
│ │ └── skies.js
├── ScriptsAndReferences
│ ├── DailyStatusReport.htm
│ ├── DashboardAlertMail.htm
│ ├── DeployDashboardTasks.ps1
│ ├── LoadTestReport.htm
│ └── WeeklyStatusReport.htm
├── Tasks
│ ├── DashBoardTasks
│ │ ├── AzureManagementTasks
│ │ │ ├── CreateCloudServiceDetailsReportTask.cs
│ │ │ └── CreateTrafficManagerStatusOverviewReportTask.cs
│ │ ├── ConsolidatedSearch
│ │ │ └── CreateSearchIndexingStatusReportTask.cs
│ │ ├── CreateStatsMonthlyReport.cs
│ │ ├── CreateSupportRequestReportTask.cs
│ │ ├── CreateWADPerformanceDiagnosticsReportTask.cs
│ │ ├── DatabaseTasks
│ │ │ ├── CreateDatabaseDetailedReportTask.cs
│ │ │ ├── CreateDatabaseMetricsReportTask.cs
│ │ │ └── CreateDatabaseSizeReportTask.cs
│ │ ├── IssLogCleanUptask.cs
│ │ ├── PingdomTasks
│ │ │ ├── CreatePingdomDetailedReportTask.cs
│ │ │ ├── CreatePingdomServiceDisruptionReportTask.cs
│ │ │ └── CreatePingdomWeeklyAndHourlyReportTask.cs
│ │ ├── ReportMailTasks
│ │ │ ├── SendAlertMailTask.cs
│ │ │ ├── SendDailyStatusReportEmailTask.cs
│ │ │ ├── SendLoadTestReportEmailTask.cs
│ │ │ └── SendWeeklyStatusReportEmailTask.cs
│ │ ├── RunBackgroundCheckForMetricsService.cs
│ │ ├── SearchServiceTasks
│ │ │ ├── CreateSearchCpuMemStatusReportTask.cs
│ │ │ └── CreateSearchIndexingStatusReportTask.cs
│ │ ├── TrendingTasks
│ │ │ ├── CreateStatsHourlyReportTask.cs
│ │ │ ├── CreateStatsMonthlyReportTask.cs
│ │ │ └── CreateVsTrendingReportTask.cs
│ │ ├── UnixTimeStampUtility.cs
│ │ ├── V2GalleryFrontendTasks
│ │ │ ├── CreateE2ELatencyReportTask.cs
│ │ │ ├── CreateElmahErrorDetailedReportTask.cs
│ │ │ ├── CreateElmahErrorOverviewReportTask.cs
│ │ │ ├── CreateIPDetailsPerDayReportTask.cs
│ │ │ └── CreateRequestsPerHourReportTask.cs
│ │ ├── V3JobsBackGroundTasks
│ │ │ ├── CreateBackupLuceneIndexTask.cs
│ │ │ ├── V3CatalogMonitoringTask.cs
│ │ │ ├── V3SearchAndRegistrationBlobMonitoringTask.cs
│ │ │ └── V3Utility.cs
│ │ ├── VerifyPostValidationCursorTask.cs
│ │ └── WorkServiceTasks
│ │ │ ├── CreateVMWorkJobDetailReportTask.cs
│ │ │ ├── CreateWorkJobDetailReportTask.cs
│ │ │ ├── CreateWorkJobWeeklyReport.cs
│ │ │ ├── RunBackGroundChecksForWorkerJobs.cs
│ │ │ └── RunBackgroundCheckForFailoverDC.cs
│ ├── DashboardAlertMail.htm
│ ├── OpsTask.cs
│ └── TaskBases.cs
├── Util.cs
├── content
│ ├── Promise.js
│ ├── d3.v3.min.js
│ ├── further.js
│ └── jsonld.js
└── packages.config
├── NuGet.Services.Dashboard.sln
├── Nuget.config
├── README.md
└── build.ps1
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 | *.sln merge=union
7 | *.csproj merge=union
8 | *.vbproj merge=union
9 | *.fsproj merge=union
10 | *.dbproj merge=union
11 |
12 | # Standard to msysgit
13 | *.doc diff=astextplain
14 | *.DOC diff=astextplain
15 | *.docx diff=astextplain
16 | *.DOCX diff=astextplain
17 | *.dot diff=astextplain
18 | *.DOT diff=astextplain
19 | *.pdf diff=astextplain
20 | *.PDF diff=astextplain
21 | *.rtf diff=astextplain
22 | *.RTF diff=astextplain
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
2 | [Bb]in/
3 | [Oo]bj/
4 |
5 | # mstest test results
6 | TestResults
7 |
8 | ## Ignore Visual Studio temporary files, build results, and
9 | ## files generated by popular Visual Studio add-ons.
10 |
11 | # User-specific files
12 | *.suo
13 | *.user
14 | *.sln.docstates
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Rr]elease/
19 | x64/
20 | *_i.c
21 | *_p.c
22 | *.ilk
23 | *.meta
24 | *.obj
25 | *.pch
26 | *.pdb
27 | *.pgc
28 | *.pgd
29 | *.rsp
30 | *.sbr
31 | *.tlb
32 | *.tli
33 | *.tlh
34 | *.tmp
35 | *.log
36 | *.vspscc
37 | *.vssscc
38 | .builds
39 |
40 | # Visual C++ cache files
41 | ipch/
42 | *.aps
43 | *.ncb
44 | *.opensdf
45 | *.sdf
46 |
47 | # Visual Studio profiler
48 | *.psess
49 | *.vsp
50 | *.vspx
51 |
52 | # Guidance Automation Toolkit
53 | *.gpState
54 |
55 | # ReSharper is a .NET coding add-in
56 | _ReSharper*
57 |
58 | # NCrunch
59 | *.ncrunch*
60 | .*crunch*.local.xml
61 |
62 | # Installshield output folder
63 | [Ee]xpress
64 |
65 | # DocProject is a documentation generator add-in
66 | DocProject/buildhelp/
67 | DocProject/Help/*.HxT
68 | DocProject/Help/*.HxC
69 | DocProject/Help/*.hhc
70 | DocProject/Help/*.hhk
71 | DocProject/Help/*.hhp
72 | DocProject/Help/Html2
73 | DocProject/Help/html
74 |
75 | # Click-Once directory
76 | publish
77 |
78 | # Publish Web Output
79 | *.Publish.xml
80 |
81 | # NuGet Packages Directory
82 | packages/
83 |
84 | # Windows Azure Build Output
85 | csx
86 | *.build.csdef
87 |
88 | # Windows Store app package directory
89 | AppPackages/
90 |
91 | # Others
92 | [Bb]in
93 | [Oo]bj
94 | sql
95 | TestResults
96 | [Tt]est[Rr]esult*
97 | *.Cache
98 | ClientBin
99 | [Ss]tyle[Cc]op.*
100 | ~$*
101 | *.dbmdl
102 | Generated_Code #added for RIA/Silverlight projects
103 |
104 | # Backup & report files from converting an old project file to a newer
105 | # Visual Studio version. Backup files are not needed, because we have git ;-)
106 | _UpgradeReport_Files/
107 | Backup*/
108 | UpgradeLog*.XML
109 | *.pubxml
110 |
111 | ##########
112 | # Custom #
113 | ##########
114 | AssemblyInfo.g.cs
115 | tools
116 | build
117 | .nuget/CredentialProviderBundle.zip
118 | .nuget/CredentialProvider.VSS.exe
119 | .nuget/EULA_Microsoft Visual Studio Team Services Credential Provider.docx
120 | .nuget/NuGet.exe
121 | .nuget/ThirdPartyNotices.txt
122 |
--------------------------------------------------------------------------------
/.nuget/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Common/App_Readme/Elmah.txt:
--------------------------------------------------------------------------------
1 | A new HTTP handler has been configured in your application for consulting the
2 | error log and its feeds. It is reachable at elmah.axd under your application
3 | root. If, for example, your application is deployed at http://www.example.com,
4 | the URL for ELMAH would be http://www.example.com/elmah.axd. You can, of
5 | course, change this path in your application's configuration file.
6 |
7 | ELMAH is also set up to be secure such that it can only be accessed locally.
8 | You can enable remote access but then it is paramount that you secure access
9 | to authorized users or/and roles only. This can be done using standard
10 | authorization rules and configuration already built into ASP.NET. For more
11 | information, see http://code.google.com/p/elmah/wiki/SecuringErrorLogPages on
12 | the project site.
13 |
14 | Please review the commented out authorization section under
15 | and make the appropriate changes.
16 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Common/ConfigurationProcessor.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) .NET Foundation. All rights reserved.
2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3 |
4 | using System.Collections;
5 | using System.Collections.Generic;
6 | using System.Collections.Specialized;
7 | using NuGet.Services.KeyVault;
8 |
9 | namespace NuGet.Services.Dashboard.Common
10 | {
11 | public class ConfigurationProcessor
12 | {
13 | private ISecretReaderFactory _secretReaderFactory;
14 |
15 | public ConfigurationProcessor(ISecretReaderFactory secretReaderFactory)
16 | {
17 | _secretReaderFactory = secretReaderFactory;
18 | }
19 |
20 | public void InjectSecretsInto(NameValueCollection collection)
21 | {
22 | var secretReader = _secretReaderFactory.CreateSecretReader();
23 | var secretInjector = _secretReaderFactory.CreateSecretInjector(secretReader);
24 |
25 | IEnumerable keys = new List(collection.AllKeys);
26 |
27 | foreach (string key in keys)
28 | {
29 | var framedString = collection[key];
30 | var newValue = secretInjector.InjectAsync(framedString).Result;
31 | collection.Set(key, newValue);
32 | }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Common/DatabaseEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace NuGet.Services.Dashboard.Common
8 | { public class DatabaseEvent
9 | {
10 | public DateTime start_time;
11 | public DateTime end_time;
12 | public string event_type;
13 | public int event_count;
14 | public string description;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Common/DatabaseIndex.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace NuGet.Services.Dashboard.Common
8 | {
9 | public class DatabaseIndex
10 | {
11 | public string ObjectName;
12 | public string IndexName;
13 | public double Fragmentation;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Common/DatabaseRequest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace NuGet.Services.Dashboard.Common
8 | {
9 | public class DatabaseRequest
10 | {
11 | public string text;
12 | public DateTime start_time;
13 | public string Status;
14 | public string Command;
15 | public string Wait_Type;
16 | public int wait_time;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Common/DatabaseSize.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace NuGet.Services.Dashboard.Common
8 | {
9 | public class DatabaseSize
10 | {
11 | public string DBName;
12 | public int SizeInMb;
13 | public string Edition;
14 | public Int64 MaxSizeInMb;
15 | public DatabaseSize()
16 | {
17 |
18 | }
19 |
20 | public DatabaseSize(string dbName,int sizeInMb, Int64 maxSize, string edition)
21 | {
22 | this.DBName = dbName;
23 | this.SizeInMb = sizeInMb;
24 | this.MaxSizeInMb = maxSize;
25 | this.Edition = edition;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Common/ElmahError.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace NuGet.Services.Dashboard.Common
8 | {
9 | public class ElmahError
10 | {
11 | public string Error;
12 | public int Occurecnes;
13 | public DateTime FirstReported;
14 | public DateTime LastReported;
15 | public string Link;
16 | public string Detail;
17 | public int Severity;
18 |
19 | public ElmahError(string error,int occurences,DateTime firstReported,DateTime lastReported, string link, string detail,int severity)
20 | {
21 | this.Error = error;
22 | this.Occurecnes = occurences;
23 | this.FirstReported = firstReported;
24 | this.LastReported = lastReported;
25 | this.Link = link;
26 | this.Detail = detail;
27 | this.Severity = severity;
28 |
29 | }
30 | public ElmahError()
31 | {
32 |
33 | }
34 |
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Common/IISIPDetails.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace NuGet.Services.Dashboard.Common
8 | {
9 | public class IISIPDetails
10 | {
11 | public string cip;
12 | public int AvgTimeTakenInMilliSeconds;
13 | public int RequestsPerHour;
14 |
15 | public IISIPDetails()
16 | {
17 |
18 | }
19 | public IISIPDetails(string cip, int avgTime, int requestsPerHour)
20 | {
21 | this.cip = cip;
22 | this.AvgTimeTakenInMilliSeconds = avgTime;
23 | this.RequestsPerHour = requestsPerHour;
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Common/IISRequestDetails.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace NuGet.Services.Dashboard.Common
8 | {
9 | public class IISRequestDetails
10 | {
11 | public string ScenarioName;
12 | public string UriStem;
13 | public int AvgTimeTakenInMilliSeconds;
14 | public int RequestsPerHour;
15 |
16 | public IISRequestDetails()
17 | {
18 |
19 | }
20 | public IISRequestDetails(string scenarioName,string uriStem, int avgTime, int requestsPerHour)
21 | {
22 | this.ScenarioName = scenarioName;
23 | this.UriStem = uriStem;
24 | this.AvgTimeTakenInMilliSeconds = avgTime;
25 | this.RequestsPerHour = requestsPerHour;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Common/IISResponseTimeDetails.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace NuGet.Services.Dashboard.Common
8 | {
9 | public class IISResponseTimeDetails
10 | {
11 | public string UriStem;
12 | public int AvgTimeTakenInMilliSeconds;
13 |
14 | public IISResponseTimeDetails()
15 | {
16 |
17 | }
18 | public IISResponseTimeDetails(string uriStem, int avgTime)
19 | {
20 | this.UriStem = uriStem;
21 | this.AvgTimeTakenInMilliSeconds = avgTime;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Common/IISUserAgentDetails.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace NuGet.Services.Dashboard.Common
8 | {
9 | public class IISUserAgentDetails
10 | {
11 | public string UserAgentName;
12 | public string UserAgent;
13 | public int AvgTimeTakenInMilliSeconds;
14 | public int RequestsPerHour;
15 |
16 | public IISUserAgentDetails()
17 | {
18 |
19 | }
20 | public IISUserAgentDetails(string userAgentName, string userAgent, int avgTime, int requestsPerHour)
21 | {
22 | this.UserAgentName = userAgentName;
23 | this.UserAgent = userAgent;
24 | this.AvgTimeTakenInMilliSeconds = avgTime;
25 | this.RequestsPerHour = requestsPerHour;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Common/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | [assembly: AssemblyTitle("NuGet.Services.Dashboard.Common")]
5 | [assembly: AssemblyDescription("")]
6 |
7 | // The following GUID is for the ID of the typelib if this project is exposed to COM
8 | [assembly: Guid("aeae461d-c225-4567-99f3-9e62e898d8ab")]
9 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Common/RefreshDB.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Microsoft.WindowsAzure.Storage;
7 | using Microsoft.WindowsAzure.Storage.Blob;
8 | using System.Data.SqlClient;
9 | using AnglicanGeek.DbExecutor;
10 |
11 |
12 | namespace NuGet.Services.Dashboard.Common
13 | {
14 | public class RefreshDB
15 | {
16 | private string ConnectionString { get; set; }
17 |
18 | private int LastNHours { get; set; }
19 |
20 | public RefreshDB(string ConnectionString, int LastNHours)
21 | {
22 | this.ConnectionString = ConnectionString;
23 | this.LastNHours = LastNHours;
24 | }
25 |
26 | public List RefreshDatabaseEvent()
27 | {
28 | var masterConnectionString = new SqlConnectionStringBuilder(ConnectionString) { InitialCatalog = "master" }.ToString();
29 | var currentDbName = new SqlConnectionStringBuilder(ConnectionString).InitialCatalog;
30 | using (var sqlConnection = new SqlConnection(masterConnectionString))
31 | {
32 | using (var dbExecutor = new SqlExecutor(sqlConnection))
33 | {
34 | sqlConnection.Open();
35 |
36 | var usageSeconds = dbExecutor.Query(string.Format("select start_time, end_time,event_type,event_count,description from sys.event_log where start_time>='{0}' and start_time<='{1}' and database_name = '{2}' and severity = 2", DateTime.UtcNow.AddHours(-LastNHours).ToString("yyyy-MM-dd hh:mm:ss"), DateTime.UtcNow.ToString("yyyy-MM-dd hh:mm:ss"), currentDbName));
37 | return usageSeconds.ToList();
38 | }
39 |
40 | }
41 | }
42 |
43 | public List RefreshDatebaseRequest()
44 | {
45 | List> connectionCountDataPoints = new List>();
46 | using (var sqlConnection = new SqlConnection(ConnectionString))
47 | {
48 | using (var dbExecutor = new SqlExecutor(sqlConnection))
49 | {
50 | sqlConnection.Open();
51 | var requests = dbExecutor.Query("SELECT t.text, r.start_time, r.status, r.command, r.wait_type, r.wait_time FROM sys.dm_exec_requests r OUTER APPLY sys.dm_exec_sql_text(sql_handle) t");
52 | return requests.ToList();
53 | }
54 | }
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Common/RefreshElmahError.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System.Data;
4 | using System.Data.SqlClient;
5 | using System.IO;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 | using Microsoft.WindowsAzure.Storage;
9 | using Microsoft.WindowsAzure.Storage.Blob;
10 | using Newtonsoft.Json.Linq;
11 | using AnglicanGeek.DbExecutor;
12 | using System;
13 | using System.Net;
14 | using System.Web.Script.Serialization;
15 | using NuGetGallery;
16 | using NuGetGallery.Infrastructure;
17 | using Elmah;
18 | using NuGet.Services.Dashboard.Common;
19 | using System.Net.Mail;
20 | using System.Configuration;
21 | using System.Net.Mime;
22 |
23 | namespace NuGet.Services.Dashboard.Common
24 | {
25 |
26 | public class RefreshElmahError
27 | {
28 | private string ElmahAccountCredentials { get; set; }
29 | private int LastNHours { get; set; }
30 | private CloudStorageAccount StorageAccount { get; set; }
31 | private string ContainerName { get; set; }
32 | private string ConnectionString { get; set; }
33 |
34 | public RefreshElmahError(string ConnectionString, string ContainerName, int LastNHours, string ElmahAccountCredentials)
35 | {
36 | this.ConnectionString = ConnectionString;
37 | this.ContainerName = ContainerName;
38 | this.LastNHours = LastNHours;
39 | this.ElmahAccountCredentials = ElmahAccountCredentials;
40 | }
41 |
42 | public RefreshElmahError(CloudStorageAccount StorageAccount, string ContainerName, int LastNHours, string ElmahAccountCredentials)
43 | {
44 | this.StorageAccount = StorageAccount;
45 | this.ContainerName = ContainerName;
46 | this.LastNHours = LastNHours;
47 | this.ElmahAccountCredentials = ElmahAccountCredentials;
48 | }
49 |
50 |
51 |
52 |
53 | public List ExecuteRefresh()
54 | {
55 | return GetElmahError(DateTime.Now.Subtract(new TimeSpan(LastNHours, 0, 0)), DateTime.Now);
56 | }
57 |
58 | public List GetElmahError(DateTime start, DateTime end)
59 | {
60 | if (StorageAccount == null) StorageAccount = CloudStorageAccount.Parse(ConnectionString);
61 | List nonCriticalErrorDictionary = new JavaScriptSerializer().Deserialize>(Load(StorageAccount, "Configuration.ElmahNonCriticalErrors.json", ContainerName));
62 | TableErrorLog log = new TableErrorLog(string.Format(ElmahAccountCredentials));
63 | List entities = new List();
64 |
65 | int lasthours = DateTime.Now.Subtract(start).Hours + 1;
66 |
67 | log.GetErrors(0, 500 * lasthours, entities); //retrieve n * LastNHours errors assuming a max of 500 errors per hour.
68 | List listOfErrors = new List();
69 |
70 | //Get the error from Last N hours.
71 | if (entities.Any(entity => entity.Error.Time.ToUniversalTime() > start.ToUniversalTime() && entity.Error.Time.ToUniversalTime() < end.ToUniversalTime()))
72 | {
73 | entities = entities.Where(entity => entity.Error.Time.ToUniversalTime() > start.ToUniversalTime() && entity.Error.Time.ToUniversalTime() < end.ToUniversalTime()).ToList();
74 | var elmahGroups = entities.GroupBy(item => item.Error.Message);
75 |
76 | //Group the error based on exception and send alerts if critical errors exceed the thresold values.
77 | foreach (IGrouping errorGroups in elmahGroups)
78 | {
79 | Console.WriteLine(errorGroups.Key.ToString() + " " + errorGroups.Count());
80 | int severity = 0;
81 | if (nonCriticalErrorDictionary.Any(item => errorGroups.Key.ToString().Contains(item)))
82 | {
83 | severity = 1; //sev 1 is low pri and sev 0 is high pri.
84 | }
85 | string link = "https://www.nuget.org/Admin/Errors.axd/detail?id={0}";
86 | if (ContainerName.Contains("qa"))
87 | {
88 | link = "https://int.nugettest.org/Admin/Errors.axd/detail?id={0}";
89 | }
90 | //for severity, assume all refresh error, severity = 0
91 | listOfErrors.Add(new ElmahError(errorGroups.Key.ToString(), errorGroups.Count(), errorGroups.Min(item => item.Error.Time.ToLocalTime()), errorGroups.Max(item => item.Error.Time.ToLocalTime()), string.Format(link, errorGroups.First().Id), errorGroups.First().Error.Detail, severity));
92 |
93 | }
94 | }
95 |
96 | return listOfErrors;
97 | }
98 |
99 | private string Load(CloudStorageAccount storageAccount, string name, string containerName = "dashboard")
100 | {
101 | CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
102 | CloudBlobContainer container = blobClient.GetContainerReference(containerName);
103 | CloudBlockBlob blob = container.GetBlockBlobReference(name);
104 | string content = string.Empty;
105 | if (blob != null)
106 | {
107 | using (var memoryStream = new MemoryStream())
108 | {
109 | blob.DownloadToStream(memoryStream);
110 | content = System.Text.Encoding.UTF8.GetString(memoryStream.ToArray());
111 | }
112 | }
113 |
114 | return content;
115 | }
116 |
117 |
118 |
119 | }
120 |
121 | }
122 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Common/SearchResult.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace NuGet.Services.Dashboard.Common
9 | {
10 | public class SearchDocument
11 | {
12 | public string Version;
13 | public PackageRegistration PackageRegistration;
14 | public SearchDocument()
15 | {
16 |
17 | }
18 |
19 | public SearchDocument(PackageRegistration _registration, string _version)
20 | {
21 | this.PackageRegistration = _registration;
22 | this.Version = _version;
23 | }
24 | }
25 |
26 | public class PackageRegistration
27 | {
28 | public string Id;
29 | public PackageRegistration()
30 | {
31 |
32 | }
33 |
34 | public PackageRegistration(string Id)
35 | {
36 | this.Id = Id;
37 | }
38 | }
39 |
40 | public class SearchResult:IEnumerator,IEnumerable
41 | {
42 | public List data = new List();
43 | int position = -1;
44 | public SearchResult()
45 | {
46 |
47 | }
48 |
49 | public IEnumerator GetEnumerator()
50 | {
51 | return (IEnumerator)this;
52 | }
53 |
54 | //IEnumerator
55 | public bool MoveNext()
56 | {
57 | if (position < data.Count)
58 | {
59 | position++;
60 | return true;
61 | }
62 | else
63 | {
64 | return false;
65 | }
66 | }
67 |
68 | //IEnumerable
69 | public void Reset()
70 | { position = -1; }
71 |
72 | //IEnumerable
73 | public object Current
74 | {
75 | get { return data[position]; }
76 | }
77 |
78 | }
79 |
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Common/SecretReaderFactory.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) .NET Foundation. All rights reserved.
2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3 |
4 | using System;
5 | using System.Collections.Specialized;
6 | using System.Security.Cryptography.X509Certificates;
7 | using NuGet.Services.KeyVault;
8 |
9 | namespace NuGet.Services.Dashboard.Common
10 | {
11 | public class SecretReaderFactory : ISecretReaderFactory
12 | {
13 | private string _vaultName;
14 | private string _clientId;
15 | private string _certificateThumbprint;
16 | private string _storeName;
17 | private string _storeLocation;
18 | private bool _validateCertificate;
19 |
20 | public SecretReaderFactory(NameValueCollection config)
21 | {
22 | _vaultName = config["keyVault-VaultName"];
23 | _clientId = config["keyVault-ClientId"];
24 | _certificateThumbprint = config["keyVault-CertificateThumbprint"];
25 | _storeName = config["keyVault-StoreName"];
26 | _storeLocation = config["keyVault-StoreLocation"];
27 | _validateCertificate = bool.Parse(config["keyVault-ValidateCertificate"]);
28 | }
29 |
30 | public ISecretReader CreateSecretReader()
31 | {
32 | if (string.IsNullOrEmpty(_vaultName))
33 | {
34 | return new EmptySecretReader();
35 | }
36 |
37 | var keyVaultConfiguration = new KeyVaultConfiguration(
38 | _vaultName,
39 | _clientId,
40 | _certificateThumbprint,
41 | !string.IsNullOrEmpty(_storeName) ? (StoreName)Enum.Parse(typeof(StoreName), _storeName) : StoreName.My,
42 | !string.IsNullOrEmpty(_storeLocation) ? (StoreLocation)Enum.Parse(typeof(StoreLocation), _storeLocation) : StoreLocation.LocalMachine,
43 | _validateCertificate);
44 |
45 | return new KeyVaultReader(keyVaultConfiguration);
46 | }
47 |
48 | public ISecretInjector CreateSecretInjector(ISecretReader secretReader)
49 | {
50 | return new SecretInjector(secretReader);
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Common/VsTrending.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace NuGet.Services.Dashboard.Common
8 | {
9 | public class OperationRequest
10 | {
11 | public string Operation;
12 | public int download;
13 | }
14 |
15 | public class agentRequest
16 | {
17 | public string key;
18 | public int value;
19 |
20 | public agentRequest(string Version, int download)
21 | {
22 | this.key = Version;
23 | this.value = download;
24 | }
25 | }
26 |
27 | public class VsRequest
28 | {
29 | public string key;
30 | public string value;
31 |
32 | public VsRequest(string VsVersion, string download)
33 | {
34 | this.key = VsVersion;
35 | this.value = download;
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Common/WorkJobInstanceDetails.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace NuGet.Services.Dashboard.Common
8 | {
9 | public class WorkJobInstanceDetails
10 | {
11 |
12 | public string JobInstanceName;
13 | public int FrequencyInMinutes;
14 | public string url;
15 |
16 | public WorkJobInstanceDetails(string jobInstanceName,int repeatFrequency,string url)
17 | {
18 | this.JobInstanceName = jobInstanceName;
19 | this.FrequencyInMinutes = repeatFrequency;
20 | this.url = url;
21 | }
22 | public WorkJobInstanceDetails()
23 | {
24 |
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Common/WorkJobInvocation.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace NuGet.Services.Dashboard.Common
8 | {
9 | public class WorkJobInvocation
10 | {
11 | public Guid id;
12 | public string job;
13 | public string jobInstanceName;
14 | public string source;
15 | public string status;
16 | public string result;
17 | public string resultMessage;
18 | public string lastUpdatedBy;
19 | public string logUrl;
20 | public int dequeueCount;
21 | public bool isContinuation;
22 | public DateTime lastDequeuedAt;
23 | public DateTime completedAt;
24 | public DateTime queuedAt;
25 | public DateTime nextVisibleAt;
26 | public DateTime updatedAt;
27 | }
28 | public class WorkInstanceDetail
29 | {
30 | public string jobName;
31 | public string Frequency;
32 | public string LastTime;
33 | public string RunTime;
34 | public string InvocationNo;
35 | public string FaultedNo;
36 | public int FaultRate;
37 | public Dictionary> ErrorMessage;
38 |
39 | public WorkInstanceDetail(string jobName, string Frequency, string LastTime, string RunTime, string InvocationNo, string FaultedNo, int FaultRate,Dictionary> ErrorMessage)
40 | {
41 | this.jobName = jobName;
42 | this.Frequency = Frequency;
43 | this.LastTime = LastTime;
44 | this.RunTime = RunTime;
45 | this.InvocationNo = InvocationNo;
46 | this.FaultedNo = FaultedNo;
47 | this.FaultRate = FaultRate;
48 | this.ErrorMessage = ErrorMessage;
49 | }
50 |
51 | public WorkInstanceDetail()
52 | {
53 |
54 | }
55 | }
56 |
57 | public class WorkServiceAdmin
58 | {
59 | public string username;
60 | public string key;
61 |
62 | public WorkServiceAdmin(string username, string key)
63 | {
64 | this.username = username;
65 | this.key = key;
66 | }
67 |
68 | public WorkServiceAdmin()
69 | {
70 |
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Common/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Common/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations.Tools/DebugHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Linq;
4 | using System.Threading;
5 |
6 | namespace NuGetGallery.Operations.Tools
7 | {
8 | public static class DebugHelper
9 | {
10 | [Conditional("DEBUG")]
11 | public static void WaitForDebugger(ref string[] args)
12 | {
13 | if (args.Length >= 1 &&
14 | (String.Equals("dbg", args[0], StringComparison.OrdinalIgnoreCase) ||
15 | String.Equals("debug", args[0], StringComparison.OrdinalIgnoreCase)))
16 | {
17 | args = args.Skip(1).ToArray();
18 | Console.WriteLine("Waiting for Debugger...");
19 | SpinWait.SpinUntil(() => Debugger.IsAttached);
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations.Tools/ExceptionUtility.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Reflection;
3 |
4 | namespace NuGet
5 | {
6 | public static class ExceptionUtility
7 | {
8 | public static Exception Unwrap(Exception exception)
9 | {
10 | if (exception == null)
11 | {
12 | throw new ArgumentNullException("exception");
13 | }
14 |
15 | if (exception.InnerException == null)
16 | {
17 | return exception;
18 | }
19 |
20 | // Always return the inner exception from a target invocation exception
21 | if (exception is AggregateException ||
22 | exception is TargetInvocationException)
23 | {
24 | return exception.GetBaseException();
25 | }
26 |
27 | return exception;
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations.Tools/NuGet.Services.Dashboard.Operations.Tools.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | galops
5 | $version$
6 | .NET Foundation
7 | .NET Foundation
8 | galops
9 | Copyright .NET Foundation
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations.Tools/Program.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) .NET Foundation. All rights reserved.
2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3 |
4 | using System;
5 | using System.Linq;
6 | using System.Collections.Generic;
7 | using System.ComponentModel.Composition;
8 | using System.ComponentModel.Composition.Hosting;
9 | using System.Configuration;
10 | using NuBot.Infrastructure;
11 | using NuGet;
12 | using NuGet.Services.Dashboard.Common;
13 | using NLog.Config;
14 | using NLog;
15 | using System.Net;
16 |
17 | namespace NuGetGallery.Operations.Tools
18 | {
19 | [Export]
20 | class Program
21 | {
22 | private Logger _logger = LogManager.GetLogger("Program");
23 |
24 | public HelpCommand HelpCommand { get; set; }
25 |
26 | [ImportMany]
27 | public IEnumerable Commands { get; set; }
28 |
29 | [Import]
30 | public ICommandManager Manager { get; set; }
31 |
32 | static int Main(string[] args)
33 | {
34 | DebugHelper.WaitForDebugger(ref args);
35 |
36 | // Configure Logging
37 | ConfigureLogs();
38 |
39 | // Compose
40 | var catalog = new AggregateCatalog(
41 | new AssemblyCatalog(typeof(Program).Assembly),
42 | new AssemblyCatalog(typeof(HelpCommand).Assembly));
43 | var container = new CompositionContainer(catalog);
44 | var p = container.GetExportedValue();
45 |
46 | // Execute
47 | return p.Invoke(args);
48 | }
49 |
50 | public int Invoke(string[] args)
51 | {
52 | try
53 | {
54 | HelpCommand = new HelpCommand(Manager, "galops", "NuGet Gallery Operations", "https://github.com/NuGet/NuGetOperations/wiki/GalOps---Gallery-Operations-Commands");
55 |
56 | // Add commands
57 | foreach (ICommand cmd in Commands)
58 | {
59 | Manager.RegisterCommand(cmd);
60 | }
61 |
62 | var secretReaderFactory = new SecretReaderFactory(ConfigurationManager.AppSettings);
63 |
64 | var configurationProcessor = new ConfigurationProcessor(secretReaderFactory);
65 | configurationProcessor.InjectSecretsInto(ConfigurationManager.AppSettings);
66 |
67 | // Parse the command
68 | var parser = new CommandLineParser(Manager, secretReaderFactory);
69 | ICommand command = parser.ParseCommandLine(args) ?? HelpCommand;
70 |
71 | // Fall back on help command if we failed to parse a valid command
72 | if (!ArgumentCountValid(command))
73 | {
74 | string commandName = command.CommandAttribute.CommandName;
75 | Console.WriteLine("{0}: invalid arguments..", commandName);
76 | HelpCommand.ViewHelpForCommand(commandName);
77 | }
78 | else
79 | {
80 | // Ensure that SSLv3 is disabled and that Tls v1.2 is enabled.
81 | ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Ssl3;
82 | ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
83 |
84 | command.Execute();
85 | }
86 | }
87 | catch (AggregateException exception)
88 | {
89 | string message;
90 | Exception unwrappedEx = ExceptionUtility.Unwrap(exception);
91 | if (unwrappedEx == exception)
92 | {
93 | // If the AggregateException contains more than one InnerException, it cannot be unwrapped. In which case, simply print out individual error messages
94 | message = String.Join(Environment.NewLine, exception.InnerExceptions.Select(ex => ex.Message).Distinct(StringComparer.CurrentCulture));
95 | }
96 | else
97 | {
98 | message = ExceptionUtility.Unwrap(exception).Message;
99 | }
100 | _logger.Error("{0}: {1}", unwrappedEx.GetType().Name, message);
101 | _logger.Error(" Stack Trace: " + unwrappedEx.StackTrace);
102 | return 1;
103 | }
104 | catch (Exception e)
105 | {
106 | var ex = ExceptionUtility.Unwrap(e);
107 | _logger.Error("{0}: {1}", ex.GetType().Name, ex.Message);
108 | _logger.Error(" Stack Trace: " + ex.StackTrace);
109 | return 1;
110 | }
111 | return 0;
112 | }
113 |
114 | private static void ConfigureLogs()
115 | {
116 | // Just a simple logging mechanism
117 | var consoleTarget = new SnazzyConsoleTarget()
118 | {
119 | Layout = "${message}"
120 | };
121 |
122 | var config = new LoggingConfiguration();
123 | config.AddTarget("console", consoleTarget);
124 | config.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, consoleTarget));
125 |
126 | LogManager.Configuration = config;
127 | }
128 |
129 | public static bool ArgumentCountValid(ICommand command)
130 | {
131 | CommandAttribute attribute = command.CommandAttribute;
132 | return command.Arguments.Count >= attribute.MinArgs &&
133 | command.Arguments.Count <= attribute.MaxArgs;
134 | }
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations.Tools/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | [assembly: AssemblyTitle("galops")]
5 | [assembly: AssemblyDescription("Command-line runner for NuGet Gallery Operations commands")]
6 |
7 | // The following GUID is for the ID of the typelib if this project is exposed to COM
8 | [assembly: Guid("ce2f7d7f-caae-4399-b5f9-d32e0a0c525f")]
9 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations.Tools/SnazzyConsoleTarget.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using NLog;
5 | using NLog.Targets;
6 | using ColorPair = System.Tuple;
7 |
8 | namespace NuBot.Infrastructure
9 | {
10 | public class SnazzyConsoleTarget : TargetWithLayout
11 | {
12 | private static readonly Dictionary ColorTable = new Dictionary()
13 | {
14 | { LogLevel.Debug, new ColorPair(ConsoleColor.Magenta, null) },
15 | { LogLevel.Error, new ColorPair(ConsoleColor.Red, null) },
16 | { LogLevel.Fatal, new ColorPair(ConsoleColor.White, ConsoleColor.Red) },
17 | { LogLevel.Info, new ColorPair(ConsoleColor.Green, null) },
18 | { LogLevel.Trace, new ColorPair(ConsoleColor.DarkGray, null) },
19 | { LogLevel.Warn, new ColorPair(ConsoleColor.Black, ConsoleColor.Yellow) }
20 | };
21 |
22 | private static readonly Dictionary LevelNames = new Dictionary() {
23 | { LogLevel.Debug, "debug" },
24 | { LogLevel.Error, "error" },
25 | { LogLevel.Fatal, "fatal" },
26 | { LogLevel.Info, "info" },
27 | { LogLevel.Trace, "trace" },
28 | { LogLevel.Warn, "warn" },
29 | };
30 |
31 | private static readonly int LevelLength = LevelNames.Values.Max(s => s.Length);
32 |
33 | protected override void Write(LogEventInfo logEvent)
34 | {
35 | var oldForeground = Console.ForegroundColor;
36 | var oldBackground = Console.BackgroundColor;
37 |
38 | // Get us to the start of a line
39 | if (Console.CursorLeft > 0)
40 | {
41 | Console.WriteLine();
42 | }
43 |
44 | // Get Color Pair colors
45 | ColorPair pair;
46 | if (!ColorTable.TryGetValue(logEvent.Level, out pair))
47 | {
48 | pair = new ColorPair(Console.ForegroundColor, Console.BackgroundColor);
49 | }
50 |
51 | // Get level string
52 | string levelName;
53 | if (!LevelNames.TryGetValue(logEvent.Level, out levelName))
54 | {
55 | levelName = logEvent.Level.ToString();
56 | }
57 | levelName = levelName.PadRight(LevelLength).Substring(0, LevelLength);
58 |
59 | // Break the message in to lines as necessary
60 | var message = Layout.Render(logEvent);
61 | var existingLines = message.Split(new string[] {Environment.NewLine}, StringSplitOptions.None);
62 | var lines = new List();
63 | foreach (var existingLine in existingLines)
64 | {
65 | var prefix = levelName + ": ";
66 | var fullMessage = prefix + existingLine;
67 | var maxWidth = Console.BufferWidth - 2;
68 | var currentLine = existingLine;
69 | while (fullMessage.Length > maxWidth)
70 | {
71 | int end = maxWidth - prefix.Length;
72 | int spaceIndex = currentLine.LastIndexOf(' ', Math.Min(end, message.Length - 1));
73 | if (spaceIndex < 10)
74 | {
75 | spaceIndex = end;
76 | }
77 | lines.Add(currentLine.Substring(0, spaceIndex).Trim());
78 | currentLine = currentLine.Substring(spaceIndex).Trim();
79 | fullMessage = prefix + currentLine;
80 | }
81 | lines.Add(currentLine);
82 | }
83 |
84 | // Write lines
85 | bool first = true;
86 | foreach (var line in lines.Where(l => !String.IsNullOrWhiteSpace(l)))
87 | {
88 | if (first)
89 | {
90 | first = false;
91 | }
92 | else
93 | {
94 | Console.WriteLine();
95 | }
96 |
97 | // Write Level
98 | Console.ForegroundColor = pair.Item1;
99 | if (pair.Item2.HasValue)
100 | {
101 | Console.BackgroundColor = pair.Item2.Value;
102 | }
103 | Console.Write(levelName);
104 |
105 | // Write the message using the default foreground color, but the specified background color
106 | // UNLESS: The background color has been changed. In which case the foreground color applies here too
107 | var foreground = pair.Item2.HasValue
108 | ? pair.Item1
109 | : oldForeground;
110 | Console.ForegroundColor = foreground;
111 | Console.Write(": " + line);
112 | }
113 | Console.WriteLine();
114 |
115 | Console.ForegroundColor = oldForeground;
116 | Console.BackgroundColor = oldBackground;
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations.Tools/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations.Tools/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/App_Readme/Elmah.txt:
--------------------------------------------------------------------------------
1 | A new HTTP handler has been configured in your application for consulting the
2 | error log and its feeds. It is reachable at elmah.axd under your application
3 | root. If, for example, your application is deployed at http://www.example.com,
4 | the URL for ELMAH would be http://www.example.com/elmah.axd. You can, of
5 | course, change this path in your application's configuration file.
6 |
7 | ELMAH is also set up to be secure such that it can only be accessed locally.
8 | You can enable remote access but then it is paramount that you secure access
9 | to authorized users or/and roles only. This can be done using standard
10 | authorization rules and configuration already built into ASP.NET. For more
11 | information, see http://code.google.com/p/elmah/wiki/SecuringErrorLogPages on
12 | the project site.
13 |
14 | Please review the commented out authorization section under
15 | and make the appropriate changes.
16 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Attributes/CommandAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace NuGetGallery.Operations
4 | {
5 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
6 | public sealed class CommandAttribute : Attribute
7 | {
8 | private string _description;
9 | private string _usageSummary;
10 | private string _usageDescription;
11 | private string _example;
12 |
13 | public string CommandName { get; private set; }
14 | public Type ResourceType { get; private set; }
15 | public string DescriptionResourceName { get; private set; }
16 |
17 |
18 | public string AltName { get; set; }
19 | public int MinArgs { get; set; }
20 | public int MaxArgs { get; set; }
21 | public string UsageSummaryResourceName { get; set; }
22 | public string UsageDescriptionResourceName { get; set; }
23 | public string UsageExampleResourceName { get; set; }
24 | public bool IsSpecialPurpose { get; set; }
25 |
26 | public string Description
27 | {
28 | get
29 | {
30 | if (ResourceType != null && !String.IsNullOrEmpty(DescriptionResourceName))
31 | {
32 | return ResourceHelper.GetLocalizedString(ResourceType, DescriptionResourceName);
33 | }
34 | return _description;
35 | }
36 | private set
37 | {
38 | _description = value;
39 | }
40 | }
41 |
42 | public string UsageSummary
43 | {
44 | get
45 | {
46 | if (ResourceType != null && !String.IsNullOrEmpty(UsageSummaryResourceName))
47 | {
48 | return ResourceHelper.GetLocalizedString(ResourceType, UsageSummaryResourceName);
49 | }
50 | return _usageSummary;
51 | }
52 | set
53 | {
54 | _usageSummary = value;
55 | }
56 | }
57 |
58 | public string UsageDescription
59 | {
60 | get
61 | {
62 | if (ResourceType != null && !String.IsNullOrEmpty(UsageDescriptionResourceName))
63 | {
64 | return ResourceHelper.GetLocalizedString(ResourceType, UsageDescriptionResourceName);
65 | }
66 | return _usageDescription;
67 | }
68 | set
69 | {
70 | _usageDescription = value;
71 | }
72 | }
73 |
74 | public string UsageExample
75 | {
76 | get
77 | {
78 | if (ResourceType != null && !String.IsNullOrEmpty(UsageExampleResourceName))
79 | {
80 | return ResourceHelper.GetLocalizedString(ResourceType, UsageExampleResourceName);
81 | }
82 | return _example;
83 | }
84 | set
85 | {
86 | _example = value;
87 | }
88 | }
89 |
90 | public CommandAttribute(string commandName, string description)
91 | {
92 | CommandName = commandName;
93 | Description = description;
94 | MinArgs = 0;
95 | MaxArgs = Int32.MaxValue;
96 | }
97 |
98 | public CommandAttribute(Type resourceType, string commandName, string descriptionResourceName)
99 | {
100 | ResourceType = resourceType;
101 | CommandName = commandName;
102 | DescriptionResourceName = descriptionResourceName;
103 | MinArgs = 0;
104 | MaxArgs = Int32.MaxValue;
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Attributes/OptionAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace NuGetGallery.Operations
4 | {
5 | [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
6 | public sealed class OptionAttribute : Attribute
7 | {
8 | private string _description;
9 |
10 | public string AltName { get; set; }
11 | public string DescriptionResourceName { get; private set; }
12 |
13 | public string Description
14 | {
15 | get
16 | {
17 | if (ResourceType != null && !String.IsNullOrEmpty(DescriptionResourceName))
18 | {
19 | return ResourceHelper.GetLocalizedString(ResourceType, DescriptionResourceName);
20 | }
21 | return _description;
22 |
23 | }
24 | private set
25 | {
26 | _description = value;
27 | }
28 | }
29 |
30 | public Type ResourceType { get; private set; }
31 |
32 | public OptionAttribute(string description)
33 | {
34 | Description = description;
35 | }
36 |
37 | public OptionAttribute(Type resourceType, string descriptionResourceName)
38 | {
39 | ResourceType = resourceType;
40 | DescriptionResourceName = descriptionResourceName;
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Common/ArgCheck.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace NuGetGallery.Operations.Common
4 | {
5 | public static class ArgCheck
6 | {
7 | public static void RequiredOrConfig(object value, string name)
8 | {
9 | if (value == null)
10 | {
11 | throw CreateRequiredOrConfigEx(name);
12 | }
13 | }
14 |
15 | public static void RequiredOrConfig(string value, string name)
16 | {
17 | if (String.IsNullOrWhiteSpace(value))
18 | {
19 | throw CreateRequiredOrConfigEx(name);
20 | }
21 | }
22 |
23 | public static void Required(object value, string name)
24 | {
25 | if (value == null)
26 | {
27 | throw CreateRequiredEx(name);
28 | }
29 | }
30 |
31 | public static void Required(string value, string name)
32 | {
33 | if (String.IsNullOrWhiteSpace(value))
34 | {
35 | throw CreateRequiredEx(name);
36 | }
37 | }
38 |
39 | private static CommandLineException CreateRequiredEx(string name)
40 | {
41 | return new CommandLineException(String.Format(CommandHelp.Option_Required, name));
42 | }
43 |
44 | private static CommandLineException CreateRequiredOrConfigEx(string name)
45 | {
46 | return new CommandLineException(String.Format(CommandHelp.Option_RequiredOrConfig, name));
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Common/CloudStorageAccountConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using Microsoft.WindowsAzure.Storage;
4 |
5 | namespace NuGetGallery.Operations.Common
6 | {
7 | public class CloudStorageAccountConverter : TypeConverter
8 | {
9 | public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
10 | {
11 | return sourceType == typeof(string);
12 | }
13 |
14 | public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
15 | {
16 | string s = value as string;
17 | if (s != null)
18 | {
19 | CloudStorageAccount acct;
20 | if (CloudStorageAccount.TryParse(s, out acct))
21 | {
22 | return acct;
23 | }
24 | }
25 | return null;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Common/CommandLineConstants.cs:
--------------------------------------------------------------------------------
1 | namespace NuGet.Common
2 | {
3 | internal static class CommandLineConstants
4 | {
5 | internal static string ReferencePage = "https://github.com/NuGet/NuGetOperations";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Common/CommandLineException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Runtime.Serialization;
4 |
5 | namespace NuGetGallery.Operations
6 | {
7 | [Serializable]
8 | public class CommandLineException : Exception
9 | {
10 | public CommandLineException()
11 | {
12 | }
13 |
14 | public CommandLineException(string message)
15 | : base(message)
16 | {
17 | }
18 |
19 | public CommandLineException(string format, params object[] args)
20 | : base(String.Format(CultureInfo.CurrentCulture, format, args))
21 | {
22 | }
23 |
24 | public CommandLineException(string message, Exception exception)
25 | : base(message, exception)
26 | {
27 | }
28 |
29 | protected CommandLineException(SerializationInfo info, StreamingContext context)
30 | : base(info, context)
31 | {
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Common/LocalizedResourceManager.cs:
--------------------------------------------------------------------------------
1 | using System.Resources;
2 | using System.Threading;
3 |
4 | namespace NuGetGallery.Operations
5 | {
6 | internal static class LocalizedResourceManager
7 | {
8 | private static readonly ResourceManager _resourceManager = new ResourceManager("NuGet.Resources", typeof(LocalizedResourceManager).Assembly);
9 |
10 | public static string GetString(string resourceName)
11 | {
12 | var culture = Thread.CurrentThread.CurrentUICulture.ThreeLetterISOLanguageName;
13 | return _resourceManager.GetString(resourceName + '_' + culture) ??
14 | _resourceManager.GetString(resourceName);
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Common/ResourceHelper.cs:
--------------------------------------------------------------------------------
1 | using NuGetGallery.Operations.Common;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Globalization;
5 | using System.IO;
6 | using System.Reflection;
7 | using System.Resources;
8 | using System.Text;
9 |
10 | namespace NuGetGallery.Operations
11 | {
12 | public static class ResourceHelper
13 | {
14 | private static Dictionary _cachedManagers;
15 |
16 | public static string GetLocalizedString(Type resourceType, string resourceNames)
17 | {
18 | if (String.IsNullOrEmpty(resourceNames))
19 | {
20 | throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "resourceNames");
21 | }
22 |
23 | if (resourceType == null)
24 | {
25 | throw new ArgumentNullException("resourceType");
26 | }
27 |
28 | if (_cachedManagers == null)
29 | {
30 | _cachedManagers = new Dictionary();
31 | }
32 |
33 | ResourceManager resourceManager;
34 | if (!_cachedManagers.TryGetValue(resourceType, out resourceManager))
35 | {
36 | PropertyInfo property = resourceType.GetProperty("ResourceManager", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
37 |
38 | if (property == null || property.GetGetMethod(nonPublic: true) == null)
39 | {
40 | throw new InvalidOperationException(
41 | String.Format(CultureInfo.CurrentCulture, TaskResources.ResourceTypeDoesNotHaveProperty, resourceType, "ResourceManager"));
42 | }
43 |
44 | if (property.PropertyType != typeof(ResourceManager))
45 | {
46 | throw new InvalidOperationException(
47 | String.Format(CultureInfo.CurrentCulture, TaskResources.ResourcePropertyIncorrectType, resourceNames, resourceType));
48 | }
49 |
50 | resourceManager = (ResourceManager)property.GetGetMethod(nonPublic: true)
51 | .Invoke(obj: null, parameters: null);
52 | }
53 |
54 | var builder = new StringBuilder();
55 | foreach (var resource in resourceNames.Split(';'))
56 | {
57 | string value = resourceManager.GetString(resource);
58 | if (String.IsNullOrEmpty(value))
59 | {
60 | throw new InvalidOperationException(
61 | String.Format(CultureInfo.CurrentCulture, TaskResources.ResourceTypeDoesNotHaveProperty, resourceType, resource));
62 | }
63 | if (builder.Length > 0)
64 | {
65 | builder.AppendLine();
66 | }
67 | builder.Append(value);
68 | }
69 |
70 | return builder.ToString();
71 | }
72 |
73 | public static string GetBatchFromSqlFile(string filename)
74 | {
75 | using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(filename))
76 | {
77 | using (var reader = new StreamReader(stream))
78 | {
79 | return reader.ReadToEnd();
80 | }
81 | }
82 | }
83 |
84 | public static IEnumerable GetBatchesFromSqlFile(string filename)
85 | {
86 | List batches = new List();
87 |
88 | using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(filename))
89 | {
90 | using (var reader = new StreamReader(stream))
91 | {
92 | StringBuilder batch = new StringBuilder();
93 |
94 | while (!reader.EndOfStream)
95 | {
96 | string line = reader.ReadLine();
97 |
98 | if (line.Trim().Equals("GO", StringComparison.OrdinalIgnoreCase))
99 | {
100 | batches.Add(batch.ToString());
101 | batch.Clear();
102 | }
103 | else
104 | {
105 | batch.AppendLine(line);
106 | }
107 | }
108 | }
109 | }
110 |
111 | return batches;
112 | }
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Common/SqlConnectionStringConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Data.SqlClient;
4 | using System.Globalization;
5 |
6 | namespace NuGetGallery.Operations.Common
7 | {
8 | class SqlConnectionStringConverter : TypeConverter
9 | {
10 | public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
11 | {
12 | return sourceType == typeof(string);
13 | }
14 |
15 | public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
16 | {
17 | string s = value as string;
18 | if (s != null)
19 | {
20 | return new SqlConnectionStringBuilder(s);
21 | }
22 | return null;
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Common/SqlHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data.SqlClient;
3 |
4 | namespace NuGetGallery.Operations.Common
5 | {
6 | static class SqlHelper
7 | {
8 | public static void ExecuteBatch(string connectionString, string sql, int timeout = 180)
9 | {
10 | try
11 | {
12 | using (SqlConnection conn = new SqlConnection(connectionString))
13 | {
14 | conn.Open();
15 |
16 | SqlCommand command = new SqlCommand(sql, conn);
17 | command.CommandTimeout = timeout;
18 | command.ExecuteNonQuery();
19 | }
20 | }
21 | catch (Exception e)
22 | {
23 | throw new ApplicationException(string.Format("{0}\n{1}", e.Message, sql), e);
24 | }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Common/StreamConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.IO;
4 |
5 | namespace NuGetGallery.Operations.Common
6 | {
7 | public class FileStreamConverter : TypeConverter
8 | {
9 | public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
10 | {
11 | return sourceType == typeof(string);
12 | }
13 |
14 | public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
15 | {
16 | string s = value as string;
17 | if (s != null)
18 | {
19 | return File.Open(s, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
20 | }
21 | return null;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Common/TypeHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data.SqlClient;
5 | using System.Globalization;
6 | using System.IO;
7 | using System.Linq;
8 | using System.Reflection;
9 | using Microsoft.WindowsAzure.Storage;
10 | using NuGetGallery.Operations.Common;
11 |
12 | namespace NuGetGallery.Operations
13 | {
14 | internal static class TypeHelper
15 | {
16 | private static Dictionary> _additionalConverters = new Dictionary>();
17 |
18 | static TypeHelper()
19 | {
20 | RegisterConverter(typeof(Stream), () => new FileStreamConverter());
21 | RegisterConverter(typeof(CloudStorageAccount), () => new CloudStorageAccountConverter());
22 | RegisterConverter(typeof(SqlConnectionStringBuilder), () => new SqlConnectionStringConverter());
23 | }
24 |
25 | public static void RegisterConverter(Type type, Func ctor)
26 | {
27 | _additionalConverters[type] = ctor;
28 | }
29 |
30 | public static Type RemoveNullableFromType(Type type)
31 | {
32 | return Nullable.GetUnderlyingType(type) ?? type;
33 | }
34 |
35 | public static object ChangeType(object value, Type type)
36 | {
37 | if (type == null)
38 | {
39 | throw new ArgumentNullException("type");
40 | }
41 |
42 | if (value == null)
43 | {
44 | if (TypeAllowsNull(type))
45 | {
46 | return null;
47 | }
48 | return Convert.ChangeType(value, type, CultureInfo.CurrentCulture);
49 | }
50 |
51 | type = RemoveNullableFromType(type);
52 |
53 | if (value.GetType() == type)
54 | {
55 | return value;
56 | }
57 |
58 | TypeConverter converter = TypeDescriptor.GetConverter(type);
59 | if (converter.CanConvertFrom(value.GetType()))
60 | {
61 | return converter.ConvertFrom(value);
62 | }
63 |
64 | converter = TypeDescriptor.GetConverter(value.GetType());
65 | if (converter.CanConvertTo(type))
66 | {
67 | return converter.ConvertTo(value, type);
68 | }
69 |
70 | Func ctor;
71 | if (_additionalConverters.TryGetValue(type, out ctor))
72 | {
73 | converter = ctor();
74 | if (converter.CanConvertFrom(value.GetType()))
75 | {
76 | return converter.ConvertFrom(value);
77 | }
78 | }
79 |
80 | if (_additionalConverters.TryGetValue(value.GetType(), out ctor))
81 | {
82 | converter = ctor();
83 | if (converter.CanConvertTo(type))
84 | {
85 | return converter.ConvertTo(value, type);
86 | }
87 | }
88 |
89 | throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture,
90 | TaskResources.UnableToConvertTypeError, value.GetType(), type));
91 | }
92 |
93 | public static bool TypeAllowsNull(Type type)
94 | {
95 | return Nullable.GetUnderlyingType(type) != null || !type.IsValueType;
96 | }
97 |
98 | public static Type GetGenericCollectionType(Type type)
99 | {
100 | return GetInterfaceType(type, typeof(ICollection<>));
101 | }
102 |
103 | public static Type GetDictionaryType(Type type)
104 | {
105 | return GetInterfaceType(type, typeof(IDictionary<,>));
106 | }
107 |
108 | private static Type GetInterfaceType(Type type, Type interfaceType)
109 | {
110 | if (type.IsGenericType && type.GetGenericTypeDefinition() == interfaceType)
111 | {
112 | return type;
113 | }
114 | return (from t in type.GetInterfaces()
115 | where t.IsGenericType && t.GetGenericTypeDefinition() == interfaceType
116 | select t).SingleOrDefault();
117 | }
118 |
119 | public static bool IsKeyValueProperty(PropertyInfo property)
120 | {
121 | return GetDictionaryType(property.PropertyType) != null;
122 | }
123 |
124 | public static bool IsMultiValuedProperty(PropertyInfo property)
125 | {
126 | return GetGenericCollectionType(property.PropertyType) != null || IsKeyValueProperty(property);
127 | }
128 |
129 | public static bool IsEnumProperty(PropertyInfo property)
130 | {
131 | return property.PropertyType.IsEnum;
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/DeploymentEnvironment.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data.SqlClient;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Xml.Linq;
8 | using Microsoft.WindowsAzure.Storage;
9 |
10 | namespace NuGetGallery.Operations
11 | {
12 | public class DeploymentEnvironment
13 | {
14 | public IDictionary Settings { get; private set; }
15 | public SqlConnectionStringBuilder MainDatabase { get; private set; }
16 | public SqlConnectionStringBuilder WarehouseDatabase { get; private set; }
17 | public SqlConnectionStringBuilder BackupSourceDatabase { get; set; }
18 |
19 | public CloudStorageAccount MainStorage { get; private set; }
20 | public CloudStorageAccount ReportStorage { get; private set; }
21 | public CloudStorageAccount BackupSourceStorage { get; private set; }
22 |
23 | public DeploymentEnvironment(IDictionary deploymentSettings)
24 | {
25 | Settings = deploymentSettings;
26 | MainDatabase = GetSqlConnectionStringBuilder(deploymentSettings["Operations.Sql.Primary"]);
27 | WarehouseDatabase = GetSqlConnectionStringBuilder(deploymentSettings["Operations.Sql.Warehouse"]);
28 | BackupSourceDatabase = GetSqlConnectionStringBuilder(deploymentSettings["Operations.Sql.BackupSource"]);
29 |
30 | MainStorage = GetCloudStorageAccount(deploymentSettings["Operations.Storage.Primary"]);
31 | ReportStorage = GetCloudStorageAccount(deploymentSettings["Operations.Storage.Reports"]);
32 | BackupSourceStorage = GetCloudStorageAccount(deploymentSettings["Operations.Storage.BackupSource"]);
33 | }
34 |
35 | public static DeploymentEnvironment FromConfigFile(string configFile)
36 | {
37 | // Load the file
38 | var doc = XDocument.Load(configFile);
39 |
40 | // Build a dictionary of settings
41 | var settings = BuildSettingsDictionary(doc);
42 |
43 | // Construct the deployment environment
44 | return new DeploymentEnvironment(settings);
45 | }
46 |
47 | private CloudStorageAccount GetCloudStorageAccount(string connectionString)
48 | {
49 | return String.IsNullOrEmpty(connectionString) ? null : CloudStorageAccount.Parse(connectionString);
50 | }
51 |
52 | private SqlConnectionStringBuilder GetSqlConnectionStringBuilder(string connectionString)
53 | {
54 | return String.IsNullOrEmpty(connectionString) ? null : new SqlConnectionStringBuilder(connectionString);
55 | }
56 |
57 | private static IDictionary BuildSettingsDictionary(XDocument doc)
58 | {
59 | XNamespace ns = XNamespace.Get("http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration");
60 | return (from s in doc.Element(ns + "ServiceConfiguration")
61 | .Element(ns + "Role")
62 | .Element(ns + "ConfigurationSettings")
63 | .Elements(ns + "Setting")
64 | select new KeyValuePair(
65 | s.Attribute("name").Value,
66 | s.Attribute("value").Value))
67 | .ToDictionary(p => p.Key, p => p.Value);
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Infrastructure/CommandManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel.Composition;
4 | using System.Globalization;
5 | using System.Linq;
6 | using System.Reflection;
7 | using NuGetGallery.Operations.Common;
8 |
9 | namespace NuGetGallery.Operations
10 | {
11 | [Export(typeof(ICommandManager))]
12 | public class CommandManager : ICommandManager
13 | {
14 | private readonly IList _commands = new List();
15 |
16 | public IEnumerable GetCommands()
17 | {
18 | return _commands;
19 | }
20 |
21 | public ICommand GetCommand(string commandName)
22 | {
23 | if (String.IsNullOrEmpty(commandName))
24 | {
25 | throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, commandName);
26 | }
27 |
28 | IEnumerable results = from command in _commands
29 | where command.CommandAttribute.CommandName.StartsWith(commandName, StringComparison.OrdinalIgnoreCase) ||
30 | (command.CommandAttribute.AltName ?? String.Empty).StartsWith(commandName, StringComparison.OrdinalIgnoreCase)
31 | select command;
32 |
33 | if (!results.Any())
34 | {
35 | throw new CommandLineException(TaskResources.UnknownCommandError, commandName);
36 | }
37 |
38 | var matchedCommand = results.First();
39 | if (results.Skip(1).Any())
40 | {
41 | // Were there more than one results found?
42 | matchedCommand = results.FirstOrDefault(c => c.CommandAttribute.CommandName.Equals(commandName, StringComparison.OrdinalIgnoreCase)
43 | || commandName.Equals(c.CommandAttribute.AltName, StringComparison.OrdinalIgnoreCase));
44 |
45 | if (matchedCommand == null)
46 | {
47 | // No exact match was found and the result returned multiple prefixes.
48 | throw new CommandLineException(String.Format(CultureInfo.CurrentCulture, TaskResources.AmbiguousCommand, commandName,
49 | String.Join(" ", from c in results select c.CommandAttribute.CommandName)));
50 | }
51 | }
52 | return matchedCommand;
53 | }
54 |
55 | public IDictionary GetCommandOptions(ICommand command)
56 | {
57 | var result = new Dictionary();
58 |
59 | foreach (PropertyInfo propInfo in command.GetType().GetProperties())
60 | {
61 | foreach (OptionAttribute attr in propInfo.GetCustomAttributes(typeof(OptionAttribute), inherit: true))
62 | {
63 | if (!propInfo.CanWrite && !TypeHelper.IsMultiValuedProperty(propInfo))
64 | {
65 | // If the property has neither a setter nor is of a type that can be cast to ICollection<> then there's no way to assign
66 | // values to it. In this case throw.
67 | throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture,
68 | TaskResources.OptionInvalidWithoutSetter, command.GetType().FullName + "." + propInfo.Name));
69 | }
70 | result.Add(attr, propInfo);
71 | }
72 | }
73 |
74 | return result;
75 | }
76 |
77 | public void RegisterCommand(ICommand command)
78 | {
79 | var attrib = command.CommandAttribute;
80 | if (attrib != null)
81 | {
82 | _commands.Add(command);
83 | }
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Infrastructure/ICommand.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel.Composition;
3 |
4 | namespace NuGetGallery.Operations
5 | {
6 | [InheritedExport]
7 | public interface ICommand
8 | {
9 | CommandAttribute CommandAttribute { get; }
10 |
11 | IList Arguments { get; }
12 |
13 | void Execute();
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Infrastructure/ICommandManager.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Diagnostics.CodeAnalysis;
3 | using System.Reflection;
4 |
5 | namespace NuGetGallery.Operations
6 | {
7 | public interface ICommandManager
8 | {
9 | [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Method would do reflection and a property would be inappropriate.")]
10 | IEnumerable GetCommands();
11 | ICommand GetCommand(string commandName);
12 | IDictionary GetCommandOptions(ICommand command);
13 | void RegisterCommand(ICommand command);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Infrastructure/Verbosity.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace NuGetGallery.Operations
3 | {
4 | public enum Verbosity
5 | {
6 | Normal,
7 | Quiet,
8 | Detailed
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | [assembly: AssemblyTitle("NuGetGallery.Operations")]
5 | [assembly: AssemblyDescription("Extensions to NuGetGallery.Monitoring for Azure Web Applications")]
6 |
7 | // The following GUID is for the ID of the typelib if this project is exposed to COM
8 | [assembly: Guid("13364c31-0176-41ce-a6d2-f0b0905e77f5")]
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Scripts/Highcharts-4.0.1/js/adapters/standalone-framework.js:
--------------------------------------------------------------------------------
1 | /*
2 | Highcharts JS v4.0.1 (2014-04-24)
3 |
4 | Standalone Highcharts Framework
5 |
6 | License: MIT License
7 | */
8 | var HighchartsAdapter=function(){function o(c){function b(b,a,d){b.removeEventListener(a,d,!1)}function d(b,a,d){d=b.HCProxiedMethods[d.toString()];b.detachEvent("on"+a,d)}function a(a,c){var f=a.HCEvents,i,g,k,j;if(a.removeEventListener)i=b;else if(a.attachEvent)i=d;else return;c?(g={},g[c]=!0):g=f;for(j in g)if(f[j])for(k=f[j].length;k--;)i(a,j,f[j][k])}c.HCExtended||Highcharts.extend(c,{HCExtended:!0,HCEvents:{},bind:function(b,a){var d=this,c=this.HCEvents,g;if(d.addEventListener)d.addEventListener(b,
9 | a,!1);else if(d.attachEvent){g=function(b){b.target=b.srcElement||window;a.call(d,b)};if(!d.HCProxiedMethods)d.HCProxiedMethods={};d.HCProxiedMethods[a.toString()]=g;d.attachEvent("on"+b,g)}c[b]===r&&(c[b]=[]);c[b].push(a)},unbind:function(c,h){var f,i;c?(f=this.HCEvents[c]||[],h?(i=HighchartsAdapter.inArray(h,f),i>-1&&(f.splice(i,1),this.HCEvents[c]=f),this.removeEventListener?b(this,c,h):this.attachEvent&&d(this,c,h)):(a(this,c),this.HCEvents[c]=[])):(a(this),this.HCEvents={})},trigger:function(b,
10 | a){var d=this.HCEvents[b]||[],c=d.length,g,k,j;k=function(){a.defaultPrevented=!0};for(g=0;g=a.duration+this.startTime){this.now=this.end;
14 | this.pos=this.state=1;this.update();b=this.options.curAnim[this.prop]=!0;for(h in a.curAnim)a.curAnim[h]!==!0&&(b=!1);b&&a.complete&&a.complete.call(e);a=!1}else e=c-this.startTime,this.state=e/a.duration,this.pos=a.easing(e,0,1,a.duration),this.now=this.start+(this.end-this.start)*this.pos,this.update(),a=!0;return a}};this.animate=function(b,d,a){var e,h="",f,i,g;b.stopAnimation=!1;if(typeof a!=="object"||a===null)e=arguments,a={duration:e[2],easing:e[3],complete:e[4]};if(typeof a.duration!=="number")a.duration=
15 | 400;a.easing=Math[a.easing]||Math.easeInOutSine;a.curAnim=Highcharts.extend({},d);for(g in d)i=new n(b,a,g),f=null,g==="d"?(i.paths=c.init(b,b.d,d.d),i.toD=d.d,e=0,f=1):b.attr?e=b.attr(g):(e=parseFloat(HighchartsAdapter._getStyle(b,g))||0,g!=="opacity"&&(h="px")),f||(f=parseFloat(d[g])),i.custom(e,f,h)}},_getStyle:function(c,b){return window.getComputedStyle(c,void 0).getPropertyValue(b)},getScript:function(c,b){var d=l.getElementsByTagName("head")[0],a=l.createElement("script");a.type="text/javascript";
16 | a.src=c;a.onload=b;d.appendChild(a)},inArray:function(c,b){return b.indexOf?b.indexOf(c):p.indexOf.call(b,c)},adapterRun:function(c,b){return parseInt(HighchartsAdapter._getStyle(c,b),10)},grep:function(c,b){return p.filter.call(c,b)},map:function(c,b){for(var d=[],a=0,e=c.length;a=e&&c<=h&&!j&&k!==""&&(k=b.split(f),m(k,function(b,a){a>=i&&a<=g&&(d[a-i]||(d[a-i]=[]),d[a-i][o]=b)}),o+=1)}),this.dataFound())},parseTable:function(){var a=this.options,b=a.table,c=this.columns,d=a.startRow||0,e=a.endRow||Number.MAX_VALUE,h=a.startColumn||0,i=a.endColumn||Number.MAX_VALUE;b&&(typeof b==="string"&&(b=document.getElementById(b)),m(b.getElementsByTagName("tr"),function(a,
11 | b){b>=d&&b<=e&&m(a.children,function(a,e){if((a.tagName==="TD"||a.tagName==="TH")&&e>=h&&e<=i)c[e-h]||(c[e-h]=[]),c[e-h][b-d]=a.innerHTML})}),this.dataFound())},parseGoogleSpreadsheet:function(){var a=this,b=this.options,c=b.googleSpreadsheetKey,d=this.columns,e=b.startRow||0,h=b.endRow||Number.MAX_VALUE,i=b.startColumn||0,g=b.endColumn||Number.MAX_VALUE,f,k;c&&jQuery.ajax({dataType:"json",url:"https://spreadsheets.google.com/feeds/cells/"+c+"/"+(b.googleSpreadsheetWorksheet||"od6")+"/public/values?alt=json-in-script&callback=?",
12 | error:b.error,success:function(b){var b=b.feed.entry,c,j=b.length,m=0,n=0,l;for(l=0;l=i&&l<=g)d[l-i]=[],d[l-i].length=Math.min(n,h-e);for(l=0;l=i&&k<=g&&f>=e&&f<=h)d[k-i][f-e]=c.content.$t;a.dataFound()}})},findHeaderRow:function(){m(this.columns,function(){});this.headerRow=0},trim:function(a){return typeof a==="string"?a.replace(/^\s+|\s+$/g,""):a},parseTypes:function(){for(var a=
13 | this.columns,b=a.length,c,d,e,h;b--;)for(c=a[b].length;c--;)d=a[b][c],e=parseFloat(d),h=this.trim(d),h==e?(a[b][c]=e,e>31536E6?a[b].isDatetime=!0:a[b].isNumeric=!0):(d=this.parseDate(d),b===0&&typeof d==="number"&&!isNaN(d)?(a[b][c]=d,a[b].isDatetime=!0):a[b][c]=h===""?null:h)},dateFormats:{"YYYY-mm-dd":{regex:"^([0-9]{4})-([0-9]{2})-([0-9]{2})$",parser:function(a){return Date.UTC(+a[1],a[2]-1,+a[3])}}},parseDate:function(a){var b=this.options.parseDate,c,d,e;b&&(c=b(a));if(typeof a==="string")for(d in this.dateFormats)b=
14 | this.dateFormats[d],(e=a.match(b.regex))&&(c=b.parser(e));return c},rowsToColumns:function(a){var b,c,d,e,h;if(a){h=[];c=a.length;for(b=0;b1&&(b=a.shift(),this.headerRow===0&&b.shift(),b.isDatetime?c="datetime":b.isNumeric||
15 | (c="category"));for(g=0;g1&&i[f].push(a[g+1][f]!==void 0?a[g+1][f]:null),e>2&&i[f].push(a[g+2][f]!==void 0?a[g+2][f]:null),e>3&&i[f].push(a[g+3][f]!==void 0?a[g+3][f]:null),e>4&&i[f].push(a[g+4][f]!==void 0?a[g+4][f]:null);h[k]={name:a[g].name,data:i};g+=
16 | e}d.complete({xAxis:{type:c},series:h})}}});j.Data=n;j.data=function(a,b){return new n(a,b)};j.wrap(j.Chart.prototype,"init",function(a,b,c){var d=this;b&&b.data?j.data(j.extend(b.data,{complete:function(e){b.hasOwnProperty("series")&&(typeof b.series==="object"?m(b.series,function(a,c){b.series[c]=j.merge(a,e.series[c])}):delete b.series);b=j.merge(e,b);a.call(d,b,c)}}),b):a.call(d,b,c)})})(Highcharts);
17 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Scripts/Highcharts-4.0.1/js/modules/funnel.js:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Highcharts funnel module
4 |
5 | (c) 2010-2014 Torstein Honsi
6 |
7 | License: www.highcharts.com/license
8 | */
9 | (function(b){var d=b.getOptions(),v=d.plotOptions,q=b.seriesTypes,E=b.merge,D=function(){},A=b.each;v.funnel=E(v.pie,{animation:!1,center:["50%","50%"],width:"90%",neckWidth:"30%",height:"100%",neckHeight:"25%",reversed:!1,dataLabels:{connectorWidth:1,connectorColor:"#606060"},size:!0,states:{select:{color:"#C0C0C0",borderColor:"#000000",shadow:!1}}});q.funnel=b.extendClass(q.pie,{type:"funnel",animate:D,singularTooltips:!0,translate:function(){var a=function(j,a){return/%$/.test(j)?a*parseInt(j,
10 | 10)/100:parseInt(j,10)},B=0,f=this.chart,c=this.options,g=c.reversed,b=f.plotWidth,n=f.plotHeight,o=0,f=c.center,h=a(f[0],b),d=a(f[0],n),q=a(c.width,b),k,r,e=a(c.height,n),s=a(c.neckWidth,b),t=a(c.neckHeight,n),w=e-t,a=this.data,x,y,v=c.dataLabels.position==="left"?1:0,z,l,C,p,i,u,m;this.getWidthAt=r=function(j){return j>e-t||e===t?s:s+(q-s)*((e-t-j)/(e-t))};this.getX=function(j,a){return h+(a?-1:1)*(r(g?n-j:j)/2+c.dataLabels.distance)};this.center=[h,d,e];this.centerX=h;A(a,function(a){B+=a.y});
11 | A(a,function(a){m=null;y=B?a.y/B:0;l=d-e/2+o*e;i=l+y*e;k=r(l);z=h-k/2;C=z+k;k=r(i);p=h-k/2;u=p+k;l>w?(z=p=h-s/2,C=u=h+s/2):i>w&&(m=i,k=r(w),p=h-k/2,u=p+k,i=w);g&&(l=e-l,i=e-i,m=m?e-m:null);x=["M",z,l,"L",C,l,u,i];m&&x.push(u,m,p,m);x.push(p,i,"Z");a.shapeType="path";a.shapeArgs={d:x};a.percentage=y*100;a.plotX=h;a.plotY=(l+(m||i))/2;a.tooltipPos=[h,a.plotY];a.slice=D;a.half=v;o+=y})},drawPoints:function(){var a=this,b=a.options,f=a.chart.renderer;A(a.data,function(c){var g=c.graphic,d=c.shapeArgs;
12 | g?g.animate(d):c.graphic=f.path(d).attr({fill:c.color,stroke:b.borderColor,"stroke-width":b.borderWidth}).add(a.group)})},sortByAngle:function(a){a.sort(function(a,b){return a.plotY-b.plotY})},drawDataLabels:function(){var a=this.data,b=this.options.dataLabels.distance,f,c,g,d=a.length,n,o;for(this.center[2]-=2*b;d--;)g=a[d],c=(f=g.half)?1:-1,o=g.plotY,n=this.getX(o,f),g.labelPos=[0,o,n+(b-5)*c,o,n+b*c,o,f?"right":"left",0];q.pie.prototype.drawDataLabels.call(this)}});d.plotOptions.pyramid=b.merge(d.plotOptions.funnel,
13 | {neckWidth:"0%",neckHeight:"0%",reversed:!0});b.seriesTypes.pyramid=b.extendClass(b.seriesTypes.funnel,{type:"pyramid"})})(Highcharts);
14 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Scripts/Highcharts-4.0.1/js/modules/no-data-to-display.js:
--------------------------------------------------------------------------------
1 | /*
2 | Highcharts JS v4.0.1 (2014-04-24)
3 | Plugin for displaying a message when there is no data visible in chart.
4 |
5 | (c) 2010-2014 Highsoft AS
6 | Author: Oystein Moseng
7 |
8 | License: www.highcharts.com/license
9 | */
10 | (function(c){function f(){return!!this.points.length}function g(){this.hasData()?this.hideNoData():this.showNoData()}var d=c.seriesTypes,e=c.Chart.prototype,h=c.getOptions(),i=c.extend;i(h.lang,{noData:"No data to display"});h.noData={position:{x:0,y:0,align:"center",verticalAlign:"middle"},attr:{},style:{fontWeight:"bold",fontSize:"12px",color:"#60606a"}};if(d.pie)d.pie.prototype.hasData=f;if(d.gauge)d.gauge.prototype.hasData=f;if(d.waterfall)d.waterfall.prototype.hasData=f;c.Series.prototype.hasData=
11 | function(){return this.dataMax!==void 0&&this.dataMin!==void 0};e.showNoData=function(a){var b=this.options,a=a||b.lang.noData,b=b.noData;if(!this.noDataLabel)this.noDataLabel=this.renderer.label(a,0,0,null,null,null,null,null,"no-data").attr(b.attr).css(b.style).add(),this.noDataLabel.align(i(this.noDataLabel.getBBox(),b.position),!1,"plotBox")};e.hideNoData=function(){if(this.noDataLabel)this.noDataLabel=this.noDataLabel.destroy()};e.hasData=function(){for(var a=this.series,b=a.length;b--;)if(a[b].hasData()&&
12 | !a[b].options.isInternal)return!0;return!1};e.callbacks.push(function(a){c.addEvent(a,"load",g);c.addEvent(a,"redraw",g)})})(Highcharts);
13 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Scripts/Highcharts-4.0.1/js/modules/no-data-to-display.src.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license Highcharts JS v4.0.1 (2014-04-24)
3 | * Plugin for displaying a message when there is no data visible in chart.
4 | *
5 | * (c) 2010-2014 Highsoft AS
6 | * Author: Oystein Moseng
7 | *
8 | * License: www.highcharts.com/license
9 | */
10 |
11 | (function (H) { // docs
12 |
13 | var seriesTypes = H.seriesTypes,
14 | chartPrototype = H.Chart.prototype,
15 | defaultOptions = H.getOptions(),
16 | extend = H.extend;
17 |
18 | // Add language option
19 | extend(defaultOptions.lang, {
20 | noData: 'No data to display'
21 | });
22 |
23 | // Add default display options for message
24 | defaultOptions.noData = {
25 | position: {
26 | x: 0,
27 | y: 0,
28 | align: 'center',
29 | verticalAlign: 'middle'
30 | },
31 | attr: {
32 | },
33 | style: {
34 | fontWeight: 'bold',
35 | fontSize: '12px',
36 | color: '#60606a'
37 | }
38 | };
39 |
40 | /**
41 | * Define hasData functions for series. These return true if there are data points on this series within the plot area
42 | */
43 | function hasDataPie() {
44 | return !!this.points.length; /* != 0 */
45 | }
46 |
47 | if (seriesTypes.pie) {
48 | seriesTypes.pie.prototype.hasData = hasDataPie;
49 | }
50 |
51 | if (seriesTypes.gauge) {
52 | seriesTypes.gauge.prototype.hasData = hasDataPie;
53 | }
54 |
55 | if (seriesTypes.waterfall) {
56 | seriesTypes.waterfall.prototype.hasData = hasDataPie;
57 | }
58 |
59 | H.Series.prototype.hasData = function () {
60 | return this.dataMax !== undefined && this.dataMin !== undefined;
61 | };
62 |
63 | /**
64 | * Display a no-data message.
65 | *
66 | * @param {String} str An optional message to show in place of the default one
67 | */
68 | chartPrototype.showNoData = function (str) {
69 | var chart = this,
70 | options = chart.options,
71 | text = str || options.lang.noData,
72 | noDataOptions = options.noData;
73 |
74 | if (!chart.noDataLabel) {
75 | chart.noDataLabel = chart.renderer.label(text, 0, 0, null, null, null, null, null, 'no-data')
76 | .attr(noDataOptions.attr)
77 | .css(noDataOptions.style)
78 | .add();
79 | chart.noDataLabel.align(extend(chart.noDataLabel.getBBox(), noDataOptions.position), false, 'plotBox');
80 | }
81 | };
82 |
83 | /**
84 | * Hide no-data message
85 | */
86 | chartPrototype.hideNoData = function () {
87 | var chart = this;
88 | if (chart.noDataLabel) {
89 | chart.noDataLabel = chart.noDataLabel.destroy();
90 | }
91 | };
92 |
93 | /**
94 | * Returns true if there are data points within the plot area now
95 | */
96 | chartPrototype.hasData = function () {
97 | var chart = this,
98 | series = chart.series,
99 | i = series.length;
100 |
101 | while (i--) {
102 | if (series[i].hasData() && !series[i].options.isInternal) {
103 | return true;
104 | }
105 | }
106 |
107 | return false;
108 | };
109 |
110 | /**
111 | * Show no-data message if there is no data in sight. Otherwise, hide it.
112 | */
113 | function handleNoData() {
114 | var chart = this;
115 | if (chart.hasData()) {
116 | chart.hideNoData();
117 | } else {
118 | chart.showNoData();
119 | }
120 | }
121 |
122 | /**
123 | * Add event listener to handle automatic display of no-data message
124 | */
125 | chartPrototype.callbacks.push(function (chart) {
126 | H.addEvent(chart, 'load', handleNoData);
127 | H.addEvent(chart, 'redraw', handleNoData);
128 | });
129 |
130 | }(Highcharts));
131 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Scripts/Highcharts-4.0.1/js/modules/solid-gauge.js:
--------------------------------------------------------------------------------
1 | /*
2 | Highcharts JS v4.0.1 (2014-04-24)
3 | Solid angular gauge module
4 |
5 | (c) 2010-2014 Torstein Honsi
6 |
7 | License: www.highcharts.com/license
8 | */
9 | (function(a){var l=a.getOptions().plotOptions,o=a.pInt,p=a.pick,j=a.each,m;l.solidgauge=a.merge(l.gauge,{colorByPoint:!0});m={initDataClasses:function(b){var h=this,e=this.chart,c,k=0,f=this.options;this.dataClasses=c=[];j(b.dataClasses,function(g,d){var i,g=a.merge(g);c.push(g);if(!g.color)f.dataClassColor==="category"?(i=e.options.colors,g.color=i[k++],k===i.length&&(k=0)):g.color=h.tweenColors(a.Color(f.minColor),a.Color(f.maxColor),d/(b.dataClasses.length-1))})},initStops:function(b){this.stops=
10 | b.stops||[[0,this.options.minColor],[1,this.options.maxColor]];j(this.stops,function(b){b.color=a.Color(b[1])})},toColor:function(b,h){var e,c=this.stops,a,f=this.dataClasses,g,d;if(f)for(d=f.length;d--;){if(g=f[d],a=g.from,c=g.to,(a===void 0||b>=a)&&(c===void 0||b<=c)){e=g.color;if(h)h.dataClass=d;break}}else{this.isLog&&(b=this.val2lin(b));e=1-(this.max-b)/(this.max-this.min);for(d=c.length;d--;)if(e>c[d][0])break;a=c[d]||c[d+1];c=c[d+1]||a;e=1-(c[0]-e)/(c[0]-a[0]||1);e=this.tweenColors(a.color,
11 | c.color,e)}return e},tweenColors:function(b,a,e){var c=a.rgba[3]!==1||b.rgba[3]!==1;return b.rgba.length===0||a.rgba.length===0?"none":(c?"rgba(":"rgb(")+Math.round(a.rgba[0]+(b.rgba[0]-a.rgba[0])*(1-e))+","+Math.round(a.rgba[1]+(b.rgba[1]-a.rgba[1])*(1-e))+","+Math.round(a.rgba[2]+(b.rgba[2]-a.rgba[2])*(1-e))+(c?","+(a.rgba[3]+(b.rgba[3]-a.rgba[3])*(1-e)):"")+")"}};a.seriesTypes.solidgauge=a.extendClass(a.seriesTypes.gauge,{type:"solidgauge",bindAxes:function(){var b;a.seriesTypes.gauge.prototype.bindAxes.call(this);
12 | b=this.yAxis;a.extend(b,m);b.options.dataClasses&&b.initDataClasses(b.options);b.initStops(b.options)},drawPoints:function(){var b=this,h=b.yAxis,e=h.center,c=b.options,k=b.chart.renderer;a.each(b.points,function(f){var g=f.graphic,d=h.startAngleRad+h.translate(f.y,null,null,null,!0),i=o(p(c.radius,100))*e[2]/200,l=o(p(c.innerRadius,60))*e[2]/200,n=h.toColor(f.y,f),j;if(n!=="none")j=f.color,f.color=n;c.wrap===!1&&(d=Math.max(h.startAngleRad,Math.min(h.endAngleRad,d)));d=d*180/Math.PI;d={x:e[0],y:e[1],
13 | r:i,innerR:l,start:h.startAngleRad,end:d/(180/Math.PI)};g?(i=d.d,g.attr({fill:f.color}).animate(d,{step:function(b,c){g.attr("fill",m.tweenColors(a.Color(j),a.Color(n),c.pos))}}),d.d=i):f.graphic=k.arc(d).attr({stroke:c.borderColor||"none","stroke-width":c.borderWidth||0,fill:f.color}).add(b.group)})},animate:null})})(Highcharts);
14 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Scripts/Highcharts-4.0.1/js/themes/dark-blue.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Dark blue theme for Highcharts JS
3 | * @author Torstein Honsi
4 | */
5 |
6 | Highcharts.theme = {
7 | colors: ["#DDDF0D", "#55BF3B", "#DF5353", "#7798BF", "#aaeeee", "#ff0066", "#eeaaee",
8 | "#55BF3B", "#DF5353", "#7798BF", "#aaeeee"],
9 | chart: {
10 | backgroundColor: {
11 | linearGradient: { x1: 0, y1: 0, x2: 1, y2: 1 },
12 | stops: [
13 | [0, 'rgb(48, 48, 96)'],
14 | [1, 'rgb(0, 0, 0)']
15 | ]
16 | },
17 | borderColor: '#000000',
18 | borderWidth: 2,
19 | className: 'dark-container',
20 | plotBackgroundColor: 'rgba(255, 255, 255, .1)',
21 | plotBorderColor: '#CCCCCC',
22 | plotBorderWidth: 1
23 | },
24 | title: {
25 | style: {
26 | color: '#C0C0C0',
27 | font: 'bold 16px "Trebuchet MS", Verdana, sans-serif'
28 | }
29 | },
30 | subtitle: {
31 | style: {
32 | color: '#666666',
33 | font: 'bold 12px "Trebuchet MS", Verdana, sans-serif'
34 | }
35 | },
36 | xAxis: {
37 | gridLineColor: '#333333',
38 | gridLineWidth: 1,
39 | labels: {
40 | style: {
41 | color: '#A0A0A0'
42 | }
43 | },
44 | lineColor: '#A0A0A0',
45 | tickColor: '#A0A0A0',
46 | title: {
47 | style: {
48 | color: '#CCC',
49 | fontWeight: 'bold',
50 | fontSize: '12px',
51 | fontFamily: 'Trebuchet MS, Verdana, sans-serif'
52 |
53 | }
54 | }
55 | },
56 | yAxis: {
57 | gridLineColor: '#333333',
58 | labels: {
59 | style: {
60 | color: '#A0A0A0'
61 | }
62 | },
63 | lineColor: '#A0A0A0',
64 | minorTickInterval: null,
65 | tickColor: '#A0A0A0',
66 | tickWidth: 1,
67 | title: {
68 | style: {
69 | color: '#CCC',
70 | fontWeight: 'bold',
71 | fontSize: '12px',
72 | fontFamily: 'Trebuchet MS, Verdana, sans-serif'
73 | }
74 | }
75 | },
76 | tooltip: {
77 | backgroundColor: 'rgba(0, 0, 0, 0.75)',
78 | style: {
79 | color: '#F0F0F0'
80 | }
81 | },
82 | toolbar: {
83 | itemStyle: {
84 | color: 'silver'
85 | }
86 | },
87 | plotOptions: {
88 | line: {
89 | dataLabels: {
90 | color: '#CCC'
91 | },
92 | marker: {
93 | lineColor: '#333'
94 | }
95 | },
96 | spline: {
97 | marker: {
98 | lineColor: '#333'
99 | }
100 | },
101 | scatter: {
102 | marker: {
103 | lineColor: '#333'
104 | }
105 | },
106 | candlestick: {
107 | lineColor: 'white'
108 | }
109 | },
110 | legend: {
111 | itemStyle: {
112 | font: '9pt Trebuchet MS, Verdana, sans-serif',
113 | color: '#A0A0A0'
114 | },
115 | itemHoverStyle: {
116 | color: '#FFF'
117 | },
118 | itemHiddenStyle: {
119 | color: '#444'
120 | }
121 | },
122 | credits: {
123 | style: {
124 | color: '#666'
125 | }
126 | },
127 | labels: {
128 | style: {
129 | color: '#CCC'
130 | }
131 | },
132 |
133 | navigation: {
134 | buttonOptions: {
135 | symbolStroke: '#DDDDDD',
136 | hoverSymbolStroke: '#FFFFFF',
137 | theme: {
138 | fill: {
139 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
140 | stops: [
141 | [0.4, '#606060'],
142 | [0.6, '#333333']
143 | ]
144 | },
145 | stroke: '#000000'
146 | }
147 | }
148 | },
149 |
150 | // scroll charts
151 | rangeSelector: {
152 | buttonTheme: {
153 | fill: {
154 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
155 | stops: [
156 | [0.4, '#888'],
157 | [0.6, '#555']
158 | ]
159 | },
160 | stroke: '#000000',
161 | style: {
162 | color: '#CCC',
163 | fontWeight: 'bold'
164 | },
165 | states: {
166 | hover: {
167 | fill: {
168 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
169 | stops: [
170 | [0.4, '#BBB'],
171 | [0.6, '#888']
172 | ]
173 | },
174 | stroke: '#000000',
175 | style: {
176 | color: 'white'
177 | }
178 | },
179 | select: {
180 | fill: {
181 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
182 | stops: [
183 | [0.1, '#000'],
184 | [0.3, '#333']
185 | ]
186 | },
187 | stroke: '#000000',
188 | style: {
189 | color: 'yellow'
190 | }
191 | }
192 | }
193 | },
194 | inputStyle: {
195 | backgroundColor: '#333',
196 | color: 'silver'
197 | },
198 | labelStyle: {
199 | color: 'silver'
200 | }
201 | },
202 |
203 | navigator: {
204 | handles: {
205 | backgroundColor: '#666',
206 | borderColor: '#AAA'
207 | },
208 | outlineColor: '#CCC',
209 | maskFill: 'rgba(16, 16, 16, 0.5)',
210 | series: {
211 | color: '#7798BF',
212 | lineColor: '#A6C7ED'
213 | }
214 | },
215 |
216 | scrollbar: {
217 | barBackgroundColor: {
218 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
219 | stops: [
220 | [0.4, '#888'],
221 | [0.6, '#555']
222 | ]
223 | },
224 | barBorderColor: '#CCC',
225 | buttonArrowColor: '#CCC',
226 | buttonBackgroundColor: {
227 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
228 | stops: [
229 | [0.4, '#888'],
230 | [0.6, '#555']
231 | ]
232 | },
233 | buttonBorderColor: '#CCC',
234 | rifleColor: '#FFF',
235 | trackBackgroundColor: {
236 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
237 | stops: [
238 | [0, '#000'],
239 | [1, '#333']
240 | ]
241 | },
242 | trackBorderColor: '#666'
243 | },
244 |
245 | // special colors for some of the
246 | legendBackgroundColor: 'rgba(0, 0, 0, 0.5)',
247 | background2: 'rgb(35, 35, 70)',
248 | dataLabelsColor: '#444',
249 | textColor: '#C0C0C0',
250 | maskColor: 'rgba(255,255,255,0.3)'
251 | };
252 |
253 | // Apply the theme
254 | var highchartsOptions = Highcharts.setOptions(Highcharts.theme);
255 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Scripts/Highcharts-4.0.1/js/themes/dark-green.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Dark blue theme for Highcharts JS
3 | * @author Torstein Honsi
4 | */
5 |
6 | Highcharts.theme = {
7 | colors: ["#DDDF0D", "#55BF3B", "#DF5353", "#7798BF", "#aaeeee", "#ff0066", "#eeaaee",
8 | "#55BF3B", "#DF5353", "#7798BF", "#aaeeee"],
9 | chart: {
10 | backgroundColor: {
11 | linearGradient: [0, 0, 250, 500],
12 | stops: [
13 | [0, 'rgb(48, 96, 48)'],
14 | [1, 'rgb(0, 0, 0)']
15 | ]
16 | },
17 | borderColor: '#000000',
18 | borderWidth: 2,
19 | className: 'dark-container',
20 | plotBackgroundColor: 'rgba(255, 255, 255, .1)',
21 | plotBorderColor: '#CCCCCC',
22 | plotBorderWidth: 1
23 | },
24 | title: {
25 | style: {
26 | color: '#C0C0C0',
27 | font: 'bold 16px "Trebuchet MS", Verdana, sans-serif'
28 | }
29 | },
30 | subtitle: {
31 | style: {
32 | color: '#666666',
33 | font: 'bold 12px "Trebuchet MS", Verdana, sans-serif'
34 | }
35 | },
36 | xAxis: {
37 | gridLineColor: '#333333',
38 | gridLineWidth: 1,
39 | labels: {
40 | style: {
41 | color: '#A0A0A0'
42 | }
43 | },
44 | lineColor: '#A0A0A0',
45 | tickColor: '#A0A0A0',
46 | title: {
47 | style: {
48 | color: '#CCC',
49 | fontWeight: 'bold',
50 | fontSize: '12px',
51 | fontFamily: 'Trebuchet MS, Verdana, sans-serif'
52 |
53 | }
54 | }
55 | },
56 | yAxis: {
57 | gridLineColor: '#333333',
58 | labels: {
59 | style: {
60 | color: '#A0A0A0'
61 | }
62 | },
63 | lineColor: '#A0A0A0',
64 | minorTickInterval: null,
65 | tickColor: '#A0A0A0',
66 | tickWidth: 1,
67 | title: {
68 | style: {
69 | color: '#CCC',
70 | fontWeight: 'bold',
71 | fontSize: '12px',
72 | fontFamily: 'Trebuchet MS, Verdana, sans-serif'
73 | }
74 | }
75 | },
76 | tooltip: {
77 | backgroundColor: 'rgba(0, 0, 0, 0.75)',
78 | style: {
79 | color: '#F0F0F0'
80 | }
81 | },
82 | toolbar: {
83 | itemStyle: {
84 | color: 'silver'
85 | }
86 | },
87 | plotOptions: {
88 | line: {
89 | dataLabels: {
90 | color: '#CCC'
91 | },
92 | marker: {
93 | lineColor: '#333'
94 | }
95 | },
96 | spline: {
97 | marker: {
98 | lineColor: '#333'
99 | }
100 | },
101 | scatter: {
102 | marker: {
103 | lineColor: '#333'
104 | }
105 | },
106 | candlestick: {
107 | lineColor: 'white'
108 | }
109 | },
110 | legend: {
111 | itemStyle: {
112 | font: '9pt Trebuchet MS, Verdana, sans-serif',
113 | color: '#A0A0A0'
114 | },
115 | itemHoverStyle: {
116 | color: '#FFF'
117 | },
118 | itemHiddenStyle: {
119 | color: '#444'
120 | }
121 | },
122 | credits: {
123 | style: {
124 | color: '#666'
125 | }
126 | },
127 | labels: {
128 | style: {
129 | color: '#CCC'
130 | }
131 | },
132 |
133 |
134 | navigation: {
135 | buttonOptions: {
136 | symbolStroke: '#DDDDDD',
137 | hoverSymbolStroke: '#FFFFFF',
138 | theme: {
139 | fill: {
140 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
141 | stops: [
142 | [0.4, '#606060'],
143 | [0.6, '#333333']
144 | ]
145 | },
146 | stroke: '#000000'
147 | }
148 | }
149 | },
150 |
151 | // scroll charts
152 | rangeSelector: {
153 | buttonTheme: {
154 | fill: {
155 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
156 | stops: [
157 | [0.4, '#888'],
158 | [0.6, '#555']
159 | ]
160 | },
161 | stroke: '#000000',
162 | style: {
163 | color: '#CCC',
164 | fontWeight: 'bold'
165 | },
166 | states: {
167 | hover: {
168 | fill: {
169 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
170 | stops: [
171 | [0.4, '#BBB'],
172 | [0.6, '#888']
173 | ]
174 | },
175 | stroke: '#000000',
176 | style: {
177 | color: 'white'
178 | }
179 | },
180 | select: {
181 | fill: {
182 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
183 | stops: [
184 | [0.1, '#000'],
185 | [0.3, '#333']
186 | ]
187 | },
188 | stroke: '#000000',
189 | style: {
190 | color: 'yellow'
191 | }
192 | }
193 | }
194 | },
195 | inputStyle: {
196 | backgroundColor: '#333',
197 | color: 'silver'
198 | },
199 | labelStyle: {
200 | color: 'silver'
201 | }
202 | },
203 |
204 | navigator: {
205 | handles: {
206 | backgroundColor: '#666',
207 | borderColor: '#AAA'
208 | },
209 | outlineColor: '#CCC',
210 | maskFill: 'rgba(16, 16, 16, 0.5)',
211 | series: {
212 | color: '#7798BF',
213 | lineColor: '#A6C7ED'
214 | }
215 | },
216 |
217 | scrollbar: {
218 | barBackgroundColor: {
219 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
220 | stops: [
221 | [0.4, '#888'],
222 | [0.6, '#555']
223 | ]
224 | },
225 | barBorderColor: '#CCC',
226 | buttonArrowColor: '#CCC',
227 | buttonBackgroundColor: {
228 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
229 | stops: [
230 | [0.4, '#888'],
231 | [0.6, '#555']
232 | ]
233 | },
234 | buttonBorderColor: '#CCC',
235 | rifleColor: '#FFF',
236 | trackBackgroundColor: {
237 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
238 | stops: [
239 | [0, '#000'],
240 | [1, '#333']
241 | ]
242 | },
243 | trackBorderColor: '#666'
244 | },
245 |
246 | // special colors for some of the
247 | legendBackgroundColor: 'rgba(0, 0, 0, 0.5)',
248 | background2: 'rgb(35, 35, 70)',
249 | dataLabelsColor: '#444',
250 | textColor: '#C0C0C0',
251 | maskColor: 'rgba(255,255,255,0.3)'
252 | };
253 |
254 | // Apply the theme
255 | var highchartsOptions = Highcharts.setOptions(Highcharts.theme);
256 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Scripts/Highcharts-4.0.1/js/themes/dark-unica.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Dark theme for Highcharts JS
3 | * @author Torstein Honsi
4 | */
5 |
6 | // Load the fonts
7 | Highcharts.createElement('link', {
8 | href: 'http://fonts.googleapis.com/css?family=Unica+One',
9 | rel: 'stylesheet',
10 | type: 'text/css'
11 | }, null, document.getElementsByTagName('head')[0]);
12 |
13 | Highcharts.theme = {
14 | colors: ["#2b908f", "#90ee7e", "#f45b5b", "#7798BF", "#aaeeee", "#ff0066", "#eeaaee",
15 | "#55BF3B", "#DF5353", "#7798BF", "#aaeeee"],
16 | chart: {
17 | backgroundColor: {
18 | linearGradient: { x1: 0, y1: 0, x2: 1, y2: 1 },
19 | stops: [
20 | [0, '#2a2a2b'],
21 | [1, '#3e3e40']
22 | ]
23 | },
24 | style: {
25 | fontFamily: "'Unica One', sans-serif"
26 | },
27 | plotBorderColor: '#606063'
28 | },
29 | title: {
30 | style: {
31 | color: '#E0E0E3',
32 | textTransform: 'uppercase',
33 | fontSize: '20px'
34 | }
35 | },
36 | subtitle: {
37 | style: {
38 | color: '#E0E0E3',
39 | textTransform: 'uppercase'
40 | }
41 | },
42 | xAxis: {
43 | gridLineColor: '#707073',
44 | labels: {
45 | style: {
46 | color: '#E0E0E3'
47 | }
48 | },
49 | lineColor: '#707073',
50 | minorGridLineColor: '#505053',
51 | tickColor: '#707073',
52 | title: {
53 | style: {
54 | color: '#A0A0A3'
55 |
56 | }
57 | }
58 | },
59 | yAxis: {
60 | gridLineColor: '#707073',
61 | labels: {
62 | style: {
63 | color: '#E0E0E3'
64 | }
65 | },
66 | lineColor: '#707073',
67 | minorGridLineColor: '#505053',
68 | tickColor: '#707073',
69 | tickWidth: 1,
70 | title: {
71 | style: {
72 | color: '#A0A0A3'
73 | }
74 | }
75 | },
76 | tooltip: {
77 | backgroundColor: 'rgba(0, 0, 0, 0.85)',
78 | style: {
79 | color: '#F0F0F0'
80 | }
81 | },
82 | plotOptions: {
83 | series: {
84 | dataLabels: {
85 | color: '#B0B0B3'
86 | },
87 | marker: {
88 | lineColor: '#333'
89 | }
90 | },
91 | boxplot: {
92 | fillColor: '#505053'
93 | },
94 | candlestick: {
95 | lineColor: 'white'
96 | },
97 | errorbar: {
98 | color: 'white'
99 | }
100 | },
101 | legend: {
102 | itemStyle: {
103 | color: '#E0E0E3'
104 | },
105 | itemHoverStyle: {
106 | color: '#FFF'
107 | },
108 | itemHiddenStyle: {
109 | color: '#606063'
110 | }
111 | },
112 | credits: {
113 | style: {
114 | color: '#666'
115 | }
116 | },
117 | labels: {
118 | style: {
119 | color: '#707073'
120 | }
121 | },
122 |
123 | drilldown: {
124 | activeAxisLabelStyle: {
125 | color: '#F0F0F3'
126 | },
127 | activeDataLabelStyle: {
128 | color: '#F0F0F3'
129 | }
130 | },
131 |
132 | navigation: {
133 | buttonOptions: {
134 | symbolStroke: '#DDDDDD',
135 | theme: {
136 | fill: '#505053'
137 | }
138 | }
139 | },
140 |
141 | // scroll charts
142 | rangeSelector: {
143 | buttonTheme: {
144 | fill: '#505053',
145 | stroke: '#000000',
146 | style: {
147 | color: '#CCC'
148 | },
149 | states: {
150 | hover: {
151 | fill: '#707073',
152 | stroke: '#000000',
153 | style: {
154 | color: 'white'
155 | }
156 | },
157 | select: {
158 | fill: '#000003',
159 | stroke: '#000000',
160 | style: {
161 | color: 'white'
162 | }
163 | }
164 | }
165 | },
166 | inputBoxBorderColor: '#505053',
167 | inputStyle: {
168 | backgroundColor: '#333',
169 | color: 'silver'
170 | },
171 | labelStyle: {
172 | color: 'silver'
173 | }
174 | },
175 |
176 | navigator: {
177 | handles: {
178 | backgroundColor: '#666',
179 | borderColor: '#AAA'
180 | },
181 | outlineColor: '#CCC',
182 | maskFill: 'rgba(255,255,255,0.1)',
183 | series: {
184 | color: '#7798BF',
185 | lineColor: '#A6C7ED'
186 | },
187 | xAxis: {
188 | gridLineColor: '#505053'
189 | }
190 | },
191 |
192 | scrollbar: {
193 | barBackgroundColor: '#808083',
194 | barBorderColor: '#808083',
195 | buttonArrowColor: '#CCC',
196 | buttonBackgroundColor: '#606063',
197 | buttonBorderColor: '#606063',
198 | rifleColor: '#FFF',
199 | trackBackgroundColor: '#404043',
200 | trackBorderColor: '#404043'
201 | },
202 |
203 | // special colors for some of the
204 | legendBackgroundColor: 'rgba(0, 0, 0, 0.5)',
205 | background2: '#505053',
206 | dataLabelsColor: '#B0B0B3',
207 | textColor: '#C0C0C0',
208 | contrastTextColor: '#F0F0F3',
209 | maskColor: 'rgba(255,255,255,0.3)'
210 | };
211 |
212 | // Apply the theme
213 | Highcharts.setOptions(Highcharts.theme);
214 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Scripts/Highcharts-4.0.1/js/themes/gray.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Gray theme for Highcharts JS
3 | * @author Torstein Honsi
4 | */
5 |
6 | Highcharts.theme = {
7 | colors: ["#DDDF0D", "#7798BF", "#55BF3B", "#DF5353", "#aaeeee", "#ff0066", "#eeaaee",
8 | "#55BF3B", "#DF5353", "#7798BF", "#aaeeee"],
9 | chart: {
10 | backgroundColor: {
11 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
12 | stops: [
13 | [0, 'rgb(96, 96, 96)'],
14 | [1, 'rgb(16, 16, 16)']
15 | ]
16 | },
17 | borderWidth: 0,
18 | borderRadius: 0,
19 | plotBackgroundColor: null,
20 | plotShadow: false,
21 | plotBorderWidth: 0
22 | },
23 | title: {
24 | style: {
25 | color: '#FFF',
26 | font: '16px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
27 | }
28 | },
29 | subtitle: {
30 | style: {
31 | color: '#DDD',
32 | font: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
33 | }
34 | },
35 | xAxis: {
36 | gridLineWidth: 0,
37 | lineColor: '#999',
38 | tickColor: '#999',
39 | labels: {
40 | style: {
41 | color: '#999',
42 | fontWeight: 'bold'
43 | }
44 | },
45 | title: {
46 | style: {
47 | color: '#AAA',
48 | font: 'bold 12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
49 | }
50 | }
51 | },
52 | yAxis: {
53 | alternateGridColor: null,
54 | minorTickInterval: null,
55 | gridLineColor: 'rgba(255, 255, 255, .1)',
56 | minorGridLineColor: 'rgba(255,255,255,0.07)',
57 | lineWidth: 0,
58 | tickWidth: 0,
59 | labels: {
60 | style: {
61 | color: '#999',
62 | fontWeight: 'bold'
63 | }
64 | },
65 | title: {
66 | style: {
67 | color: '#AAA',
68 | font: 'bold 12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
69 | }
70 | }
71 | },
72 | legend: {
73 | itemStyle: {
74 | color: '#CCC'
75 | },
76 | itemHoverStyle: {
77 | color: '#FFF'
78 | },
79 | itemHiddenStyle: {
80 | color: '#333'
81 | }
82 | },
83 | labels: {
84 | style: {
85 | color: '#CCC'
86 | }
87 | },
88 | tooltip: {
89 | backgroundColor: {
90 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
91 | stops: [
92 | [0, 'rgba(96, 96, 96, .8)'],
93 | [1, 'rgba(16, 16, 16, .8)']
94 | ]
95 | },
96 | borderWidth: 0,
97 | style: {
98 | color: '#FFF'
99 | }
100 | },
101 |
102 |
103 | plotOptions: {
104 | series: {
105 | nullColor: '#444444'
106 | },
107 | line: {
108 | dataLabels: {
109 | color: '#CCC'
110 | },
111 | marker: {
112 | lineColor: '#333'
113 | }
114 | },
115 | spline: {
116 | marker: {
117 | lineColor: '#333'
118 | }
119 | },
120 | scatter: {
121 | marker: {
122 | lineColor: '#333'
123 | }
124 | },
125 | candlestick: {
126 | lineColor: 'white'
127 | }
128 | },
129 |
130 | toolbar: {
131 | itemStyle: {
132 | color: '#CCC'
133 | }
134 | },
135 |
136 | navigation: {
137 | buttonOptions: {
138 | symbolStroke: '#DDDDDD',
139 | hoverSymbolStroke: '#FFFFFF',
140 | theme: {
141 | fill: {
142 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
143 | stops: [
144 | [0.4, '#606060'],
145 | [0.6, '#333333']
146 | ]
147 | },
148 | stroke: '#000000'
149 | }
150 | }
151 | },
152 |
153 | // scroll charts
154 | rangeSelector: {
155 | buttonTheme: {
156 | fill: {
157 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
158 | stops: [
159 | [0.4, '#888'],
160 | [0.6, '#555']
161 | ]
162 | },
163 | stroke: '#000000',
164 | style: {
165 | color: '#CCC',
166 | fontWeight: 'bold'
167 | },
168 | states: {
169 | hover: {
170 | fill: {
171 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
172 | stops: [
173 | [0.4, '#BBB'],
174 | [0.6, '#888']
175 | ]
176 | },
177 | stroke: '#000000',
178 | style: {
179 | color: 'white'
180 | }
181 | },
182 | select: {
183 | fill: {
184 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
185 | stops: [
186 | [0.1, '#000'],
187 | [0.3, '#333']
188 | ]
189 | },
190 | stroke: '#000000',
191 | style: {
192 | color: 'yellow'
193 | }
194 | }
195 | }
196 | },
197 | inputStyle: {
198 | backgroundColor: '#333',
199 | color: 'silver'
200 | },
201 | labelStyle: {
202 | color: 'silver'
203 | }
204 | },
205 |
206 | navigator: {
207 | handles: {
208 | backgroundColor: '#666',
209 | borderColor: '#AAA'
210 | },
211 | outlineColor: '#CCC',
212 | maskFill: 'rgba(16, 16, 16, 0.5)',
213 | series: {
214 | color: '#7798BF',
215 | lineColor: '#A6C7ED'
216 | }
217 | },
218 |
219 | scrollbar: {
220 | barBackgroundColor: {
221 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
222 | stops: [
223 | [0.4, '#888'],
224 | [0.6, '#555']
225 | ]
226 | },
227 | barBorderColor: '#CCC',
228 | buttonArrowColor: '#CCC',
229 | buttonBackgroundColor: {
230 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
231 | stops: [
232 | [0.4, '#888'],
233 | [0.6, '#555']
234 | ]
235 | },
236 | buttonBorderColor: '#CCC',
237 | rifleColor: '#FFF',
238 | trackBackgroundColor: {
239 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
240 | stops: [
241 | [0, '#000'],
242 | [1, '#333']
243 | ]
244 | },
245 | trackBorderColor: '#666'
246 | },
247 |
248 | // special colors for some of the demo examples
249 | legendBackgroundColor: 'rgba(48, 48, 48, 0.8)',
250 | background2: 'rgb(70, 70, 70)',
251 | dataLabelsColor: '#444',
252 | textColor: '#E0E0E0',
253 | maskColor: 'rgba(255,255,255,0.3)'
254 | };
255 |
256 | // Apply the theme
257 | var highchartsOptions = Highcharts.setOptions(Highcharts.theme);
258 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Scripts/Highcharts-4.0.1/js/themes/grid-light.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Grid-light theme for Highcharts JS
3 | * @author Torstein Honsi
4 | */
5 |
6 | // Load the fonts
7 | Highcharts.createElement('link', {
8 | href: 'http://fonts.googleapis.com/css?family=Dosis:400,600',
9 | rel: 'stylesheet',
10 | type: 'text/css'
11 | }, null, document.getElementsByTagName('head')[0]);
12 |
13 | Highcharts.theme = {
14 | colors: ["#7cb5ec", "#f7a35c", "#90ee7e", "#7798BF", "#aaeeee", "#ff0066", "#eeaaee",
15 | "#55BF3B", "#DF5353", "#7798BF", "#aaeeee"],
16 | chart: {
17 | backgroundColor: null,
18 | style: {
19 | fontFamily: "Dosis, sans-serif"
20 | }
21 | },
22 | title: {
23 | style: {
24 | fontSize: '16px',
25 | fontWeight: 'bold',
26 | textTransform: 'uppercase'
27 | }
28 | },
29 | tooltip: {
30 | borderWidth: 0,
31 | backgroundColor: 'rgba(219,219,216,0.8)',
32 | shadow: false
33 | },
34 | legend: {
35 | itemStyle: {
36 | fontWeight: 'bold',
37 | fontSize: '13px'
38 | }
39 | },
40 | xAxis: {
41 | gridLineWidth: 1,
42 | labels: {
43 | style: {
44 | fontSize: '12px'
45 | }
46 | }
47 | },
48 | yAxis: {
49 | minorTickInterval: 'auto',
50 | title: {
51 | style: {
52 | textTransform: 'uppercase'
53 | }
54 | },
55 | labels: {
56 | style: {
57 | fontSize: '12px'
58 | }
59 | }
60 | },
61 | plotOptions: {
62 | candlestick: {
63 | lineColor: '#404048'
64 | }
65 | },
66 |
67 |
68 | // General
69 | background2: '#F0F0EA'
70 |
71 | };
72 |
73 | // Apply the theme
74 | Highcharts.setOptions(Highcharts.theme);
75 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Scripts/Highcharts-4.0.1/js/themes/grid.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Grid theme for Highcharts JS
3 | * @author Torstein Honsi
4 | */
5 |
6 | Highcharts.theme = {
7 | colors: ['#058DC7', '#50B432', '#ED561B', '#DDDF00', '#24CBE5', '#64E572', '#FF9655', '#FFF263', '#6AF9C4'],
8 | chart: {
9 | backgroundColor: {
10 | linearGradient: { x1: 0, y1: 0, x2: 1, y2: 1 },
11 | stops: [
12 | [0, 'rgb(255, 255, 255)'],
13 | [1, 'rgb(240, 240, 255)']
14 | ]
15 | },
16 | borderWidth: 2,
17 | plotBackgroundColor: 'rgba(255, 255, 255, .9)',
18 | plotShadow: true,
19 | plotBorderWidth: 1
20 | },
21 | title: {
22 | style: {
23 | color: '#000',
24 | font: 'bold 16px "Trebuchet MS", Verdana, sans-serif'
25 | }
26 | },
27 | subtitle: {
28 | style: {
29 | color: '#666666',
30 | font: 'bold 12px "Trebuchet MS", Verdana, sans-serif'
31 | }
32 | },
33 | xAxis: {
34 | gridLineWidth: 1,
35 | lineColor: '#000',
36 | tickColor: '#000',
37 | labels: {
38 | style: {
39 | color: '#000',
40 | font: '11px Trebuchet MS, Verdana, sans-serif'
41 | }
42 | },
43 | title: {
44 | style: {
45 | color: '#333',
46 | fontWeight: 'bold',
47 | fontSize: '12px',
48 | fontFamily: 'Trebuchet MS, Verdana, sans-serif'
49 |
50 | }
51 | }
52 | },
53 | yAxis: {
54 | minorTickInterval: 'auto',
55 | lineColor: '#000',
56 | lineWidth: 1,
57 | tickWidth: 1,
58 | tickColor: '#000',
59 | labels: {
60 | style: {
61 | color: '#000',
62 | font: '11px Trebuchet MS, Verdana, sans-serif'
63 | }
64 | },
65 | title: {
66 | style: {
67 | color: '#333',
68 | fontWeight: 'bold',
69 | fontSize: '12px',
70 | fontFamily: 'Trebuchet MS, Verdana, sans-serif'
71 | }
72 | }
73 | },
74 | legend: {
75 | itemStyle: {
76 | font: '9pt Trebuchet MS, Verdana, sans-serif',
77 | color: 'black'
78 |
79 | },
80 | itemHoverStyle: {
81 | color: '#039'
82 | },
83 | itemHiddenStyle: {
84 | color: 'gray'
85 | }
86 | },
87 | labels: {
88 | style: {
89 | color: '#99b'
90 | }
91 | },
92 |
93 | navigation: {
94 | buttonOptions: {
95 | theme: {
96 | stroke: '#CCCCCC'
97 | }
98 | }
99 | }
100 | };
101 |
102 | // Apply the theme
103 | var highchartsOptions = Highcharts.setOptions(Highcharts.theme);
104 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Scripts/Highcharts-4.0.1/js/themes/sand-signika.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Sand-Signika theme for Highcharts JS
3 | * @author Torstein Honsi
4 | */
5 |
6 | // Load the fonts
7 | Highcharts.createElement('link', {
8 | href: 'http://fonts.googleapis.com/css?family=Signika:400,700',
9 | rel: 'stylesheet',
10 | type: 'text/css'
11 | }, null, document.getElementsByTagName('head')[0]);
12 |
13 | // Add the background image to the container
14 | Highcharts.wrap(Highcharts.Chart.prototype, 'getContainer', function (proceed) {
15 | proceed.call(this);
16 | this.container.style.background = 'url(http://www.highcharts.com/samples/graphics/sand.png)';
17 | });
18 |
19 |
20 | Highcharts.theme = {
21 | colors: ["#f45b5b", "#8085e9", "#8d4654", "#7798BF", "#aaeeee", "#ff0066", "#eeaaee",
22 | "#55BF3B", "#DF5353", "#7798BF", "#aaeeee"],
23 | chart: {
24 | backgroundColor: null,
25 | style: {
26 | fontFamily: "Signika, serif"
27 | }
28 | },
29 | title: {
30 | style: {
31 | color: 'black',
32 | fontSize: '16px',
33 | fontWeight: 'bold'
34 | }
35 | },
36 | subtitle: {
37 | style: {
38 | color: 'black'
39 | }
40 | },
41 | tooltip: {
42 | borderWidth: 0
43 | },
44 | legend: {
45 | itemStyle: {
46 | fontWeight: 'bold',
47 | fontSize: '13px'
48 | }
49 | },
50 | xAxis: {
51 | labels: {
52 | style: {
53 | color: '#6e6e70'
54 | }
55 | }
56 | },
57 | yAxis: {
58 | labels: {
59 | style: {
60 | color: '#6e6e70'
61 | }
62 | }
63 | },
64 | plotOptions: {
65 | series: {
66 | shadow: true
67 | },
68 | candlestick: {
69 | lineColor: '#404048'
70 | }
71 | },
72 |
73 | // Highstock specific
74 | navigator: {
75 | xAxis: {
76 | gridLineColor: '#D0D0D8'
77 | }
78 | },
79 | rangeSelector: {
80 | buttonTheme: {
81 | fill: 'white',
82 | stroke: '#C0C0C8',
83 | 'stroke-width': 1,
84 | states: {
85 | select: {
86 | fill: '#D0D0D8'
87 | }
88 | }
89 | }
90 | },
91 | scrollbar: {
92 | trackBorderColor: '#C0C0C8'
93 | },
94 |
95 | // General
96 | background2: '#E0E0E8'
97 |
98 | };
99 |
100 | // Apply the theme
101 | Highcharts.setOptions(Highcharts.theme);
102 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Scripts/Highcharts-4.0.1/js/themes/skies.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Skies theme for Highcharts JS
3 | * @author Torstein Honsi
4 | */
5 |
6 | Highcharts.theme = {
7 | colors: ["#514F78", "#42A07B", "#9B5E4A", "#72727F", "#1F949A", "#82914E", "#86777F", "#42A07B"],
8 | chart: {
9 | className: 'skies',
10 | borderWidth: 0,
11 | plotShadow: true,
12 | plotBackgroundImage: 'http://www.highcharts.com/demo/gfx/skies.jpg',
13 | plotBackgroundColor: {
14 | linearGradient: [0, 0, 250, 500],
15 | stops: [
16 | [0, 'rgba(255, 255, 255, 1)'],
17 | [1, 'rgba(255, 255, 255, 0)']
18 | ]
19 | },
20 | plotBorderWidth: 1
21 | },
22 | title: {
23 | style: {
24 | color: '#3E576F',
25 | font: '16px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
26 | }
27 | },
28 | subtitle: {
29 | style: {
30 | color: '#6D869F',
31 | font: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
32 | }
33 | },
34 | xAxis: {
35 | gridLineWidth: 0,
36 | lineColor: '#C0D0E0',
37 | tickColor: '#C0D0E0',
38 | labels: {
39 | style: {
40 | color: '#666',
41 | fontWeight: 'bold'
42 | }
43 | },
44 | title: {
45 | style: {
46 | color: '#666',
47 | font: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
48 | }
49 | }
50 | },
51 | yAxis: {
52 | alternateGridColor: 'rgba(255, 255, 255, .5)',
53 | lineColor: '#C0D0E0',
54 | tickColor: '#C0D0E0',
55 | tickWidth: 1,
56 | labels: {
57 | style: {
58 | color: '#666',
59 | fontWeight: 'bold'
60 | }
61 | },
62 | title: {
63 | style: {
64 | color: '#666',
65 | font: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
66 | }
67 | }
68 | },
69 | legend: {
70 | itemStyle: {
71 | font: '9pt Trebuchet MS, Verdana, sans-serif',
72 | color: '#3E576F'
73 | },
74 | itemHoverStyle: {
75 | color: 'black'
76 | },
77 | itemHiddenStyle: {
78 | color: 'silver'
79 | }
80 | },
81 | labels: {
82 | style: {
83 | color: '#3E576F'
84 | }
85 | }
86 | };
87 |
88 | // Apply the theme
89 | var highchartsOptions = Highcharts.setOptions(Highcharts.theme);
90 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/ScriptsAndReferences/DeployDashboardTasks.ps1:
--------------------------------------------------------------------------------
1 | param(
2 | [Parameter(Mandatory=$true)] [string]$FrontEndStorageConnectionString,
3 | [Parameter(Mandatory=$true)] [string]$FrontEndLegacyDBConnectionString,
4 | [Parameter(Mandatory=$true)] [string]$SubscriptionId,
5 | [Parameter(Mandatory=$false)][string]$FrontEndCloudServiceName,
6 | [Parameter(Mandatory=$false)][string]$TrafficManagerProfileName,
7 | [Parameter(Mandatory=$false)][string]$ProdManagementCertName,
8 | [Parameter(Mandatory=$true)] [string]$PingdomUserName,
9 | [Parameter(Mandatory=$true)] [string]$PingdomPassword,
10 | [Parameter(Mandatory=$true)] [string]$PingdomAppKey,
11 | [Parameter(Mandatory=$true)] [string]$DashboardStorageConnectionString,
12 | [Parameter(Mandatory=$true)] [string]$DashboardStorageContainerName,
13 | [Parameter(Mandatory=$true)] [string]$WorkingDir,
14 | [Parameter(Mandatory=$true)] [string]$CurrentUserPassword,
15 | [Parameter(Mandatory=$false)][string]$EnvName,
16 | [Parameter(Mandatory=$false)][string]$ConsolidatedSearchServiceEndPoint
17 | )
18 |
19 | $time = [System.DateTime]::Now
20 | $time = $time.AddMinutes(-($time.Minute))
21 |
22 | function CreateTask() {
23 | param([string]$taskName, [string]$argument, [int]$interval)
24 |
25 | $settings = New-ScheduledTaskSettingsSet -MultipleInstances P
26 | $Action = New-ScheduledTaskAction -Execute "$WorkingDir\galops.exe" -WorkingDirectory $WorkingDir -Argument $argument
27 | $trigger = New-ScheduledTaskTrigger -Once -At $time -RepetitionDuration ([Timespan]::MaxValue) -RepetitionInterval (New-TimeSpan -Minutes $interval)
28 | Unregister-ScheduledTask -TaskName $taskName -TaskPath "\NuGetDashboard\$EnvName\" -ErrorAction SilentlyContinue -Confirm:$false
29 | Register-ScheduledTask -TaskName $taskName -TaskPath "\NuGetDashboard\$EnvName\" -User $env:USERDOMAIN\$env:USERNAME -Password $CurrentUserPassword -Action $Action -Trigger $trigger -Settings $settings
30 | }
31 |
32 | # Database related tasks
33 | CreateTask "CreateTrendingOverviewReport" "cshr -db `"$FrontEndLegacyDBConnectionString`" -st `"$DashboardStorageConnectionString`" -ct $DashboardStorageContainerName" 60
34 |
35 | # Enable or remove based on the outcome of:
36 | # https://github.com/NuGet/Engineering/issues/291
37 | # CreateTask "CreateDataBaseOverviewReport" "cdrt -db `"$FrontEndLegacyDBConnectionString`" -st `"$DashboardStorageConnectionString`" -ct $DashboardStorageContainerName" 30
38 | # CreateTask "CreateDataBase24HourDetailedReport" "cddrt -db `"$FrontEndLegacyDBConnectionString`" -st `"$DashboardStorageConnectionString`" -ct $DashboardStorageContainerName -n 24" 30
39 |
40 | # ElmahError related tasks
41 | CreateTask "CreateElmaherrorOverviewReport" "ceeort -ea `"$FrontEndStorageConnectionString`" -st `"$DashboardStorageConnectionString`" -ct $DashboardStorageContainerName" 60
42 | CreateTask "CreateElmaherror1HourDetailedReport" "ceedrt -ea `"$FrontEndStorageConnectionString`" -st `"$DashboardStorageConnectionString`" -ct $DashboardStorageContainerName -n 1" 30
43 | CreateTask "CreateElmaherror6HourDetailedReport" "ceedrt -ea `"$FrontEndStorageConnectionString`" -st `"$DashboardStorageConnectionString`" -ct $DashboardStorageContainerName -n 6" 30
44 | CreateTask "CreateElmaherror24HourDetailedReport" "ceedrt -ea `"$FrontEndStorageConnectionString`" -st `"$DashboardStorageConnectionString`" -ct $DashboardStorageContainerName -n 24" 30
45 |
46 | # Pingdom tasks
47 | CreateTask "CreatePingdomHourlyReport" "cpdwr -user `"$PingdomUserName`" -password `"$PingdomPassword`" -appkey `"$PingdomAppKey`" -frequency Hourly -st `"$DashboardStorageConnectionString`" -ct $DashboardStorageContainerName" 60
48 | CreateTask "CreatePingdomServiceDisruptionReport" "psdrt -user `"$PingdomUserName`" -password `"$PingdomPassword`" -appkey `"$PingdomAppKey`" -n 1 -st `"$DashboardStorageConnectionString`" -ct $DashboardStorageContainerName" 60
49 |
50 | # SearchService tasks
51 | CreateTask "CreateConsolidatedSearchIndexingStatusReportTask" "ccsisrt -db `"$FrontEndLegacyDBConnectionString`" -se $ConsolidatedSearchServiceEndPoint -st `"$DashboardStorageConnectionString`" -ct $DashboardStorageContainerName -alsev1 120 -alsev2 30 -disn -disic" 10
52 |
53 | # Misc
54 | CreateTask "CreateRequestsCountOverviewReport" "crphrt -iis `"$FrontEndStorageConnectionString`" -retry 3 -servicename $FrontEndCloudServiceName -st `"$DashboardStorageConnectionString`" -ct $DashboardStorageContainerName" 60
55 | CreateTask "CreateTrafficManagerStatusOverviewReport" "ctmort -id $SubscriptionId -name $TrafficManagerProfileName -cername $ProdManagementCertName -st `"$DashboardStorageConnectionString`" -ct $DashboardStorageContainerName" 5
56 | CreateTask "CreateV2GalleryInstanceCountReport" "ccsdrt -id $SubscriptionId -name $FrontEndCloudServiceName -cername $ProdManagementCertName -st `"$DashboardStorageConnectionString`" -ct $DashboardStorageContainerName" 60
57 |
58 | # Clean-up
59 | CreateTask "IISLogCleanUpTask" "clean" 1440
60 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/ScriptsAndReferences/LoadTestReport.htm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NuGet/NuGet.Services.Dashboard/000734d70fe984b351d09d08fc92debf280ae96b/NuGet.Services.Dashboard.Operations/ScriptsAndReferences/LoadTestReport.htm
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Tasks/DashBoardTasks/AzureManagementTasks/CreateTrafficManagerStatusOverviewReportTask.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.IO;
3 | using Newtonsoft.Json.Linq;
4 | using NuGetGallery.Operations.Common;
5 | using System;
6 | using System.Net;
7 | using System.Security.Cryptography.X509Certificates;
8 | using System.Xml;
9 |
10 |
11 | namespace NuGetGallery.Operations
12 | {
13 | [Command("CreateTrafficManagerStatusOverviewReportTask", "Creates report for highlevel status of Traffic manager", AltName = "ctmort")]
14 | public class CreateTrafficManagerStatusOverviewReportTask : StorageTask
15 | {
16 | [Option("SubsciptionId", AltName = "id")]
17 | public string SubscriptionId { get; set; }
18 |
19 | [Option("ProfileName", AltName = "name")]
20 | public string ProfileName { get; set; }
21 |
22 | [Option("CertificateName", AltName = "cername")]
23 | public string CertificateName { get; set; }
24 | public override void ExecuteCommand()
25 | {
26 | X509Certificate cert = X509Certificate.CreateFromCertFile(CertificateName);
27 | HttpWebRequest request = (HttpWebRequest)WebRequest.Create(string.Format("https://management.core.windows.net/{0}/services/WATM/profiles/{1}/definitions", SubscriptionId, ProfileName));
28 | request.ClientCertificates.Add(cert);
29 | request.Headers.Add("x-ms-version: 2014-02-01");
30 | request.PreAuthenticate = true;
31 | request.Method = "GET";
32 | var response = request.GetResponse();
33 | //Schema of the response would be as specified in http://msdn.microsoft.com/en-us/library/azure/hh758251.aspx
34 | using (var reader = new StreamReader(response.GetResponseStream()))
35 | {
36 | var responseContent = reader.ReadToEnd();
37 | Console.WriteLine(responseContent);
38 |
39 | var responseDoc = new XmlDocument();
40 | responseDoc.LoadXml(responseContent);
41 | var endpointNodes = responseDoc.GetElementsByTagName("Endpoint", "http://schemas.microsoft.com/windowsazure");
42 | //Endpoint Structure
43 | //
44 | // Name
45 | // Enabled
46 | // CloudService
47 | // North Central US
48 | // Online
49 | // 1
50 | //
51 |
52 | var endpointValues = new List>();
53 | foreach (XmlNode endpointNode in endpointNodes)
54 | {
55 | string endpointName = endpointNode["DomainName"].InnerText;
56 | string endpointStatus = endpointNode["MonitorStatus"].InnerText;
57 | Console.WriteLine(string.Format("Endpoint name {0}, status {1}", endpointName, endpointStatus));
58 | endpointValues.Add(Tuple.Create(endpointName, endpointStatus));
59 | if (!endpointStatus.Equals("Online", StringComparison.OrdinalIgnoreCase))
60 | {
61 | new SendAlertMailTask
62 | {
63 | AlertSubject = string.Format("Error: Traffic manager endpoint alert activated for {0}", endpointName),
64 | Details = string.Format("The status of the endpoint {0} monitoring by traffic manager {1} is {2}", endpointName, ProfileName, endpointStatus),
65 | AlertName = "Error: Alert for TrafficManagerEndpoint",
66 | Component = "TrafficManager",
67 | Level = "Error"
68 | }.ExecuteCommand();
69 | }
70 |
71 | }
72 | JArray reportObject = ReportHelpers.GetJson(endpointValues);
73 | ReportHelpers.CreateBlob(StorageAccount, "TrafficManagerStatus.json", ContainerName, "application/json", ReportHelpers.ToStream(reportObject));
74 | }
75 | }
76 |
77 |
78 |
79 | }
80 | }
81 |
82 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Tasks/DashBoardTasks/CreateStatsMonthlyReport.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace NuGetGallery.Operations.Tasks.DashBoardTasks
8 | {
9 | class CreateStatsMonthlyReport
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Tasks/DashBoardTasks/CreateWADPerformanceDiagnosticsReportTask.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Web.Script.Serialization;
3 | using Microsoft.WindowsAzure.Storage;
4 | using Microsoft.WindowsAzure.Storage.Table;
5 | using NuGetGallery.Operations.Common;
6 |
7 |
8 | namespace NuGetGallery.Operations
9 | {
10 | [Command("CreatePerfUsageReportTask", "Create performance counter usage report task", AltName = "cpurt")]
11 | public class CreateWADPerformanceDiagnosticsReportTask : StorageTask
12 | {
13 | [Option("PerfCounterTableStorageAccount", AltName = "table")]
14 | public string PerfCounterTableStorageAccount { get; set; }
15 |
16 | [Option("PerfCounterName", AltName = "counter")]
17 | public string PerfCounterName { get; set; }
18 |
19 | [Option("frequencyInMin", AltName = "f")]
20 | public int frequencyInMin { get; set; }
21 |
22 | [Option("ServiceName", AltName = "name")]
23 | public string ServiceName { get; set; }
24 |
25 | public override void ExecuteCommand()
26 | {
27 | string DeployId = new JavaScriptSerializer().Deserialize(ReportHelpers.Load(StorageAccount, "DeploymentId_" + ServiceName + ".json", ContainerName));
28 | CloudStorageAccount storageAccount = CloudStorageAccount.Parse(PerfCounterTableStorageAccount);
29 | CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
30 | CloudTable table = tableClient.GetTableReference("WAD"+DeployId+"PT5MRTable");
31 | int count = 0;
32 | double sum = 0;
33 |
34 | TableQuery rangeQuery = new TableQuery().Where(TableQuery.CombineFilters(
35 | TableQuery.GenerateFilterConditionForDate("Timestamp", QueryComparisons.GreaterThan, DateTime.UtcNow.AddMinutes(-frequencyInMin)),
36 | TableOperators.And,
37 | TableQuery.GenerateFilterCondition("CounterName", QueryComparisons.Equal, PerfCounterName)));
38 |
39 | foreach (dataEntity entity in table.ExecuteQuery(rangeQuery))
40 | {
41 | count++;
42 | sum += entity.Total / entity.Count;
43 | }
44 |
45 | ReportHelpers.AppendDatatoBlob(StorageAccount, ServiceName + PerfCounterName + string.Format("{0:MMdd}", DateTime.Now) + ".json", new Tuple(String.Format("{0:HH:mm}", DateTime.Now), (sum/count).ToString("F")), 24*60 / frequencyInMin, ContainerName);
46 |
47 | }
48 |
49 | private class dataEntity : TableEntity
50 | {
51 | public int Count { get; set; }
52 | public double Total { get; set; }
53 |
54 | public string CounterName { get; set; }
55 |
56 | public string Role { get; set; }
57 |
58 | public string DepolymentId { get; set; }
59 |
60 | public dataEntity() { }
61 |
62 | public dataEntity(string PartitionKey, string RowKey)
63 | {
64 | this.PartitionKey = PartitionKey;
65 | this.RowKey = RowKey;
66 | }
67 | }
68 |
69 |
70 |
71 | }
72 | }
73 |
74 |
75 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Tasks/DashBoardTasks/DatabaseTasks/CreateDatabaseSizeReportTask.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System.Data.SqlClient;
4 | using NuGetGallery.Operations.Common;
5 | using AnglicanGeek.DbExecutor;
6 | using System;
7 | using System.Web.Script.Serialization;
8 | using NuGet.Services.Dashboard.Common;
9 |
10 |
11 | namespace NuGetGallery.Operations
12 | {
13 | [Command("CreateDatabaseSizeReportTask", "Creates database size report", AltName = "cdsrt")]
14 | public class CreateDatabaseSizeReportTask : StorageTask
15 | {
16 | private string SqlQueryForDbSize = @"SELECT CONVERT(int,SUM(reserved_page_count)*8.0/1024) FROM sys.dm_db_partition_stats";
17 | private string SqlQueryForEdition = @"SELECT DATABASEPROPERTYEX (DB_NAME(), 'Edition') AS Edition";
18 |
19 | private string SqlQueryForMaxSize = @"SELECT (CONVERT(bigint, DATABASEPROPERTYEX (DB_NAME(), 'MaxSizeInBytes')) / (1024*1024)) AS MaxSizeInMB";
20 |
21 |
22 | //[Option("Connection string to the primary database", AltName = "pdb")]
23 | //public SqlConnectionStringBuilder PrimaryConnectionString { get; set; }
24 |
25 | [Option("Connection string to the legacy database", AltName = "ldb")]
26 | public SqlConnectionStringBuilder LegacyConnectionString { get; set; }
27 |
28 | [Option("Connection string to the warehouse database", AltName = "wdb")]
29 | public SqlConnectionStringBuilder WarehouseConnectionString { get; set; }
30 |
31 |
32 |
33 | public override void ExecuteCommand()
34 | {
35 | JavaScriptSerializer js = new JavaScriptSerializer();
36 | AlertThresholds thresholdValues = js.Deserialize(ReportHelpers.Load(StorageAccount, "Configuration.AlertThresholds.json", ContainerName));
37 | int error = thresholdValues.DatabaseSizePercentErrorThreshold;
38 | int warning = thresholdValues.DatabaseSizePercentWarningThreshold;
39 |
40 | List dbSizeDetails = new List();
41 | // dbSizeDetails.Add(GetDataSize(PrimaryConnectionString.ConnectionString,threshold));
42 | dbSizeDetails.Add(GetDataSize(LegacyConnectionString.ConnectionString, error,warning));
43 | dbSizeDetails.Add(GetDataSize(WarehouseConnectionString.ConnectionString, error,warning));
44 |
45 | var json = js.Serialize(dbSizeDetails);
46 | ReportHelpers.CreateBlob(StorageAccount, "DBSize.json", ContainerName, "application/json",ReportHelpers.ToStream(json));
47 | }
48 |
49 | private DatabaseSize GetDataSize(string connectionString,int error, int warning)
50 | {
51 |
52 | using (var sqlConnection = new SqlConnection(connectionString))
53 | {
54 | using (var dbExecutor = new SqlExecutor(sqlConnection))
55 | {
56 | sqlConnection.Open();
57 | int sizeInMb = dbExecutor.Query(SqlQueryForDbSize).SingleOrDefault();
58 | Int64 maxSizeInMb = dbExecutor.Query(SqlQueryForMaxSize).SingleOrDefault();
59 | double percentUsed = (sizeInMb/maxSizeInMb)*100;
60 | string edition = dbExecutor.Query(SqlQueryForEdition).SingleOrDefault();
61 | string dbName = Util.GetDbName(connectionString);
62 |
63 | if (percentUsed > error)
64 | {
65 | new SendAlertMailTask
66 | {
67 | AlertSubject = string.Format("Error: SQL Azure database size alert activated for {0}",dbName),
68 | Details = string.Format("DB Size excced the Error threshold percent.Current Used % {0}, Threshold % : {1}", percentUsed, error ),
69 | AlertName = "Error: SQL Azure DB alert for database size limit",
70 | Component = string.Format("SQL Azure database-{0}",dbName),
71 | Level = "Error"
72 | }.ExecuteCommand();
73 | }
74 | else if (percentUsed > warning)
75 | {
76 | new SendAlertMailTask
77 | {
78 | AlertSubject = string.Format("Warning: SQL Azure database size alert activated for {0}", dbName),
79 | Details = string.Format("DB Size excced the Warning threshold percent.Current Used % {0}, Threshold % : {1}", percentUsed, warning),
80 | AlertName = "Warning: SQL Azure DB alert for database size limit",
81 | Component = string.Format("SQL Azure database-{0}", dbName),
82 | Level = "Warning"
83 | }.ExecuteCommand();
84 | }
85 |
86 | return new DatabaseSize(dbName, sizeInMb, maxSizeInMb, edition);
87 | }
88 | }
89 | }
90 |
91 |
92 | }
93 | }
94 |
95 |
96 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Tasks/DashBoardTasks/IssLogCleanUptask.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 |
4 | namespace NuGetGallery.Operations.Tasks.DashBoardTasks
5 | {
6 | [Command("IssCleanUpTask", "clean up old iss log in current dir", AltName = "clean")]
7 | class IssLogCleanUptask : OpsTask
8 | {
9 | public override void ExecuteCommand()
10 | {
11 | var dirs = Directory.EnumerateDirectories(Environment.CurrentDirectory, "*.log");
12 | var files = Directory.EnumerateFiles(Environment.CurrentDirectory, "*.log");
13 |
14 | foreach (string file in files)
15 | {
16 | try
17 | {
18 | string filename = file.Substring(Environment.CurrentDirectory.Length);
19 | string date = filename.Substring("\\u_ex".Length, "yyMMddHH".Length);
20 | DateTime logdate = new DateTime();
21 | logdate = DateTime.ParseExact(date, "yyMMddHH", null);
22 | if (logdate < DateTime.UtcNow.AddHours(-48)) File.Delete(file);
23 | }
24 | catch (Exception e)
25 | {
26 | Console.WriteLine("clean up error: {0}", e.Message);
27 | }
28 | }
29 | foreach (string dir in dirs)
30 | {
31 | try
32 | {
33 | string date = RemoveLetter(dir.Substring(Environment.CurrentDirectory.Length));
34 | DateTime logdate = new DateTime();
35 | logdate = DateTime.ParseExact(date, "yyMMddHH", null);
36 | if (logdate < DateTime.UtcNow.AddHours(-48)) Directory.Delete(dir, true);
37 | }
38 | catch (Exception e)
39 | {
40 | Console.WriteLine("clean up error: {0}", e.Message);
41 | }
42 | }
43 | }
44 | private string RemoveLetter(string src)
45 | {
46 | if (src.Equals("")) return src;
47 | if (char.IsDigit(src[0])) return src[0] + RemoveLetter(src.Substring(1));
48 | else return RemoveLetter(src.Substring(1));
49 | }
50 | }
51 | }
52 |
53 |
54 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Tasks/DashBoardTasks/PingdomTasks/CreatePingdomWeeklyAndHourlyReportTask.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System.Data;
4 | using System.Data.SqlClient;
5 | using System.IO;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 | using Microsoft.WindowsAzure.Storage;
9 | using Microsoft.WindowsAzure.Storage.Blob;
10 | using Newtonsoft.Json.Linq;
11 | using NuGetGallery.Operations.Common;
12 | using AnglicanGeek.DbExecutor;
13 | using System;
14 | using System.Net;
15 | using System.Web.Script.Serialization;
16 |
17 | namespace NuGetGallery.Operations
18 | {
19 | [Command("createpingdomweeklyreport", "Creates report for average response time for all the pingdom checks for fhe last 7 days/hours.", AltName = "cpdwr")]
20 | public class CreatePingdomWeeklyAndHourlyReportTask : StorageTask
21 | {
22 | [Option("PingdomUserName", AltName = "user")]
23 | public string UserName { get; set; }
24 |
25 | [Option("PingdomUserpassword", AltName = "password")]
26 | public string Password { get; set; }
27 |
28 | [Option("PingdomAppKey", AltName = "appkey")]
29 | public string AppKey { get; set; }
30 |
31 | [Option("Frequency", AltName = "f")]
32 | public string Frequency { get; set; }
33 |
34 |
35 | public override void ExecuteCommand()
36 | {
37 | NetworkCredential nc = new NetworkCredential(UserName, Password);
38 | WebRequest request = WebRequest.Create("https://api.pingdom.com/api/2.0/checks");
39 | request.Credentials = nc;
40 | request.Headers.Add(AppKey);
41 | request.PreAuthenticate = true;
42 | request.Method = "GET";
43 | WebResponse respose = request.GetResponse();
44 | using (var reader = new StreamReader(respose.GetResponseStream()))
45 | {
46 | JavaScriptSerializer js = new JavaScriptSerializer();
47 | var objects = js.Deserialize(reader.ReadToEnd());
48 | foreach (var o in objects["checks"])
49 | {
50 | List> summary = GetCheckSummaryAvgForSpecifiedTimeSpan(o["id"]);
51 | JArray reportObject = ReportHelpers.GetJson(summary);
52 | string checkAlias = o["name"].ToString();
53 | checkAlias = checkAlias.Replace(" ",".");
54 | checkAlias = checkAlias.Replace("(", "").Replace(")", "");
55 | ReportHelpers.CreateBlob(StorageAccount, checkAlias + Frequency + "Report.json", ContainerName, "application/json", ReportHelpers.ToStream(reportObject));
56 | }
57 | }
58 | }
59 |
60 | private List> GetCheckSummaryAvgForSpecifiedTimeSpan(int checkId)
61 | {
62 | int i = 7;
63 | List> summaryValues = new List>();
64 | while (i >= 1)
65 | {
66 | //Get the average response time for the past 7 hours/weeks based on the frequency.
67 | long fromTime = 0;
68 | long toTime = 0;
69 | if (Frequency.Equals("Hourly", StringComparison.OrdinalIgnoreCase))
70 | {
71 | fromTime = UnixTimeStampUtility.GetUnixTimestampSeconds(DateTime.UtcNow.Subtract(new TimeSpan(0, i, 0, 0)));
72 | toTime = UnixTimeStampUtility.GetUnixTimestampSeconds(DateTime.UtcNow.Subtract(new TimeSpan(0, i-1, 0, 0)));
73 | }
74 | else
75 | {
76 | fromTime = UnixTimeStampUtility.GetUnixTimestampSeconds(DateTime.UtcNow.Subtract(new TimeSpan(i, 0, 0, 0)));
77 | toTime = UnixTimeStampUtility.GetUnixTimestampSeconds(DateTime.UtcNow.Subtract(new TimeSpan(i - 1, 0, 0, 0)));
78 | }
79 | NetworkCredential nc = new NetworkCredential(UserName, Password);
80 | WebRequest request = WebRequest.Create(string.Format("https://api.pingdom.com/api/2.0/summary.average/{0}?from={1}&to={2}", checkId, fromTime, toTime));
81 | request.Credentials = nc;
82 | request.Headers.Add(AppKey);
83 | request.PreAuthenticate = true;
84 | request.Method = "GET";
85 | WebResponse respose = request.GetResponse();
86 | using (var reader = new StreamReader(respose.GetResponseStream()))
87 | {
88 | JavaScriptSerializer js = new JavaScriptSerializer();
89 | var summaryObject = js.Deserialize(reader.ReadToEnd());
90 | foreach (var summary in summaryObject["summary"])
91 | {
92 | foreach (var status in summary.Value)
93 | {
94 | //Get the average response time and store it to the JSON object.
95 | if (status.Key == "avgresponse")
96 | {
97 | if(Frequency.Equals("Hourly",StringComparison.OrdinalIgnoreCase))
98 | summaryValues.Add(new Tuple(String.Format("{0:HH:mm}", UnixTimeStampUtility.DateTimeFromUnixTimestampSeconds(fromTime).ToLocalTime()), status.Value.ToString()));
99 | else
100 | summaryValues.Add(new Tuple(String.Format("{0:MM/dd}", UnixTimeStampUtility.DateTimeFromUnixTimestampSeconds(fromTime).ToLocalTime()), status.Value.ToString()));
101 | }
102 | }
103 | }
104 | }
105 | i--;
106 | }
107 | return summaryValues;
108 | }
109 | }
110 | }
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Tasks/DashBoardTasks/SearchServiceTasks/CreateSearchCpuMemStatusReportTask.cs:
--------------------------------------------------------------------------------
1 | using NuGet.Services.Dashboard.Common;
2 | using NuGetGallery.Operations.Common;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Net;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 | using System.Web.Script.Serialization;
11 |
12 | namespace NuGetGallery.Operations.Tasks.DashBoardTasks
13 | {
14 | [Command("CreateSearchCpuMemStatusReportTask", "Creates the report for CPU and Mem usage of search service.", AltName = "cscmsrt")]
15 | class CreateSearchCpuMemStatusReportTask : StorageTask
16 | {
17 | [Option("SearchEndPoint", AltName = "se")]
18 | public string SearchEndPoint { get; set; }
19 |
20 | [Option("SearchAdminUserName", AltName = "sa")]
21 | public string SearchAdminUserName { get; set; }
22 |
23 | [Option("SearchAdminkey", AltName = "sk")]
24 | public string SearchAdminKey { get; set; }
25 |
26 | public override void ExecuteCommand()
27 | {
28 | NetworkCredential nc = new NetworkCredential(SearchAdminUserName, SearchAdminKey);
29 | WebRequest request = WebRequest.Create(SearchEndPoint);
30 | AlertThresholds thresholdValues = new JavaScriptSerializer().Deserialize(ReportHelpers.Load(StorageAccount, "Configuration.AlertThresholds.json", ContainerName));
31 | request.Credentials = nc;
32 | request.PreAuthenticate = true;
33 | request.Method = "GET";
34 | WebResponse respose = request.GetResponse();
35 | using (var reader = new StreamReader(respose.GetResponseStream()))
36 | {
37 | JavaScriptSerializer js = new JavaScriptSerializer();
38 | var objects = js.Deserialize(reader.ReadToEnd());
39 | var process_info = objects["process"];
40 | double cpusecond = (double)process_info["cpuSeconds"];
41 | long memory = (long)process_info["virtualMemorySize"];
42 | int cpuUsage = 0;
43 | int memUsage = 0;
44 |
45 | if (cpuUsage > thresholdValues.SearchCpuPercentErrorThreshold)
46 | {
47 | new SendAlertMailTask
48 | {
49 | AlertSubject = "Error: Search Service Alert activated for cpu usage",
50 | Details = string.Format("Search service process cpu usage is above Error threshold: {0}% , it's {1}% ", thresholdValues.SearchCpuPercentErrorThreshold, cpuUsage.ToString()),
51 | AlertName = "Error: Alert for Serach CPU Usage",
52 | Component = "SearchService",
53 | Level = "Error"
54 | }.ExecuteCommand();
55 | }
56 | else if (cpuUsage > thresholdValues.SearchCpuPercentWarningThreshold)
57 | {
58 | new SendAlertMailTask
59 | {
60 | AlertSubject = "Warning: Search Service Alert activated for cpu usage",
61 | Details = string.Format("Search service process cpu usage is above Warning threshold: {0}% , it's {1}% ", thresholdValues.SearchCpuPercentWarningThreshold, cpuUsage.ToString()),
62 | AlertName = "Warning: Alert for Serach CPU Usage",
63 | Component = "SearchService",
64 | Level = "Warning"
65 | }.ExecuteCommand();
66 | }
67 |
68 | if (memUsage > thresholdValues.SearchMemErrorThresholdInGb*(1<<30))
69 | {
70 | new SendAlertMailTask
71 | {
72 | AlertSubject = "Error: Search Service Alert activated for memory usage",
73 | Details = string.Format("Search service process memory usage is above Error threshold: {0}% GB, it's {1}% Byte ", thresholdValues.SearchMemErrorThresholdInGb, memUsage.ToString()),
74 | AlertName = "Error: Alert for Serach Memory Usage",
75 | Component = "SearchService",
76 | Level = "Error"
77 | }.ExecuteCommand();
78 | }
79 | else if (memUsage > thresholdValues.SearchMemWarningThresholdInGb * (1 << 30))
80 | {
81 | new SendAlertMailTask
82 | {
83 | AlertSubject = "Warning: Search Service Alert activated for memory usage",
84 | Details = string.Format("Search service process memory usage is above Warning threshold {0}% GB, it's {1}% Byte ", thresholdValues.SearchMemWarningThresholdInGb, memUsage.ToString()),
85 | AlertName = "Warning: Alert for Serach Memory Usage",
86 | Component = "SearchService",
87 | Level = "Warning"
88 | }.ExecuteCommand();
89 | }
90 | ReportHelpers.AppendDatatoBlob(StorageAccount, "SearchCpuUsage" + string.Format("{0:MMdd}", DateTime.Now) + "HourlyReport.json", new Tuple(string.Format("{0:HH-mm}", DateTime.Now), cpusecond.ToString()), 24, ContainerName);
91 | ReportHelpers.AppendDatatoBlob(StorageAccount, "SearchMemUsage" + string.Format("{0:MMdd}", DateTime.Now) + "HourlyReport.json", new Tuple(string.Format("{0:HH-mm}", DateTime.Now), memory.ToString()), 24, ContainerName);
92 | }
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Tasks/DashBoardTasks/TrendingTasks/CreateStatsHourlyReportTask.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System.Data;
4 | using System.Data.SqlClient;
5 | using System.IO;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 | using Microsoft.WindowsAzure.Storage;
9 | using Microsoft.WindowsAzure.Storage.Blob;
10 | using Newtonsoft.Json.Linq;
11 | using NuGetGallery.Operations.Common;
12 | using AnglicanGeek.DbExecutor;
13 | using System;
14 |
15 | namespace NuGetGallery.Operations
16 | {
17 | [Command("createstatshourlyreport", "Creates the stats (uploads,downloads and users) hoourly report for Gallery ", AltName = "cshr")]
18 | public class CreateStatsHourlyReportTask : DatabaseAndStorageTask
19 | {
20 | private string SqlQueryForUploads = @"SELECT Count (*) FROM [dbo].[Packages] where [Created] >= '{0}' AND [Created] <= '{1}'";
21 | private string SqlQueryForUniqueUploads = @"SELECT COUNT(*)
22 | From
23 | (
24 | SELECT Id
25 | FROM [dbo].Packages
26 | INNER JOIN PackageRegistrations ON Packages.PackageRegistrationKey = PackageRegistrations.[Key]
27 | GROUP BY PackageRegistrations.Id
28 | HAVING MIN([Created]) >= '{0}' AND MIN([Created]) <= '{1}') data";
29 |
30 | private string SqlQueryForUsers = @"SELECT Count (*) FROM [dbo].[Users] where [CreatedUtc] >= '{0}' AND [CreatedUtc] <= '{1}'";
31 | private DateTime startingTime; //initialize start date to the NuGet initial release time.
32 |
33 | public override void ExecuteCommand()
34 | {
35 | CreateWeeklyStatReportFor(ConnectionString.ConnectionString, SqlQueryForUploads, "Uploads" + string.Format("{0:MMdd}", DateTime.Now));
36 | CreateWeeklyStatReportFor(ConnectionString.ConnectionString, SqlQueryForUniqueUploads, "UniqueUploads" + string.Format("{0:MMdd}", DateTime.Now));
37 | CreateWeeklyStatReportFor(ConnectionString.ConnectionString, SqlQueryForUsers, "Users" + string.Format("{0:MMdd}", DateTime.Now));
38 | }
39 |
40 | private void CreateWeeklyStatReportFor(string connectionString, string sqlQuery, string reportName)
41 | {
42 | startingTime = DateTime.Now.AddHours(-1).ToUniversalTime(); //initialize to day 01 of the given month.
43 | DateTime endTime = DateTime.Now.ToUniversalTime();
44 | List> uploadsDataPoints = new List>();
45 | using (var sqlConnection = new SqlConnection(connectionString))
46 | {
47 | using (var dbExecutor = new SqlExecutor(sqlConnection))
48 | {
49 | sqlConnection.Open();
50 | try
51 | {
52 | var count = dbExecutor.Query(string.Format(sqlQuery, startingTime.ToString("yyyy-MM-dd HH:mm:ss"), endTime.ToString("yyyy-MM-dd HH:mm:ss"))).SingleOrDefault();
53 | ReportHelpers.AppendDatatoBlob(StorageAccount, reportName + "HourlyReport.json", new Tuple(string.Format("{0:HH:mm}", endTime.ToLocalTime()), count.ToString()), 50, ContainerName);
54 | }
55 | catch (NullReferenceException)
56 | {
57 | uploadsDataPoints.Add(new Tuple("0", "0"));
58 | }
59 | }
60 | }
61 | }
62 | }
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Tasks/DashBoardTasks/TrendingTasks/CreateStatsMonthlyReportTask.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System.Data;
4 | using System.Data.SqlClient;
5 | using System.IO;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 | using Microsoft.WindowsAzure.Storage;
9 | using Microsoft.WindowsAzure.Storage.Blob;
10 | using Newtonsoft.Json.Linq;
11 | using NuGetGallery.Operations.Common;
12 | using AnglicanGeek.DbExecutor;
13 | using System;
14 |
15 | namespace NuGetGallery.Operations
16 | {
17 | [Command("createpackagedownloadreport", "Creates the stats (uploads,downloads and users) for Gallery for a given month", AltName = "csmr")]
18 | public class CreateStatsMonthlyReport : ReportsTask
19 | {
20 | private string SqlQueryForDownloads = @" SELECT SUM(f.DownloadCount) FROM [dbo].[Fact_Download] f JOIN [dbo].[Dimension_Date] dd ON dd.[Id] = f.Dimension_Date_Id WHERE dd.[Date] >= '{0}'AND dd.[Date] <= '{1}'";
21 | private string SqlQueryForUploads = @"SELECT Count (*) FROM [dbo].[Packages] where [Created] >= '{0}' AND [Created] <= '{1}'";
22 | private string SqlQueryForUsers = @"SELECT Count (*) FROM [dbo].[Users] where [CreatedUtc] >= '{0}' AND [CreatedUtc] <= '{1}'";
23 | private DateTime startingTime; //initialize start date to the NuGet initial release time.
24 | [Option("MonthName", AltName = "m")]
25 | public string Month { get; set; }
26 |
27 | [Option("Year", AltName = "y")]
28 | public int Year { get; set; }
29 |
30 | [Option("WarehouseConnectionString", AltName = "wrdb")]
31 | public string WarehouseConnectionString { get; set; }
32 |
33 | public override void ExecuteCommand()
34 | {
35 | CreateWeeklyStatReportFor(ConnectionString.ConnectionString, SqlQueryForUploads,"Uploads");
36 | CreateWeeklyStatReportFor(ConnectionString.ConnectionString, SqlQueryForUsers, "Users");
37 | CreateWeeklyStatReportFor(WarehouseConnectionString, SqlQueryForDownloads, "Downloads"); //uploads and users data can be data from Gallery DB whereas downloads stats will be present in warehouse.
38 | }
39 |
40 | private void CreateWeeklyStatReportFor(string connectionString,string sqlQuery,string reportName)
41 | {
42 | startingTime = new DateTime(Year, UnixTimeStampUtility.GetMonthNumber(Month), 01); //initialize to day 01 of the given month.
43 | DateTime monthEndTime = new DateTime(Year, UnixTimeStampUtility.GetMonthNumber(Month), UnixTimeStampUtility.GetDaysInMonth(Month));
44 | List> uploadsDataPoints = new List>();
45 | int week = 1;
46 | using (var sqlConnection = new SqlConnection(connectionString))
47 | {
48 | using (var dbExecutor = new SqlExecutor(sqlConnection))
49 | {
50 | sqlConnection.Open();
51 |
52 | while (startingTime <= monthEndTime)
53 | {
54 | DateTime endTime = startingTime.AddDays(7);
55 | if (endTime > monthEndTime) endTime = monthEndTime;
56 | try
57 | {
58 | var count = dbExecutor.Query(string.Format(sqlQuery, startingTime.ToString("yyyy-MM-dd"), endTime.ToString("yyyy-MM-dd"))).SingleOrDefault();
59 | uploadsDataPoints.Add(new Tuple("Week" + week++, count.ToString()));
60 | }
61 | catch (NullReferenceException)
62 | {
63 | uploadsDataPoints.Add(new Tuple("Week" + week++, "0"));
64 | }
65 |
66 | startingTime = startingTime.AddDays(7);
67 | }
68 | }
69 | }
70 | JArray reportObject = ReportHelpers.GetJson(uploadsDataPoints);
71 | ReportHelpers.CreateBlob(ReportStorage, reportName + Month + "MonthlyReport.json", "dashboard", "application/json", ReportHelpers.ToStream(reportObject));
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Tasks/DashBoardTasks/UnixTimeStampUtility.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Globalization;
7 |
8 | namespace NuGetGallery.Operations
9 | {
10 | ///
11 | /// Helper class to convert C# DateTime to UNIX time stamp.
12 | ///
13 | public class UnixTimeStampUtility
14 | {
15 | private static readonly DateTime UnixEpoch =
16 | new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
17 |
18 | public static long GetCurrentUnixTimestampMillis()
19 | {
20 | return (long)(DateTime.UtcNow - UnixEpoch).TotalMilliseconds;
21 | }
22 |
23 | public static DateTime DateTimeFromUnixTimestampMillis(long millis)
24 | {
25 | return UnixEpoch.AddMilliseconds(millis);
26 | }
27 |
28 | public static long GetCurrentUnixTimestampSeconds()
29 | {
30 | return (long)(DateTime.UtcNow - UnixEpoch).TotalSeconds;
31 | }
32 |
33 | public static long GetUnixTimestampSeconds(DateTime time)
34 | {
35 | return (long)(time - UnixEpoch).TotalSeconds;
36 | }
37 |
38 | public static long GetLastMonthUnixTimestampSeconds()
39 | {
40 | return (long)(DateTime.UtcNow.Subtract(new TimeSpan(30, 0, 0, 0)) - UnixEpoch).TotalSeconds;
41 | }
42 |
43 | public static long GetLastWeekUnixTimestampSeconds()
44 | {
45 | return (long)(DateTime.UtcNow.Subtract(new TimeSpan(7, 0, 0, 0)) - UnixEpoch).TotalSeconds;
46 | }
47 |
48 | public static long GetSecondsForDays(int noOfDays)
49 | {
50 | double total = new TimeSpan(noOfDays, 0, 0, 0).TotalSeconds;
51 | return (long)total;
52 | }
53 |
54 | public static DateTime DateTimeFromUnixTimestampSeconds(long seconds)
55 | {
56 | return UnixEpoch.AddSeconds(seconds);
57 | }
58 |
59 | public static int GetDaysInMonth(string month)
60 | {
61 | return DateTime.DaysInMonth(DateTime.Now.Year, GetMonthNumber(month));
62 | }
63 |
64 | public static string GetMonthName(int Month)
65 | {
66 | DateTimeFormatInfo dfi = new DateTimeFormatInfo();
67 | string monthName = dfi.GetAbbreviatedMonthName(Month);
68 | return monthName;
69 | }
70 |
71 | public static int GetMonthNumber(string monthName)
72 | {
73 | int iMonthNo = Convert.ToDateTime("01-" + monthName + "-2011").Month;
74 | return iMonthNo;
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Tasks/DashBoardTasks/V2GalleryFrontendTasks/CreateElmahErrorDetailedReportTask.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Web.Script.Serialization;
4 | using NuGet.Services.Dashboard.Common;
5 | using NuGetGallery.Operations.Common;
6 |
7 |
8 | namespace NuGetGallery.Operations
9 | {
10 | [Command("CreateElmahErrorDetailedReportTask", "Creates detailed error report for last N hours from Elmah logs", AltName = "ceedrt")]
11 | public class CreateElmahErrorDetailedReportTask : StorageTask
12 | {
13 | [Option("LastNHours", AltName = "n")]
14 | public int LastNHours { get; set; }
15 |
16 | [Option("ElmahAccountCredentials", AltName = "ea")]
17 | public string ElmahAccountCredentials { get; set; }
18 |
19 | public override void ExecuteCommand()
20 | {
21 |
22 | AlertThresholds thresholds = new JavaScriptSerializer().Deserialize(ReportHelpers.Load(StorageAccount, "Configuration.AlertThresholds.json", ContainerName));
23 |
24 | List listOfErrors = new List();
25 | RefreshElmahError RefreshExecute = new RefreshElmahError(StorageAccount, ContainerName, LastNHours, ElmahAccountCredentials);
26 |
27 | listOfErrors = RefreshExecute.ExecuteRefresh();
28 |
29 | foreach (ElmahError error in listOfErrors)
30 | {
31 | if (error.Severity == 0)
32 | {
33 | if (error.Occurecnes > thresholds.ElmahCriticalErrorPerHourAlertErrorThreshold && LastNHours == 1)
34 | {
35 | new SendAlertMailTask
36 | {
37 | AlertSubject = string.Format("Error: Elmah Error Alert on {0} activated for {1}", ContainerName, error.Error),
38 | Details = String.Format("Number of {0} exceeded Error threshold limit during the last hour.Threshold error count per hour : {1}, Events recorded in the last hour: {2}", error.Error, thresholds.ElmahCriticalErrorPerHourAlertErrorThreshold, error.Occurecnes.ToString()),
39 | AlertName = string.Format("Error: {0} Elmah Error Alert for {1}", ContainerName, error.Error),
40 | Component = "Web Server",
41 | Level = "Error"
42 | }.ExecuteCommand();
43 | }
44 | else if (error.Occurecnes > thresholds.ElmahCriticalErrorPerHourAlertWarningThreshold && LastNHours == 1)
45 | {
46 | new SendAlertMailTask
47 | {
48 | AlertSubject = string.Format("Warning: Elmah Error Alert on {0} activated for {1}", ContainerName, error.Error),
49 | Details = String.Format("Number of {0} exceeded Warning threshold limit during the last hour.Threshold error count per hour : {1}, Events recorded in the last hour: {2}", error.Error, thresholds.ElmahCriticalErrorPerHourAlertWarningThreshold, error.Occurecnes.ToString()),
50 | AlertName = string.Format("Warning: {0} Elmah Error Alert for {1}", ContainerName, error.Error),
51 | Component = "Web Server",
52 | Level = "Warning"
53 | }.ExecuteCommand();
54 | }
55 | }
56 | }
57 |
58 | var json = new JavaScriptSerializer().Serialize(listOfErrors);
59 | ReportHelpers.CreateBlob(StorageAccount, "ElmahErrorsDetailed" + LastNHours.ToString() + "hours.json", ContainerName, "application/json", ReportHelpers.ToStream(json));
60 |
61 | }
62 |
63 |
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Tasks/DashBoardTasks/V2GalleryFrontendTasks/CreateElmahErrorOverviewReportTask.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data;
4 | using System.Linq;
5 | using Elmah;
6 | using NuGetGallery.Infrastructure;
7 | using NuGetGallery.Operations.Common;
8 |
9 |
10 | namespace NuGetGallery.Operations
11 | {
12 | [Command("CreateElmahErrorOverviewReportTask", "Creates trending report for Elmah error count", AltName = "ceeort")]
13 | public class CreateElmahErrorOverviewReportTask : StorageTask
14 | {
15 | [Option("ElmahAccountCredentials", AltName = "ea")]
16 | public string ElmahAccountCredentials { get; set; }
17 | public override void ExecuteCommand()
18 | {
19 | TableErrorLog log = new TableErrorLog(string.Format(ElmahAccountCredentials));
20 | List entities = new List();
21 | log.GetErrors(0, 500, entities); //retrieve n * LastNHours errors assuming a max of 500 errors per hour.
22 | int count = entities.Where(entity => entity.Error.Time.ToUniversalTime() > DateTime.UtcNow.AddHours(-1) && entity.Error.Time.ToUniversalTime() < DateTime.UtcNow).ToList().Count;
23 | ReportHelpers.AppendDatatoBlob(StorageAccount, "ErrorRate" + string.Format("{0:MMdd}", DateTime.Now) + ".json", new Tuple(String.Format("{0:HH:mm}", DateTime.Now), count.ToString()), 50, ContainerName);
24 | }
25 |
26 |
27 |
28 | }
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Tasks/DashBoardTasks/V3JobsBackGroundTasks/V3Utility.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data;
4 | using System.Data.SqlClient;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Net;
8 | using System.Threading;
9 | using System.Threading.Tasks;
10 | using System.Web.Script.Serialization;
11 | using Microsoft.WindowsAzure.Storage;
12 | using Microsoft.WindowsAzure.Storage.Blob;
13 | using Newtonsoft.Json.Linq;
14 | using NuGet.Services.Dashboard.Common;
15 | using NuGetGallery.Operations.Common;
16 | using NuGet.Services.Metadata.Catalog;
17 |
18 |
19 | namespace NuGetGallery.Operations.Tasks.DashBoardTasks.V3JobsBackGroundTasks
20 | {
21 | public class V3Utility
22 | {
23 | public static HashSet GetCatalogPackages(string catalogRootUrl, string storageConnectionString)
24 | {
25 | return GetCatalogPackages(catalogRootUrl, storageConnectionString, DateTime.MinValue, DateTime.MaxValue);
26 | }
27 |
28 | public static HashSet GetCatalogPackages(string catalogRootUrl,string storageConnectionString,DateTime startCommitTimeStamp,DateTime endCommitTimeStamp)
29 | {
30 | CollectorHttpClient client = new CollectorHttpClient();
31 | CloudStorageAccount csa = CloudStorageAccount.Parse(storageConnectionString);
32 | var blobClient = csa.CreateCloudBlobClient();
33 | Uri catalogIndex = new Uri(catalogRootUrl);
34 | CatalogIndexReader reader = new CatalogIndexReader(catalogIndex, client);
35 | //TBD Update CatalogIndexReader to return packages based on commit time stamp.Right now it returns all packages.
36 | var task = reader.GetEntries();
37 | task.Wait();
38 | List entries = task.Result.ToList();
39 | entries = entries.Where(e => e.CommitTimeStamp >= startCommitTimeStamp && e.CommitTimeStamp <= endCommitTimeStamp).ToList();
40 | var catalogPackages = new HashSet(entries.Select(e => new PackageEntry(e.Id, e.Version.ToNormalizedString())), PackageEntry.Comparer);
41 | return catalogPackages;
42 | }
43 | public static DateTime GetValueFromCatalogIndex(string catalogRootUrl, string keyName)
44 | {
45 | WebRequest request = WebRequest.Create(catalogRootUrl);
46 | request.PreAuthenticate = true;
47 | request.Method = "GET";
48 | WebResponse respose = request.GetResponse();
49 | using (var reader = new StreamReader(respose.GetResponseStream()))
50 | {
51 | JavaScriptSerializer js = new JavaScriptSerializer();
52 | var objects = js.Deserialize(reader.ReadToEnd());
53 | DateTime catalogCommitTimeStamp = Convert.ToDateTime(objects[keyName]);
54 | return catalogCommitTimeStamp.ToUniversalTime();
55 | }
56 | }
57 | }
58 |
59 | public class PackageEntry : IEquatable
60 | {
61 | public string Id { get; private set; }
62 | public string Version { get; private set; }
63 |
64 | public PackageEntry(string id, string version)
65 | {
66 | Id = id.ToLowerInvariant();
67 | Version = version.ToLowerInvariant();
68 | }
69 |
70 | public bool Equals(PackageEntry other)
71 | {
72 | return Compare(this, other);
73 | }
74 |
75 | public override string ToString()
76 | {
77 | return String.Format("{0} {1}", Id, Version);
78 | }
79 |
80 | public static bool Compare(PackageEntry x, PackageEntry y)
81 | {
82 | return StringComparer.OrdinalIgnoreCase.Equals(x.Id, y.Id) && StringComparer.OrdinalIgnoreCase.Equals(x.Version, y.Version);
83 | }
84 |
85 | public static IEqualityComparer Comparer
86 | {
87 | get
88 | {
89 | return new PackageEntryComparer();
90 | }
91 | }
92 |
93 | public class PackageEntryComparer : IEqualityComparer
94 | {
95 | public bool Equals(PackageEntry x, PackageEntry y)
96 | {
97 | return PackageEntry.Compare(x, y);
98 | }
99 |
100 | public int GetHashCode(PackageEntry obj)
101 | {
102 | return obj.ToString().GetHashCode();
103 | }
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Tasks/DashBoardTasks/VerifyPostValidationCursorTask.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Net;
4 | using System.Web.Script.Serialization;
5 |
6 | namespace NuGetGallery.Operations.Tasks.DashBoardTasks
7 | {
8 | [Command("VerifyPostValidationCursorTask", "Checks the post-validation cursor lag.", AltName = "vpvc")]
9 | class VerifyPostValidationCursorTask : OpsTask
10 | {
11 | [Option("CursorUrl", AltName = "cu")]
12 | public string CursorUrl { get; set; }
13 |
14 | public override void ExecuteCommand()
15 | {
16 | WebRequest request = WebRequest.Create(CursorUrl);
17 | request.Method = "GET";
18 | WebResponse respose = request.GetResponse();
19 | using (var reader = new StreamReader(respose.GetResponseStream()))
20 | {
21 | JavaScriptSerializer js = new JavaScriptSerializer();
22 | var objects = js.Deserialize(reader.ReadToEnd());
23 |
24 | var lastCreated = DateTimeOffset.Parse(objects["lastCreated"]);
25 |
26 | if (lastCreated.UtcDateTime < DateTimeOffset.UtcNow.AddDays(-2).UtcDateTime)
27 | {
28 | new SendAlertMailTask
29 | {
30 | AlertSubject = "Error: Post validation job may not be running",
31 | Details = string.Format("Post validation job may not be running. Cursor was last updated {0} (UTC).", lastCreated.UtcDateTime.ToString("O")),
32 | AlertName = "Error: Post validation",
33 | Component = "PostValidation",
34 | Level = "Error"
35 | }.ExecuteCommand();
36 | }
37 | else if (lastCreated.UtcDateTime < DateTimeOffset.UtcNow.AddDays(-1).UtcDateTime)
38 | {
39 | new SendAlertMailTask
40 | {
41 | AlertSubject = "Warning: Post validation job may not be running",
42 | Details = string.Format("Post validation job may not be running. Cursor was last updated {0} (UTC).", lastCreated.UtcDateTime.ToString("O")),
43 | AlertName = "Warning: Post validation",
44 | Component = "PostValidation",
45 | Level = "Warning"
46 | }.ExecuteCommand();
47 | }
48 | }
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Tasks/OpsTask.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel.Composition;
4 | using System.Diagnostics.CodeAnalysis;
5 | using System.Linq;
6 | using NLog;
7 | using NuGetGallery.Operations.Common;
8 | using System.Configuration;
9 |
10 | namespace NuGetGallery.Operations
11 | {
12 | public abstract class OpsTask : ICommand
13 | {
14 | private const string CommandSuffix = "Task";
15 |
16 | private CommandAttribute _commandAttribute;
17 | private List _arguments = new List();
18 | private Logger _logger;
19 | protected internal Logger Log
20 | {
21 | get { return _logger ?? (_logger = LogManager.GetLogger(GetType().Name)); }
22 | internal set { _logger = value; }
23 | }
24 |
25 | public CommandAttribute CommandAttribute
26 | {
27 | get
28 | {
29 | if (_commandAttribute == null)
30 | {
31 | _commandAttribute = GetCommandAttribute();
32 | }
33 | return _commandAttribute;
34 | }
35 | }
36 |
37 | public IList Arguments
38 | {
39 | get { return _arguments; }
40 | }
41 |
42 | [Import]
43 | public HelpCommand HelpCommand { get; set; }
44 |
45 | public DeploymentEnvironment CurrentEnvironment
46 | {
47 | get
48 | {
49 | return !String.IsNullOrEmpty(ConfigFile) ?
50 | DeploymentEnvironment.FromConfigFile(ConfigFile) :
51 | null;
52 | }
53 | }
54 |
55 | [Option("DisableNotification", AltName = "disn")]
56 | public bool DisableNotification { get; set; }
57 |
58 | [Option("DisableIncidentCreation", AltName = "disic")]
59 | public bool DisableIncidentCreation { get; set; }
60 |
61 | [Option("Path to the configuration file to use when command line arguments aren't specified")]
62 | public string ConfigFile { get; set; }
63 |
64 | [Option("Name of the environment specified by the configuration file")]
65 | public string EnvironmentName { get; set; }
66 |
67 | [Option("Gets help for this command", AltName = "?")]
68 | public bool Help { get; set; }
69 |
70 | [Option("Instead of performing any write operations, the command will just output what it WOULD do. Read operations are still performed.", AltName = "!")]
71 | public bool WhatIf { get; set; }
72 |
73 | public void Execute()
74 | {
75 | if (!String.IsNullOrEmpty(ConfigFile))
76 | {
77 | Log.Info("Running against {0} environment", EnvironmentName);
78 | }
79 |
80 | if (WhatIf)
81 | {
82 | Log.Info("Running in WhatIf mode");
83 | }
84 | if (Help)
85 | {
86 | HelpCommand.ViewHelpForCommand(CommandAttribute.CommandName);
87 | }
88 | else
89 | {
90 | try
91 | {
92 | ValidateArguments();
93 | ExecuteCommand();
94 | }
95 | catch (Exception e)
96 | {
97 | if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["SmtpUserName"]) && !string.IsNullOrEmpty(ConfigurationManager.AppSettings["SmtpPassword"]))
98 | {
99 | new SendAlertMailTask
100 | {
101 | AlertSubject = string.Format("Error executing task {0}", this.GetType().ToString()),
102 | Details = String.Format("Exception thrown while executing task {0}. Exception Message : {1}, Stack Trace : {2}", this.GetType().ToString(), e.Message, e.StackTrace),
103 | AlertName = "Exception from Dashboard OpsTask",
104 | Component = "Dashboard Ops"
105 | }.ExecuteCommand();
106 | }
107 | throw;
108 | }
109 | }
110 | }
111 |
112 | public abstract void ExecuteCommand();
113 |
114 | public virtual void ValidateArguments()
115 | {
116 | }
117 |
118 | [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "This method does quite a bit of processing.")]
119 | public virtual CommandAttribute GetCommandAttribute()
120 | {
121 | var attributes = GetType().GetCustomAttributes(typeof(CommandAttribute), true);
122 | if (attributes.Any())
123 | {
124 | return (CommandAttribute)attributes.FirstOrDefault();
125 | }
126 |
127 | // Use the command name minus the suffix if present and default description
128 | string name = GetType().Name;
129 | int idx = name.LastIndexOf(CommandSuffix, StringComparison.OrdinalIgnoreCase);
130 | if (idx >= 0)
131 | {
132 | name = name.Substring(0, idx);
133 | }
134 | if (!String.IsNullOrEmpty(name))
135 | {
136 | return new CommandAttribute(name, TaskResources.DefaultCommandDescription);
137 | }
138 | return null;
139 | }
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/Util.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data.SqlClient;
4 | using System.Globalization;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Security.Cryptography;
8 | using System.Web;
9 | using AnglicanGeek.DbExecutor;
10 | using Microsoft.WindowsAzure.Storage.Blob;
11 | using System.Text.RegularExpressions;
12 |
13 | namespace NuGetGallery.Operations
14 | {
15 | public static class Util
16 | {
17 | public const byte OnlineState = 0;
18 | private static readonly Regex BackupNameFormat = new Regex(@"^(?.+)_(?\d{4}[A-Za-z]{3}\d{2}_\d{4})Z$",RegexOptions.IgnoreCase); // Backup_2013Apr12_1452Z
19 | public static string GetDbName(string connectionString)
20 | {
21 | var connectionStringBuilder = new SqlConnectionStringBuilder(connectionString);
22 | return connectionStringBuilder.InitialCatalog;
23 | }
24 | public static string GetMasterConnectionString(string connectionString)
25 | {
26 | var connectionStringBuilder = new SqlConnectionStringBuilder(connectionString) { InitialCatalog = "master" };
27 | return connectionStringBuilder.ToString();
28 | }
29 |
30 | public static DateTime GetDateTimeFromTimestamp(string timestamp)
31 | {
32 | DateTime result;
33 | if (DateTime.TryParseExact(timestamp, "yyyyMMddHHmmss", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out result))
34 | {
35 | return result;
36 | }
37 | else if (DateTime.TryParseExact(timestamp, "yyyyMMMdd_HHmmZ", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out result))
38 | {
39 | return result;
40 | }
41 | return DateTime.MinValue;
42 | }
43 |
44 | public static Db GetLastBackup(SqlExecutor dbExecutor, string backupNamePrefix)
45 | {
46 | var allBackups = dbExecutor.Query(
47 | "SELECT name, state FROM sys.databases WHERE name LIKE '" + backupNamePrefix + "%' AND state = @state",
48 | new { state = OnlineState });
49 | var orderedBackups = from db in allBackups
50 | let t = ParseNewTimestamp(BackupNameFormat.Match(db.Name).Groups["timestamp"].Value)
51 | where t != null
52 | orderby t descending
53 | select db;
54 |
55 | return orderedBackups.FirstOrDefault();
56 | }
57 |
58 | public static DateTime GetLastBackupTime(SqlExecutor dbExecutor, string backupNamePrefix)
59 | {
60 | var lastBackup = GetLastBackup(dbExecutor, backupNamePrefix);
61 |
62 | if (lastBackup == null)
63 | return DateTime.MinValue;
64 |
65 | var timestamp = lastBackup.Name.Substring(backupNamePrefix.Length);
66 |
67 | return GetDateTimeFromTimestamp(timestamp);
68 | }
69 |
70 | private static DateTimeOffset ParseNewTimestamp(string timestamp)
71 | {
72 | return new DateTimeOffset(
73 | DateTime.ParseExact(timestamp, "yyyyMMMdd_HHmm", CultureInfo.CurrentCulture),
74 | TimeSpan.Zero);
75 | }
76 | }
77 |
78 | public class Db
79 | {
80 | public string Name { get; set; }
81 | public byte State { get; set; }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/content/further.js:
--------------------------------------------------------------------------------
1 |
2 | // further flattens and already flattened JSON-LD document
3 |
4 | var further = function (flattened) {
5 | var result = [];
6 | for (var i = 0; i !== flattened.length; i += 1) {
7 | var subject = flattened[i]['@id'];
8 | for (var prop in flattened[i]) {
9 | if (prop !== '@id') {
10 | var predicate = prop;
11 | for (var j = 0; j !== flattened[i][prop].length; j += 1) {
12 | var object = {};
13 | if (flattened[i][prop][j]['@id'] !== undefined) {
14 | object = { value: flattened[i][prop][j]['@id'], type: 'uri' };
15 | }
16 | else {
17 | object = { value: flattened[i][prop][j]['@value'], type: 'literal' };
18 | }
19 | result[result.length] = { subject: subject, predicate: predicate, object: object };
20 | }
21 | }
22 | }
23 | }
24 | return result;
25 | }
26 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.Operations/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/NuGet.Services.Dashboard.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{E4F8E102-7447-4D41-A244-9AC4E352271C}"
7 | ProjectSection(SolutionItems) = preProject
8 | .nuget\NuGet.Config = .nuget\NuGet.Config
9 | .nuget\NuGet.exe = .nuget\NuGet.exe
10 | .nuget\NuGet.targets = .nuget\NuGet.targets
11 | EndProjectSection
12 | EndProject
13 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NuGet.Services.Dashboard.Operations", "NuGet.Services.Dashboard.Operations\NuGet.Services.Dashboard.Operations.csproj", "{DBECF66B-8F2F-4B32-9143-E243BAFF12DF}"
14 | EndProject
15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NuGet.Services.Dashboard.Operations.Tools", "NuGet.Services.Dashboard.Operations.Tools\NuGet.Services.Dashboard.Operations.Tools.csproj", "{F240D1BC-BBFB-4F22-9DF8-3FDE36BFD665}"
16 | EndProject
17 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NuGet.Services.Dashboard.Common", "NuGet.Services.Dashboard.Common\NuGet.Services.Dashboard.Common.csproj", "{5566AE9C-8466-4316-9372-7B38B57DBB20}"
18 | EndProject
19 | Global
20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
21 | Debug|Any CPU = Debug|Any CPU
22 | Debug|Mixed Platforms = Debug|Mixed Platforms
23 | Debug|x86 = Debug|x86
24 | Release|Any CPU = Release|Any CPU
25 | Release|Mixed Platforms = Release|Mixed Platforms
26 | Release|x86 = Release|x86
27 | EndGlobalSection
28 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
29 | {DBECF66B-8F2F-4B32-9143-E243BAFF12DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
30 | {DBECF66B-8F2F-4B32-9143-E243BAFF12DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
31 | {DBECF66B-8F2F-4B32-9143-E243BAFF12DF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
32 | {DBECF66B-8F2F-4B32-9143-E243BAFF12DF}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
33 | {DBECF66B-8F2F-4B32-9143-E243BAFF12DF}.Debug|x86.ActiveCfg = Debug|Any CPU
34 | {DBECF66B-8F2F-4B32-9143-E243BAFF12DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 | {DBECF66B-8F2F-4B32-9143-E243BAFF12DF}.Release|Any CPU.Build.0 = Release|Any CPU
36 | {DBECF66B-8F2F-4B32-9143-E243BAFF12DF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
37 | {DBECF66B-8F2F-4B32-9143-E243BAFF12DF}.Release|Mixed Platforms.Build.0 = Release|Any CPU
38 | {DBECF66B-8F2F-4B32-9143-E243BAFF12DF}.Release|x86.ActiveCfg = Release|Any CPU
39 | {F240D1BC-BBFB-4F22-9DF8-3FDE36BFD665}.Debug|Any CPU.ActiveCfg = Debug|x86
40 | {F240D1BC-BBFB-4F22-9DF8-3FDE36BFD665}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
41 | {F240D1BC-BBFB-4F22-9DF8-3FDE36BFD665}.Debug|Mixed Platforms.Build.0 = Debug|x86
42 | {F240D1BC-BBFB-4F22-9DF8-3FDE36BFD665}.Debug|x86.ActiveCfg = Debug|x86
43 | {F240D1BC-BBFB-4F22-9DF8-3FDE36BFD665}.Debug|x86.Build.0 = Debug|x86
44 | {F240D1BC-BBFB-4F22-9DF8-3FDE36BFD665}.Release|Any CPU.ActiveCfg = Release|x86
45 | {F240D1BC-BBFB-4F22-9DF8-3FDE36BFD665}.Release|Mixed Platforms.ActiveCfg = Release|x86
46 | {F240D1BC-BBFB-4F22-9DF8-3FDE36BFD665}.Release|Mixed Platforms.Build.0 = Release|x86
47 | {F240D1BC-BBFB-4F22-9DF8-3FDE36BFD665}.Release|x86.ActiveCfg = Release|x86
48 | {F240D1BC-BBFB-4F22-9DF8-3FDE36BFD665}.Release|x86.Build.0 = Release|x86
49 | {5566AE9C-8466-4316-9372-7B38B57DBB20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
50 | {5566AE9C-8466-4316-9372-7B38B57DBB20}.Debug|Any CPU.Build.0 = Debug|Any CPU
51 | {5566AE9C-8466-4316-9372-7B38B57DBB20}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
52 | {5566AE9C-8466-4316-9372-7B38B57DBB20}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
53 | {5566AE9C-8466-4316-9372-7B38B57DBB20}.Debug|x86.ActiveCfg = Debug|Any CPU
54 | {5566AE9C-8466-4316-9372-7B38B57DBB20}.Release|Any CPU.ActiveCfg = Release|Any CPU
55 | {5566AE9C-8466-4316-9372-7B38B57DBB20}.Release|Any CPU.Build.0 = Release|Any CPU
56 | {5566AE9C-8466-4316-9372-7B38B57DBB20}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
57 | {5566AE9C-8466-4316-9372-7B38B57DBB20}.Release|Mixed Platforms.Build.0 = Release|Any CPU
58 | {5566AE9C-8466-4316-9372-7B38B57DBB20}.Release|x86.ActiveCfg = Release|Any CPU
59 | EndGlobalSection
60 | GlobalSection(SolutionProperties) = preSolution
61 | HideSolutionNode = FALSE
62 | EndGlobalSection
63 | EndGlobal
64 |
--------------------------------------------------------------------------------
/Nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | NuGet.Services.Dashboard
2 | ========================
3 |
4 | This repo contains the source code for NuGet Dashboard frontend website and back end operations.
5 |
6 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
7 |
8 | ###NuGet.Services.Dashboard.Operations###
9 |
10 | Contains tasks that retrieves monitoring data from various sources like Pingdom, WAD performance data, SQL Azure DMV queries and gallery database.
11 | Each task collects the required data and generates a json report which gets uploaded to the specified blob storage container.
12 |
13 | ###NuGet.Services.Dashboard.FrontEnd###
14 |
15 | Contains the Web application that displays the monitoring data. The Website reads the json report created by the backend tasks and displays them as charts and tables.
16 |
17 | ###NuGet.Services.Dashboard.Operations.Tools###
18 |
19 | Contains the commandline runner (galops.exe) that is used to invoke invidiual dashboard tasks.
20 |
--------------------------------------------------------------------------------
/build.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding(DefaultParameterSetName='RegularBuild')]
2 | param (
3 | [ValidateSet("debug", "release")]
4 | [string]$Configuration = 'debug',
5 | [int]$BuildNumber,
6 | [switch]$SkipRestore,
7 | [switch]$CleanCache,
8 | [string]$SimpleVersion = '1.0.0',
9 | [string]$SemanticVersion = '1.0.0-zlocal',
10 | [string]$Branch,
11 | [string]$CommitSHA,
12 | [string]$BuildBranch = '1c479a7381ebbc0fe1fded765de70d513b8bd68e'
13 | )
14 |
15 | # For TeamCity - If any issue occurs, this script fail the build. - By default, TeamCity returns an exit code of 0 for all powershell scripts, even if they fail
16 | trap {
17 | Write-Host "BUILD FAILED: $_" -ForegroundColor Red
18 | Write-Host "ERROR DETAILS:" -ForegroundColor Red
19 | Write-Host $_.Exception -ForegroundColor Red
20 | Write-Host ("`r`n" * 3)
21 | exit 1
22 | }
23 |
24 | if (-not (Test-Path "$PSScriptRoot/build")) {
25 | New-Item -Path "$PSScriptRoot/build" -ItemType "directory"
26 | }
27 | wget -UseBasicParsing -Uri "https://raw.githubusercontent.com/NuGet/ServerCommon/$BuildBranch/build/init.ps1" -OutFile "$PSScriptRoot/build/init.ps1"
28 | . "$PSScriptRoot/build/init.ps1" -BuildBranch "$BuildBranch"
29 |
30 | Write-Host ("`r`n" * 3)
31 | Trace-Log ('=' * 60)
32 |
33 | $startTime = [DateTime]::UtcNow
34 | if (-not $BuildNumber) {
35 | $BuildNumber = Get-BuildNumber
36 | }
37 | Trace-Log "Build #$BuildNumber started at $startTime"
38 |
39 | $BuildErrors = @()
40 |
41 | Invoke-BuildStep 'Getting private build tools' { Install-PrivateBuildTools } `
42 | -ev +BuildErrors
43 |
44 | Invoke-BuildStep 'Installing NuGet.exe' { Install-NuGet } `
45 | -ev +BuildErrors
46 |
47 | Invoke-BuildStep 'Clearing package cache' { Clear-PackageCache } `
48 | -skip:(-not $CleanCache) `
49 | -ev +BuildErrors
50 |
51 | Invoke-BuildStep 'Clearing artifacts' { Clear-Artifacts } `
52 | -ev +BuildErrors
53 |
54 | Invoke-BuildStep 'Restoring solution packages' { `
55 | Install-SolutionPackages -path (Join-Path $PSScriptRoot ".nuget\packages.config") -output (Join-Path $PSScriptRoot "packages") -excludeversion } `
56 | -skip:$SkipRestore `
57 | -ev +BuildErrors
58 |
59 | Invoke-BuildStep 'Set version metadata in AssemblyInfo.cs' {
60 | $Paths = `
61 | (Join-Path $PSScriptRoot "NuGet.Services.Dashboard.Common\Properties\AssemblyInfo.g.cs"), `
62 | (Join-Path $PSScriptRoot "NuGet.Services.Dashboard.Operations\Properties\AssemblyInfo.g.cs"), `
63 | (Join-Path $PSScriptRoot "NuGet.Services.Dashboard.Operations.Tools\Properties\AssemblyInfo.g.cs")
64 |
65 | Foreach ($Path in $Paths) {
66 | Set-VersionInfo -Path $Path -Version $SimpleVersion -Branch $Branch -Commit $CommitSHA
67 | }
68 | } `
69 | -ev +BuildErrors
70 |
71 | Invoke-BuildStep 'Building solution' {
72 | $SolutionPath = Join-Path $PSScriptRoot "NuGet.Services.Dashboard.sln"
73 | Build-Solution $Configuration $BuildNumber -MSBuildVersion "14" $SolutionPath -SkipRestore:$SkipRestore `
74 | } `
75 | -ev +BuildErrors
76 |
77 | Invoke-BuildStep 'Creating artifacts' {
78 | New-Package (Join-Path $PSScriptRoot "NuGet.Services.Dashboard.Operations.Tools\NuGet.Services.Dashboard.Operations.Tools.csproj") -Configuration $Configuration -Symbols -BuildNumber $BuildNumber -Version $SemanticVersion -Branch $Branch
79 | } `
80 | -ev +BuildErrors
81 |
82 | Trace-Log ('-' * 60)
83 |
84 | ## Calculating Build time
85 | $endTime = [DateTime]::UtcNow
86 | Trace-Log "Build #$BuildNumber ended at $endTime"
87 | Trace-Log "Time elapsed $(Format-ElapsedTime ($endTime - $startTime))"
88 |
89 | Trace-Log ('=' * 60)
90 |
91 | if ($BuildErrors) {
92 | $ErrorLines = $BuildErrors | %{ ">>> $($_.Exception.Message)" }
93 | Error-Log "Builds completed with $($BuildErrors.Count) error(s):`r`n$($ErrorLines -join "`r`n")" -Fatal
94 | }
95 |
96 | Write-Host ("`r`n" * 3)
97 |
--------------------------------------------------------------------------------