InfluxDB.Client 4.16.0-dev.13775

This is a prerelease version of InfluxDB.Client.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package InfluxDB.Client --version 4.16.0-dev.13775
NuGet\Install-Package InfluxDB.Client -Version 4.16.0-dev.13775
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="InfluxDB.Client" Version="4.16.0-dev.13775" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add InfluxDB.Client --version 4.16.0-dev.13775
#r "nuget: InfluxDB.Client, 4.16.0-dev.13775"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install InfluxDB.Client as a Cake Addin
#addin nuget:?package=InfluxDB.Client&version=4.16.0-dev.13775&prerelease

// Install InfluxDB.Client as a Cake Tool
#tool nuget:?package=InfluxDB.Client&version=4.16.0-dev.13775&prerelease

InfluxDB.Client

CircleCI

The reference client that allows query, write and management (bucket, organization, users) for the InfluxDB 2.x.

Documentation

This section contains links to the client library documentation.

Features

Queries

For querying data we use QueryApi that allow perform asynchronous, streaming, synchronous and also use raw query response.

Asynchronous Query

The asynchronous query is not intended for large query results because the Flux response can be potentially unbound.

using System;
using System.Threading.Tasks;
using InfluxDB.Client;

namespace Examples
{
    public static class AsynchronousQuery
    {
        private static readonly string Token = "";

        public static async Task Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", Token);

            var flux = "from(bucket:\"temperature-sensors\") |> range(start: 0)";
            
            var queryApi = client.GetQueryApi();

            //
            // QueryData
            //
            var tables = await queryApi.QueryAsync(flux, "org_id");
            tables.ForEach(table =>
            {
                table.Records.ForEach(record =>
                {
                    Console.WriteLine($"{record.GetTime()}: {record.GetValueByKey("_value")}");
                });
            });
        }        
    }
}

The asynchronous query offers a possibility map FluxRecords to POCO:

using System;
using System.Threading.Tasks;
using InfluxDB.Client;
using InfluxDB.Client.Core;

namespace Examples
{
    public static class AsynchronousQuery
    {
        private static readonly string Token = "";

        public static async Task Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", Token);

            var flux = "from(bucket:\"temperature-sensors\") |> range(start: 0)";
            
            var queryApi = client.GetQueryApi();

            //
            // QueryData
            //
            var temperatures = await queryApi.QueryAsync<Temperature>(flux, "org_id");
            temperatures.ForEach(temperature =>
            {
                Console.WriteLine($"{temperature.Location}: {temperature.Value} at {temperature.Time}");
            });
        }  
        
        [Measurement("temperature")]
        private class Temperature
        {
            [Column("location", IsTag = true)] public string Location { get; set; }

            [Column("value")] public double Value { get; set; }

            [Column(IsTimestamp = true)] public DateTime Time { get; set; }
        }
    }
}

Streaming Query

The Streaming query offers possibility to process unbound query and allow user to handle exceptions, stop receiving more results and notify that all data arrived.

using System;
using System.Threading.Tasks;
using InfluxDB.Client;

namespace Examples
{
    public static class StreamingQuery
    {
        private static readonly string Token = "";

        public static async Task Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", Token);

            var flux = "from(bucket:\"temperature-sensors\") |> range(start: 0)";

            var queryApi = client.GetQueryApi();

            //
            // QueryData
            //
            await queryApi.QueryAsync(flux, record =>
            {
                //
                // The callback to consume a FluxRecord.
                //
                Console.WriteLine($"{record.GetTime()}: {record.GetValueByKey("_value")}");
            }, exception =>
            {
                //
                // The callback to consume any error notification.
                //
                Console.WriteLine($"Error occurred: {exception.Message}");
            }, () =>
            {
                //
                // The callback to consume a notification about successfully end of stream.
                //
                Console.WriteLine("Query completed");
            }, "org_id");
        }
    }
}

And there is also a possibility map FluxRecords to POCO:

using System;
using System.Threading.Tasks;
using InfluxDB.Client;
using InfluxDB.Client.Core;

namespace Examples
{
    public static class StreamingQuery
    {
        private static readonly string Token = "";

        public static async Task Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", Token);

            var flux = "from(bucket:\"temperature-sensors\") |> range(start: 0)";
            
            var queryApi = client.GetQueryApi();

            //
            // QueryData
            //
            await queryApi.QueryAsync<Temperature>(flux, temperature =>
            {
                //
                // The callback to consume a FluxRecord mapped to POCO.
                //
                Console.WriteLine($"{temperature.Location}: {temperature.Value} at {temperature.Time}");
            }, org: "org_id");
        }  
        
        [Measurement("temperature")]
        private class Temperature
        {
            [Column("location", IsTag = true)] public string Location { get; set; }

            [Column("value")] public double Value { get; set; }

            [Column(IsTimestamp = true)] public DateTime Time { get; set; }
        }
    }
}

Raw Query

The Raw query allows direct processing original CSV response:

using System;
using System.Threading.Tasks;
using InfluxDB.Client;

namespace Examples
{
    public static class RawQuery
    {
        private static readonly string Token = "";

        public static async Task Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", Token);

            var flux = "from(bucket:\"temperature-sensors\") |> range(start: 0)";

            var queryApi = client.GetQueryApi();

            //
            // QueryData
            //
            var csv = await queryApi.QueryRawAsync(flux, org: "org_id");
            
            Console.WriteLine($"CSV response: {csv}");
        }
    }
}

The Streaming version allows processing line by line:

using System;
using System.Threading.Tasks;
using InfluxDB.Client;

namespace Examples
{
    public static class RawQueryAsynchronous
    {
        private static readonly string Token = "";

        public static async Task Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", Token);

            var flux = "from(bucket:\"temperature-sensors\") |> range(start: 0)";

            var queryApi = client.GetQueryApi();

            //
            // QueryData
            //
            await queryApi.QueryRawAsync(flux, line =>
            {
                //
                // The callback to consume a line of CSV response
                //
                Console.WriteLine($"Response: {line}");
            }, org: "org_id");
        }
    }
}

Synchronous query

The synchronous query is not intended for large query results because the response can be potentially unbound.

using System;
using InfluxDB.Client;

namespace Examples
{
    public static class SynchronousQuery
    {
        public static void Main()
        {
            using var client = new InfluxDBClient("http://localhost:9999", "my-token");

            const string query = "from(bucket:\"my-bucket\") |> range(start: 0)";
           
            //
            // QueryData
            //
            var queryApi = client.GetQueryApiSync();
            var tables = queryApi.QuerySync(query, "my-org");
            
            //
            // Process results
            //
            tables.ForEach(table =>
            {
                table.Records.ForEach(record =>
                {
                    Console.WriteLine($"{record.GetTime()}: {record.GetValueByKey("_value")}");
                });
            });
        }
    }
}

Writes

