public async Task MetricSetsAreReported() { var metricSet = new TestMetricSet(); var collector = new MetricsCollector( new MetricsCollectorOptions { Endpoints = new [] { new MetricEndpoint("Local", new LocalMetricHandler()), }, Sets = new[] { metricSet }, RetryInterval = TimeSpan.Zero, SnapshotInterval = TimeSpan.FromMilliseconds(20), } ); try { // make sure initialization happened await Task.WhenAny(metricSet.InitializeTask, Task.Delay(1000)); Assert.True(metricSet.InitializeTask.IsCompleted, "Metric set was not initialized"); // and then make sure we actually got snapshotted! await Task.WhenAny(metricSet.SnapshotTask, Task.Delay(1000)); Assert.True(metricSet.SnapshotTask.IsCompleted, "Metric set was not snapshotted"); } finally { collector.Shutdown(); } }
public void CleanUp() { _cancellationTokenSource.Cancel(); _cancellationTokenSource.Dispose(); _emptyCollector.Shutdown(); _httpCollector.Shutdown(); _udpCollector.Shutdown(); }
static async Task Main(string[] args) { //BenchmarkRunner.Run<Benchmark>(); //var x = 1; //if (x == 1) //{ // return; //} s_cancellationTokenSource = new CancellationTokenSource(); Debug.AutoFlush = true; const string LocalEndpointKey = "Local"; var localHandler = new LocalMetricHandler(); var options = new MetricsCollectorOptions(exception => { Console.WriteLine("Hey, there was an exception."); Console.WriteLine(exception); foreach (var key in exception.Data.Keys) { Console.WriteLine($"{key}={exception.Data[key]}"); } }) { Endpoints = new MetricEndpoint[] { //new MetricEndpoint(LocalEndpointKey, localHandler), //new MetricEndpoint("Test UDP", new TestUdpMetricHandler(s_cancellationTokenSource.Token) { MaxPayloadSize = 320 }), //new MetricEndpoint("Bosun (no URL)", new BosunMetricHandler(null)), //new MetricEndpoint("Bosun", new BosunMetricHandler(new Uri("http://devbosun.ds.stackexchange.com/"))), //new MetricEndpoint("SignalFx Agent", new SignalFxMetricHandler(new Uri("http://sfxgateway.signalfx.svc.ny-intkube.k8s.ds.stackexchange.com:18080"))), new MetricEndpoint("SignalFx StatsD Agent", new SignalFxMetricHandler(new Uri("udp://[::1]:8125")) { }), //new MetricEndpoint("SignalFx Cloud", new SignalFxMetricHandler(new Uri("https://ingest.us1.signalfx.com/"), "{API_KEY}")), //new MetricEndpoint("SignalFx Cloud (no URL)", new SignalFxMetricHandler(null, "{API_KEY}")), }, MetricsNamePrefix = "bosun.reporter.", ThrowOnPostFail = true, ThrowOnQueueFull = false, SnapshotInterval = TimeSpan.FromSeconds(10), PropertyToTagName = NameTransformers.CamelToLowerSnakeCase, TagValueConverter = (name, value) => name == "converted" ? value.ToLowerInvariant() : value, DefaultTags = new Dictionary <string, string> { { "host", NameTransformers.Sanitize(Environment.MachineName.ToLower()) } } }; var collector = new MetricsCollector(options); foreach (var endpoint in collector.Endpoints) { switch (endpoint.Handler) { case BosunMetricHandler bosunHandler: Console.WriteLine($"{endpoint.Name}: {bosunHandler.BaseUri?.AbsoluteUri ?? "null"}"); break; case SignalFxMetricHandler signalFxHandler: Console.WriteLine($"{endpoint.Name}: {signalFxHandler.BaseUri?.AbsoluteUri ?? "null"}"); break; } } collector.BeforeSerialization += () => Console.WriteLine("BosunReporter: Running metrics snapshot."); collector.AfterSerialization += info => Console.WriteLine($"BosunReporter: Metric Snapshot wrote {info.Count} metrics ({info.BytesWritten} bytes) to {info.Endpoint} in {info.Duration.TotalMilliseconds.ToString("0.##")}ms"); collector.AfterSend += info => { if (info.Endpoint == LocalEndpointKey) { foreach (var reading in localHandler.GetReadings()) { Console.WriteLine($"{reading.Name}{reading.Suffix}@{reading.Timestamp:s} {reading.Value}"); } } Console.WriteLine($"BosunReporter: Payload {info.PayloadType} - {info.BytesWritten} bytes posted to endpoint {info.Endpoint} in {info.Duration.TotalMilliseconds.ToString("0.##")}ms ({(info.Successful ? "SUCCESS" : "FAILED")})"); }; collector.BindMetric("my_counter", "increments", typeof(TestCounter)); var counter = collector.GetMetric <TestCounter>("my_counter", "increments", "This is meaningless."); counter.Increment(); counter.Increment(); var gauge = collector.CreateMetric("gauge", "watts", "Some description of a gauge.", new TestAggregateGauge("1")); if (gauge != collector.GetMetric("gauge", "watts", null, new TestAggregateGauge("1"))) { throw new Exception("WAT?"); } try { collector.CreateMetric("gauge", "watts", "Some description of a gauge.", new TestAggregateGauge("1")); } catch (Exception) { goto SKIP_EXCEPTION; } throw new Exception("CreateMetric should have failed for duplicate metric."); SKIP_EXCEPTION: var gauge2 = collector.GetMetric <CountGauge>("gauge2", "newtons", "Number of newtons currently applied."); for (var i = 0; i < 6; i++) { new Thread(Run).Start(new Tuple <AggregateGauge, AggregateGauge, int>(gauge, gauge2, i)); } var enumCounter = collector.GetMetricGroup <SomeEnum, EnumCounter>("some_enum", "things", "Some of something"); enumCounter.PopulateFromEnum(); Type t; string u; if (collector.TryGetMetricInfo("gauge2", out t, out u)) { Console.WriteLine(t); Console.WriteLine(u); } else { Console.WriteLine("NOOOOO!!!!!"); } var si = 0; var snapshot = collector.GetMetric("my_snapshot", "snappys", "Snap snap snap.", new SnapshotGauge(() => ++ si % 5)); var group = collector.GetMetricGroup <string, TestGroupGauge>("test_group", "tests", "These gauges are for testing."); group.Add("low").Description = "Low testing."; group.Add("medium").Description = "Medium testing."; group.Add("high").Description = "High testing."; var sampler = collector.GetMetric("sampler", "french fries", "Collect them all.", new SamplingGauge()); var eventGauge = collector.GetMetric("event", "count", "How many last time.", new EventGauge()); var converted = collector.CreateMetric("convert_test", "units", "Checking to see if the tag value converter works.", new ConvertedTagsTestCounter("ThingsAndStuff")); var noHost = collector.CreateMetric <ExcludeHostCounter>("no_host", "units", "Shouldn't have a host tag."); var externalCounter = collector.GetMetricGroup <SomeEnum, TestExternalCounter>("external.test", "units", "Should aggregate externally."); externalCounter.PopulateFromEnum(); // var externalNoTags = collector.CreateMetric<ExternalNoTagsCounter>("external.no_tags", "units", "Shouldn't have any tags except relay."); var lotsOfCounters = new List <Counter>(); for (var i = 0; i < 400; i++) { lotsOfCounters.Add(collector.GetMetric("counter_" + i, "counts", "Testing lots of counters", new Counter())); } var sai = 0; var random = new Random(); s_samplerTask = Task.Run(async() => { while (true) { await Task.Delay(100); sampler.Record(++sai % 35); eventGauge.Record(sai % 35); group["low"].Record(random.Next(0, 10)); group["medium"].Record(random.Next(10, 20)); group["high"].Record(random.Next(20, 30)); enumCounter[SomeEnum.One].Increment(); enumCounter[SomeEnum.Two].Increment(2); enumCounter[SomeEnum.Three].Increment(3); enumCounter[SomeEnum.Four].Increment(4); externalCounter[SomeEnum.One].Increment(); if (sai % 2 == 0) { externalCounter[SomeEnum.Two].Increment(); } if (sai % 3 == 0) { externalCounter[SomeEnum.Three].Increment(); } if (sai % 4 == 0) { externalCounter[SomeEnum.Four].Increment(); } foreach (var lotsOfCounter in lotsOfCounters) { lotsOfCounter.Increment(random.Next(0, 5)); } // externalNoTags.Increment(); converted.Increment(); noHost.Increment(); if (sai == 1000 || s_cancellationTokenSource.IsCancellationRequested) { collector.Shutdown(); break; } } }); Console.CancelKeyPress += (object sender, ConsoleCancelEventArgs e) => { s_cancellationTokenSource.Cancel(); }; try { await s_samplerTask; } catch (TaskCanceledException) { // meh, ignore } }
static void Main(string[] args) { Debug.Listeners.Add(new TextWriterTraceListener(Console.Out)); Debug.AutoFlush = true; Func <Uri> getUrl = () => { return(new Uri("http://192.168.99.100:8070/")); // return new Uri("http://127.0.0.1:1337/"); }; // for testing minimum event threshold // AggregateGauge.GetDefaultMinimumEvents = () => 1306000; var options = new BosunOptions() { MetricsNamePrefix = "bret.", GetBosunUrl = getUrl, ThrowOnPostFail = true, ReportingInterval = 5, PropertyToTagName = NameTransformers.CamelToLowerSnakeCase, TagValueConverter = (name, value) => name == "converted" ? value.ToLowerInvariant() : value, DefaultTags = new Dictionary <string, string> { { "host", NameTransformers.Sanitize(Environment.MachineName.ToLower()) } } }; var collector = new MetricsCollector(options); collector.OnBackgroundException += exception => { Console.WriteLine("Hey, there was an exception."); Console.WriteLine(exception); }; collector.BeforeSerialization += () => Console.WriteLine("BosunReporter: Running metrics snapshot."); collector.AfterSerialization += info => Console.WriteLine($"BosunReporter: Metric Snapshot took {info.MillisecondsDuration.ToString("0.##")}ms"); collector.AfterPost += info => Console.WriteLine($"BosunReporter: {info.Count} metrics posted to Bosun in {info.MillisecondsDuration.ToString("0.##")}ms ({(info.Successful ? "SUCCESS" : "FAILED")})"); collector.BindMetric("my_counter", "increments", typeof(TestCounter)); var counter = collector.GetMetric <TestCounter>("my_counter", "increments", "This is meaningless."); counter.Increment(); counter.Increment(); var gauge = collector.CreateMetric("gauge", "watts", "Some description of a gauge.", new TestAggregateGauge("1")); if (gauge != collector.GetMetric("gauge", "watts", null, new TestAggregateGauge("1"))) { throw new Exception("WAT?"); } try { collector.CreateMetric("gauge", "watts", "Some description of a gauge.", new TestAggregateGauge("1")); } catch (Exception) { goto SKIP_EXCEPTION; } throw new Exception("CreateMetric should have failed for duplicate metric."); SKIP_EXCEPTION: var gauge2 = collector.GetMetric <AggregateGauge>("gauge2", "newtons", "Number of newtons currently applied."); for (var i = 0; i < 6; i++) { new Thread(Run).Start(new Tuple <AggregateGauge, AggregateGauge, int>(gauge, gauge2, i)); } var enumCounter = collector.GetMetricGroup <SomeEnum, EnumCounter>("some_enum", "things", "Some of something"); enumCounter.PopulateFromEnum(); Type t; string u; if (collector.TryGetMetricInfo("gauge2", out t, out u)) { Console.WriteLine(t); Console.WriteLine(u); } else { Console.WriteLine("NOOOOO!!!!!"); } var si = 0; var snapshot = collector.GetMetric("my_snapshot", "snappys", "Snap snap snap.", new SnapshotGauge(() => ++ si % 5)); var group = collector.GetMetricGroup <string, TestGroupGauge>("test_group", "tests", "These gauges are for testing."); group.Add("low").Description = "Low testing."; group.Add("medium").Description = "Medium testing."; group.Add("high").Description = "High testing."; var sampler = collector.GetMetric("sampler", "french fries", "Collect them all.", new SamplingGauge()); var eventGauge = collector.GetMetric("event", "count", "How many last time.", new EventGauge()); var converted = collector.CreateMetric("convert_test", "units", "Checking to see if the tag value converter works.", new ConvertedTagsTestCounter("ThingsAndStuff")); var noHost = collector.CreateMetric <ExcludeHostCounter>("no_host", "units", "Shouldn't have a host tag."); var externalCounter = collector.GetMetricGroup <SomeEnum, TestExternalCounter>("external.test", "units", "Should aggregate externally."); externalCounter.PopulateFromEnum(); // var externalNoTags = collector.CreateMetric<ExternalNoTagsCounter>("external.no_tags", "units", "Shouldn't have any tags except relay."); var sai = 0; var random = new Random(); _samplerTimer = new Timer(o => { sampler.Record(++sai % 35); eventGauge.Record(sai % 35); group["low"].Record(random.Next(0, 10)); group["medium"].Record(random.Next(10, 20)); group["high"].Record(random.Next(20, 30)); enumCounter[SomeEnum.One].Increment(); enumCounter[SomeEnum.Two].Increment(2); enumCounter[SomeEnum.Three].Increment(3); enumCounter[SomeEnum.Four].Increment(4); externalCounter[SomeEnum.One].Increment(); if (sai % 2 == 0) { externalCounter[SomeEnum.Two].Increment(); } if (sai % 3 == 0) { externalCounter[SomeEnum.Three].Increment(); } if (sai % 4 == 0) { externalCounter[SomeEnum.Four].Increment(); } // externalNoTags.Increment(); converted.Increment(); noHost.Increment(); if (sai == 40) { collector.Shutdown(); Environment.Exit(0); } }, null, 1000, 1000); Thread.Sleep(4000); collector.UpdateDefaultTags(new Dictionary <string, string> { { "host", NameTransformers.Sanitize(Environment.MachineName.ToLower()) } }); // Thread.Sleep(4000); // collector.UpdateDefaultTags(new Dictionary<string, string>() { { "host", "test_env" } }); }
static void Main(string[] args) { Debug.Listeners.Add(new TextWriterTraceListener(Console.Out)); Debug.AutoFlush = true; Func<Uri> getUrl = () => { return new Uri("http://192.168.99.100:8070/"); }; // for testing minimum event threshold // AggregateGauge.GetDefaultMinimumEvents = () => 306000; var options = new BosunOptions() { MetricsNamePrefix = "bret.", GetBosunUrl = getUrl, ThrowOnPostFail = true, ReportingInterval = 5, PropertyToTagName = NameTransformers.CamelToLowerSnakeCase, TagValueConverter = (name, value) => name == "converted" ? value.ToLowerInvariant() : value, DefaultTags = new Dictionary<string, string> { {"host", NameTransformers.Sanitize(Environment.MachineName.ToLower())} } }; var collector = new MetricsCollector(options); collector.OnBackgroundException += exception => { Console.WriteLine("Hey, there was an exception."); Console.WriteLine(exception); }; collector.BeforeSerialization += () => Debug.WriteLine("BosunReporter: Running metrics snapshot."); collector.AfterSerialization += info => Debug.WriteLine($"BosunReporter: Metric Snapshot took {info.MillisecondsDuration.ToString("0.##")}ms"); collector.AfterPost += info => Debug.WriteLine($"BosunReporter: {info.Count} metrics posted to Bosun in {info.MillisecondsDuration.ToString("0.##")}ms ({(info.Successful ? "SUCCESS" : "FAILED")})"); collector.BindMetric("my_counter", "increments", typeof(TestCounter)); var counter = collector.GetMetric<TestCounter>("my_counter", "increments", "This is meaningless."); counter.Increment(); counter.Increment(); var gauge = collector.CreateMetric("gauge", "watts", "Some description of a gauge.", new TestAggregateGauge("1")); if (gauge != collector.GetMetric("gauge", "watts", null, new TestAggregateGauge("1"))) throw new Exception("WAT?"); try { collector.CreateMetric("gauge", "watts", "Some description of a gauge.", new TestAggregateGauge("1")); } catch(Exception) { goto SKIP_EXCEPTION; } throw new Exception("CreateMetric should have failed for duplicate metric."); SKIP_EXCEPTION: var gauge2 = collector.GetMetric<AggregateGauge>("gauge2", "newtons", "Number of newtons currently applied."); for (var i = 0; i < 6; i++) { new Thread(Run).Start(new Tuple<AggregateGauge, AggregateGauge, int>(gauge, gauge2, i)); } var enumCounter = collector.GetMetricGroup<SomeEnum, EnumCounter>("some_enum", "things", "Some of something"); enumCounter.PopulateFromEnum(); Type t; string u; if (collector.TryGetMetricInfo("gauge2", out t, out u)) { Console.WriteLine(t); Console.WriteLine(u); } else { Console.WriteLine("NOOOOO!!!!!"); } var si = 0; var snapshot = collector.GetMetric("my_snapshot", "snappys", "Snap snap snap.", new SnapshotGauge(() => ++si % 5)); var group = collector.GetMetricGroup<string, TestGroupGauge>("test_group", "tests", "These gauges are for testing."); group.Add("low").Description = "Low testing."; group.Add("medium").Description = "Medium testing."; group.Add("high").Description = "High testing."; var sampler = collector.GetMetric("sampler", "french fries", "Collect them all.", new SamplingGauge()); var eventGauge = collector.GetMetric("event", "count", "How many last time.", new EventGauge()); var converted = collector.CreateMetric("convert_test", "units", "Checking to see if the tag value converter works.", new ConvertedTagsTestCounter("ThingsAndStuff")); var sai = 0; var random = new Random(); _samplerTimer = new Timer(o => { sampler.Record(++sai%35); eventGauge.Record(sai%35); group["low"].Record(random.Next(0, 10)); group["medium"].Record(random.Next(10, 20)); group["high"].Record(random.Next(20, 30)); enumCounter[SomeEnum.One].Increment(); enumCounter[SomeEnum.Two].Increment(2); enumCounter[SomeEnum.Three].Increment(3); enumCounter[SomeEnum.Four].Increment(4); converted.Increment(); if (sai == 40) { collector.Shutdown(); Environment.Exit(0); } }, null, 1000, 1000); Thread.Sleep(4000); collector.UpdateDefaultTags(new Dictionary<string, string> { { "host", NameTransformers.Sanitize(Environment.MachineName.ToLower()) } }); // Thread.Sleep(4000); // collector.UpdateDefaultTags(new Dictionary<string, string>() { { "host", "test_env" } }); }
public async Task FailedSend_OnlyAffectsFailedHandler() { var completionEvent = new ManualResetEventSlim(false); var failHandler = new TestMetricHandler( (_, __, ___) => throw new MetricPostException(new Exception("Boom!")) ) { MaxPayloadCount = 10 }; var successHandler = new TestMetricHandler( async(handler, type, sequence) => { if (type != PayloadType.Counter) { return; } Assert.Equal(PayloadType.Counter, type); using (var memoryStream = new MemoryStream()) { await memoryStream.WriteAsync(sequence); // verify that the bytes written to the stream match what we received var actualBytes = memoryStream.ToArray(); var expectedBytes = handler.GetNextWrittenChunk(PayloadType.Counter); while (expectedBytes.Length < actualBytes.Length) { // collect bytes until we have no more to get expectedBytes = expectedBytes.Concat(handler.GetNextWrittenChunk(PayloadType.Counter)).ToArray(); } Assert.Equal(expectedBytes, actualBytes); } if (!handler.HasPendingChunks(PayloadType.Counter)) { completionEvent.Set(); } } ) { MaxPayloadCount = 1000 }; var collector = new MetricsCollector( new MetricsCollectorOptions(_ => { }) { DefaultTags = new Dictionary <string, string> { ["host"] = Environment.MachineName }, Endpoints = new[] { new MetricEndpoint("Failed", failHandler), new MetricEndpoint("Success", successHandler) }, SnapshotInterval = TimeSpan.FromMilliseconds(20), RetryInterval = TimeSpan.Zero } ); var metrics = new Counter[10]; for (var i = 0; i < metrics.Length; i++) { metrics[i] = collector.CreateMetric <Counter>("metric_" + i, "requests", string.Empty); } // report some metrics foreach (var metric in metrics) { metric.Increment(); // waiting for the snapshot interval before we send out next batch of data await Task.Delay(20); } // give some time for everything to complete var completed = completionEvent.Wait(TimeSpan.FromMilliseconds(2000)); var pendingEvents = successHandler.GetPendingChunks(PayloadType.Counter); collector.Shutdown(); Assert.True(completed, $"Success handler did not complete successfully. {pendingEvents} pending"); } }