Skip to content

Commit

Permalink
Fix readme telemetry (#4905)
Browse files Browse the repository at this point in the history
  • Loading branch information
chenriksson committed Oct 27, 2017
1 parent 5f88eec commit 4d8c2ec
Show file tree
Hide file tree
Showing 15 changed files with 348 additions and 92 deletions.
17 changes: 13 additions & 4 deletions src/NuGetGallery/App_Start/DefaultDependenciesModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ public class DefaultDependenciesModule : Module
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:CyclomaticComplexity", Justification = "This code is more maintainable in the same function.")]
protected override void Load(ContainerBuilder builder)
{
var diagnosticsService = new DiagnosticsService();
var telemetryClient = TelemetryClientWrapper.Instance;
builder.RegisterInstance(telemetryClient)
.As<ITelemetryClient>()
.SingleInstance();

var diagnosticsService = new DiagnosticsService(telemetryClient);
builder.RegisterInstance(diagnosticsService)
.AsSelf()
.As<IDiagnosticsService>()
Expand Down Expand Up @@ -295,7 +300,7 @@ protected override void Load(ContainerBuilder builder)
defaultAuditingService = GetAuditingServiceForLocalFileSystem(configuration);
break;
case StorageType.AzureStorage:
ConfigureForAzureStorage(builder, configuration);
ConfigureForAzureStorage(builder, configuration, telemetryClient);
defaultAuditingService = GetAuditingServiceForAzureStorage(builder, configuration);
break;
}
Expand Down Expand Up @@ -502,7 +507,7 @@ private static IAuditingService GetAuditingServiceForLocalFileSystem(IGalleryCon
return new FileSystemAuditingService(auditingPath, AuditActor.GetAspNetOnBehalfOfAsync);
}

private static void ConfigureForAzureStorage(ContainerBuilder builder, IGalleryConfigurationService configuration)
private static void ConfigureForAzureStorage(ContainerBuilder builder, IGalleryConfigurationService configuration, ITelemetryClient telemetryClient)
{
/// The goal here is to initialize a <see cref="ICloudBlobClient"/> and <see cref="IFileStorageService"/>
/// instance for each unique connection string. Each dependent of <see cref="IFileStorageService"/> (that
Expand Down Expand Up @@ -563,7 +568,11 @@ private static void ConfigureForAzureStorage(ContainerBuilder builder, IGalleryC
.SingleInstance();

// when running on Windows Azure, download counts come from the downloads.v1.json blob
var downloadCountService = new CloudDownloadCountService(configuration.Current.AzureStorage_Statistics_ConnectionString, configuration.Current.AzureStorageReadAccessGeoRedundant);
var downloadCountService = new CloudDownloadCountService(
telemetryClient,
configuration.Current.AzureStorage_Statistics_ConnectionString,
configuration.Current.AzureStorageReadAccessGeoRedundant);

builder.RegisterInstance(downloadCountService)
.AsSelf()
.As<IDownloadCountService>()
Expand Down
5 changes: 3 additions & 2 deletions src/NuGetGallery/App_Start/OwinStartup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,10 @@ public static void Configuration(IAppBuilder app)
return processor;
});


var telemetry = dependencyResolver.GetService<TelemetryClientWrapper>();
telemetryProcessorChainBuilder.Use(
next => new ExceptionTelemetryProcessor(next, Telemetry.TelemetryClient));
next => new ExceptionTelemetryProcessor(next, telemetry.UnderlyingClient));

// Note: sampling rate must be a factor 100/N where N is a whole number
// e.g.: 50 (= 100/2), 33.33 (= 100/3), 25 (= 100/4), ...
Expand Down
13 changes: 11 additions & 2 deletions src/NuGetGallery/Diagnostics/DiagnosticsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,28 @@ namespace NuGetGallery.Diagnostics
{
public class DiagnosticsService : IDiagnosticsService
{
public DiagnosticsService()
private readonly ITelemetryClient _telemetryClient;

public DiagnosticsService(ITelemetryClient telemetryClient)
{
_telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));

Trace.AutoFlush = true;
}

// Test constructor
internal DiagnosticsService() : this(TelemetryClientWrapper.Instance)
{
}

public IDiagnosticsSource GetSource(string name)
{
if (String.IsNullOrEmpty(name))
{
throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Strings.ParameterCannotBeNullOrEmpty, "name"), nameof(name));
}