For writing data we use WriteApi or WriteApiAsync which is simplified version of WriteApi without batching support.

WriteApi supports:

  1. writing data using InfluxDB Line Protocol, Data Point, POCO
  2. use batching for writes
  3. produces events that allow user to be notified and react to this events
    • WriteSuccessEvent - published when arrived the success response from server
    • WriteErrorEvent - published when occurs a unhandled exception from server
    • WriteRetriableErrorEvent - published when occurs a retriable error from server
    • WriteRuntimeExceptionEvent - published when occurs a runtime exception in background batch processing
  4. use GZIP compression for data

The writes are processed in batches which are configurable by WriteOptions:

Property Description Default Value
BatchSize the number of data point to collect in batch 1000
FlushInterval the number of milliseconds before the batch is written 1000
JitterInterval the number of milliseconds to increase the batch flush interval by a random amount 0
RetryInterval the number of milliseconds to retry unsuccessful write. The retry interval is used when the InfluxDB server does not specify "Retry-After" header. 5000
MaxRetries the number of max retries when write fails 3
MaxRetryDelay the maximum delay between each retry attempt in milliseconds 125_000
ExponentialBase the base for the exponential retry delay, the next delay is computed using random exponential backoff as a random value within the interval retryInterval * exponentialBase^(attempts-1) and retryInterval * exponentialBase^(attempts). Example for retryInterval=5_000, exponentialBase=2, maxRetryDelay=125_000, maxRetries=5 Retry delays are random distributed values within the ranges of [5_000-10_000, 10_000-20_000, 20_000-40_000, 40_000-80_000, 80_000-125_000] 2

Writing data

By POCO

Write Measurement into specified bucket:

using System;
using InfluxDB.Client;
using InfluxDB.Client.Api.Domain;
using InfluxDB.Client.Core;

namespace Examples
{
    public static class WritePoco
    {
        private static readonly string Token = "";

        public static void Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", Token);

            //
            // Write Data
            //
            using (var writeApi = client.GetWriteApi())
            {
                //
                // Write by POCO
                //
                var temperature = new Temperature {Location = "south", Value = 62D, Time = DateTime.UtcNow};

                writeApi.WriteMeasurement(temperature, WritePrecision.Ns, "bucket_name", "org_id");
            }
        }
        
        [Measurement("temperature")]
        private class Temperature
        {
            [Column("location", IsTag = true)] public string Location { get; set; }

            [Column("value")] public double Value { get; set; }

            [Column(IsTimestamp = true)] public DateTime Time { get; set; }
        }
    }
}
By Data Point

Write Data point into specified bucket:

using System;
using InfluxDB.Client;
using InfluxDB.Client.Api.Domain;
using InfluxDB.Client.Writes;

namespace Examples
{
    public static class WriteDataPoint
    {
        private static readonly string Token = "";

        public static void Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", Token);

            //
            // Write Data
            //
            using (var writeApi = client.GetWriteApi())
            {
                //
                // Write by Data Point
                
                var point = PointData.Measurement("temperature")
                    .Tag("location", "west")
                    .Field("value", 55D)
                    .Timestamp(DateTime.UtcNow.AddSeconds(-10), WritePrecision.Ns);
                
                writeApi.WritePoint(point, "bucket_name", "org_id");
            }
        }
    }
}

DataPoint Builder Immutability: The builder is immutable therefore won't have side effect when using for building multiple point with single builder.

using System;
using InfluxDB.Client;
using InfluxDB.Client.Api.Domain;
using InfluxDB.Client.Writes;

namespace Examples
{
    public static class WriteDataPoint
    {
        private static readonly string Token = "";

        public static void Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", Token);

            //
            // Write Data
            //
            using (var writeApi = client.GetWriteApi())
            {
                //
                // Write by Data Point
                
                var builder = PointData.Measurement("temperature")
                    .Tag("location", "west");
                
                var pointA = builder
                    .Field("value", 55D)
                    .Timestamp(DateTime.UtcNow.AddSeconds(-10), WritePrecision.Ns);
                
                writeApi.WritePoint(pointA, "bucket_name", "org_id");
                
                var pointB = builder
                    .Field("age", 32)
                    .Timestamp(DateTime.UtcNow, WritePrecision.Ns);
                
                writeApi.WritePoint(pointB, "bucket_name", "org_id");
            }
        }
    }
}
By LineProtocol

Write Line Protocol record into specified bucket:

using InfluxDB.Client;
using InfluxDB.Client.Api.Domain;

namespace Examples
{
    public static class WriteLineProtocol
    {
        private static readonly string Token = "";

        public static void Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", Token);

            //
            // Write Data
            //
            using (var writeApi = client.GetWriteApi())
            {
                //
                //
                // Write by LineProtocol
                //
                writeApi.WriteRecord("temperature,location=north value=60.0", WritePrecision.Ns,"bucket_name", "org_id");
            }
        }
    }
}
Using WriteApiAsync
using System;
using System.Threading.Tasks;
using InfluxDB.Client;
using InfluxDB.Client.Api.Domain;
using InfluxDB.Client.Core;
using InfluxDB.Client.Writes;

namespace Examples
{
    public static class WriteApiAsyncExample
    {   
        [Measurement("temperature")]
        private class Temperature
        {
            [Column("location", IsTag = true)] public string Location { get; set; }

            [Column("value")] public double Value { get; set; }

            [Column(IsTimestamp = true)] public DateTime Time { get; set; }
        }
        
        public static async Task Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", 
                            "my-user", "my-password");

            //
            // Write Data
            //
            var writeApiAsync = client.GetWriteApiAsync();

            //
            //
            // Write by LineProtocol
            //
            await writeApiAsync.WriteRecordAsync("temperature,location=north value=60.0", WritePrecision.Ns,
                "my-bucket", "my-org");

            //
            //
            // Write by Data Point
            //               
            var point = PointData.Measurement("temperature")
                            .Tag("location", "west")
                            .Field("value", 55D)
                            .Timestamp(DateTime.UtcNow.AddSeconds(-10), WritePrecision.Ns);

            await writeApiAsync.WritePointAsync(point, "my-bucket", "my-org");

            //
            // Write by POCO
            //
            var temperature = new Temperature {Location = "south", Value = 62D, Time = DateTime.UtcNow};

            await writeApiAsync.WriteMeasurementAsync(temperature, WritePrecision.Ns, "my-bucket", "my-org");

            //
            // Check written data
            //
            var tables = await influxDbClient.GetQueryApi()
                            .QueryAsync("from(bucket:\"my-bucket\") |> range(start: 0)", "my-org");
            
            tables.ForEach(table =>
            {
                var fluxRecords = table.Records;
                fluxRecords.ForEach(record =>
                {
                    Console.WriteLine($"{record.GetTime()}: {record.GetValue()}");
                });
            });
        }
    }
}
Default Tags

