private static async Task <ConcurrentQueue <string> > GetSubscriptions(string subscription,
                                                                               CustomCredentials credentials)
        {
            ConcurrentQueue <string> subscriptions = null;

            if (subscription == "all")
            {
                await ResourceManager.Configure()
                .Authenticate(credentials.ToAzureCredentials())
                .Subscriptions
                .ListAsync()
                .ContinueWith(c =>
                              subscriptions =
                                  new ConcurrentQueue <string>(c.Result.Select(s => s.SubscriptionId)));
            }
            else
            {
                subscriptions = new ConcurrentQueue <string>(subscription.Split(','));
            }

            return(subscriptions);
        }
 public ActivityLogProvider(CustomCredentials credentials, string subscriptionId)
 {
     _credentials    = credentials;
     _subscriptionId = subscriptionId;
 }
Beispiel #3
0
 public ResourceProvider(CustomCredentials credentials, string subscriptionId)
 {
     _credentials    = credentials;
     _subscriptionId = subscriptionId;
 }
        private static async Task <int> Main(string[] args)
        {
            var clientId                = string.Empty;
            var clientSecret            = string.Empty;
            var tenantId                = string.Empty;
            var showHelp                = false;
            var numberOfMonthsToAnalyze = 1;
            var outputFolder            = Path.GetTempPath();
            var openReport              = false;
            var subscription            = string.Empty;
            var onlyWithOverages        = false;

            var optionSet = new OptionSet()
                            .Add("clientId=", o => clientId         = o)
                            .Add("clientSecret=", o => clientSecret = o)
                            .Add("tenantId=", o => tenantId         = o)
                            .Add("subscription=", o => subscription = o)
                            .Add("numberOfMonths=", o => numberOfMonthsToAnalyze = int.Parse(o))
                            .Add("outputFolder=", o => outputFolder        = o)
                            .Add("openReport", o => openReport             = o != null)
                            .Add("onlyWithOverages", o => onlyWithOverages = true)
                            .Add("h|?|help", o => showHelp = o != null);

            optionSet.Parse(args);

            Log.Logger = new LoggerConfiguration()
                         .WriteTo.Console()
                         .WriteTo.File($"log-{DateTime.UtcNow:yyyy_MM_dd_hh_mm}.txt")
                         .CreateLogger();

            if (showHelp)
            {
                ShowHelp();
                return(0);
            }

            if (string.IsNullOrEmpty(subscription))
            {
                Console.WriteLine("Mandatory parameter -subscriptionId is missing");
                ShowHelp();
                return(-1);
            }

            if (!Directory.Exists(outputFolder))
            {
                Directory.CreateDirectory(outputFolder);
            }
            else if (Directory.GetFiles(outputFolder).Length > 0)
            {
                Console.WriteLine("Output directory is not empty");
                return(-1);
            }

            var credentials = new CustomCredentials(clientId, clientSecret, tenantId);

            var subscriptions = await GetSubscriptions(subscription, credentials);

            await Process(credentials, subscriptions, numberOfMonthsToAnalyze, outputFolder, onlyWithOverages);

            var reportFile = CsvReporter.MergeReports(outputFolder);

            // Open report
            if (openReport && !string.IsNullOrEmpty(reportFile))
            {
                var process = new Process {
                    StartInfo = new ProcessStartInfo(reportFile)
                    {
                        UseShellExecute = true
                    }
                };
                process.Start();
            }

            return(0);
        }
        private static async Task Process(CustomCredentials credentials, ConcurrentQueue <string> subscriptions,
                                          int numberOfMonthsToAnalyze, string outputFolder,
                                          bool onlyWithOverages)
        {
            var processingThreads = subscriptions.Count > MaxNumberOfSubscriptionsToAnalyzeInParallel
                ? MaxNumberOfSubscriptionsToAnalyzeInParallel
                : subscriptions.Count;
            var threads            = new List <Task>(processingThreads);
            var subscriptionsTotal = subscriptions.Count;
            var processed          = 0;

            for (var i = 0; i < processingThreads; i++)
            {
                threads.Add(Task.Run(() =>
                {
                    while (subscriptions.TryDequeue(out var subscriptionId))
                    {
                        try
                        {
                            var consumption  = new ConsumptionProvider(credentials, subscriptionId);
                            var usageDetails = consumption.GetConsumptionAsync(numberOfMonthsToAnalyze).GetAwaiter()
                                               .GetResult();
                            if (usageDetails.Count == 0)
                            {
                                Log.Warning($"No billing information found for subscription {subscriptionId}");
                                continue;
                            }

                            var consumptionAnalyzer =
                                new ConsumptionAnalyzer(new ActivityLogProvider(credentials, subscriptionId),
                                                        new ResourceProvider(credentials, subscriptionId),
                                                        subscriptionId);
                            var report = consumptionAnalyzer
                                         .AnalyzeConsumptionForDeletedResources(usageDetails, onlyWithOverages).GetAwaiter()
                                         .GetResult();

                            var reportFile = Path.Combine(outputFolder,
                                                          $"consumption_{subscriptionId}_{DateTime.UtcNow:yyyy_MM_dd_hh_mm}.csv");

                            CsvReporter.WriteReport(report, reportFile);
                            processed++;
                        }
                        catch (Exception exception)
                        {
                            Log.Error(exception, $"Exception while processing {subscriptionId}");
                        }
                    }
                }).ContinueWith(t =>
                {
                    if (!t.IsCompletedSuccessfully)
                    {
                        Log.Error(t.Exception?.GetBaseException(), "Processing thread crashed");
                    }
                }));
            }

            using var timer = new Timer(data =>
                                        Log.Information($"Processed ... {processed} of {subscriptionsTotal} subscriptions"), null, 0, 10000);

            await Task.WhenAll(threads);
        }