public void CreatingLabelledMetric_AfterObservingLabelledData_DoesNotExportUnlabelled() { var registry = new DefaultCollectorRegistry(); var factory = Metrics.WithCustomRegistry(registry); var gauge = factory.CreateGauge("gauge", "", "labelname"); var counter = factory.CreateCounter("counter", "", "labelname"); var summary = factory.CreateSummary("summary", "", "labelname"); var histogram = factory.CreateHistogram("histogram", "", null, "labelname"); // Touch some labelled metrics. gauge.Labels("labelvalue").Inc(); counter.Labels("labelvalue").Inc(); summary.Labels("labelvalue").Observe(123); histogram.Labels("labelvalue").Observe(123); // Without touching any unlabelled metrics, there should be only labelled output. var exported = registry.CollectAll().ToArray(); // There is a family for each of the above, in each family we expect to see 1 metric (for the labelled case). Assert.AreEqual(4, exported.Length); foreach (var family in exported) { Assert.AreEqual(1, family.metric.Count, $"Family {family.type} had unexpected metric count."); } }
public void TestResponsesTotalRecordsFailureViaLabel() { string metricName = "test"; DefaultCollectorRegistry registry = GetEmptyRegistry(); string totalMetricName = string.Format("{0}_responses_total", metricName); try { Metrics.Instrument(metricName, () => { throw new ApplicationException("Simulate error during request"); }); Assert.Fail("Metrics.Instrument should not swallow exceptions"); } catch (ApplicationException) { } var family = registry.CollectAll().First(x => x.name == totalMetricName); var metric = family.metric[0]; var label = metric.label.Find(l => l.name == "success"); Assert.IsNotNull(label, "success label not found"); Assert.AreEqual("0", label.value); }
public void CreatingUnlabelledMetric_WithInitialValueSuppression_ExportsNothingByDefault() { var registry = new DefaultCollectorRegistry(); var factory = Metrics.WithCustomRegistry(registry); var gauge = factory.CreateGauge("gauge", "", new GaugeConfiguration { SuppressInitialValue = true }); var counter = factory.CreateCounter("counter", "", new CounterConfiguration { SuppressInitialValue = true }); var summary = factory.CreateSummary("summary", "", new SummaryConfiguration { SuppressInitialValue = true }); var histogram = factory.CreateHistogram("histogram", "", new HistogramConfiguration { SuppressInitialValue = true }); var exported = registry.CollectAll().ToArray(); // There is a family for each of the above, in each family we expect to see 0 metrics. Assert.AreEqual(4, exported.Length); foreach (var family in exported) { Assert.AreEqual(0, family.metric.Count, $"Family {family.type} had unexpected metric count."); } }
public void CreatingLabelledMetric_WithoutObservingAnyData_ExportsImmediately() { var registry = new DefaultCollectorRegistry(); var factory = Metrics.WithCustomRegistry(registry); var gauge = factory.CreateGauge("gauge", "", new GaugeConfiguration { LabelNames = new[] { "foo" } }).WithLabels("bar"); var counter = factory.CreateCounter("counter", "", new CounterConfiguration { LabelNames = new[] { "foo" } }).WithLabels("bar"); var summary = factory.CreateSummary("summary", "", new SummaryConfiguration { LabelNames = new[] { "foo" } }).WithLabels("bar"); var histogram = factory.CreateHistogram("histogram", "", new HistogramConfiguration { LabelNames = new[] { "foo" } }).WithLabels("bar"); // Without touching any metrics, there should be output for all because default config publishes immediately. var exported = registry.CollectAll().ToArray(); // There is a family for each of the above, in each family we expect to see 1 metrics. Assert.AreEqual(4, exported.Length); foreach (var family in exported) { Assert.AreEqual(1, family.metric.Count, $"Family {family.type} had unexpected metric count."); } }
private DefaultCollectorRegistry GetEmptyRegistry() { DefaultCollectorRegistry registry = DefaultCollectorRegistry.Instance; registry.Clear(); Assert.IsFalse(registry.CollectAll().Any()); return(registry); }
private void TestHistogramIsCreated(string name, Action instrument) { DefaultCollectorRegistry registry = GetEmptyRegistry(); instrument(); var histogram = registry.CollectAll().First(x => x.name == string.Format("{0}_request_duration_seconds", name)); Assert.IsTrue(histogram.metric.Count > 0); }
private void TestCounterIsIncremented(string name, Action instrument) { DefaultCollectorRegistry registry = GetEmptyRegistry(); instrument(); var counter = registry.CollectAll().First(x => x.name == name); Assert.AreEqual(1, counter.metric.Count); }
private static ICollectorRegistry CreateCollectorRegistry(IServiceProvider serviceProvider) { var circuitBreakerManager = serviceProvider.GetService <ICircuitBreakerManager>(); var collectorRegistry = new DefaultCollectorRegistry(); collectorRegistry.GetOrAdd(new CircuitBreakerStateCollector(circuitBreakerManager)); return(collectorRegistry); }
private void TestCurrentRequestCounterIsIncrementedAndDecremented(string name, Action <Action> instrument) { string fullName = string.Format("{0}_current_requests", name); DefaultCollectorRegistry registry = GetEmptyRegistry(); instrument(() => { Assert.AreEqual(1, registry.CollectAll().First(x => x.name == fullName).metric[0].gauge.value); }); Assert.AreEqual(0, registry.CollectAll().First(x => x.name == fullName).metric[0].gauge.value); }
public void OnNext_RequestObserver_With_Null_Action_Value_And_Null_Controller_Value() { // Arrange var observer = new AspNetCoreDiagnosticListenerObserver(); var registry = new DefaultCollectorRegistry(); var factory = Metrics.WithCustomRegistry(registry); var listener = new DiagnosticListener("TestListener2"); listener.Subscribe(observer); var context = new DefaultHttpContext(); context.Request.Method = "GET"; context.Request.Path = new PathString("/api/test2"); context.Response.StatusCode = 200; var httpConnectionFeature = new HttpConnectionFeature { ConnectionId = "12345" }; context.Features.Set <IHttpConnectionFeature>(httpConnectionFeature); var routeData = new RouteData(); routeData.Values.Add("controller", null); routeData.Values.Add("action", null); // Act var activity = new Activity("Microsoft.AspNetCore.Hosting.HttpRequestIn"); listener.StartActivity(activity, new { HttpContext = context }); listener.Write("Microsoft.AspNetCore.Mvc.AfterAction", new { httpContext = context, routeData }); listener.StopActivity(activity, new { HttpContext = context }); // Assert var requestCounter = (Counter)observer.GetType().GetField("_requestCounter", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(observer); var requestSummary = (Summary)observer.GetType().GetField("_requestSummary", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(observer); var counterMetrics = requestCounter.Collect(); var summaryMetrics = requestSummary.Collect(); Assert.IsTrue(counterMetrics.First().metric.Any(p => p.label[1].value == "/api/test2")); Assert.IsNotNull(summaryMetrics.First().metric[0].summary); }
public void custom_registry() { var myRegistry = new DefaultCollectorRegistry(); var counter1 = Metrics.WithCustomRegistry(myRegistry).CreateCounter("counter1", "help1"); //registered on a custom registry var counter2 = Metrics.CreateCounter("counter1", "help1"); //created on different registry - same name is hence permitted counter1.Inc(3); counter2.Inc(4); Assert.Equal(3, myRegistry.CollectAll().ToArray()[0].metric[0].counter.value); //counter1 == 3 Assert.Equal(4, DefaultCollectorRegistry.Instance.CollectAll().ToArray()[0].metric[0].counter.value); //counter2 == 4 }
public void TestRequestDurationRecordsSuccessViaLabel() { string metricName = "test"; string durationMetricName = string.Format("{0}_request_duration_seconds", metricName); DefaultCollectorRegistry registry = GetEmptyRegistry(); Metrics.Instrument(metricName, () => { }); var family = registry.CollectAll().First(x => x.name == durationMetricName); var metric = family.metric[1]; var label = metric.label.Find(l => l.name == "success"); Assert.IsNotNull(label, "success label not found"); Assert.AreEqual("1", label.value); }
public void TestResponsesTotalRecordsSuccessViaLabel() { string metricName = "test"; Metrics.Instrument(metricName, () => { }); DefaultCollectorRegistry registry = GetEmptyRegistry(); string totalMetricName = string.Format("{0}_responses_total", metricName); Metrics.Instrument(metricName, () => { }); var family = registry.CollectAll().First(x => x.name == totalMetricName); var metric = family.metric[0]; var label = metric.label.Find(l => l.name == "success"); Assert.IsNotNull(label, "success label not found"); Assert.AreEqual("1", label.value); }
public void StartCollecting_Allows_Multiple_Collectors_For_Non_Default_Registries() { #if PROMV2 var registry1 = new DefaultCollectorRegistry(); var registry2 = new DefaultCollectorRegistry(); #elif PROMV3 var registry1 = Metrics.NewCustomRegistry(); var registry2 = Metrics.NewCustomRegistry(); #endif using (DotNetRuntimeStatsBuilder.Customize().StartCollecting()) { using (DotNetRuntimeStatsBuilder.Customize().StartCollecting(registry1)) { using (DotNetRuntimeStatsBuilder.Customize().StartCollecting(registry2)) { } } } }
public void CreatingLabelledMetric_WithoutObservingAnyData_DoesNotExportUnlabelled() { var registry = new DefaultCollectorRegistry(); var factory = Metrics.WithCustomRegistry(registry); var gauge = factory.CreateGauge("gauge", "", "labelname"); var counter = factory.CreateCounter("counter", "", "labelname"); var summary = factory.CreateSummary("summary", "", "labelname"); var histogram = factory.CreateHistogram("histogram", "", null, "labelname"); // Without touching any metrics, there should be no output. var exported = registry.CollectAll().ToArray(); // There is a family for each of the above, in each family we expect to see 0 metrics. Assert.AreEqual(4, exported.Length); foreach (var family in exported) { Assert.AreEqual(0, family.metric.Count, $"Family {family.type} had unexpected metric count."); } }
public void TestRequestCounterIsDecrementedOnException() { const string name = "request_counter_dec_on_exception"; DefaultCollectorRegistry registry = GetEmptyRegistry(); try { Metrics.Instrument(name, () => { throw new ApplicationException("Simulate exception during request."); }); } catch (ApplicationException) { var family = registry.CollectAll().First(x => x.name == string.Format("{0}_current_requests", name)); Assert.AreEqual(0, family.metric[0].gauge.value); return; } Assert.Fail("Metrics.Instrument should not swallow exceptions"); }
public void CreatingUnlabelledMetric_WithInitialValueSuppression_ExportsAfterValueChange() { var registry = new DefaultCollectorRegistry(); var factory = Metrics.WithCustomRegistry(registry); var gauge = factory.CreateGauge("gauge", "", new GaugeConfiguration { SuppressInitialValue = true }); var counter = factory.CreateCounter("counter", "", new CounterConfiguration { SuppressInitialValue = true }); var summary = factory.CreateSummary("summary", "", new SummaryConfiguration { SuppressInitialValue = true }); var histogram = factory.CreateHistogram("histogram", "", new HistogramConfiguration { SuppressInitialValue = true }); gauge.Set(123); counter.Inc(); summary.Observe(123); histogram.Observe(31); // Without touching any metrics, there should be output for all because default config publishes immediately. var exported = registry.CollectAll().ToArray(); // There is a family for each of the above, in each family we expect to see 1 metric. Assert.AreEqual(4, exported.Length); foreach (var family in exported) { Assert.AreEqual(1, family.metric.Count, $"Family {family.type} had unexpected metric count."); } }
private async Task Assert_Expected_Stats_Are_Present_In_Registry( #if PROMV2 DefaultCollectorRegistry registry
public DefaultCollectorRegistry ReadMetrics(string resourceId) { var reg = new DefaultCollectorRegistry(); var metricFactory = new MetricFactory(reg); var now = DateTime.UtcNow.AddMinutes(-1); string prefix = "azure"; // fallback prefix var resourceGroupMatch = Regex.Match(resourceId, "resourceGroups/(.+)/providers"); var resourceGroup = resourceGroupMatch.Groups[1].Value; var labels = new List <string>() { "resource_group" }; var labelValues = new List <string>() { resourceGroup }; if (resourceId.Contains("Microsoft.Web/certificates")) { var certificate = _azure.AppServices.AppServiceCertificates.GetById(resourceId); // var certificate = _azure.AppServices.AppServiceCertificates.List().SingleOrDefault(cert => cert.Id == resourceId); // _azure.AppServices.AppServiceCertificates.List(). prefix = "certificate"; metricFactory.CreateGauge(prefix + "_expires_in", "Certificate will expire in X days", labels.ToArray()) .Labels(labelValues.ToArray()).Set((certificate.ExpirationDate - DateTime.UtcNow).TotalDays); metricFactory.CreateGauge(prefix + "_expired", "Certificate is expired", labels.ToArray()) .Labels(labelValues.ToArray()).Set(((certificate.ExpirationDate - DateTime.UtcNow).TotalDays < 0) ? 1 : 0); metricFactory.CreateGauge(prefix + "_lifetime", "Had a lifetime of X days", labels.ToArray()) .Labels(labelValues.ToArray()).Set((certificate.ExpirationDate - certificate.IssueDate).TotalDays); // certificate.Inner. var kvStatus = 0; // Not in keyvault if (!String.IsNullOrEmpty(certificate.Inner.KeyVaultId)) { if (certificate.Inner.KeyVaultSecretStatus == Microsoft.Azure.Management.AppService.Fluent.Models.KeyVaultSecretStatus.Succeeded) { kvStatus = 1; // Ok } else { kvStatus = 2; // ??? } } metricFactory.CreateGauge(prefix + "_keyvault_status", "Keyvault status", labels.ToArray()) .Labels(labelValues.ToArray()).Set(kvStatus); return(reg); } var before = now.AddMinutes(-1); var periodString = "startTime eq " + before.ToString("s", System.Globalization.CultureInfo.InvariantCulture) + " and endTime eq " + now.ToString("s", System.Globalization.CultureInfo.InvariantCulture); try { var filter = ""; if (resourceId.Contains("Microsoft.Web/sites")) { prefix = "webapp"; } else if (resourceId.Contains("Microsoft.Web/serverfarms/")) { prefix = "appplan"; } else if (resourceId.Contains("Microsoft.Sql/servers/") && resourceId.Contains("/databases/")) { prefix = "database"; } else if (resourceId.Contains("Microsoft.Compute/virtualMachines")) { prefix = "vm"; } else if (resourceId.Contains("Microsoft.Storage")) { prefix = "storage"; } else if (resourceId.Contains("ApiManagement")) { prefix = "apim"; } if (resourceId.Contains("Microsoft.Web") && false) { filter = "$filter=(name.value eq 'AverageResponseTime'" + " or name.value eq 'Requests'" + " or name.value eq 'CpuTime'" + " or name.value eq 'Http2xx'" + " or name.value eq 'Http4xx'" + " or name.value eq 'Http5xx'" + " or name.value eq 'BytesReceived'" + " or name.value eq 'BytesSent'" + " or name.value eq 'MemoryWorkingSet'" + ")" + " and (aggregationType eq 'Total' or aggregationType eq 'Maximum' or aggregationType eq 'Minimum' or aggregationType eq 'Average' or aggregationType eq 'Count')" + " and " + periodString + " and timeGrain eq duration'PT1M'"; } else // if (resourceId.Contains("Microsoft.Sql")) { var sqlInfoMatch = Regex.Match(resourceId, "servers/(\\w+)/databases/(\\w+)"); if (sqlInfoMatch.Groups[1].Success) { labels.Add("server"); labelValues.Add(sqlInfoMatch.Groups[1].Value); } if (sqlInfoMatch.Groups[2].Success) { labels.Add("database"); labelValues.Add(sqlInfoMatch.Groups[2].Value); } //var resourceGroup = resourceGroupMatch.Groups[1].Value; string metricFilter; if (metricDefCache.ContainsKey(resourceId)) { metricFilter = metricDefCache[resourceId]; Console.WriteLine("FROM CACHE"); } else { var defs = new List <String>(); var metricDefinitions = _monitorClient.MetricDefinitions.List(resourceId); foreach (var mDef in metricDefinitions) { defs.Add($"name.value eq '{mDef.Name.Value}'"); } if (defs.Count == 0) { Console.WriteLine("Failed to get metric defs!!!"); return(null); } metricFilter = String.Join(" or ", defs); metricDefCache.Add(resourceId, metricFilter); } filter = "$filter=(" + metricFilter + ")" + " and (aggregationType eq 'Total' or aggregationType eq 'Maximum' or aggregationType eq 'Minimum' or aggregationType eq 'Average' or aggregationType eq 'Count')" + " and " + periodString + " and timeGrain eq duration'PT1M'"; } var metrics = _monitorClient.Metrics.List(resourceId, filter); foreach (var metric in metrics) { var localLabels = new List <String>(labels); var localLabelValues = new List <String>(labelValues); string metricName = metric.Name.Value.Trim(); if (Regex.Match(metricName, "^Http\\d").Success) { metricName = "Http"; localLabels.Add("status_code"); localLabelValues.Add(metric.Name.Value.Substring(4)); } var name = prefix + "_" + Regex.Replace(metricName, "(?<=.)([A-Z])", "_$0", RegexOptions.Compiled).ToLower().Trim() + "_" + metric.Unit.ToString().ToLower().Trim(); name = name.Replace("percent_percent", "percent"); // Fix double pct ... hackish name = name.Replace("bytes_bytes", "bytes"); name = name.Replace(" ", "_"); name = name.Replace("/", "_"); name = name.Replace("__", "_"); name = name.Replace("c_p_u", "cpu"); Console.WriteLine("Metric: {0} ({1} {2} {3})", metric.Name.Value, metricName, String.Join(",", localLabels), String.Join(",", localLabelValues)); Console.WriteLine("Metric: {0}", name); if (metric.Data.Any()) { metricFactory.CreateGauge(name + "_total", "", localLabels.ToArray()) .Labels(localLabelValues.ToArray()).Set(metric.Data.Last().Total.GetValueOrDefault()); metricFactory.CreateGauge(name + "_average", "", localLabels.ToArray()) .Labels(localLabelValues.ToArray()).Set(metric.Data.Last().Average.GetValueOrDefault()); metricFactory.CreateGauge(name + "_minimum", "", localLabels.ToArray()) .Labels(localLabelValues.ToArray()).Set(metric.Data.Last().Minimum.GetValueOrDefault()); metricFactory.CreateGauge(name + "_maximum", "", localLabels.ToArray()) .Labels(localLabelValues.ToArray()).Set(metric.Data.Last().Maximum.GetValueOrDefault()); } } } catch (Exception ex) { Console.WriteLine("Outer exception: {0}", ex.ToString()); return(null); } return(reg); }