コード例 #1
0
        private static MetricsDeclaration InterpretYamlStream(YamlStream metricsDeclarationYamlStream)
        {
            var document = metricsDeclarationYamlStream.Documents.First();
            var rootNode = (YamlMappingNode)document.RootNode;

            AzureMetadata azureMetadata = null;

            if (rootNode.Children.ContainsKey("azureMetadata"))
            {
                var azureMetadataNode       = (YamlMappingNode)rootNode.Children[new YamlScalarNode("azureMetadata")];
                var azureMetadataSerializer = new AzureMetadataDeserializer();
                azureMetadata = azureMetadataSerializer.Deserialize(azureMetadataNode);
            }

            List <MetricDefinition> metrics = null;

            if (rootNode.Children.ContainsKey("metrics"))
            {
                var metricsNode         = (YamlSequenceNode)rootNode.Children[new YamlScalarNode("metrics")];
                var metricsDeserializer = new MetricsDeserializer();
                metrics = metricsDeserializer.Deserialize(metricsNode);
            }

            var metricsDeclaration = new MetricsDeclaration
            {
                AzureMetadata = azureMetadata,
                Metrics       = metrics
            };

            return(metricsDeclaration);
        }
コード例 #2
0
        private static AzureMonitorClient ConfigureAzureMonitorClient(MetricsDeclaration metricsDeclaration, IRuntimeMetricsCollector runtimeMetricCollector, IConfiguration configuration, IOptions <AzureMonitorLoggingConfiguration> azureMonitorLoggingConfiguration, ILoggerFactory loggerFactory)
        {
            var azureCredentials   = DetermineAzureCredentials(configuration);
            var azureMetadata      = metricsDeclaration.AzureMetadata;
            var azureMonitorClient = new AzureMonitorClient(azureMetadata.Cloud, azureMetadata.TenantId, azureMetadata.SubscriptionId, azureCredentials.ApplicationId, azureCredentials.Secret, azureMonitorLoggingConfiguration, runtimeMetricCollector, loggerFactory);

            return(azureMonitorClient);
        }
コード例 #3
0
        private void LogMetricsDeclaration(MetricsDeclaration metricsDeclaration)
        {
            metricsDeclaration.Metrics.ForEach(SanitizeStorageQueueDeclaration);

            var serializer     = YamlSerialization.CreateSerializer();
            var rawDeclaration = serializer.Serialize(metricsDeclaration);

            Logger.LogInformation("Following metrics configuration was configured:\n{Configuration}", rawDeclaration);
        }
コード例 #4
0
        public static string Serialize(MetricsDeclaration metricsDeclaration)
        {
            Guard.NotNull(metricsDeclaration, nameof(metricsDeclaration));

            var serializer            = YamlSerialization.CreateSerializer();
            var rawMetricsDeclaration = serializer.Serialize(metricsDeclaration);

            return(rawMetricsDeclaration);
        }
コード例 #5
0
        public string Build()
        {
            var metricsDeclaration = new MetricsDeclaration
            {
                AzureMetadata = _azureMetadata,
                Metrics       = _metrics
            };

            return(ConfigurationSerializer.Serialize(metricsDeclaration));
        }
コード例 #6
0
        public string Build()
        {
            var metricsDeclaration = new MetricsDeclaration
            {
                AzureMetadata = _azureMetadata,
                Metrics       = _metrics
            };

            var configurationSerializer = new ConfigurationSerializer(NullLogger.Instance);

            return(configurationSerializer.Serialize(metricsDeclaration));
        }
コード例 #7
0
        public string Build()
        {
            var metricsDeclaration = new MetricsDeclaration
            {
                AzureMetadata = azureMetadata,
                Metrics       = metrics
            };

            var serializer = YamlSerialization.CreateSerializer();

            return(serializer.Serialize(metricsDeclaration));
        }