return new TraceDiagnosticsSource(name);
return new TraceDiagnosticsSource(name, _telemetryClient);
}
}
}
7 changes: 5 additions & 2 deletions src/NuGetGallery/Diagnostics/TraceDiagnosticsSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ public class TraceDiagnosticsSource : IDiagnosticsSource, IDisposable
{
private const string ObjectName = "TraceDiagnosticsSource";
private TraceSource _source;
private ITelemetryClient _telemetryClient;

public string Name { get; private set; }

public TraceDiagnosticsSource(string name)
public TraceDiagnosticsSource(string name, ITelemetryClient telemetryClient)
{
_telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));

Name = name;
_source = new TraceSource(name, SourceLevels.All);

Expand All @@ -43,7 +46,7 @@ public virtual void ExceptionEvent(Exception exception)
throw new ArgumentNullException(nameof(exception));
}

Telemetry.TrackException(exception);
_telemetryClient.TrackException(exception);
}

/// <summary>
Expand Down
3 changes: 2 additions & 1 deletion src/NuGetGallery/NuGetGallery.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,7 @@
<Compile Include="Services\CloudBlobFileStorageService.cs" />
<Compile Include="Services\IFileStorageService.cs" />
<Compile Include="Services\ImmediatePackageValidator.cs" />
<Compile Include="Services\ITelemetryClient.cs" />
<Compile Include="Services\PackageOwnershipManagementService.cs" />
<Compile Include="Services\IPackageOwnershipManagementService.cs" />
<Compile Include="Services\IPackageValidationInitiator.cs" />
Expand Down Expand Up @@ -869,6 +870,7 @@
<Compile Include="Services\IPackageUploadService.cs" />
<Compile Include="Services\ReservedNamespaceService.cs" />
<Compile Include="Services\ReadMeService.cs" />
<Compile Include="Services\TelemetryClientWrapper.cs" />
<Compile Include="Services\ValidationService.cs" />
<Compile Include="Telemetry\ClientInformationTelemetryEnricher.cs" />
<Compile Include="Telemetry\QuietExceptionLogger.cs" />
Expand Down Expand Up @@ -986,7 +988,6 @@
<Compile Include="Extensions\HttpRequestExtensions.cs" />
<Compile Include="Helpers\HostMachine.cs" />
<Compile Include="Telemetry\AppInsightsHealthIndicatorLogger.cs" />
<Compile Include="Telemetry\Telemetry.cs" />
<Compile Include="Infrastructure\DependencyResolverServiceProviderAdapter.cs" />
<Compile Include="Infrastructure\Lucene\CloudDownloadCountServiceRefreshJob.cs" />
<Compile Include="Infrastructure\MessageQueue.cs" />
Expand Down
11 changes: 4 additions & 7 deletions src/NuGetGallery/OData/QueryAllowed/ODataQueryVerifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Web.Http.OData.Query;

namespace NuGetGallery.OData.QueryFilter
Expand Down Expand Up @@ -124,12 +123,10 @@ public static bool AreODataOptionsAllowed<TEntity>(ODataQueryOptions<TEntity> od
}
catch (Exception ex)
{
var telemetryProperties = new Dictionary<string, string>();
telemetryProperties.Add(TelemetryService.CallContext, $"{telemetryContext}:{nameof(AreODataOptionsAllowed)}");
telemetryProperties.Add(TelemetryService.IsEnabled, $"{isFeatureEnabled}");

// Log and do not throw
Telemetry.TrackException(ex, telemetryProperties);
_telemetryService.TrackException(ex, properties => {
properties.Add(TelemetryService.CallContext, $"{telemetryContext}:{nameof(AreODataOptionsAllowed)}");
properties.Add(TelemetryService.IsEnabled, $"{isFeatureEnabled}");
});
}

