-
Notifications
You must be signed in to change notification settings - Fork 645
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Statistics]Adding Support for other reports from alternate container #8472
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -707,27 +707,41 @@ private static void RegisterDeleteAccountService(ContainerBuilder builder, Confi | |||||||
|
||||||||
private static void RegisterStatisticsServices(ContainerBuilder builder, IGalleryConfigurationService configuration, ITelemetryService telemetryService) | ||||||||
{ | ||||||||
// when running on Windows Azure, download counts come from the downloads.v1.json blob | ||||||||
builder.Register(c => new SimpleBlobStorageConfiguration(configuration.Current.AzureStorage_Statistics_ConnectionString, configuration.Current.AzureStorageReadAccessGeoRedundant)) | ||||||||
agr marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
.SingleInstance() | ||||||||
.Keyed<IBlobStorageConfiguration>(BindingKeys.PrimaryStatisticsKey); | ||||||||
|
||||||||
builder.Register(c => new SimpleBlobStorageConfiguration(configuration.Current.AzureStorage_Statistics_ConnectionString_Alternate, configuration.Current.AzureStorageReadAccessGeoRedundant)) | ||||||||
.SingleInstance() | ||||||||
.Keyed<IBlobStorageConfiguration>(BindingKeys.AlternateStatisticsKey); | ||||||||
|
||||||||
// when running on Windows Azure, we use a back-end job to calculate stats totals and store in the blobs | ||||||||
builder.RegisterInstance(new JsonAggregateStatsService(configuration.Current.AzureStorage_Statistics_ConnectionString, configuration.Current.AzureStorageReadAccessGeoRedundant)) | ||||||||
builder.Register(c => | ||||||||
{ | ||||||||
var primaryConfiguration = c.ResolveKeyed<IBlobStorageConfiguration>(BindingKeys.PrimaryStatisticsKey); | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
What do you think about using attributes for resolving keyed dependencies: https://autofaccn.readthedocs.io/en/latest/advanced/keyed-services.html#resolving-with-attributes ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks like it could be good idea, and might make this block a bit easier to read. I'll experiment with it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we typically use NuGetGallery/src/NuGetGallery/App_Start/DefaultDependenciesModule.cs Lines 1407 to 1409 in be38792
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm having a little trouble getting this to work right now. I've filed #8477 to make this change after things are in place (if I am understanding this correctly, we should be able to make this change independent of the overall functionality. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, we have two arguments of type |
||||||||
var alternateConfiguration = c.ResolveKeyed<IBlobStorageConfiguration>(BindingKeys.AlternateStatisticsKey); | ||||||||
var featureFlagService = c.Resolve<IFeatureFlagService>(); | ||||||||
var jsonAggregateStatsService = new JsonAggregateStatsService(featureFlagService, primaryConfiguration, alternateConfiguration); | ||||||||
return jsonAggregateStatsService; | ||||||||
}) | ||||||||
.AsSelf() | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need all those |
||||||||
.As<IAggregateStatsService>() | ||||||||
.SingleInstance(); | ||||||||
|
||||||||
// when running on Windows Azure, pull the statistics from the warehouse via storage | ||||||||
builder.RegisterInstance(new CloudReportService(configuration.Current.AzureStorage_Statistics_ConnectionString, configuration.Current.AzureStorageReadAccessGeoRedundant)) | ||||||||
builder.Register(c => | ||||||||
{ | ||||||||
var primaryConfiguration = c.ResolveKeyed<IBlobStorageConfiguration>(BindingKeys.PrimaryStatisticsKey); | ||||||||
var alternateConfiguration = c.ResolveKeyed<IBlobStorageConfiguration>(BindingKeys.AlternateStatisticsKey); | ||||||||
var featureFlagService = c.Resolve<IFeatureFlagService>(); | ||||||||
var cloudReportService = new CloudReportService(featureFlagService, primaryConfiguration, alternateConfiguration); | ||||||||
return cloudReportService; | ||||||||
}) | ||||||||
.AsSelf() | ||||||||
.As<IReportService>() | ||||||||
.SingleInstance(); | ||||||||
|
||||||||
// when running on Windows Azure, download counts come from the downloads.v1.json blob | ||||||||
builder.Register(c => new SimpleBlobStorageConfiguration(configuration.Current.AzureStorage_Statistics_ConnectionString, configuration.Current.AzureStorageReadAccessGeoRedundant)) | ||||||||
.SingleInstance() | ||||||||
.Keyed<IBlobStorageConfiguration>(BindingKeys.PrimaryStatisticsKey); | ||||||||
|
||||||||
builder.Register(c => new SimpleBlobStorageConfiguration(configuration.Current.AzureStorage_Statistics_ConnectionString_Alternate, configuration.Current.AzureStorageReadAccessGeoRedundant)) | ||||||||
.SingleInstance() | ||||||||
.Keyed<IBlobStorageConfiguration>(BindingKeys.AlternateStatisticsKey); | ||||||||
|
||||||||
builder.Register(c => | ||||||||
{ | ||||||||
var primaryConfiguration = c.ResolveKeyed<IBlobStorageConfiguration>(BindingKeys.PrimaryStatisticsKey); | ||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,30 @@ | ||
// 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.Threading.Tasks; | ||
using Microsoft.WindowsAzure.Storage; | ||
using Microsoft.WindowsAzure.Storage.Blob; | ||
using Microsoft.WindowsAzure.Storage.RetryPolicies; | ||
using NuGetGallery.Services; | ||
|
||
namespace NuGetGallery | ||
{ | ||
public class CloudReportService : IReportService | ||
{ | ||
private const string _statsContainerName = "nuget-cdnstats"; | ||
private readonly string _connectionString; | ||
private readonly bool _readAccessGeoRedundant; | ||
private readonly IFeatureFlagService _featureFlagService; | ||
private readonly IBlobStorageConfiguration _primaryStorageConfiguration; | ||
private readonly IBlobStorageConfiguration _alternateBlobStorageConfiguration; | ||
|
||
public CloudReportService(string connectionString, bool readAccessGeoRedundant) | ||
public CloudReportService( | ||
IFeatureFlagService featureFlagService, | ||
IBlobStorageConfiguration primaryBlobStorageConfiguration, | ||
IBlobStorageConfiguration alternateBlobStorageConfiguration) | ||
{ | ||
_connectionString = connectionString; | ||
_readAccessGeoRedundant = readAccessGeoRedundant; | ||
_featureFlagService = featureFlagService ?? throw new ArgumentNullException(nameof(featureFlagService)); | ||
_primaryStorageConfiguration = primaryBlobStorageConfiguration ?? throw new ArgumentNullException(nameof(primaryBlobStorageConfiguration)); | ||
_alternateBlobStorageConfiguration = alternateBlobStorageConfiguration; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will it be better if we also do the null check here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did no null check intentionally to not force alternate blob storage configuration to have to be set so that it works in place with current config. |
||
} | ||
|
||
public async Task<StatisticsReport> Load(string reportName) | ||
|
@@ -42,10 +49,19 @@ public async Task<StatisticsReport> Load(string reportName) | |
|
||
private CloudBlobContainer GetCloudBlobContainer() | ||
{ | ||
var storageAccount = CloudStorageAccount.Parse(_connectionString); | ||
var connectionString = _primaryStorageConfiguration.ConnectionString; | ||
var readAccessGeoRedundant = _primaryStorageConfiguration.ReadAccessGeoRedundant; | ||
|
||
if(_alternateBlobStorageConfiguration != null && _featureFlagService.IsAlternateStatisticsSourceEnabled()) | ||
{ | ||
connectionString = _alternateBlobStorageConfiguration.ConnectionString; | ||
readAccessGeoRedundant = _alternateBlobStorageConfiguration.ReadAccessGeoRedundant; | ||
} | ||
|
||
var storageAccount = CloudStorageAccount.Parse(connectionString); | ||
var blobClient = storageAccount.CreateCloudBlobClient(); | ||
|
||
if (_readAccessGeoRedundant) | ||
if (readAccessGeoRedundant) | ||
{ | ||
blobClient.DefaultRequestOptions.LocationMode = LocationMode.PrimaryThenSecondary; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,47 @@ | ||
// 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.Threading.Tasks; | ||
using Microsoft.WindowsAzure.Storage; | ||
using Microsoft.WindowsAzure.Storage.Blob; | ||
using Microsoft.WindowsAzure.Storage.RetryPolicies; | ||
using Newtonsoft.Json; | ||
using NuGetGallery.Services; | ||
|
||
namespace NuGetGallery | ||
{ | ||
public class JsonAggregateStatsService : IAggregateStatsService | ||
{ | ||
private readonly string _connectionString; | ||
private readonly bool _readAccessGeoRedundant; | ||
private readonly IFeatureFlagService _featureFlagService; | ||
private readonly IBlobStorageConfiguration _primaryStorageConfiguration; | ||
private readonly IBlobStorageConfiguration _alternateBlobStorageConfiguration; | ||
|
||
public JsonAggregateStatsService(string connectionString, bool readAccessGeoRedundant) | ||
public JsonAggregateStatsService( | ||
IFeatureFlagService featureFlagService, | ||
IBlobStorageConfiguration primaryBlobStorageConfiguration, | ||
IBlobStorageConfiguration alternateBlobStorageConfiguration) | ||
{ | ||
_connectionString = connectionString; | ||
_readAccessGeoRedundant = readAccessGeoRedundant; | ||
_featureFlagService = featureFlagService ?? throw new ArgumentNullException(nameof(featureFlagService)); | ||
_primaryStorageConfiguration = primaryBlobStorageConfiguration ?? throw new ArgumentNullException(nameof(primaryBlobStorageConfiguration)); | ||
_alternateBlobStorageConfiguration = alternateBlobStorageConfiguration; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will it be better if we also do the null check here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did no null check intentionally to not force alternate blob storage configuration to have to be set so that it works in place with current config. |
||
} | ||
|
||
public async Task<AggregateStats> GetAggregateStats() | ||
{ | ||
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(_connectionString); | ||
var connectionString = _primaryStorageConfiguration.ConnectionString; | ||
var readAccessGeoRedundant = _primaryStorageConfiguration.ReadAccessGeoRedundant; | ||
|
||
if (_alternateBlobStorageConfiguration != null && _featureFlagService.IsAlternateStatisticsSourceEnabled()) | ||
{ | ||
connectionString = _alternateBlobStorageConfiguration.ConnectionString; | ||
readAccessGeoRedundant = _alternateBlobStorageConfiguration.ReadAccessGeoRedundant; | ||
} | ||
|
||
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString); | ||
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient(); | ||
|
||
if (_readAccessGeoRedundant) | ||
if (readAccessGeoRedundant) | ||
{ | ||
blobClient.DefaultRequestOptions.LocationMode = LocationMode.PrimaryThenSecondary; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment here looks a little confused, is it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment was around this block when i initially made code changes. I'm not sure where it went, but it's back here. I imagine this was originally here to note the difference from running locally, where stats come from DB.