public void InfluxReport_CanAddRecords_ForTimer()
        {
            var config      = new InfluxConfig("localhost", "testdb");
            var writer      = new InfluxdbTestWriter(config); config.Writer = writer;
            var report      = new InfluxdbHttpReport(config);
            var context     = new DefaultMetricsContext("TestContext");
            var precision   = config.Precision ?? InfluxConfig.Default.Precision;
            var metricsData = context.DataProvider.CurrentMetricsData;
            var timer       = context.Timer("test_timer", Unit.Bytes, SamplingType.Default, TimeUnit.Seconds, TimeUnit.Seconds, new MetricTags("key1=value1,tag2,tag3,key4=value4"));

            // add normally
            timer.Record(100, TimeUnit.Seconds);
            metricsData = context.DataProvider.CurrentMetricsData;
            report.RunReport(metricsData, hsFunc, CancellationToken.None);
            writer.LastBatch.Should().HaveCount(1);

            var expTime = InfluxLineProtocol.FormatTimestamp(metricsData.Timestamp, precision);

            writer.LastBatch[0].ToLineProtocol(precision).Should().StartWith($@"testcontext.test_timer,key1=value1,key4=value4 active_sessions=0i,total_time=100i,count=1i,").And.EndWith($@",1_min_rate=0,5_min_rate=0,15_min_rate=0,last=100,min=100,mean=100,max=100,stddev=0,median=100,sample_size=1i,percentile_75%=100,percentile_95%=100,percentile_98%=100,percentile_99%=100,percentile_99.9%=100 {expTime}");

            // add with set item
            timer.Record(50, TimeUnit.Seconds, "item1,item2=ival2,item3=ival3");
            metricsData = context.DataProvider.CurrentMetricsData;
            report.RunReport(metricsData, hsFunc, CancellationToken.None);
            writer.LastBatch.Should().HaveCount(1);

            expTime = InfluxLineProtocol.FormatTimestamp(metricsData.Timestamp, precision);
            writer.LastBatch[0].ToLineProtocol(precision).Should().StartWith($@"testcontext.test_timer,key1=value1,key4=value4 active_sessions=0i,total_time=150i,count=2i,").And.EndWith($@",1_min_rate=0,5_min_rate=0,15_min_rate=0,last=50,min=50,mean=75,max=100,stddev=25,median=100,sample_size=2i,percentile_75%=100,percentile_95%=100,percentile_98%=100,percentile_99%=100,percentile_99.9%=100 {expTime}");
        }
        public void InfluxReport_CanAddRecords_ForHealthCheck()
        {
            var config      = new InfluxConfig("localhost", "testdb");
            var writer      = new InfluxdbTestWriter(config); config.Writer = writer;
            var report      = new InfluxdbHttpReport(config);
            var context     = new DefaultMetricsContext("TestContext");
            var precision   = config.Precision ?? InfluxConfig.Default.Precision;
            var metricsData = context.DataProvider.CurrentMetricsData;

            HealthChecks.UnregisterAllHealthChecks();
            HealthChecks.RegisterHealthCheck("Health Check 1", () => HealthCheckResult.Healthy($"Healthy check!"));
            HealthChecks.RegisterHealthCheck("Health Check 2", () => HealthCheckResult.Unhealthy($"Unhealthy check!"));
            HealthChecks.RegisterHealthCheck("Health Check 3,tag3=key3", () => HealthCheckResult.Healthy($"Healthy check!"));
            HealthChecks.RegisterHealthCheck("Health Check 4,tag 4=key 4", () => HealthCheckResult.Healthy($"Healthy check!"));
            HealthChecks.RegisterHealthCheck("Name=Health Check 5,tag5=key5", () => HealthCheckResult.Healthy($"Healthy check!"));

            metricsData = context.DataProvider.CurrentMetricsData;
            report.RunReport(metricsData, () => HealthChecks.GetStatus(), CancellationToken.None);
            HealthChecks.UnregisterAllHealthChecks();             // unreg first in case something below throws
            writer.LastBatch.Should().HaveCount(5);

            var expTime = InfluxLineProtocol.FormatTimestamp(metricsData.Timestamp, precision);

            writer.LastBatch[0].ToLineProtocol(precision).Should().Be($@"health_checks,name=health_check_1 ishealthy=True,message=""Healthy check!"" {expTime}");
            writer.LastBatch[1].ToLineProtocol(precision).Should().Be($@"health_checks,name=health_check_2 ishealthy=False,message=""Unhealthy check!"" {expTime}");
            writer.LastBatch[2].ToLineProtocol(precision).Should().Be($@"health_checks,name=health_check_3,tag3=key3 ishealthy=True,message=""Healthy check!"" {expTime}");
            writer.LastBatch[3].ToLineProtocol(precision).Should().Be($@"health_checks,name=health_check_4,tag_4=key\ 4 ishealthy=True,message=""Healthy check!"" {expTime}");
            writer.LastBatch[4].ToLineProtocol(precision).Should().Be($@"health_checks,name=health\ check\ 5,tag5=key5 ishealthy=True,message=""Healthy check!"" {expTime}");
        }
        public void InfluxReport_CanAddRecords_ForHistogram()
        {
            var config      = new InfluxConfig("localhost", "testdb");
            var writer      = new InfluxdbTestWriter(config); config.Writer = writer;
            var report      = new InfluxdbHttpReport(config);
            var context     = new DefaultMetricsContext("TestContext");
            var precision   = config.Precision ?? InfluxConfig.Default.Precision;
            var metricsData = context.DataProvider.CurrentMetricsData;
            var hist        = context.Histogram("test_hist", Unit.Bytes, SamplingType.Default, new MetricTags("key1=value1,tag2,tag3,key4=value4"));

            // add normally
            hist.Update(300);
            metricsData = context.DataProvider.CurrentMetricsData;
            report.RunReport(metricsData, hsFunc, CancellationToken.None);
            writer.LastBatch.Should().HaveCount(1);

            var expTime = InfluxLineProtocol.FormatTimestamp(metricsData.Timestamp, precision);

            writer.LastBatch[0].ToLineProtocol(precision).Should().Be($@"testcontext.test_hist,key1=value1,key4=value4 count=1i,last=300,min=300,mean=300,max=300,stddev=0,median=300,sample_size=1i,percentile_75%=300,percentile_95%=300,percentile_98%=300,percentile_99%=300,percentile_99.9%=300 {expTime}");

            // add with set item
            hist.Update(100, "item1,item2=ival2,item3=ival3");
            metricsData = context.DataProvider.CurrentMetricsData;
            report.RunReport(metricsData, hsFunc, CancellationToken.None);
            writer.LastBatch.Should().HaveCount(1);

            expTime = InfluxLineProtocol.FormatTimestamp(metricsData.Timestamp, precision);
            writer.LastBatch[0].ToLineProtocol(precision).Should().Be($@"testcontext.test_hist,key1=value1,key4=value4 count=2i,last=100,min=100,mean=200,max=300,stddev=100,median=300,sample_size=2i,percentile_75%=300,percentile_95%=300,percentile_98%=300,percentile_99%=300,percentile_99.9%=300 {expTime}");
        }
        public void InfluxReport_CanAddRecords_ForMeter()
        {
            var config      = new InfluxConfig("localhost", "testdb");
            var writer      = new InfluxdbTestWriter(config); config.Writer = writer;
            var report      = new InfluxdbHttpReport(config);
            var context     = new DefaultMetricsContext("TestContext");
            var precision   = config.Precision ?? InfluxConfig.Default.Precision;
            var metricsData = context.DataProvider.CurrentMetricsData;
            var meter       = context.Meter("test_meter", Unit.Bytes, TimeUnit.Seconds, new MetricTags("key1=value1,tag2,tag3,key4=value4"));

            // add normally
            meter.Mark(300);
            metricsData = context.DataProvider.CurrentMetricsData;
            report.RunReport(metricsData, hsFunc, CancellationToken.None);
            writer.LastBatch.Should().HaveCount(1);

            var expTime = InfluxLineProtocol.FormatTimestamp(metricsData.Timestamp, precision);

            writer.LastBatch[0].ToLineProtocol(precision).Should().StartWith($@"testcontext.test_meter,key1=value1,key4=value4 count=300i,mean_rate=").And.EndWith($@",1_min_rate=0,5_min_rate=0,15_min_rate=0 {expTime}");;

            // add with set item
            meter.Mark("item1,item2=ival2,item3=ival3", 100);
            metricsData = context.DataProvider.CurrentMetricsData;
            report.RunReport(metricsData, hsFunc, CancellationToken.None);
            writer.LastBatch.Should().HaveCount(2);

            expTime = InfluxLineProtocol.FormatTimestamp(metricsData.Timestamp, precision);
            writer.LastBatch[0].ToLineProtocol(precision).Should().StartWith($@"testcontext.test_meter,key1=value1,key4=value4 count=400i,mean_rate=").And.EndWith($@",1_min_rate=0,5_min_rate=0,15_min_rate=0 {expTime}");
            writer.LastBatch[1].ToLineProtocol(precision).Should().StartWith($@"testcontext.test_meter,item2=ival2,item3=ival3,key1=value1,key4=value4 count=100i,percent=25,mean_rate=").And.EndWith($@",1_min_rate=0,5_min_rate=0,15_min_rate=0 {expTime}");
        }
        public void InfluxBatch_FormatsTo_LineProtocol()
        {
            var testNow    = new DateTime(2016, 6, 1, 0, 0, 0, DateTimeKind.Utc);
            var testTags   = TagTestCases.Select(tc => tc.Tag);
            var testFields = FieldTestCases.Select(tc => tc.Field);
            var precision  = InfluxConfig.Default.Precision;
            var expTime    = InfluxLineProtocol.FormatTimestamp(testNow, precision);

            // test with empty batch
            InfluxBatch batch = new InfluxBatch();

            batch.ToLineProtocol(precision).Should().BeEmpty();

            // test with single record
            batch.Add(new InfluxRecord("test_name", new[] { new InfluxTag("tag1", "value1") }, new[] { new InfluxField("field1", 123456) }));
            batch.ToLineProtocol(precision).Should().NotEndWith("\n").And.Be(@"test_name,tag1=value1 field1=123456i");
            batch.Clear();

            // test with multiple records
            batch.Add(new InfluxRecord("test_name1", new[] { new InfluxTag("tag1", "value1") }, new[] { new InfluxField("field1", 123456) }));
            batch.Add(new InfluxRecord("test_name2", new[] { new InfluxTag("tag2", "value2") }, new[] { new InfluxField("field2", 234561) }));
            batch.Add(new InfluxRecord("test_name3", new[] { new InfluxTag("tag3", "value3") }, new[] { new InfluxField("field3", 345612) }, testNow));
            batch.Add(new InfluxRecord("test_name4", new[] { new InfluxTag("tag4", "value4") }, new[] { new InfluxField("field4", 456123) }, testNow));
            batch.Add(new InfluxRecord("test_name5", new[] { new InfluxTag("tag5", "value5") }, new[] { new InfluxField("field5", 561234) }, testNow));

            String expOutput = String.Join("\n",
                                           $@"test_name1,tag1=value1 field1=123456i",
                                           $@"test_name2,tag2=value2 field2=234561i",
                                           $@"test_name3,tag3=value3 field3=345612i {expTime}",
                                           $@"test_name4,tag4=value4 field4=456123i {expTime}",
                                           $@"test_name5,tag5=value5 field5=561234i {expTime}"
                                           );

            batch.ToLineProtocol(precision).Should().NotEndWith("\n").And.Be(expOutput);
        }
        public void InfluxRecord_FormatsTo_LineProtocol()
        {
            // test values
            var testNow    = new DateTime(2016, 6, 1, 0, 0, 0, DateTimeKind.Utc);
            var testTags   = TagTestCases.Select(tc => tc.Tag);
            var testFields = FieldTestCases.Select(tc => tc.Field);
            var precision  = InfluxConfig.Default.Precision;

            // expected values
            String expTime   = InfluxLineProtocol.FormatTimestamp(testNow, precision);
            String expTags   = String.Join(",", TagTestCases.Select(tc => tc.Output));
            String expFields = String.Join(",", FieldTestCases.Select(tc => tc.Output));
            String expOutput = String.Format("test_name,{0} {1} {2}", expTags, expFields, expTime);

            // assert line values match expected
            new InfluxRecord("name spaces", new[] { new InfluxField("field1", 123456) })
            .ToLineProtocol(precision).Should().Be(@"name\ spaces field1=123456i");
            new InfluxRecord("test_name", new[] { new InfluxTag("tag1", "value1") }, new[] { new InfluxField("field1", 123456) })
            .ToLineProtocol(precision).Should().Be(@"test_name,tag1=value1 field1=123456i");
            new InfluxRecord("test_name", new[] { new InfluxTag("tag1", "value1"), new InfluxTag("tag2", "value2") }, new[] { new InfluxField("field1", 123456), new InfluxField("field2", true) })
            .ToLineProtocol(precision).Should().Be(@"test_name,tag1=value1,tag2=value2 field1=123456i,field2=True");
            new InfluxRecord("test_name", new[] { new InfluxTag("tag1", "value1") }, new[] { new InfluxField("field1", "test string") }, testNow)
            .ToLineProtocol(precision).Should().Be($@"test_name,tag1=value1 field1=""test string"" {expTime}");
            new InfluxRecord("test_name", testTags, testFields, testNow)
            .ToLineProtocol(precision).Should().Be(expOutput);
        }
        public void InfluxReport_CanAddRecords_ForGauge()
        {
            var config      = new InfluxConfig("localhost", "testdb");
            var writer      = new InfluxdbTestWriter(config); config.Writer = writer;
            var report      = new InfluxdbHttpReport(config);
            var context     = new DefaultMetricsContext("TestContext");
            var precision   = config.Precision ?? InfluxConfig.Default.Precision;
            var metricsData = context.DataProvider.CurrentMetricsData;

            report.RunReport(metricsData, hsFunc, CancellationToken.None);
            writer.LastBatch.Should().BeEmpty("Because running a report with no metrics should not result in any records.");

            context.Gauge("test_gauge", () => 123.456, Unit.Bytes, new MetricTags("key1=value1,tag2,tag3,key4=value4"));
            metricsData = context.DataProvider.CurrentMetricsData;
            report.RunReport(metricsData, hsFunc, CancellationToken.None);
            writer.LastBatch.Should().HaveCount(1);

            var expTime = InfluxLineProtocol.FormatTimestamp(metricsData.Timestamp, precision);

            writer.LastBatch[0].ToLineProtocol(precision).Should().Be($@"testcontext.test_gauge,key1=value1,key4=value4 value=123.456 {expTime}");
        }