Sometimes is useful to store same information in every measurement e.g. hostname, location, customer. The client is able to use static value, app settings or env variable as a tag value.

The expressions:

  • California Miner - static value
  • ${version} - application settings
  • ${env.hostname} - environment property
Via Configuration file

In a configuration file you are able to specify default tags by tags element.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
        <section name="influx2" type="InfluxDB.Client.Configurations.Influx2, InfluxDB.Client" />
    </configSections>
    <appSettings>
        <add key="SensorVersion" value="v1.00"/>
    </appSettings>
    <influx2 url="http://localhost:8086"
             org="my-org"
             bucket="my-bucket"
             token="my-token"
             logLevel="BODY"
             timeout="10s">
        <tags>
            <tag name="id" value="132-987-655"/>
            <tag name="customer" value="California Miner"/>
            <tag name="hostname" value="${env.Hostname}"/>
            <tag name="sensor-version" value="${SensorVersion}"/>
        </tags>
    </influx2>
</configuration>
Via API
var options = new InfluxDBClientOptions(Url)
{
    Token = token,
    DefaultTags = new Dictionary<string, string>
    {
        {"id", "132-987-655"},
        {"customer", "California Miner"},
    }
};   
options.AddDefaultTag("hostname", "${env.Hostname}")
options.AddDefaultTags(new Dictionary<string, string>{{ "sensor-version", "${SensorVersion}" }})

Both of configurations will produce the Line protocol:

mine-sensor,id=132-987-655,customer="California Miner",hostname=example.com,sensor-version=v1.00 altitude=10

Handle the Events

Events that can be handle by WriteAPI EventHandler are:

  • WriteSuccessEvent - for success response from server
  • WriteErrorEvent - for unhandled exception from server
  • WriteRetriableErrorEvent - for retriable error from server
  • WriteRuntimeExceptionEvent - for runtime exception in background batch processing

Number of events depends on number of data points to collect in batch. The batch size is configured by BatchSize option (default size is 1000) - in case of one data point, event is handled for each point, independently on used writing method (even for mass writing of data like WriteMeasurements, WritePoints and WriteRecords).

Events can be handled by register writeApi.EventHandler or by creating custom EventListener:

Register EventHandler
writeApi.EventHandler += (sender, eventArgs) =>
{
    switch (eventArgs)
    {
        case WriteSuccessEvent successEvent:
            string data = @event.LineProtocol;
            //
            // handle success response from server
            // Console.WriteLine($"{data}");
            //
            break;
        case WriteErrorEvent error:
            string data = @error.LineProtocol;
            string errorMessage = @error.Exception.Message;
            //
            // handle unhandled exception from server
            //
            // Console.WriteLine($"{data}");
            // throw new Exception(errorMessage);
            //
            break;
        case WriteRetriableErrorEvent error:
            string data = @error.LineProtocol;
            string errorMessage = @error.Exception.Message;
            //
            // handle retrievable error from server
            //
            // Console.WriteLine($"{data}");
            // throw new Exception(errorMessage);
            //
            break;
        case WriteRuntimeExceptionEvent error:
            string errorMessage = @error.Exception.Message;
            //
            // handle runtime exception in background batch processing
            // throw new Exception(errorMessage);
            //
            break;
    }
};

//
// Write by LineProtocol
//
writeApi.WriteRecord("influxPoint,writeType=lineProtocol value=11.11" +
    $" {DateTime.UtcNow.Subtract(EpochStart).Ticks * 100}", WritePrecision.Ns, "my-bucket", "my-org");
Custom EventListener

Advantage of using custom Event Listener is possibility of waiting on handled event between different writings - for more info see EventListener.

Delete Data

Delete data from specified bucket:

using InfluxDB.Client;
using InfluxDB.Client.Api.Domain;

namespace Examples
{
    public static class WriteLineProtocol
    {
        private static readonly string Token = "";

        public static void Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", Token);

            //
            // Delete data
            //
            await client.GetDeleteApi().Delete(DateTime.UtcNow.AddMinutes(-1), DateTime.Now, "", "bucket", "org");
        }
    }
}

Filter trace verbose

You can filter out verbose messages from InfluxDB.Client by using TraceListener.

using System;
using System.Diagnostics;
using InfluxDB.Client.Core;

namespace Examples
{
  public static class MyProgram
  {
    public static void Main()
    {
      TraceListener ConsoleOutListener = new TextWriterTraceListener(Console.Out)
      {
        Filter = InfluxDBTraceFilter.SuppressInfluxVerbose(),
      };
      Trace.Listeners.Add(ConsoleOutListener);

      // My code ...
    }
  }
}

Management API

The client has following management API:

API endpoint Description Implementation
/api/v2/authorizations Managing authorization data AuthorizationsApi
/api/v2/buckets Managing bucket data BucketsApi
/api/v2/orgs Managing organization data OrganizationsApi
/api/v2/users Managing user data UsersApi
/api/v2/sources Managing sources SourcesApi
/api/v2/tasks Managing one-off and recurring tasks TasksApi
/api/v2/scrapers Managing ScraperTarget data ScraperTargetsApi
/api/v2/labels Managing resource labels LabelsApi
/api/v2/telegrafs Managing telegraf config data TelegrafsApi
/api/v2/setup Managing onboarding setup InfluxDBClient#OnBoarding()
/ready Get the readiness of a instance at startup InfluxDBClient#Ready()
/health Get the health of an instance anytime during execution InfluxDBClient#Health()

The following example demonstrates how to use a InfluxDB 2.x Management API. For further information see endpoints implementation.

using System;
using System.Collections.Generic;
using System.Linq;
using InfluxDB.Client;
using InfluxDB.Client.Api.Domain;
using Task = System.Threading.Tasks.Task;

namespace Examples
{
    public static class ManagementExample
    {
        public static async Task Main()
        {
            const string url = "http://localhost:8086";
            const string token = "my-token";
            const string org = "my-org";
            
            using var client = new InfluxDBClient(url, token);

            // Find ID of Organization with specified name (PermissionAPI requires ID of Organization).
            var orgId = (await client.GetOrganizationsApi().FindOrganizationsAsync(org: org)).First().Id;

            //
            // Create bucket "iot_bucket" with data retention set to 3,600 seconds
            //
            var retention = new BucketRetentionRules(BucketRetentionRules.TypeEnum.Expire, 3600);

            var bucket = await client.GetBucketsApi().CreateBucketAsync("iot_bucket", retention, orgId);

            //
            // Create access token to "iot_bucket"
            //
            var resource = new PermissionResource(PermissionResource.TypeBuckets, bucket.Id, null,
                orgId);

            // Read permission
            var read = new Permission(Permission.ActionEnum.Read, resource);

            // Write permission
            var write = new Permission(Permission.ActionEnum.Write, resource);

            var authorization = await client.GetAuthorizationsApi()
                .CreateAuthorizationAsync(orgId, new List<Permission> { read, write });

            //
            // Created token that can be use for writes to "iot_bucket"
            //
            Console.WriteLine($"Authorized token to write into iot_bucket: {authorization.Token}");
        }
    }
}

