private static void ScheduleResourceScraping(IAzureResourceDefinition resource, AzureMetadata azureMetadata, MetricDefinition metric, AzureMonitorClientFactory azureMonitorClientFactory, MetricSinkWriter metricSinkWriter, IRuntimeMetricsCollector runtimeMetricCollector, IConfiguration configuration, IOptions <AzureMonitorLoggingConfiguration> azureMonitorLoggingConfiguration, ILoggerFactory loggerFactory, ILogger <Startup> logger, IServiceCollection services) { var resourceSubscriptionId = string.IsNullOrWhiteSpace(resource.SubscriptionId) ? azureMetadata.SubscriptionId : resource.SubscriptionId; var azureMonitorClient = azureMonitorClientFactory.CreateIfNotExists(azureMetadata.Cloud, azureMetadata.TenantId, resourceSubscriptionId, metricSinkWriter, runtimeMetricCollector, configuration, azureMonitorLoggingConfiguration, loggerFactory); var scrapeDefinition = metric.CreateScrapeDefinition(resource, azureMetadata); var jobName = GenerateResourceScrapingJobName(scrapeDefinition, resource); services.AddScheduler(builder => { builder.AddJob(jobServices => { return(new ResourceScrapingJob(jobName, scrapeDefinition, metricSinkWriter, 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.UniqueName, scrapeDefinition.PrometheusMetricDefinition?.Name); }
/// <summary> /// Creates a <see cref="ScrapeDefinition{TResourceDefinition}"/> object for the specified resource. /// </summary> /// <param name="resource">The resource to scrape.</param> /// <param name="azureMetadata">The Azure global metadata.</param> /// <returns>The scrape definition.</returns> public ScrapeDefinition <IAzureResourceDefinition> CreateScrapeDefinition(IAzureResourceDefinition resource, AzureMetadata azureMetadata) { return(new ScrapeDefinition <IAzureResourceDefinition>( AzureMetricConfiguration, PrometheusMetricDefinition, Scraping, resource, string.IsNullOrEmpty(resource.ResourceGroupName) ? azureMetadata.ResourceGroupName : resource.ResourceGroupName)); }
/// <summary> /// Creates a <see cref="ScrapeDefinition{TResourceDefinition}"/> object for the specified resource. /// </summary> /// <param name="resource">The resource to scrape.</param> /// <param name="azureMetadata">The Azure global metadata.</param> /// <returns>The scrape definition.</returns> public ScrapeDefinition <IAzureResourceDefinition> CreateScrapeDefinition(IAzureResourceDefinition resource, AzureMetadata azureMetadata) { // TODO: Verify if this logic is valid as we always use defaults? 🤔 return(new ScrapeDefinition <IAzureResourceDefinition>( AzureMetricConfiguration, PrometheusMetricDefinition, Scraping, resource, string.IsNullOrEmpty(resource.SubscriptionId) ? azureMetadata.SubscriptionId : resource.SubscriptionId, string.IsNullOrEmpty(resource.ResourceGroupName) ? azureMetadata.ResourceGroupName : resource.ResourceGroupName)); }
private async Task ScrapeResourceAsync(IAzureResourceDefinition discoveredResource, AzureMonitorClient azureMonitorClient) { try { var scrapingDefinition = _metricDefinition.CreateScrapeDefinition(discoveredResource, _azureMetadata); var scraper = _metricScraperFactory.CreateScraper(scrapingDefinition.Resource.ResourceType, _metricSinkWriter, azureMonitorClient); await scraper.ScrapeAsync(scrapingDefinition); } catch (Exception exception) { Logger.LogCritical(exception, "Failed to scrape resource collection {Resource}: {Exception}", discoveredResource.UniqueName, exception.Message); } }
/// <summary> /// Creates a <see cref="ScrapeDefinition{TResourceDefinition}"/> object for the specified resource. /// </summary> /// <param name="resource">The resource to scrape.</param> /// <param name="azureMetadata">The Azure global metadata.</param> /// <returns>The scrape definition.</returns> public ScrapeDefinition <IAzureResourceDefinition> CreateScrapeDefinition(IAzureResourceDefinition resource, AzureMetadata azureMetadata) { var subscriptionId = string.IsNullOrEmpty(resource.SubscriptionId) ? azureMetadata.SubscriptionId : resource.SubscriptionId; var resourceGroupName = string.IsNullOrEmpty(resource.ResourceGroupName) ? azureMetadata.ResourceGroupName : resource.ResourceGroupName; var output = new ScrapeDefinition <IAzureResourceDefinition>( AzureMetricConfiguration, PrometheusMetricDefinition, Scraping, resource, subscriptionId, resourceGroupName); return(output); }
private static string GenerateResourceScrapingJobName(ScrapeDefinition <IAzureResourceDefinition> scrapeDefinition, IAzureResourceDefinition resource) { var jobNameBuilder = new StringBuilder(); jobNameBuilder.Append(scrapeDefinition.SubscriptionId); jobNameBuilder.Append("-"); jobNameBuilder.Append(scrapeDefinition.ResourceGroupName); jobNameBuilder.Append("-"); jobNameBuilder.Append(scrapeDefinition.PrometheusMetricDefinition.Name); jobNameBuilder.Append("-"); jobNameBuilder.Append(resource.UniqueName); jobNameBuilder.Append("-"); jobNameBuilder.Append(Guid.NewGuid().ToString()); return(jobNameBuilder.ToString()); }
private void GetResourceScrapeDefinition(IAzureResourceDefinition resourceDefinition, MetricDefinition metricDefinition, ConcurrentBag <ScrapeDefinition <IAzureResourceDefinition> > scrapeDefinitions) { var scrapeDefinition = metricDefinition.CreateScrapeDefinition(resourceDefinition, _metricsDeclaration.AzureMetadata); scrapeDefinitions.Add(scrapeDefinition); }