コード例 #8
0
        private static void ScheduleResourcesScraping(MetricsDeclaration metricsDeclaration,
                                                      MetricSinkWriter metricSinkWriter,
                                                      AzureMonitorClientFactory azureMonitorClientFactory,
                                                      IAzureScrapingPrometheusMetricsCollector azureScrapingPrometheusMetricsCollector,
                                                      IMemoryCache resourceMetricDefinitionMemoryCache,
                                                      IScrapingMutex scrapingTaskMutex,
                                                      IConfiguration configuration,
                                                      IOptions <AzureMonitorIntegrationConfiguration> azureMonitorIntegrationConfiguration,
                                                      IOptions <AzureMonitorLoggingConfiguration> azureMonitorLoggingConfiguration,
                                                      ILoggerFactory loggerFactory,
                                                      ILogger <Startup> logger,
                                                      IServiceCollection services)
        {
            var jobName = GenerateResourceScrapingJobName(metricsDeclaration, logger);

            services.AddScheduler(builder =>
            {
                builder.AddJob(jobServices =>
                               new ResourcesScrapingJob(jobName,
                                                        metricsDeclaration,
                                                        jobServices.GetService <ResourceDiscoveryRepository>(),
                                                        metricSinkWriter,
                                                        jobServices.GetService <MetricScraperFactory>(),
                                                        azureMonitorClientFactory,
                                                        azureScrapingPrometheusMetricsCollector,
                                                        resourceMetricDefinitionMemoryCache,
                                                        scrapingTaskMutex,
                                                        configuration,
                                                        azureMonitorIntegrationConfiguration,
                                                        azureMonitorLoggingConfiguration,
                                                        loggerFactory,
                                                        jobServices.GetService <ILogger <ResourcesScrapingJob> >()),
                               schedulerOptions =>
                {
                    schedulerOptions.CronSchedule   = metricsDeclaration.Metrics[0].Scraping.Schedule;
                    schedulerOptions.RunImmediately = true;
                },
                               jobName: jobName);
                builder.AddUnobservedTaskExceptionHandler(s =>
                {
                    return
                    ((_, exceptionEventArgs) =>
                    {
                        var exceptionLogger = s.GetService <ILogger <BackgroundJobMonitor> >();
                        BackgroundJobMonitor.HandleException(jobName, exceptionEventArgs, exceptionLogger);
                    });
                });
            });
            logger.LogInformation("Scheduled scraping job {JobName}.", jobName);
        }
コード例 #9
0
        /// <summary>
        /// Create a metrics scraping job for one or more resources, either enumerated specifically or
        /// identified via resource definition groups. All metrics included are expected to have
        /// the same scraping schedule.
        /// </summary>
        /// <param name="jobName">name of scheduled job</param>
        /// <param name="metricsDeclaration">declaration of which metrics to collect from which resources</param>
        /// <param name="resourceDiscoveryRepository">repository source for discovering resources via criteria</param>
        /// <param name="metricSinkWriter">destination for metric reporting output</param>
        /// <param name="metricScraperFactory">means of obtaining a metrics scraper for a particular type of resource</param>
        /// <param name="azureMonitorClientFactory">means of obtaining a Azure Monitor client</param>
        /// <param name="azureScrapingPrometheusMetricsCollector">metrics collector to write metrics to Prometheus</param>
        /// <param name="resourceMetricDefinitionMemoryCache">cache of metric definitions by resource ID</param>
        /// <param name="scrapingTaskMutex">semaphore used to limit concurrency of tasks if configured, or null for no limiting</param>
        /// <param name="configuration">Promitor configuration</param>
        /// <param name="azureMonitorIntegrationConfiguration">options for Azure Monitor integration</param>
        /// <param name="azureMonitorLoggingConfiguration">options for Azure Monitor logging</param>
        /// <param name="loggerFactory">means to obtain a logger</param>
        /// <param name="logger">logger to use for scraping detail</param>
        public ResourcesScrapingJob(string jobName,
                                    MetricsDeclaration metricsDeclaration,
                                    ResourceDiscoveryRepository resourceDiscoveryRepository,
                                    MetricSinkWriter metricSinkWriter,
                                    MetricScraperFactory metricScraperFactory,
                                    AzureMonitorClientFactory azureMonitorClientFactory,
                                    IAzureScrapingPrometheusMetricsCollector azureScrapingPrometheusMetricsCollector,
                                    IMemoryCache resourceMetricDefinitionMemoryCache,
                                    IScrapingMutex scrapingTaskMutex,
                                    IConfiguration configuration,
                                    IOptions <AzureMonitorIntegrationConfiguration> azureMonitorIntegrationConfiguration,
                                    IOptions <AzureMonitorLoggingConfiguration> azureMonitorLoggingConfiguration,
                                    ILoggerFactory loggerFactory,
                                    ILogger <ResourcesScrapingJob> logger)
            : base(jobName, logger)
        {
            Guard.NotNullOrWhitespace(jobName, nameof(jobName));
            Guard.NotNull(metricsDeclaration, nameof(metricsDeclaration));
            Guard.NotNull(metricsDeclaration.AzureMetadata, $"{nameof(metricsDeclaration)}.{nameof(metricsDeclaration.AzureMetadata)}");
            Guard.NotNull(metricsDeclaration.Metrics, $"{nameof(metricsDeclaration)}.{nameof(metricsDeclaration.Metrics)}");
            Guard.NotNull(resourceDiscoveryRepository, nameof(resourceDiscoveryRepository));
            Guard.NotNull(metricSinkWriter, nameof(metricSinkWriter));
            Guard.NotNull(metricScraperFactory, nameof(metricScraperFactory));
            Guard.NotNull(azureMonitorClientFactory, nameof(azureMonitorClientFactory));
            Guard.NotNull(azureScrapingPrometheusMetricsCollector, nameof(azureScrapingPrometheusMetricsCollector));
            Guard.NotNull(resourceMetricDefinitionMemoryCache, nameof(resourceMetricDefinitionMemoryCache));
            Guard.NotNull(configuration, nameof(configuration));
            Guard.NotNull(azureMonitorIntegrationConfiguration, nameof(azureMonitorIntegrationConfiguration));
            Guard.NotNull(azureMonitorLoggingConfiguration, nameof(azureMonitorLoggingConfiguration));
            Guard.NotNull(loggerFactory, nameof(loggerFactory));

            // all metrics must have the same scraping schedule or it is not possible for them to share the same job
            VerifyAllMetricsHaveSameScrapingSchedule(metricsDeclaration);

            _metricsDeclaration                      = metricsDeclaration;
            _resourceDiscoveryRepository             = resourceDiscoveryRepository;
            _metricSinkWriter                        = metricSinkWriter;
            _metricScraperFactory                    = metricScraperFactory;
            _azureMonitorClientFactory               = azureMonitorClientFactory;
            _azureScrapingPrometheusMetricsCollector = azureScrapingPrometheusMetricsCollector;
            _resourceMetricDefinitionMemoryCache     = resourceMetricDefinitionMemoryCache;
            _scrapingTaskMutex                       = scrapingTaskMutex;
            _configuration = configuration;
            _azureMonitorIntegrationConfiguration = azureMonitorIntegrationConfiguration;
            _azureMonitorLoggingConfiguration     = azureMonitorLoggingConfiguration;
            _loggerFactory = loggerFactory;
        }