If there is no API implementation for particular service you could create the service by:

var dbrpService = _client.CreateService<DBRPsService>(typeof(DBRPsService));

Advanced Usage

Monitoring & Alerting

The example below show how to create a check for monitoring a stock price. A Slack notification is created if the price is lesser than 35.

Create Threshold Check

The Check set status to Critical if the current value for a stock measurement is lesser than 35.

var org = ...;

var query = "from(bucket: \"my-bucket\") "
        + "|> range(start: v.timeRangeStart, stop: v.timeRangeStop)  "
        + "|> filter(fn: (r) => r._measurement == \"stock\")  "
        + "|> filter(fn: (r) => r.company == \"zyz\")  "
        + "|> aggregateWindow(every: 5s, fn: mean)  "
        + "|> filter(fn: (r) => r._field == \"current\")  "
        + "|> yield(name: \"mean\")";

var threshold = new LesserThreshold(value: 35F, level: CheckStatusLevel.CRIT,
                type: LesserThreshold.TypeEnum.Lesser);

var message = "The Stock price for XYZ is on: ${ r._level } level!";

await Client
    .GetChecksApi()
    .CreateThresholdCheckAsync("XYZ Stock value", query, "5s", message, threshold, org.Id);
Create Slack Notification endpoint
var url = "https://hooks.slack.com/services/x/y/z"; 

var endpoint = await Client
    .GetNotificationEndpointsApi()
    .CreateSlackEndpointAsync("Slack Endpoint", url, org.Id);
Create Notification Rule
await Client
    .GetNotificationRulesApi()
    .CreateSlackRuleAsync("Critical status to Slack", "10s", "${ r._message }", RuleStatusLevel.CRIT, endpoint, org.Id);

Custom mapping of DomainObject to/from InfluxDB

The default mapper uses Column attributes to define how the DomainObject will be mapped to and from the InfluxDB. The our APIs also allow to specify custom mapper. For more information see following example:

using System;
using System.Threading.Tasks;
using InfluxDB.Client;
using InfluxDB.Client.Api.Domain;
using InfluxDB.Client.Core.Flux.Domain;
using InfluxDB.Client.Writes;

namespace Examples
{
    public static class CustomDomainMapping
    {
        /// <summary>
        /// Define Domain Object
        /// </summary>
        private class Sensor
        {
            /// <summary>
            /// Type of sensor.
            /// </summary>
            public String Type { get; set; }
            
            /// <summary>
            /// Version of sensor.
            /// </summary>
            public String Version { get; set; }

            /// <summary>
            /// Measured value.
            /// </summary>
            public double Value { get; set; }

            public DateTimeOffset Timestamp { get; set; }

            public override string ToString()
            {
                return $"{Timestamp:MM/dd/yyyy hh:mm:ss.fff tt} {Type}, {Version} value: {Value}";
            }
        }

        /// <summary>
        /// Define Custom Domain Object Converter
        /// </summary>
        private class DomainEntityConverter : IDomainObjectMapper
        {
            /// <summary>
            /// Convert to DomainObject.
            /// </summary>
            public object ConvertToEntity(FluxRecord fluxRecord, Type type)
            {
                if (type != typeof(Sensor))
                {
                    throw new NotSupportedException($"This converter doesn't supports: {type}");
                }

                var customEntity = new Sensor
                {
                    Type = Convert.ToString(fluxRecord.GetValueByKey("type")),
                    Version = Convert.ToString(fluxRecord.GetValueByKey("version")),
                    Value = Convert.ToDouble(fluxRecord.GetValueByKey("data")),
                    Timestamp = fluxRecord.GetTime().GetValueOrDefault().ToDateTimeUtc(),
                };
                
                return Convert.ChangeType(customEntity, type);
            }
            
            /// <summary>
            /// Convert to DomainObject.
            /// </summary>
            public T ConvertToEntity<T>(FluxRecord fluxRecord)
            {
                return (T)ConvertToEntity(fluxRecord, typeof(T));
            }

            /// <summary>
            /// Convert to Point
            /// </summary>
            public PointData ConvertToPointData<T>(T entity, WritePrecision precision)
            {
                if (!(entity is Sensor sensor))
                {
                    throw new NotSupportedException($"This converter doesn't supports: {entity}");
                }

                var point = PointData
                    .Measurement("sensor")
                    .Tag("type", sensor.Type)
                    .Tag("version", sensor.Version)
                    .Field("data", sensor.Value)
                    .Timestamp(sensor.Timestamp, precision);

                return point;
            }
        }

        public static async Task Main(string[] args)
        {
            const string host = "http://localhost:9999";
            const string token = "my-token";
            const string bucket = "my-bucket";
            const string organization = "my-org";
            var options = new InfluxDBClientOptions(host)
            {
                Token = token,
                Org = organization,
                Bucket = bucket
            };

            var converter = new DomainEntityConverter();
            using var client = new InfluxDBClient(options);

            //
            // Prepare data to write
            //
            var time = new DateTimeOffset(2020, 11, 15, 8, 20, 15,
                new TimeSpan(3, 0, 0));

            var entity1 = new Sensor
            {
                Timestamp = time,
                Type = "temperature",
                Version = "v0.0.2",
                Value = 15
            };
            var entity2 = new Sensor
            {
                Timestamp = time.AddHours(1),
                Type = "temperature",
                Version = "v0.0.2",
                Value = 15
            };
            var entity3 = new Sensor
            {
                Timestamp = time.AddHours(2),
                Type = "humidity",
                Version = "v0.13",
                Value = 74
            };
            var entity4 = new Sensor
            {
                Timestamp = time.AddHours(3),
                Type = "humidity",
                Version = "v0.13",
                Value = 82
            };

            //
            // Write data
            //
            await client.GetWriteApiAsync(converter)
                .WriteMeasurementsAsync(new []{entity1, entity2, entity3, entity4}, WritePrecision.S);

            //
            // Query Data to Domain object
            //
            var queryApi = client.GetQueryApiSync(converter);

            //
            // Select ALL
            //
            var query = $"from(bucket:\"{bucket}\") " +
                        "|> range(start: 0) " +
                        "|> filter(fn: (r) => r[\"_measurement\"] == \"sensor\")" +
                        "|> pivot(rowKey:[\"_time\"], columnKey: [\"_field\"], valueColumn: \"_value\")";
           
            var sensors = queryApi.QuerySync<Sensor>(query);
            //
            // Print result
            //
            sensors.ForEach(it => Console.WriteLine(it.ToString()));
        }
    }
}

Client configuration file

A client can be configured via App.config file.