_telemetryService.TrackODataQueryFilterEvent(
Expand Down
11 changes: 7 additions & 4 deletions src/NuGetGallery/Services/CloudDownloadCountService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class CloudDownloadCountService : IDownloadCountService
private const string DownloadCountBlobName = "downloads.v1.json";
private const string TelemetryOriginForRefreshMethod = "CloudDownloadCountService.Refresh";

private readonly ITelemetryClient _telemetryClient;
private readonly string _connectionString;
private readonly bool _readAccessGeoRedundant;

Expand All @@ -30,8 +31,10 @@ public class CloudDownloadCountService : IDownloadCountService

public DateTime LastRefresh { get; protected set; }

public CloudDownloadCountService(string connectionString, bool readAccessGeoRedundant)
public CloudDownloadCountService(ITelemetryClient telemetryClient, string connectionString, bool readAccessGeoRedundant)
{
_telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));

_connectionString = connectionString;
_readAccessGeoRedundant = readAccessGeoRedundant;
}
Expand Down Expand Up @@ -181,7 +184,7 @@ private void RefreshCore()
}
catch (JsonReaderException ex)
{
Telemetry.TrackException(ex, new Dictionary<string, string>
_telemetryClient.TrackException(ex, new Dictionary<string, string>
{
{ "Origin", TelemetryOriginForRefreshMethod },
{ "AdditionalInfo", "Invalid entry found in downloads.v1.json." }
Expand All @@ -191,7 +194,7 @@ private void RefreshCore()
}
catch (JsonReaderException ex)
{
Telemetry.TrackException(ex, new Dictionary<string, string>
_telemetryClient.TrackException(ex, new Dictionary<string, string>
{
{ "Origin", TelemetryOriginForRefreshMethod },
{ "AdditionalInfo", "Data present in downloads.v1.json is invalid. Couldn't get download data." }
Expand All @@ -201,7 +204,7 @@ private void RefreshCore()
}
catch (Exception ex)
{
Telemetry.TrackException(ex, new Dictionary<string, string>
_telemetryClient.TrackException(ex, new Dictionary<string, string>
{
{ "Origin", TelemetryOriginForRefreshMethod },
{ "AdditionalInfo", "Unknown exception." }
Expand Down
18 changes: 18 additions & 0 deletions src/NuGetGallery/Services/ITelemetryClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;

namespace NuGetGallery
{
/// <summary>
/// Interface for the Application Insights TelemetryClient class, for unit tests.
/// </summary>
public interface ITelemetryClient
{
void TrackEvent(string eventName, IDictionary<string, string> properties = null, IDictionary<string, double> metrics = null);

void TrackException(Exception exception, IDictionary<string, string> properties = null, IDictionary<string, double> metrics = null);
}
}
9 changes: 9 additions & 0 deletions src/NuGetGallery/Services/ITelemetryService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Security.Principal;

namespace NuGetGallery
Expand All @@ -18,6 +19,14 @@ public interface ITelemetryService

void TrackVerifyPackageKeyEvent(string packageId, string packageVersion, User user, IIdentity identity, int statusCode);

/// <summary>
/// Create a trace for an exception. These are informational for support requests.
/// </summary>
void TraceException(Exception exception);

/// <summary>
/// Create a log for an exception. These are warnings for live site.
/// </summary>
void TrackException(Exception exception, Action<Dictionary<string, string>> addProperties);
}
}
56 changes: 56 additions & 0 deletions src/NuGetGallery/Services/TelemetryClientWrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using Microsoft.ApplicationInsights;

namespace NuGetGallery
{
/// <summary>
/// Wrapper for the Application Insights TelemetryClient class.
/// </summary>
public class TelemetryClientWrapper : ITelemetryClient
{
private static Lazy<TelemetryClientWrapper> Singleton = new Lazy<TelemetryClientWrapper>(() => new TelemetryClientWrapper());

internal static TelemetryClientWrapper Instance
{
get
{
return Singleton.Value;
}
}

private TelemetryClientWrapper()
{
UnderlyingClient = new TelemetryClient();
}

internal TelemetryClient UnderlyingClient { get; }

public void TrackEvent(string eventName, IDictionary<string, string> properties = null, IDictionary<string, double> metrics = null)
{
try
{
UnderlyingClient.TrackEvent(eventName, properties, metrics);
}
catch
{
// logging failed, don't allow exception to escape
}
}

public void TrackException(Exception exception, IDictionary<string, string> properties = null, IDictionary<string, double> metrics = null)
{
try
{
UnderlyingClient.TrackException(exception, properties, metrics);
}
catch
{
// logging failed, don't allow exception to escape
}
}
}
}
Loading

0 comments on commit 4d8c2ec

Please sign in to comment.