public static async Task <List <Measurement> > GetMetricAsync( this IMonitorManagementClient monitorManagementClient, string resourceUri, MetricName metricName, DateTime startTimeUtc, DateTime endTimeUtc, TimeSpan samplingInterval, AggregationType aggregation, CancellationToken cancellationToken = default) { Contract.Requires(aggregation != AggregationType.None); // Unfortunately, the Azure Metrics API is pretty bad and lacking documentation, so we do our best here to // get things working. However, API may fail anyways if an invalid set of sampling frequency vs time length // is input. var startTime = startTimeUtc.ToString("o").Replace("+", "%2b"); var endTime = endTimeUtc.ToString("o").Replace("+", "%2b"); return(await RetryPolicy.ExecuteAsync(async() => { var result = await monitorManagementClient.Metrics.ListAsync( resourceUri: resourceUri, metricnames: metricName, timespan: $"{startTime}/{endTime}", interval: samplingInterval, aggregation: aggregation.ToString(), cancellationToken: cancellationToken); var metric = result.Value[0]; var extract = ExtractMetric[aggregation]; var timeSeries = metric.Timeseries[0]; return timeSeries.Data.Select(metricValue => new Measurement(metricValue.TimeStamp, extract(metricValue))).ToList(); }, cancellationToken)); }
public RedisAutoscalingAgent(Configuration configuration, IMonitorManagementClient monitorManagementClient) { Contract.Requires(configuration.UsedMemoryAggregationInterval < configuration.UsedMemoryLookback); Contract.Requires(configuration.UsedMemoryLookback <= TimeSpan.FromDays(30)); Contract.Requires(configuration.MinimumExtraMemoryAvailable > 0); _configuration = configuration; _monitorManagementClient = monitorManagementClient; }
/// <summary> /// Initializes a new instance of the <see cref="MetricClient"/> class /// </summary> /// <param name="tracer">The tracer</param> /// <param name="subscriptionId">The subscription Id</param> /// <param name="monitorManagementClient">Monitor management client to use to fetch metric data</param> public MetricClient(IExtendedTracer tracer, string subscriptionId, IMonitorManagementClient monitorManagementClient) { this.tracer = Diagnostics.EnsureArgumentNotNull(() => tracer); this.monitorManagementClient = monitorManagementClient; this.monitorManagementClient.SubscriptionId = subscriptionId; this.tracer = tracer; this.retryPolicy = PolicyExtensions.CreateDefaultPolicy(this.tracer, DependencyName); }
public DiagnosticSettingsResource CreateDiagnosticSettings( string categoryName, string settingsName, string eventHubName, string eventHubAuthorizationRuleId, string workspaceId, string resourceGroupName, string serverName, string databaseName = "master") { string resoureUri = GetResourceUri(resourceGroupName, serverName, databaseName); IMonitorManagementClient client = GetMonitorManagementClient(); DiagnosticSettingsResource settings = new DiagnosticSettingsResource { Logs = new List <LogSettings>(), Metrics = new List <MetricSettings>(), EventHubName = eventHubName, EventHubAuthorizationRuleId = eventHubAuthorizationRuleId, WorkspaceId = workspaceId }; try { IList <DiagnosticSettingsCategoryResource> supportedCategories = client.DiagnosticSettingsCategory.ListAsync(resoureUri).Result.Value; if (supportedCategories != null) { foreach (DiagnosticSettingsCategoryResource category in supportedCategories) { if (category.CategoryType == CategoryType.Metrics) { settings.Metrics.Add(new MetricSettings(false, null, category.Name)); } else { settings.Logs.Add( new LogSettings( string.Equals(category.Name, categoryName), category.Name)); } } } } catch (AggregateException ex) { if (!(ex.InnerException is ErrorResponseException ex1) || ex1.Response.StatusCode != System.Net.HttpStatusCode.NotFound) { throw ex.InnerException ?? ex; } } if (!settings.Logs.Any(l => string.Equals(l.Category, categoryName))) { settings.Logs.Add(new LogSettings(true, categoryName)); } return(client.DiagnosticSettings.CreateOrUpdateAsync( resoureUri, settings, settingsName).Result); }
/// <summary> /// Initializes a new instance of the <see cref="MdmClient"/> class /// </summary> /// <param name="tracer">The tracer</param> /// <param name="credentialsFactory">The credentials factory</param> /// <param name="resourceIdentifier">The resource for which we want to fetch data from MDM</param> /// /// <param name="monitorManagementClient">Monitor management client to use to fetch data from MDM</param> public MdmClient(ITracer tracer, ICredentialsFactory credentialsFactory, ResourceIdentifier resourceIdentifier, IMonitorManagementClient monitorManagementClient) { this.tracer = Diagnostics.EnsureArgumentNotNull(() => tracer); Diagnostics.EnsureArgumentNotNull(() => credentialsFactory); this.resourceIdentifier = resourceIdentifier; this.credentials = credentialsFactory.Create("https://management.azure.com/"); this.monitorManagementClient = monitorManagementClient; this.monitorManagementClient.SubscriptionId = resourceIdentifier.SubscriptionId; this.tracer = tracer; this.retryPolicy = PolicyExtensions.CreateDefaultPolicy(this.tracer, DependencyName); }
/// <summary> /// Dispose the resources /// </summary> /// <param name="disposing">Indicates whether the managed resources should be disposed or not</param> protected override void Dispose(bool disposing) { if (!this.disposed) { if (this.monitorManagementClient != null) { this.monitorManagementClient.Dispose(); this.monitorManagementClient = null; } this.disposed = true; } base.Dispose(disposing); }
/// <summary> /// Initializes a new instance of the <see cref="MetricClient"/> class /// </summary> /// <param name="tracer">The tracer</param> /// <param name="monitorManagementClient">Monitor management client to use to fetch metric data</param> public MetricClient(ITracer tracer, IMonitorManagementClient monitorManagementClient) { if (tracer == null) { throw new ArgumentNullException(nameof(tracer)); } if (monitorManagementClient == null) { throw new ArgumentNullException(nameof(monitorManagementClient)); } this.tracer = tracer; this.monitorManagementClient = monitorManagementClient; this.retryPolicy = PolicyExtensions.CreateDefaultPolicy(this.tracer, DependencyName); }
private void SetupManagementClients(RestTestFramework.MockContext context) { if (HttpMockServer.Mode == HttpRecorderMode.Record) { // This allows the use of a particular subscription if the user is associated to several // "TEST_CSM_ORGID_AUTHENTICATION=SubscriptionId=<subscription-id>" string subId = Environment.GetEnvironmentVariable("TEST_CSM_ORGID_AUTHENTICATION"); RestTestFramework.TestEnvironment environment = new RestTestFramework.TestEnvironment(connectionString: subId); this.MonitorManagementClient = this.GetInsightsManagementClient(context: context, env: environment); } else if (HttpMockServer.Mode == HttpRecorderMode.Playback) { this.MonitorManagementClient = this.GetInsightsManagementClient(context: context, env: null); } _helper.SetupManagementClients( this.MonitorManagementClient); }
public EnvironmentResources(IAzure azure, IMonitorManagementClient monitorManagementClient, IReadOnlyDictionary <string, IRedisCache> redisCaches) { Azure = azure; MonitorManagementClient = monitorManagementClient; RedisCaches = redisCaches; }
public static async Task<Dictionary<MetricName, List<MetricValue>>> GetMetricsWithDimensionAsync( this IMonitorManagementClient monitorManagementClient, string resourceUri, IReadOnlyList<MetricName> metrics, string dimension, DateTime startTimeUtc, DateTime endTimeUtc, TimeSpan samplingInterval, IReadOnlyList<AggregationType> aggregations, CancellationToken cancellationToken = default) { Contract.Requires(startTimeUtc < endTimeUtc); // HERE BE DRAGONS. The Azure Monitor Metrics API is basically nondeterministic. It may fail at random, for // unknown periods of time, and for unknown reasons. This function is an attempt to make a sane wrapper // over it. // We remove the seconds in an attempt to play nicely with the Azure Metrics API. Format is not strictly // ISO, as they claim is supported, but what we have found to work by trial and error and looking at // examples. var startTime = startTimeUtc.ToString("yyyy-MM-ddTHH:mm:00Z"); var endTime = endTimeUtc.ToString("yyyy-MM-ddTHH:mm:00Z"); var interval = $"{startTime}/{endTime}"; return await RetryPolicy.ExecuteAsync(async () => { var metricNames = string.Join(",", metrics.Select(name => name.Name.ToLower())); var odataQuery = new ODataQuery<MetadataValue>(odataExpression: $"{dimension} eq '*'"); var aggregation = string.Join( ",", aggregations.Select( agg => { Contract.Assert(agg != AggregationType.None); return agg.ToString().ToLower(); })); var result = await monitorManagementClient.Metrics.ListAsync( resourceUri: resourceUri, metricnames: metricNames, odataQuery: odataQuery, timespan: interval, interval: samplingInterval, aggregation: aggregation, cancellationToken: cancellationToken); result.Validate(); if (result.Value.Count == 0) { // Sometimes, for unknown reasons, this can be empty. This is an error, but can go away when // retried. That's exactly what we do here (look at the retry policy's detection strategy). throw new AzureMetricsClientValidationException("Invalid `result.Value` returned"); } var output = new Dictionary<MetricName, List<MetricValue>>(); foreach (var metric in result.Value) { if (metric.Timeseries.Count == 0) { // Sometimes, there may be no timeseries. Reasons seem to be varied, but here's the predominant // example that would brick us in production: // - We'd attempt to fetch operationsPerSecond going back several weeks for all possible 10 // shards. // - The current number of shards is less than 10, say 1 // - Shard 0 would have a result. Shards 1-9 wouldn't. // WARNING: this continue means that we won't report the result for this metric. Usages must // account for arbitrary metric disappearance. continue; } var metricNameFromApi = metric.Name.Value; if (string.IsNullOrEmpty(metricNameFromApi)) { throw new AzureMetricsClientValidationException("Received empty metric name"); } foreach (var timeseries in metric.Timeseries) { var metricGroupFromApi = timeseries.Metadatavalues.ToDictionary(v => v.Name.Value, v => v.Value); var timeSeriesFromApi = timeseries.Data; if (timeSeriesFromApi == null || timeSeriesFromApi.Count < 1) { throw new AzureMetricsClientValidationException($"Received invalid time series for metric `{metricNameFromApi}`. Size=[{timeSeriesFromApi?.Count ?? -1}]"); } var metricName = new MetricName(metricNameFromApi, metricGroupFromApi); output[metricName] = timeSeriesFromApi .OrderBy(m => m.TimeStamp) .ToList(); } } return output; }, cancellationToken); }
public AzureMetricsClient(IMonitorManagementClient monitorManagementClient) { _monitorManagementClient = monitorManagementClient; }