The following options are supported:

Property name default description
Url - the url to connect to InfluxDB
Org - default destination organization for writes and queries
Bucket - default destination bucket for writes
Token - the token to use for the authorization
LogLevel NONE rest client verbosity level
Timeout 10000 ms The timespan to wait before the HTTP request times out
AllowHttpRedirects false Configure automatically following HTTP 3xx redirects
VerifySsl true Ignore Certificate Validation Errors when false

The Timeout supports ms, s and m as unit. Default is milliseconds.

Configuration example
<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
        <section name="influx2" type="InfluxDB.Client.Configurations.Influx2, InfluxDB.Client" />
    </configSections>

    <influx2 url="http://localhost:8086"
             org="my-org"
             bucket="my-bucket"
             token="my-token"
             logLevel="BODY"
             timeout="10s">
    </influx2>
</configuration>

and then:

var client = InfluxDBClientFactory.Create();

Client connection string

A client can be constructed using a connection string that can contain the InfluxDBClientOptions parameters encoded into the URL.

var client = new InfluxDBClient("http://localhost:8086?timeout=5000&logLevel=BASIC");

The following options are supported:

Property name default description
org - default destination organization for writes and queries
bucket - default destination bucket for writes
token - the token to use for the authorization
logLevel NONE rest client verbosity level
timeout 10000 ms The timespan to wait before the HTTP request times out.
allowHttpRedirects false Configure automatically following HTTP 3xx redirects
verifySsl true Ignore Certificate Validation Errors when false

The timeout supports ms, s and m as unit. Default is milliseconds.

Gzip support

InfluxDBClient does not enable gzip compress for http requests by default. If you want to enable gzip to reduce transfer data's size, you can call:

influxDBClient.EnableGzip();

How to use WebProxy

You can configure the client to tunnel requests through an HTTP proxy. The WebProxy could be configured via InfluxDBClientOptions parameter WebProxy:

var options = new InfluxDBClientOptions("http://localhost:8086")
{
    Token = "my-token",
    WebProxy = new WebProxy("http://proxyserver:80/", true)
};

var client = new InfluxDBClient(options);

Redirects configuration

Client automatically doesn't follows HTTP redirects. You can enable redirects by AllowRedirects configuration option:

var options = new InfluxDBClientOptions("http://localhost:8086")
{
    Token = "my-token",
    AllowRedirects = true
};

using var client = new InfluxDBClient(options);

⚠️ Due to a security reason Authorization header is not forwarded when redirect leads to a different domain. You can create custom Authenticator which change this behaviour - see more.

Log HTTP Request and Response

The Requests and Responses can be logged by changing the LogLevel. LogLevel values are None, Basic, Headers, Body. Note that applying the Body LogLevel will disable chunking while streaming and will load the whole response into memory.

client.SetLogLevel(LogLevel.Body)
Check the server status and version

Server availability can be checked using the influxDBClient.PingAsync() endpoint.

Version

The latest package for .NET CLI:

dotnet add package InfluxDB.Client

Or when using with Package Manager:

Install-Package InfluxDB.Client
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 is compatible. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (29)

Showing the top 5 NuGet packages that depend on InfluxDB.Client:

Package Downloads
AWF.Fabric

基础结构模块,提供框架级支持

InfluxDB.Client.Linq

The library supports querying InfluxDB 2.x by LINQ expressions.

NBomber.Sinks.InfluxDB

NBomber sink that writes stats data to InfluxDB.

Serilog.Sinks.InfluxDB.Syslog

InfluxDB sink for Serilog with .NET standard 2.0 using syslog format for Influx 2.X

IoTSharp.HealthChecks.InfluxDB

HealthChecks.InfluxDB is the health check package for InfluxDB.

GitHub repositories (8)

Showing the top 5 popular GitHub repositories that depend on InfluxDB.Client:

Repository Stars
Xabaril/AspNetCore.Diagnostics.HealthChecks
Enterprise HealthChecks for ASP.NET Core Diagnostics Package
testcontainers/testcontainers-dotnet
A library to support tests with throwaway instances of Docker containers for all compatible .NET Standard versions.
IoTSharp/IoTSharp
IoTSharp is an open-source IoT platform for data collection, processing, visualization, and device management.
ConcreteMC/Alex
A Minecraft client written in C# aimed at compatibility with MC:Java & MC:Bedrock
melanchall/drywetmidi
.NET library to read, write, process MIDI files and to work with MIDI devices
Version Downloads Last updated
4.16.0-dev.13990 166 6/3/2024
4.16.0-dev.13973 34 6/3/2024
4.16.0-dev.13972 37 6/3/2024
4.16.0-dev.13963 45 6/3/2024
4.16.0-dev.13962 40 6/3/2024
4.16.0-dev.13881 39 6/3/2024
4.16.0-dev.13775 115 5/17/2024
4.16.0-dev.13702 52 5/17/2024
4.15.0 8,806 5/17/2024
4.15.0-dev.13674 59 5/14/2024
4.15.0-dev.13567 447 4/2/2024
4.15.0-dev.13558 48 4/2/2024
4.15.0-dev.13525 47 4/2/2024
4.15.0-dev.13524 43 4/2/2024
4.15.0-dev.13433 175 3/7/2024
4.15.0-dev.13432 48 3/7/2024
4.15.0-dev.13407 82 3/7/2024
4.15.0-dev.13390 46 3/7/2024
4.15.0-dev.13388 44 3/7/2024
4.15.0-dev.13282 238 3/6/2024
4.15.0-dev.13257 58 3/6/2024
4.15.0-dev.13113 1,093 2/1/2024
4.15.0-dev.13104 52 2/1/2024
4.15.0-dev.13081 51 2/1/2024
4.15.0-dev.13040 108 2/1/2024
4.15.0-dev.13039 45 2/1/2024
4.15.0-dev.12863 2,049 1/8/2024
4.15.0-dev.12846 60 1/8/2024
4.15.0-dev.12837 56 1/8/2024
4.15.0-dev.12726 2,422 12/1/2023
4.15.0-dev.12725 61 12/1/2023
4.15.0-dev.12724 59 12/1/2023
4.15.0-dev.12691 63 12/1/2023
4.15.0-dev.12658 69 12/1/2023
4.15.0-dev.12649 62 12/1/2023
4.15.0-dev.12624 59 12/1/2023
4.15.0-dev.12471 873 11/7/2023
4.15.0-dev.12462 59 11/7/2023
4.14.0 268,068 11/7/2023
4.14.0-dev.12437 59 11/7/2023
4.14.0-dev.12343 103 11/2/2023
4.14.0-dev.12310 60 11/2/2023
4.14.0-dev.12284 336 11/1/2023
4.14.0-dev.12235 81 11/1/2023
4.14.0-dev.12226 66 11/1/2023
4.14.0-dev.11972 4,698 8/8/2023
4.14.0-dev.11915 122 7/31/2023
4.14.0-dev.11879 143 7/28/2023
4.13.0 226,399 7/28/2023
4.13.0-dev.11854 88 7/28/2023
4.13.0-dev.11814 342 7/21/2023
4.13.0-dev.11771 129 7/19/2023
4.13.0-dev.11770 88 7/19/2023
4.13.0-dev.11728 113 7/18/2023
4.13.0-dev.11686 183 7/17/2023
4.13.0-dev.11685 79 7/17/2023
4.13.0-dev.11676 88 7/17/2023
4.13.0-dev.11479 1,559 6/27/2023
4.13.0-dev.11478 83 6/27/2023
4.13.0-dev.11477 87 6/27/2023
4.13.0-dev.11396 437 6/19/2023
4.13.0-dev.11395 81 6/19/2023
4.13.0-dev.11342 330 6/15/2023
4.13.0-dev.11330 260 6/12/2023
4.13.0-dev.11305 86 6/12/2023
4.13.0-dev.11296 86 6/12/2023
4.13.0-dev.11217 355 6/6/2023
4.13.0-dev.11089 274 5/30/2023
4.13.0-dev.11064 108 5/30/2023
4.13.0-dev.10998 147 5/29/2023
4.13.0-dev.10989 99 5/29/2023
4.13.0-dev.10871 836 5/8/2023
4.13.0-dev.10870 77 5/8/2023
4.13.0-dev.10819 261 4/28/2023
4.12.0 145,274 4/28/2023
4.12.0-dev.10777 116 4/27/2023
4.12.0-dev.10768 102 4/27/2023
4.12.0-dev.10759 97 4/27/2023
4.12.0-dev.10742 79 4/27/2023
4.12.0-dev.10685 91 4/27/2023
4.12.0-dev.10684 87 4/27/2023
4.12.0-dev.10643 95 4/27/2023
4.12.0-dev.10642 86 4/27/2023
4.12.0-dev.10569 81 4/27/2023
4.12.0-dev.10193 1,722 2/23/2023
4.11.0 101,622 2/23/2023
4.11.0-dev.10176 161 2/23/2023
4.11.0-dev.10059 2,718 1/26/2023
4.10.0 65,325 1/26/2023
4.10.0-dev.10033 134 1/25/2023
4.10.0-dev.10032 105 1/25/2023
4.10.0-dev.10031 118 1/25/2023
4.10.0-dev.9936 3,432 12/26/2022
4.10.0-dev.9935 123 12/26/2022
4.10.0-dev.9881 167 12/21/2022
4.10.0-dev.9880 103 12/21/2022
4.10.0-dev.9818 600 12/16/2022
4.10.0-dev.9773 249 12/12/2022
4.10.0-dev.9756 100 12/12/2022
4.10.0-dev.9693 349 12/6/2022
4.9.0 153,691 12/6/2022
4.9.0-dev.9684 100 12/6/2022
4.9.0-dev.9666 107 12/6/2022
4.9.0-dev.9617 119 12/6/2022
4.9.0-dev.9478 186 12/5/2022
4.9.0-dev.9469 119 12/5/2022
4.9.0-dev.9444 92 12/5/2022
4.9.0-dev.9411 106 12/5/2022
4.9.0-dev.9350 148 12/1/2022
4.8.0 5,049 12/1/2022
4.8.0-dev.9324 185 11/30/2022
4.8.0-dev.9232 172 11/28/2022
4.8.0-dev.9223 104 11/28/2022
4.8.0-dev.9222 106 11/28/2022
4.8.0-dev.9117 387 11/21/2022
4.8.0-dev.9108 112 11/21/2022
4.8.0-dev.9099 112 11/21/2022
4.8.0-dev.9029 184 11/16/2022
4.8.0-dev.8971 109 11/15/2022
4.8.0-dev.8961 118 11/14/2022
4.8.0-dev.8928 118 11/14/2022
4.8.0-dev.8899 115 11/14/2022
4.8.0-dev.8898 125 11/14/2022
4.8.0-dev.8839 115 11/14/2022
4.8.0-dev.8740 233 11/7/2022
4.8.0-dev.8725 104 11/7/2022
4.8.0-dev.8648 346 11/3/2022
4.7.0 92,323 11/3/2022
4.7.0-dev.8625 258 11/2/2022
4.7.0-dev.8594 261 10/31/2022
4.7.0-dev.8579 106 10/31/2022
4.7.0-dev.8557 98 10/31/2022
4.7.0-dev.8540 110 10/31/2022
4.7.0-dev.8518 109 10/31/2022
4.7.0-dev.8517 108 10/31/2022
4.7.0-dev.8509 101 10/31/2022
4.7.0-dev.8377 798 10/26/2022
4.7.0-dev.8360 121 10/25/2022
4.7.0-dev.8350 155 10/24/2022
4.7.0-dev.8335 112 10/24/2022
4.7.0-dev.8334 109 10/24/2022
4.7.0-dev.8223 211 10/19/2022
4.7.0-dev.8178 226 10/17/2022
4.7.0-dev.8170 112 10/17/2022
4.7.0-dev.8148 118 10/17/2022
4.7.0-dev.8133 108 10/17/2022
4.7.0-dev.8097 100 10/17/2022
4.7.0-dev.8034 927 10/11/2022
4.7.0-dev.8025 125 10/11/2022
4.7.0-dev.8009 182 10/10/2022
4.7.0-dev.8001 119 10/10/2022
4.7.0-dev.7959 193 10/4/2022
4.7.0-dev.7905 313 9/30/2022
4.7.0-dev.7875 158 9/29/2022
4.6.0 45,574 9/29/2022
4.6.0-dev.7832 158 9/29/2022
4.6.0-dev.7817 116 9/29/2022
4.6.0-dev.7779 182 9/27/2022
4.6.0-dev.7778 129 9/27/2022
4.6.0-dev.7734 145 9/26/2022
4.6.0-dev.7733 119 9/26/2022
4.6.0-dev.7677 221 9/20/2022
4.6.0-dev.7650 213 9/16/2022
4.6.0-dev.7626 190 9/14/2022
4.6.0-dev.7618 166 9/14/2022
4.6.0-dev.7574 115 9/13/2022
4.6.0-dev.7572 106 9/13/2022
4.6.0-dev.7528 250 9/12/2022
4.6.0-dev.7502 151 9/9/2022
4.6.0-dev.7479 176 9/8/2022
4.6.0-dev.7471 126 9/8/2022
4.6.0-dev.7447 173 9/7/2022
4.6.0-dev.7425 113 9/7/2022
4.6.0-dev.7395 139 9/6/2022
4.6.0-dev.7344 318 8/31/2022
4.6.0-dev.7329 105 8/31/2022
4.6.0-dev.7292 115 8/30/2022
4.6.0-dev.7240 300 8/29/2022
4.5.0 55,641 8/29/2022
4.5.0-dev.7216 135 8/27/2022
4.5.0-dev.7147 294 8/22/2022
4.5.0-dev.7134 325 8/17/2022
4.5.0-dev.7096 164 8/15/2022
4.5.0-dev.7070 257 8/11/2022
4.5.0-dev.7040 174 8/10/2022
4.5.0-dev.7011 228 8/3/2022
4.5.0-dev.6987 130 8/1/2022
4.5.0-dev.6962 141 7/29/2022
4.4.0 47,833 7/29/2022
4.4.0-dev.6901 328 7/25/2022
4.4.0-dev.6843 363 7/19/2022
4.4.0-dev.6804 128 7/19/2022
4.4.0-dev.6789 120 7/19/2022
4.4.0-dev.6760 124 7/19/2022
4.4.0-dev.6705 208 7/14/2022
4.4.0-dev.6663 1,105 6/24/2022
4.4.0-dev.6655 139 6/24/2022
4.3.0 145,150 6/24/2022
4.3.0-dev.multiple.buckets3 276 6/21/2022
4.3.0-dev.multiple.buckets2 250 6/17/2022
4.3.0-dev.multiple.buckets1 120 6/17/2022
4.3.0-dev.6631 130 6/22/2022
4.3.0-dev.6623 121 6/22/2022
4.3.0-dev.6374 447 6/13/2022
4.3.0-dev.6286 979 5/20/2022
4.2.0 65,528 5/20/2022
4.2.0-dev.6257 600 5/13/2022
4.2.0-dev.6248 132 5/12/2022
4.2.0-dev.6233 227 5/12/2022
4.2.0-dev.6194 234 5/10/2022
4.2.0-dev.6193 143 5/10/2022
4.2.0-dev.6158 3,039 5/6/2022
4.2.0-dev.6135 184 5/6/2022
4.2.0-dev.6091 514 4/28/2022
4.2.0-dev.6048 158 4/28/2022
4.2.0-dev.6047 132 4/28/2022
4.2.0-dev.5966 483 4/25/2022
4.2.0-dev.5938 378 4/19/2022
4.1.0 45,214 4/19/2022
4.1.0-dev.5910 345 4/13/2022
4.1.0-dev.5888 139 4/13/2022
4.1.0-dev.5887 146 4/13/2022
4.1.0-dev.5794 843 4/6/2022
4.1.0-dev.5725 448 3/18/2022
4.0.0 57,002 3/18/2022
4.0.0-rc3 941 3/4/2022
4.0.0-rc2 666 2/25/2022
4.0.0-rc1 2,152 2/18/2022
4.0.0-dev.5709 138 3/18/2022
4.0.0-dev.5684 156 3/15/2022
4.0.0-dev.5630 131 3/4/2022
4.0.0-dev.5607 143 3/3/2022
4.0.0-dev.5579 156 2/25/2022
4.0.0-dev.5556 148 2/24/2022
4.0.0-dev.5555 143 2/24/2022
4.0.0-dev.5497 156 2/23/2022
4.0.0-dev.5489 142 2/23/2022
4.0.0-dev.5460 143 2/23/2022
4.0.0-dev.5444 152 2/22/2022
4.0.0-dev.5333 161 2/17/2022
4.0.0-dev.5303 159 2/16/2022
4.0.0-dev.5280 148 2/16/2022
4.0.0-dev.5279 152 2/16/2022
4.0.0-dev.5241 331 2/15/2022
4.0.0-dev.5225 154 2/15/2022
4.0.0-dev.5217 142 2/15/2022
4.0.0-dev.5209 138 2/15/2022
4.0.0-dev.5200 153 2/14/2022
4.0.0-dev.5188 699 2/10/2022
4.0.0-dev.5180 369 2/10/2022
4.0.0-dev.5172 363 2/10/2022
4.0.0-dev.5130 371 2/10/2022
4.0.0-dev.5122 380 2/9/2022
4.0.0-dev.5103 378 2/9/2022
4.0.0-dev.5097 377 2/9/2022
4.0.0-dev.5091 361 2/9/2022
4.0.0-dev.5084 356 2/8/2022
3.4.0-dev.5263 150 2/15/2022
3.4.0-dev.4986 390 2/7/2022
3.4.0-dev.4968 419 2/4/2022
3.3.0 125,105 2/4/2022
3.3.0-dev.4889 401 2/3/2022
3.3.0-dev.4865 402 2/1/2022
3.3.0-dev.4823 322 1/19/2022
3.3.0-dev.4691 870 1/7/2022
3.3.0-dev.4557 2,202 11/26/2021
3.2.0 91,751 11/26/2021
3.2.0-dev.4533 5,066 11/24/2021
3.2.0-dev.4484 353 11/11/2021
3.2.0-dev.4475 213 11/10/2021
3.2.0-dev.4387 277 10/26/2021
3.2.0-dev.4363 241 10/22/2021
3.2.0-dev.4356 187 10/22/2021
3.1.0 90,464 10/22/2021
3.1.0-dev.4303 435 10/18/2021
3.1.0-dev.4293 211 10/15/2021
3.1.0-dev.4286 190 10/15/2021
3.1.0-dev.4240 252 10/12/2021
3.1.0-dev.4202 208 10/11/2021
3.1.0-dev.4183 213 10/11/2021
3.1.0-dev.4131 192 10/8/2021
3.1.0-dev.3999 208 10/5/2021
3.1.0-dev.3841 322 9/29/2021
3.1.0-dev.3798 405 9/17/2021
3.0.0 58,125 9/17/2021
3.0.0-dev.3726 2,532 8/31/2021
3.0.0-dev.3719 166 8/31/2021
3.0.0-dev.3671 396 8/20/2021
2.2.0-dev.3652 167 8/20/2021
2.1.0 239,898 8/20/2021
2.1.0-dev.3605 215 8/17/2021
2.1.0-dev.3584 528 8/16/2021
2.1.0-dev.3558 175 8/16/2021
2.1.0-dev.3527 319 7/29/2021
2.1.0-dev.3519 233 7/29/2021
2.1.0-dev.3490 304 7/20/2021
2.1.0-dev.3445 264 7/12/2021
2.1.0-dev.3434 242 7/9/2021
2.0.0 62,457 7/9/2021
2.0.0-dev.3401 7,023 6/25/2021
2.0.0-dev.3368 250 6/23/2021
2.0.0-dev.3361 221 6/23/2021
2.0.0-dev.3330 255 6/17/2021
2.0.0-dev.3291 242 6/16/2021
1.20.0-dev.3218 519 6/4/2021
1.19.0 116,116 6/4/2021
1.19.0-dev.3204 218 6/3/2021
1.19.0-dev.3160 208 6/2/2021
1.19.0-dev.3159 180 6/2/2021
1.19.0-dev.3084 2,495 5/7/2021
1.19.0-dev.3051 259 5/5/2021
1.19.0-dev.3044 207 5/5/2021
1.19.0-dev.3008 242 4/30/2021
1.18.0 35,762 4/30/2021
1.18.0-dev.2973 230 4/27/2021
1.18.0-dev.2930 1,187 4/16/2021
1.18.0-dev.2919 227 4/13/2021
1.18.0-dev.2893 227 4/12/2021
1.18.0-dev.2880 201 4/12/2021
1.18.0-dev.2856 231 4/7/2021
1.18.0-dev.2830 1,825 4/1/2021
1.18.0-dev.2816 189 4/1/2021
1.17.0 44,859 4/1/2021
1.17.0-dev.linq.17 872 3/18/2021
1.17.0-dev.linq.16 239 3/16/2021
1.17.0-dev.linq.15 218 3/15/2021
1.17.0-dev.linq.14 234 3/12/2021
1.17.0-dev.linq.13 272 3/11/2021
1.17.0-dev.linq.12 199 3/10/2021
1.17.0-dev.linq.11 237 3/8/2021
1.17.0-dev.2776 209 3/26/2021
1.17.0-dev.2713 182 3/25/2021
1.17.0-dev.2707 180 3/25/2021
1.17.0-dev.2652 242 3/19/2021
1.17.0-dev.2619 182 3/18/2021
1.17.0-dev.2566 183 3/16/2021
1.17.0-dev.2549 186 3/15/2021
1.17.0-dev.2505 226 3/12/2021
1.17.0-dev.2446 211 3/11/2021
1.17.0-dev.2402 203 3/8/2021
1.17.0-dev.2371 202 3/5/2021
1.16.0 18,987 3/5/2021
1.16.0-dev.linq.10 1,632 2/4/2021
1.16.0-dev.linq.9 224 2/4/2021
1.16.0-dev.2359 231 3/4/2021
1.16.0-dev.2273 199 2/12/2021
1.16.0-dev.2255 197 2/11/2021
1.16.0-dev.2228 204 2/5/2021
1.16.0-dev.2147 245 1/29/2021
1.15.0 31,263 1/29/2021
1.15.0-dev.linq.8 209 1/28/2021
1.15.0-dev.linq.7 199 1/27/2021
1.15.0-dev.linq.6 265 1/20/2021
1.15.0-dev.linq.5 242 1/19/2021
1.15.0-dev.linq.4 377 1/15/2021
1.15.0-dev.linq.3 196 1/14/2021
1.15.0-dev.linq.2 205 1/13/2021
1.15.0-dev.linq.1 221 1/12/2021
1.15.0-dev.2135 195 1/28/2021
1.15.0-dev.2009 203 1/19/2021
1.15.0-dev.1793 210 1/11/2021
1.15.0-dev.1753 254 1/7/2021
1.15.0-dev.1752 242 1/7/2021
1.15.0-dev.1705 860 12/16/2020
1.15.0-dev.1677 564 12/4/2020
1.14.0 44,998 12/4/2020
1.14.0-dev.1665 258 12/3/2020
1.14.0-dev.1648 250 12/2/2020
1.14.0-dev.1632 311 11/27/2020
1.14.0-dev.1577 453 10/30/2020
1.14.0-dev.1571 309 10/30/2020
1.13.0 14,838 10/30/2020
1.13.0-dev.1545 400 10/15/2020
1.13.0-dev.1516 466 10/8/2020
1.13.0-dev.1489 569 10/2/2020
1.13.0-dev.1478 301 10/2/2020
1.12.0 34,583 10/2/2020
1.12.0-dev.1466 244 10/1/2020
1.12.0-dev.1421 546 9/23/2020
1.12.0-dev.1345 316 9/18/2020
1.12.0-dev.1306 312 9/15/2020
1.12.0-dev.1251 333 9/2/2020
1.12.0-dev.1216 1,938 8/14/2020
1.11.0 24,027 8/14/2020
1.11.0-dev.1205 284 8/14/2020
1.11.0-dev.1185 288 8/10/2020
1.11.0-dev.1166 337 7/28/2020
1.11.0-dev.1150 283 7/28/2020
1.11.0-dev.1144 302 7/28/2020
1.11.0-dev.1125 280 7/20/2020
1.11.0-dev.1111 285 7/17/2020
1.10.0 16,976 7/17/2020
1.10.0-dev.1098 266 7/15/2020
1.10.0-dev.1077 384 7/10/2020
1.10.0-dev.1049 396 6/29/2020
1.10.0-dev.1022 310 6/23/2020
1.10.0-dev.1021 300 6/23/2020
1.10.0-dev.990 295 6/19/2020
1.9.0 18,103 6/19/2020
1.9.0-dev.984 316 6/19/2020
1.9.0-dev.971 267 6/17/2020
1.9.0-dev.955 277 6/17/2020
1.9.0-dev.886 292 6/10/2020
1.9.0-dev.848 312 6/8/2020
1.9.0-dev.842 273 6/8/2020
1.9.0-dev.836 268 6/8/2020
1.9.0-dev.786 1,243 5/27/2020
1.9.0-dev.762 576 5/15/2020
1.8.0 17,927 5/15/2020
1.8.0-dev.748 289 5/12/2020
1.8.0-dev.669 537 4/22/2020
1.8.0-dev.668 280 4/21/2020
1.8.0-dev.661 271 4/20/2020
1.8.0-dev.650 273 4/20/2020
1.8.0-dev.639 280 4/20/2020
1.8.0-dev.620 276 4/17/2020
1.7.0 13,987 4/17/2020
1.7.0-dev.608 301 4/16/2020
1.7.0-dev.574 271 4/14/2020
1.7.0-dev.563 278 4/14/2020
1.7.0-dev.534 285 4/6/2020
1.7.0-dev.528 291 4/6/2020
1.7.0-dev.512 322 4/3/2020
1.7.0-dev.495 290 3/30/2020
1.7.0-dev.469 1,134 3/13/2020
1.6.0 2,895 3/13/2020
1.6.0-dev.458 310 3/13/2020
1.6.0-dev.443 312 3/9/2020
1.6.0-dev.422 322 2/28/2020
1.6.0-dev.410 318 2/27/2020
1.6.0-dev.404 318 2/27/2020
1.6.0-dev.356 314 2/14/2020
1.5.0 1,437 2/14/2020
1.5.0-dev.349 299 2/14/2020
1.5.0-dev.341 303 2/12/2020
1.5.0-dev.312 315 1/22/2020
1.4.0 3,908 1/17/2020
1.3.0 2,002 12/6/2019
1.2.0 6,149 11/8/2019
1.1.0 906 10/11/2019
1.0.0 2,250 8/23/2019