コード例 #10
0
        private static void VerifyAllMetricsHaveSameScrapingSchedule(MetricsDeclaration metricsDeclaration)
        {
            if (metricsDeclaration.Metrics.Count > 1)
            {
                var metrics        = metricsDeclaration.Metrics;
                var commonScraping = metrics[0].Scraping;

                for (var i = 1; i < metrics.Count; i++)
                {
                    if (!Equals(commonScraping, metrics[i].Scraping))
                    {
                        throw new ArgumentException(
                                  $"The \"{metrics[i].Scraping?.Schedule}\" scraping schedule for {nameof(metricsDeclaration)}.{nameof(metricsDeclaration.Metrics)}[{i}] does not share the common scraping schedule \"{commonScraping?.Schedule}\".");
                    }
                }
            }
        }
コード例 #11
0
        public void YamlSerialization_SerializeAndDeserializeValidConfigForServiceBus_SucceedsWithIdenticalOutput()
        {
            // Arrange
            var azureMetadata = GenerateBogusAzureMetadata();
            var serviceBusMetricDefinition = GenerateBogusServiceBusMetricDefinition();
            var scrapingConfiguration      = new MetricsDeclaration
            {
                AzureMetadata = azureMetadata,
                Metrics       = new List <Core.Scraping.Configuration.Model.Metrics.MetricDefinition>
                {
                    serviceBusMetricDefinition
                }
            };

            // Act
            var serializedConfiguration   = ConfigurationSerializer.Serialize(scrapingConfiguration);
            var deserializedConfiguration = ConfigurationSerializer.Deserialize(serializedConfiguration);

            // Assert
            Assert.NotNull(deserializedConfiguration);
            Assert.NotNull(deserializedConfiguration.AzureMetadata);
            Assert.Equal(azureMetadata.TenantId, deserializedConfiguration.AzureMetadata.TenantId);
            Assert.Equal(azureMetadata.ResourceGroupName, deserializedConfiguration.AzureMetadata.ResourceGroupName);
            Assert.Equal(azureMetadata.SubscriptionId, deserializedConfiguration.AzureMetadata.SubscriptionId);
            Assert.NotNull(deserializedConfiguration.Metrics);
            Assert.Single(deserializedConfiguration.Metrics);
            var deserializedMetricDefinition = deserializedConfiguration.Metrics.FirstOrDefault();

            Assert.NotNull(deserializedMetricDefinition);
            Assert.Equal(serviceBusMetricDefinition.Name, deserializedMetricDefinition.Name);
            Assert.Equal(serviceBusMetricDefinition.Description, deserializedMetricDefinition.Description);
            Assert.Equal(serviceBusMetricDefinition.ResourceType, deserializedMetricDefinition.ResourceType);
            var deserializedServiceBusMetricDefinition = deserializedMetricDefinition as ServiceBusQueueMetricDefinition;

            Assert.NotNull(deserializedServiceBusMetricDefinition);
            Assert.Equal(serviceBusMetricDefinition.Namespace, deserializedServiceBusMetricDefinition.Namespace);
            Assert.Equal(serviceBusMetricDefinition.QueueName, deserializedServiceBusMetricDefinition.QueueName);
            Assert.NotNull(deserializedMetricDefinition.AzureMetricConfiguration);
            Assert.Equal(serviceBusMetricDefinition.AzureMetricConfiguration.MetricName, deserializedMetricDefinition.AzureMetricConfiguration.MetricName);
            Assert.Equal(serviceBusMetricDefinition.AzureMetricConfiguration.Aggregation, deserializedMetricDefinition.AzureMetricConfiguration.Aggregation);
        }
