InfluxDB.Client 4.19.0-dev.15190

This is a prerelease version of InfluxDB.Client.
dotnet add package InfluxDB.Client --version 4.19.0-dev.15190                
NuGet\Install-Package InfluxDB.Client -Version 4.19.0-dev.15190                
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.19.0-dev.15190" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add InfluxDB.Client --version 4.19.0-dev.15190                
#r "nuget: InfluxDB.Client, 4.19.0-dev.15190"                
#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.19.0-dev.15190&prerelease

// Install InfluxDB.Client as a Cake Tool
#tool nuget:?package=InfluxDB.Client&version=4.19.0-dev.15190&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 (31)

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

Package Downloads
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

OpenTelemetry.Exporter.InfluxDB

An OpenTelemetry .NET exporter that exports to InfluxDB.

AspNetCore.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.19.0-dev.15190 178 12/5/2024
4.19.0-dev.15189 45 12/5/2024
4.19.0-dev.15188 38 12/5/2024
4.19.0-dev.15178 38 12/5/2024
4.19.0-dev.15177 43 12/5/2024
4.19.0-dev.14906 912 10/2/2024
4.19.0-dev.14897 50 10/2/2024
4.19.0-dev.14896 55 10/2/2024
4.19.0-dev.14895 68 10/2/2024
4.19.0-dev.14811 215 9/13/2024
4.18.0 89,527 9/13/2024
4.18.0-dev.14769 125 9/4/2024
4.18.0-dev.14743 74 9/3/2024
4.18.0-dev.14694 69 9/3/2024
4.18.0-dev.14693 57 9/3/2024
4.18.0-dev.14692 59 9/3/2024
4.18.0-dev.14618 74 9/2/2024
4.18.0-dev.14609 63 9/2/2024
4.18.0-dev.14592 58 9/2/2024
4.18.0-dev.14446 468 8/19/2024
4.18.0-dev.14414 238 8/12/2024
4.17.0 66,154 8/12/2024
4.17.0-dev.headers.read.1 191 7/22/2024
4.17.0-dev.14350 47 8/5/2024
4.17.0-dev.14333 49 8/5/2024
4.17.0-dev.14300 46 8/5/2024
4.17.0-dev.14291 44 8/5/2024
4.17.0-dev.14189 90 7/23/2024
4.17.0-dev.14179 62 7/22/2024
4.17.0-dev.14101 229 7/1/2024
4.17.0-dev.14100 64 7/1/2024
4.17.0-dev.14044 108 6/24/2024
4.16.0 45,034 6/24/2024
4.16.0-dev.13990 1,908 6/3/2024
4.16.0-dev.13973 66 6/3/2024
4.16.0-dev.13972 62 6/3/2024
4.16.0-dev.13963 74 6/3/2024
4.16.0-dev.13962 66 6/3/2024
4.16.0-dev.13881 65 6/3/2024
4.16.0-dev.13775 169 5/17/2024
4.16.0-dev.13702 72 5/17/2024
4.15.0 41,354 5/17/2024
4.15.0-dev.13674 87 5/14/2024
4.15.0-dev.13567 1,140 4/2/2024
4.15.0-dev.13558 68 4/2/2024
4.15.0-dev.13525 66 4/2/2024
4.15.0-dev.13524 70 4/2/2024
4.15.0-dev.13433 235 3/7/2024
4.15.0-dev.13432 72 3/7/2024
4.15.0-dev.13407 102 3/7/2024
4.15.0-dev.13390 70 3/7/2024
4.15.0-dev.13388 68 3/7/2024
4.15.0-dev.13282 257 3/6/2024
4.15.0-dev.13257 82 3/6/2024
4.15.0-dev.13113 1,134 2/1/2024
4.15.0-dev.13104 74 2/1/2024
4.15.0-dev.13081 74 2/1/2024
4.15.0-dev.13040 138 2/1/2024
4.15.0-dev.13039 75 2/1/2024
4.15.0-dev.12863 2,076 1/8/2024
4.15.0-dev.12846 83 1/8/2024
4.15.0-dev.12837 80 1/8/2024
4.15.0-dev.12726 2,676 12/1/2023
4.15.0-dev.12725 90 12/1/2023
4.15.0-dev.12724 83 12/1/2023
4.15.0-dev.12691 89 12/1/2023
4.15.0-dev.12658 96 12/1/2023
4.15.0-dev.12649 82 12/1/2023
4.15.0-dev.12624 84 12/1/2023
4.15.0-dev.12471 1,027 11/7/2023
4.15.0-dev.12462 86 11/7/2023
4.14.0 459,260 11/7/2023
4.14.0-dev.12437 86 11/7/2023
4.14.0-dev.12343 132 11/2/2023
4.14.0-dev.12310 87 11/2/2023
4.14.0-dev.12284 354 11/1/2023
4.14.0-dev.12235 107 11/1/2023
4.14.0-dev.12226 86 11/1/2023
4.14.0-dev.11972 5,602 8/8/2023
4.14.0-dev.11915 150 7/31/2023
4.14.0-dev.11879 167 7/28/2023
4.13.0 281,095 7/28/2023
4.13.0-dev.11854 106 7/28/2023
4.13.0-dev.11814 362 7/21/2023
4.13.0-dev.11771 153 7/19/2023
4.13.0-dev.11770 112 7/19/2023
4.13.0-dev.11728 132 7/18/2023
4.13.0-dev.11686 207 7/17/2023
4.13.0-dev.11685 99 7/17/2023
4.13.0-dev.11676 110 7/17/2023
4.13.0-dev.11479 2,030 6/27/2023
4.13.0-dev.11478 105 6/27/2023
4.13.0-dev.11477 108 6/27/2023
4.13.0-dev.11396 463 6/19/2023
4.13.0-dev.11395 97 6/19/2023
4.13.0-dev.11342 352 6/15/2023
4.13.0-dev.11330 284 6/12/2023
4.13.0-dev.11305 102 6/12/2023
4.13.0-dev.11296 104 6/12/2023
4.13.0-dev.11217 378 6/6/2023
4.13.0-dev.11089 295 5/30/2023
4.13.0-dev.11064 126 5/30/2023
4.13.0-dev.10998 165 5/29/2023
4.13.0-dev.10989 120 5/29/2023
4.13.0-dev.10871 878 5/8/2023
4.13.0-dev.10870 100 5/8/2023
4.13.0-dev.10819 277 4/28/2023
4.12.0 176,116 4/28/2023
4.12.0-dev.10777 137 4/27/2023
4.12.0-dev.10768 118 4/27/2023
4.12.0-dev.10759 112 4/27/2023
4.12.0-dev.10742 95 4/27/2023
4.12.0-dev.10685 106 4/27/2023
4.12.0-dev.10684 108 4/27/2023
4.12.0-dev.10643 115 4/27/2023
4.12.0-dev.10642 101 4/27/2023
4.12.0-dev.10569 102 4/27/2023
4.12.0-dev.10193 1,750 2/23/2023
4.11.0 113,620 2/23/2023
4.11.0-dev.10176 183 2/23/2023
4.11.0-dev.10059 3,168 1/26/2023
4.10.0 69,896 1/26/2023
4.10.0-dev.10033 148 1/25/2023
4.10.0-dev.10032 125 1/25/2023
4.10.0-dev.10031 138 1/25/2023
4.10.0-dev.9936 3,587 12/26/2022
4.10.0-dev.9935 145 12/26/2022
4.10.0-dev.9881 186 12/21/2022
4.10.0-dev.9880 124 12/21/2022
4.10.0-dev.9818 617 12/16/2022
4.10.0-dev.9773 295 12/12/2022
4.10.0-dev.9756 121 12/12/2022
4.10.0-dev.9693 367 12/6/2022
4.9.0 198,533 12/6/2022
4.9.0-dev.9684 115 12/6/2022
4.9.0-dev.9666 129 12/6/2022
4.9.0-dev.9617 142 12/6/2022
4.9.0-dev.9478 207 12/5/2022
4.9.0-dev.9469 138 12/5/2022
4.9.0-dev.9444 107 12/5/2022
4.9.0-dev.9411 127 12/5/2022
4.9.0-dev.9350 163 12/1/2022
4.8.0 5,692 12/1/2022
4.8.0-dev.9324 209 11/30/2022
4.8.0-dev.9232 189 11/28/2022
4.8.0-dev.9223 125 11/28/2022
4.8.0-dev.9222 121 11/28/2022
4.8.0-dev.9117 409 11/21/2022
4.8.0-dev.9108 127 11/21/2022
4.8.0-dev.9099 129 11/21/2022
4.8.0-dev.9029 201 11/16/2022
4.8.0-dev.8971 129 11/15/2022
4.8.0-dev.8961 133 11/14/2022
4.8.0-dev.8928 139 11/14/2022
4.8.0-dev.8899 137 11/14/2022
4.8.0-dev.8898 147 11/14/2022
4.8.0-dev.8839 136 11/14/2022
4.8.0-dev.8740 248 11/7/2022
4.8.0-dev.8725 125 11/7/2022
4.8.0-dev.8648 367 11/3/2022
4.7.0 103,842 11/3/2022
4.7.0-dev.8625 273 11/2/2022
4.7.0-dev.8594 286 10/31/2022
4.7.0-dev.8579 123 10/31/2022
4.7.0-dev.8557 113 10/31/2022
4.7.0-dev.8540 131 10/31/2022
4.7.0-dev.8518 124 10/31/2022
4.7.0-dev.8517 123 10/31/2022
4.7.0-dev.8509 120 10/31/2022
4.7.0-dev.8377 819 10/26/2022
4.7.0-dev.8360 139 10/25/2022
4.7.0-dev.8350 181 10/24/2022
4.7.0-dev.8335 135 10/24/2022
4.7.0-dev.8334 136 10/24/2022
4.7.0-dev.8223 226 10/19/2022
4.7.0-dev.8178 246 10/17/2022
4.7.0-dev.8170 127 10/17/2022
4.7.0-dev.8148 133 10/17/2022
4.7.0-dev.8133 123 10/17/2022
4.7.0-dev.8097 116 10/17/2022
4.7.0-dev.8034 952 10/11/2022
4.7.0-dev.8025 153 10/11/2022
4.7.0-dev.8009 204 10/10/2022
4.7.0-dev.8001 143 10/10/2022
4.7.0-dev.7959 210 10/4/2022
4.7.0-dev.7905 334 9/30/2022
4.7.0-dev.7875 179 9/29/2022
4.6.0 48,316 9/29/2022
4.6.0-dev.7832 173 9/29/2022
4.6.0-dev.7817 137 9/29/2022
4.6.0-dev.7779 197 9/27/2022
4.6.0-dev.7778 144 9/27/2022
4.6.0-dev.7734 165 9/26/2022
4.6.0-dev.7733 134 9/26/2022
4.6.0-dev.7677 242 9/20/2022
4.6.0-dev.7650 234 9/16/2022
4.6.0-dev.7626 207 9/14/2022
4.6.0-dev.7618 189 9/14/2022
4.6.0-dev.7574 138 9/13/2022
4.6.0-dev.7572 121 9/13/2022
4.6.0-dev.7528 271 9/12/2022
4.6.0-dev.7502 166 9/9/2022
4.6.0-dev.7479 196 9/8/2022
4.6.0-dev.7471 141 9/8/2022
4.6.0-dev.7447 197 9/7/2022
4.6.0-dev.7425 134 9/7/2022
4.6.0-dev.7395 159 9/6/2022
4.6.0-dev.7344 339 8/31/2022
4.6.0-dev.7329 122 8/31/2022
4.6.0-dev.7292 137 8/30/2022
4.6.0-dev.7240 321 8/29/2022
4.5.0 65,199 8/29/2022
4.5.0-dev.7216 151 8/27/2022
4.5.0-dev.7147 309 8/22/2022
4.5.0-dev.7134 347 8/17/2022
4.5.0-dev.7096 185 8/15/2022
4.5.0-dev.7070 282 8/11/2022
4.5.0-dev.7040 195 8/10/2022
4.5.0-dev.7011 245 8/3/2022
4.5.0-dev.6987 151 8/1/2022
4.5.0-dev.6962 163 7/29/2022
4.4.0 49,701 7/29/2022
4.4.0-dev.6901 344 7/25/2022
4.4.0-dev.6843 384 7/19/2022
4.4.0-dev.6804 153 7/19/2022
4.4.0-dev.6789 146 7/19/2022
4.4.0-dev.6760 139 7/19/2022
4.4.0-dev.6705 228 7/14/2022
4.4.0-dev.6663 1,124 6/24/2022
4.4.0-dev.6655 160 6/24/2022
4.3.0 179,854 6/24/2022
4.3.0-dev.multiple.buckets3 297 6/21/2022
4.3.0-dev.multiple.buckets2 271 6/17/2022
4.3.0-dev.multiple.buckets1 140 6/17/2022
4.3.0-dev.6631 151 6/22/2022
4.3.0-dev.6623 136 6/22/2022
4.3.0-dev.6374 462 6/13/2022
4.3.0-dev.6286 997 5/20/2022
4.2.0 72,673 5/20/2022
4.2.0-dev.6257 615 5/13/2022
4.2.0-dev.6248 153 5/12/2022
4.2.0-dev.6233 242 5/12/2022
4.2.0-dev.6194 249 5/10/2022
4.2.0-dev.6193 166 5/10/2022
4.2.0-dev.6158 3,060 5/6/2022
4.2.0-dev.6135 205 5/6/2022
4.2.0-dev.6091 535 4/28/2022
4.2.0-dev.6048 174 4/28/2022
4.2.0-dev.6047 155 4/28/2022
4.2.0-dev.5966 504 4/25/2022
4.2.0-dev.5938 401 4/19/2022
4.1.0 47,371 4/19/2022
4.1.0-dev.5910 366 4/13/2022
4.1.0-dev.5888 162 4/13/2022
4.1.0-dev.5887 168 4/13/2022
4.1.0-dev.5794 862 4/6/2022
4.1.0-dev.5725 584 3/18/2022
4.0.0 59,543 3/18/2022
4.0.0-rc3 999 3/4/2022
4.0.0-rc2 728 2/25/2022
4.0.0-rc1 2,207 2/18/2022
4.0.0-dev.5709 159 3/18/2022
4.0.0-dev.5684 171 3/15/2022
4.0.0-dev.5630 156 3/4/2022
4.0.0-dev.5607 166 3/3/2022
4.0.0-dev.5579 171 2/25/2022
4.0.0-dev.5556 169 2/24/2022
4.0.0-dev.5555 165 2/24/2022
4.0.0-dev.5497 170 2/23/2022
4.0.0-dev.5489 158 2/23/2022
4.0.0-dev.5460 163 2/23/2022
4.0.0-dev.5444 168 2/22/2022
4.0.0-dev.5333 182 2/17/2022
4.0.0-dev.5303 174 2/16/2022
4.0.0-dev.5280 168 2/16/2022
4.0.0-dev.5279 166 2/16/2022
4.0.0-dev.5241 351 2/15/2022
4.0.0-dev.5225 174 2/15/2022
4.0.0-dev.5217 156 2/15/2022
4.0.0-dev.5209 158 2/15/2022
4.0.0-dev.5200 173 2/14/2022
4.0.0-dev.5188 721 2/10/2022
4.0.0-dev.5180 383 2/10/2022
4.0.0-dev.5172 385 2/10/2022
4.0.0-dev.5130 391 2/10/2022
4.0.0-dev.5122 400 2/9/2022
4.0.0-dev.5103 398 2/9/2022
4.0.0-dev.5097 399 2/9/2022
4.0.0-dev.5091 381 2/9/2022
4.0.0-dev.5084 371 2/8/2022
3.4.0-dev.5263 170 2/15/2022
3.4.0-dev.4986 405 2/7/2022
3.4.0-dev.4968 434 2/4/2022
3.3.0 150,144 2/4/2022
3.3.0-dev.4889 427 2/3/2022
3.3.0-dev.4865 426 2/1/2022
3.3.0-dev.4823 341 1/19/2022
3.3.0-dev.4691 1,233 1/7/2022
3.3.0-dev.4557 2,225 11/26/2021
3.2.0 97,862 11/26/2021
3.2.0-dev.4533 5,086 11/24/2021
3.2.0-dev.4484 371 11/11/2021
3.2.0-dev.4475 232 11/10/2021
3.2.0-dev.4387 297 10/26/2021
3.2.0-dev.4363 259 10/22/2021
3.2.0-dev.4356 207 10/22/2021
3.1.0 95,113 10/22/2021
3.1.0-dev.4303 454 10/18/2021
3.1.0-dev.4293 231 10/15/2021
3.1.0-dev.4286 212 10/15/2021
3.1.0-dev.4240 266 10/12/2021
3.1.0-dev.4202 222 10/11/2021
3.1.0-dev.4183 232 10/11/2021
3.1.0-dev.4131 206 10/8/2021
3.1.0-dev.3999 228 10/5/2021
3.1.0-dev.3841 341 9/29/2021
3.1.0-dev.3798 421 9/17/2021
3.0.0 61,400 9/17/2021
3.0.0-dev.3726 2,559 8/31/2021
3.0.0-dev.3719 185 8/31/2021
3.0.0-dev.3671 433 8/20/2021
2.2.0-dev.3652 190 8/20/2021
2.1.0 291,745 8/20/2021
2.1.0-dev.3605 229 8/17/2021
2.1.0-dev.3584 542 8/16/2021
2.1.0-dev.3558 195 8/16/2021
2.1.0-dev.3527 334 7/29/2021
2.1.0-dev.3519 254 7/29/2021
2.1.0-dev.3490 324 7/20/2021
2.1.0-dev.3445 279 7/12/2021
2.1.0-dev.3434 264 7/9/2021
2.0.0 66,622 7/9/2021
2.0.0-dev.3401 7,664 6/25/2021
2.0.0-dev.3368 265 6/23/2021
2.0.0-dev.3361 243 6/23/2021
2.0.0-dev.3330 277 6/17/2021
2.0.0-dev.3291 264 6/16/2021
1.20.0-dev.3218 538 6/4/2021
1.19.0 137,963 6/4/2021
1.19.0-dev.3204 232 6/3/2021
1.19.0-dev.3160 223 6/2/2021
1.19.0-dev.3159 196 6/2/2021
1.19.0-dev.3084 2,518 5/7/2021
1.19.0-dev.3051 274 5/5/2021
1.19.0-dev.3044 230 5/5/2021
1.19.0-dev.3008 263 4/30/2021
1.18.0 36,277 4/30/2021
1.18.0-dev.2973 253 4/27/2021
1.18.0-dev.2930 1,208 4/16/2021
1.18.0-dev.2919 253 4/13/2021
1.18.0-dev.2893 248 4/12/2021
1.18.0-dev.2880 222 4/12/2021
1.18.0-dev.2856 248 4/7/2021
1.18.0-dev.2830 1,847 4/1/2021
1.18.0-dev.2816 210 4/1/2021
1.17.0 46,613 4/1/2021
1.17.0-dev.linq.17 889 3/18/2021
1.17.0-dev.linq.16 259 3/16/2021
1.17.0-dev.linq.15 241 3/15/2021
1.17.0-dev.linq.14 257 3/12/2021
1.17.0-dev.linq.13 292 3/11/2021
1.17.0-dev.linq.12 214 3/10/2021
1.17.0-dev.linq.11 260 3/8/2021
1.17.0-dev.2776 230 3/26/2021
1.17.0-dev.2713 197 3/25/2021
1.17.0-dev.2707 200 3/25/2021
1.17.0-dev.2652 259 3/19/2021
1.17.0-dev.2619 197 3/18/2021
1.17.0-dev.2566 200 3/16/2021
1.17.0-dev.2549 206 3/15/2021
1.17.0-dev.2505 241 3/12/2021
1.17.0-dev.2446 226 3/11/2021
1.17.0-dev.2402 222 3/8/2021
1.17.0-dev.2371 219 3/5/2021
1.16.0 19,449 3/5/2021
1.16.0-dev.linq.10 1,652 2/4/2021
1.16.0-dev.linq.9 238 2/4/2021
1.16.0-dev.2359 252 3/4/2021
1.16.0-dev.2273 212 2/12/2021
1.16.0-dev.2255 218 2/11/2021
1.16.0-dev.2228 227 2/5/2021
1.16.0-dev.2147 259 1/29/2021
1.15.0 32,954 1/29/2021
1.15.0-dev.linq.8 223 1/28/2021
1.15.0-dev.linq.7 213 1/27/2021
1.15.0-dev.linq.6 284 1/20/2021
1.15.0-dev.linq.5 262 1/19/2021
1.15.0-dev.linq.4 399 1/15/2021
1.15.0-dev.linq.3 212 1/14/2021
1.15.0-dev.linq.2 225 1/13/2021
1.15.0-dev.linq.1 241 1/12/2021
1.15.0-dev.2135 217 1/28/2021
1.15.0-dev.2009 223 1/19/2021
1.15.0-dev.1793 232 1/11/2021
1.15.0-dev.1753 268 1/7/2021
1.15.0-dev.1752 256 1/7/2021
1.15.0-dev.1705 875 12/16/2020
1.15.0-dev.1677 580 12/4/2020
1.14.0 46,163 12/4/2020
1.14.0-dev.1665 276 12/3/2020
1.14.0-dev.1648 273 12/2/2020
1.14.0-dev.1632 334 11/27/2020
1.14.0-dev.1577 467 10/30/2020
1.14.0-dev.1571 330 10/30/2020
1.13.0 15,192 10/30/2020
1.13.0-dev.1545 420 10/15/2020
1.13.0-dev.1516 480 10/8/2020
1.13.0-dev.1489 583 10/2/2020
1.13.0-dev.1478 320 10/2/2020
1.12.0 37,824 10/2/2020
1.12.0-dev.1466 270 10/1/2020
1.12.0-dev.1421 569 9/23/2020
1.12.0-dev.1345 333 9/18/2020
1.12.0-dev.1306 336 9/15/2020
1.12.0-dev.1251 347 9/2/2020
1.12.0-dev.1216 1,960 8/14/2020
1.11.0 24,341 8/14/2020
1.11.0-dev.1205 304 8/14/2020
1.11.0-dev.1185 304 8/10/2020
1.11.0-dev.1166 358 7/28/2020
1.11.0-dev.1150 304 7/28/2020
1.11.0-dev.1144 319 7/28/2020
1.11.0-dev.1125 301 7/20/2020
1.11.0-dev.1111 300 7/17/2020
1.10.0 17,138 7/17/2020
1.10.0-dev.1098 288 7/15/2020
1.10.0-dev.1077 400 7/10/2020
1.10.0-dev.1049 414 6/29/2020
1.10.0-dev.1022 331 6/23/2020
1.10.0-dev.1021 316 6/23/2020
1.10.0-dev.990 317 6/19/2020
1.9.0 21,490 6/19/2020
1.9.0-dev.984 333 6/19/2020
1.9.0-dev.971 290 6/17/2020
1.9.0-dev.955 293 6/17/2020
1.9.0-dev.886 314 6/10/2020
1.9.0-dev.848 334 6/8/2020
1.9.0-dev.842 290 6/8/2020
1.9.0-dev.836 290 6/8/2020
1.9.0-dev.786 1,265 5/27/2020
1.9.0-dev.762 599 5/15/2020
1.8.0 18,579 5/15/2020
1.8.0-dev.748 306 5/12/2020
1.8.0-dev.669 560 4/22/2020
1.8.0-dev.668 300 4/21/2020
1.8.0-dev.661 294 4/20/2020
1.8.0-dev.650 290 4/20/2020
1.8.0-dev.639 304 4/20/2020
1.8.0-dev.620 293 4/17/2020
1.7.0 14,638 4/17/2020
1.7.0-dev.608 327 4/16/2020
1.7.0-dev.574 293 4/14/2020
1.7.0-dev.563 294 4/14/2020
1.7.0-dev.534 308 4/6/2020
1.7.0-dev.528 307 4/6/2020
1.7.0-dev.512 345 4/3/2020
1.7.0-dev.495 312 3/30/2020
1.7.0-dev.469 1,159 3/13/2020
1.6.0 2,941 3/13/2020
1.6.0-dev.458 333 3/13/2020
1.6.0-dev.443 326 3/9/2020
1.6.0-dev.422 338 2/28/2020
1.6.0-dev.410 340 2/27/2020
1.6.0-dev.404 342 2/27/2020
1.6.0-dev.356 336 2/14/2020
1.5.0 1,655 2/14/2020
1.5.0-dev.349 315 2/14/2020
1.5.0-dev.341 318 2/12/2020
1.5.0-dev.312 330 1/22/2020
1.4.0 4,074 1/17/2020
1.3.0 2,044 12/6/2019
1.2.0 6,207 11/8/2019
1.1.0 951 10/11/2019
1.0.0 3,532 8/23/2019