コード例 #12
0
        private static ICollection <MetricsDeclaration> GroupMetricsByScrapingInterval(MetricsDeclaration allMetrics)
        {
            var metricsGroupings = new Dictionary <Scraping, MetricsDeclaration>();

            foreach (var metric in allMetrics.Metrics)
            {
                if (!metricsGroupings.TryGetValue(metric.Scraping, out var metricsGroup))
                {
                    metricsGroup = new MetricsDeclaration
                    {
                        AzureMetadata  = allMetrics.AzureMetadata,
                        MetricDefaults = allMetrics.MetricDefaults
                    };
                    metricsGroupings.Add(metric.Scraping, metricsGroup);
                }

                metricsGroup.Metrics.Add(metric);
            }

            return(metricsGroupings.Values);
        }
コード例 #13
0
        private static string GenerateResourceScrapingJobName(MetricsDeclaration metricsDeclaration, ILogger <Startup> logger)
        {
            string scheduleDescription;

            try
            {
                scheduleDescription = CronExpressionDescriptor.ExpressionDescriptor.GetDescription(metricsDeclaration.Metrics[0].Scraping.Schedule);
                scheduleDescription = scheduleDescription.Replace(", ", "_").Replace(",", "_").Replace(" ", "_");
            }
            catch (Exception ex)
            {
                var metricName = metricsDeclaration.Metrics[0].AzureMetricConfiguration.MetricName;
                logger.LogError(ex, $"Failure to create job name for scraping resources for list of metrics which includes {metricName}.");
                scheduleDescription = $"UnparsedScheduleForMetricsIncluding{metricName}";
            }

            var metricsCount = metricsDeclaration.Metrics.Count;
            var uniqueness   = Guid.NewGuid().ToString("N");

            return($"Scraper-{metricsCount}Metrics-{scheduleDescription}-{uniqueness}");
        }
コード例 #14
0
        private static void ScheduleResourceScraping(IServiceCollection services, IAzureResourceDefinition resource, MetricsDeclaration metrics, AzureMonitorClientFactory azureMonitorClientFactory, MetricSinkWriter metricSinkWriter, IRuntimeMetricsCollector runtimeMetricCollector, IConfiguration configuration, IOptions <AzureMonitorLoggingConfiguration> azureMonitorLoggingConfiguration, ILoggerFactory loggerFactory, MetricDefinition metric, ILogger <Startup> logger)
        {
            var resourceSubscriptionId = string.IsNullOrWhiteSpace(resource.SubscriptionId) ? metrics.AzureMetadata.SubscriptionId : resource.SubscriptionId;
            var azureMonitorClient     = azureMonitorClientFactory.CreateIfNotExists(metrics.AzureMetadata.Cloud, metrics.AzureMetadata.TenantId, resourceSubscriptionId, metricSinkWriter, runtimeMetricCollector, configuration, azureMonitorLoggingConfiguration, loggerFactory);
            var scrapeDefinition       = metric.CreateScrapeDefinition(resource, metrics.AzureMetadata);
            var jobName = GenerateResourceScrapingJobName(scrapeDefinition, resource);

            services.AddScheduler(builder =>
            {
                builder.AddJob(jobServices =>
                {
                    return(new ResourceScrapingJob(jobName, scrapeDefinition,
                                                   metricSinkWriter,
                                                   jobServices.GetService <IPrometheusMetricWriter>(),
                                                   jobServices.GetService <MetricScraperFactory>(),
                                                   azureMonitorClient,
                                                   jobServices.GetService <ILogger <ResourceScrapingJob> >()));
                }, schedulerOptions =>
                {
                    schedulerOptions.CronSchedule   = scrapeDefinition.Scraping.Schedule;
                    schedulerOptions.RunImmediately = true;
                },
                               jobName: jobName);
                builder.UnobservedTaskExceptionHandler = (sender, exceptionEventArgs) => UnobservedJobHandlerHandler(jobName, exceptionEventArgs, services);
            });

            logger.LogInformation("Scheduled scraping job {JobName} for resource {Resource} which will be reported as metric {MetricName}", jobName, scrapeDefinition.Resource.GetUniqueName(), scrapeDefinition.PrometheusMetricDefinition?.Name);
        }