InfluxDB.Client 4.18.0

There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package InfluxDB.Client --version 4.18.0                
NuGet\Install-Package InfluxDB.Client -Version 4.18.0                
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.18.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add InfluxDB.Client --version 4.18.0                
#r "nuget: InfluxDB.Client, 4.18.0"                
#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.18.0

// Install InfluxDB.Client as a Cake Tool
#tool nuget:?package=InfluxDB.Client&version=4.18.0                

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 (30)

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

IoTSharp.HealthChecks.InfluxDB

HealthChecks.InfluxDB is the health check package for InfluxDB.

OpenTelemetry.Exporter.InfluxDB

An OpenTelemetry .NET exporter that exports to 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.14906 338 10/2/2024
4.19.0-dev.14897 45 10/2/2024
4.19.0-dev.14896 52 10/2/2024
4.19.0-dev.14895 65 10/2/2024
4.19.0-dev.14811 175 9/13/2024
4.18.0 52,713 9/13/2024
4.18.0-dev.14769 122 9/4/2024
4.18.0-dev.14743 71 9/3/2024
4.18.0-dev.14694 66 9/3/2024
4.18.0-dev.14693 54 9/3/2024
4.18.0-dev.14692 56 9/3/2024
4.18.0-dev.14618 67 9/2/2024
4.18.0-dev.14609 58 9/2/2024
4.18.0-dev.14592 53 9/2/2024
4.18.0-dev.14446 419 8/19/2024
4.18.0-dev.14414 171 8/12/2024
4.17.0 57,399 8/12/2024
4.17.0-dev.headers.read.1 186 7/22/2024
4.17.0-dev.14350 44 8/5/2024
4.17.0-dev.14333 44 8/5/2024
4.17.0-dev.14300 43 8/5/2024
4.17.0-dev.14291 41 8/5/2024
4.17.0-dev.14189 87 7/23/2024
4.17.0-dev.14179 59 7/22/2024
4.17.0-dev.14101 213 7/1/2024
4.17.0-dev.14100 61 7/1/2024
4.17.0-dev.14044 100 6/24/2024
4.16.0 36,875 6/24/2024
4.16.0-dev.13990 1,660 6/3/2024
4.16.0-dev.13973 61 6/3/2024
4.16.0-dev.13972 59 6/3/2024
4.16.0-dev.13963 69 6/3/2024
4.16.0-dev.13962 63 6/3/2024
4.16.0-dev.13881 62 6/3/2024
4.16.0-dev.13775 165 5/17/2024
4.16.0-dev.13702 69 5/17/2024
4.15.0 36,355 5/17/2024
4.15.0-dev.13674 84 5/14/2024
4.15.0-dev.13567 904 4/2/2024
4.15.0-dev.13558 65 4/2/2024
4.15.0-dev.13525 63 4/2/2024
4.15.0-dev.13524 67 4/2/2024
4.15.0-dev.13433 224 3/7/2024
4.15.0-dev.13432 69 3/7/2024
4.15.0-dev.13407 99 3/7/2024
4.15.0-dev.13390 67 3/7/2024
4.15.0-dev.13388 63 3/7/2024
4.15.0-dev.13282 254 3/6/2024
4.15.0-dev.13257 79 3/6/2024
4.15.0-dev.13113 1,127 2/1/2024
4.15.0-dev.13104 71 2/1/2024
4.15.0-dev.13081 71 2/1/2024
4.15.0-dev.13040 133 2/1/2024
4.15.0-dev.13039 72 2/1/2024
4.15.0-dev.12863 2,073 1/8/2024
4.15.0-dev.12846 80 1/8/2024
4.15.0-dev.12837 77 1/8/2024
4.15.0-dev.12726 2,646 12/1/2023
4.15.0-dev.12725 87 12/1/2023
4.15.0-dev.12724 80 12/1/2023
4.15.0-dev.12691 82 12/1/2023
4.15.0-dev.12658 93 12/1/2023
4.15.0-dev.12649 79 12/1/2023
4.15.0-dev.12624 81 12/1/2023
4.15.0-dev.12471 1,020 11/7/2023
4.15.0-dev.12462 83 11/7/2023
4.14.0 437,286 11/7/2023
4.14.0-dev.12437 83 11/7/2023
4.14.0-dev.12343 129 11/2/2023
4.14.0-dev.12310 84 11/2/2023
4.14.0-dev.12284 351 11/1/2023
4.14.0-dev.12235 104 11/1/2023
4.14.0-dev.12226 83 11/1/2023
4.14.0-dev.11972 5,543 8/8/2023
4.14.0-dev.11915 147 7/31/2023
4.14.0-dev.11879 164 7/28/2023
4.13.0 274,770 7/28/2023
4.13.0-dev.11854 103 7/28/2023
4.13.0-dev.11814 359 7/21/2023
4.13.0-dev.11771 150 7/19/2023
4.13.0-dev.11770 109 7/19/2023
4.13.0-dev.11728 129 7/18/2023
4.13.0-dev.11686 204 7/17/2023
4.13.0-dev.11685 92 7/17/2023
4.13.0-dev.11676 107 7/17/2023
4.13.0-dev.11479 2,020 6/27/2023
4.13.0-dev.11478 102 6/27/2023
4.13.0-dev.11477 105 6/27/2023
4.13.0-dev.11396 456 6/19/2023
4.13.0-dev.11395 94 6/19/2023
4.13.0-dev.11342 345 6/15/2023
4.13.0-dev.11330 281 6/12/2023
4.13.0-dev.11305 99 6/12/2023
4.13.0-dev.11296 101 6/12/2023
4.13.0-dev.11217 373 6/6/2023
4.13.0-dev.11089 292 5/30/2023
4.13.0-dev.11064 123 5/30/2023
4.13.0-dev.10998 162 5/29/2023
4.13.0-dev.10989 117 5/29/2023
4.13.0-dev.10871 873 5/8/2023
4.13.0-dev.10870 95 5/8/2023
4.13.0-dev.10819 274 4/28/2023
4.12.0 173,103 4/28/2023
4.12.0-dev.10777 134 4/27/2023
4.12.0-dev.10768 115 4/27/2023
4.12.0-dev.10759 109 4/27/2023
4.12.0-dev.10742 92 4/27/2023
4.12.0-dev.10685 103 4/27/2023
4.12.0-dev.10684 105 4/27/2023
4.12.0-dev.10643 112 4/27/2023
4.12.0-dev.10642 98 4/27/2023
4.12.0-dev.10569 99 4/27/2023
4.12.0-dev.10193 1,744 2/23/2023
4.11.0 112,117 2/23/2023
4.11.0-dev.10176 180 2/23/2023
4.11.0-dev.10059 3,154 1/26/2023
4.10.0 69,091 1/26/2023
4.10.0-dev.10033 145 1/25/2023
4.10.0-dev.10032 122 1/25/2023
4.10.0-dev.10031 135 1/25/2023
4.10.0-dev.9936 3,569 12/26/2022
4.10.0-dev.9935 142 12/26/2022
4.10.0-dev.9881 181 12/21/2022
4.10.0-dev.9880 121 12/21/2022
4.10.0-dev.9818 612 12/16/2022
4.10.0-dev.9773 290 12/12/2022
4.10.0-dev.9756 118 12/12/2022
4.10.0-dev.9693 364 12/6/2022
4.9.0 191,874 12/6/2022
4.9.0-dev.9684 112 12/6/2022
4.9.0-dev.9666 124 12/6/2022
4.9.0-dev.9617 139 12/6/2022
4.9.0-dev.9478 204 12/5/2022
4.9.0-dev.9469 131 12/5/2022
4.9.0-dev.9444 104 12/5/2022
4.9.0-dev.9411 124 12/5/2022
4.9.0-dev.9350 160 12/1/2022
4.8.0 5,581 12/1/2022
4.8.0-dev.9324 204 11/30/2022
4.8.0-dev.9232 184 11/28/2022
4.8.0-dev.9223 122 11/28/2022
4.8.0-dev.9222 118 11/28/2022
4.8.0-dev.9117 406 11/21/2022
4.8.0-dev.9108 124 11/21/2022
4.8.0-dev.9099 124 11/21/2022
4.8.0-dev.9029 196 11/16/2022
4.8.0-dev.8971 126 11/15/2022
4.8.0-dev.8961 130 11/14/2022
4.8.0-dev.8928 136 11/14/2022
4.8.0-dev.8899 134 11/14/2022
4.8.0-dev.8898 144 11/14/2022
4.8.0-dev.8839 133 11/14/2022
4.8.0-dev.8740 245 11/7/2022
4.8.0-dev.8725 122 11/7/2022
4.8.0-dev.8648 364 11/3/2022
4.7.0 102,605 11/3/2022
4.7.0-dev.8625 270 11/2/2022
4.7.0-dev.8594 283 10/31/2022
4.7.0-dev.8579 120 10/31/2022
4.7.0-dev.8557 110 10/31/2022
4.7.0-dev.8540 128 10/31/2022
4.7.0-dev.8518 121 10/31/2022
4.7.0-dev.8517 120 10/31/2022
4.7.0-dev.8509 117 10/31/2022
4.7.0-dev.8377 816 10/26/2022
4.7.0-dev.8360 136 10/25/2022
4.7.0-dev.8350 178 10/24/2022
4.7.0-dev.8335 132 10/24/2022
4.7.0-dev.8334 129 10/24/2022
4.7.0-dev.8223 223 10/19/2022
4.7.0-dev.8178 243 10/17/2022
4.7.0-dev.8170 124 10/17/2022
4.7.0-dev.8148 130 10/17/2022
4.7.0-dev.8133 120 10/17/2022
4.7.0-dev.8097 113 10/17/2022
4.7.0-dev.8034 947 10/11/2022
4.7.0-dev.8025 149 10/11/2022
4.7.0-dev.8009 201 10/10/2022
4.7.0-dev.8001 138 10/10/2022
4.7.0-dev.7959 205 10/4/2022
4.7.0-dev.7905 331 9/30/2022
4.7.0-dev.7875 176 9/29/2022
4.6.0 47,893 9/29/2022
4.6.0-dev.7832 170 9/29/2022
4.6.0-dev.7817 134 9/29/2022
4.6.0-dev.7779 194 9/27/2022
4.6.0-dev.7778 141 9/27/2022
4.6.0-dev.7734 162 9/26/2022
4.6.0-dev.7733 131 9/26/2022
4.6.0-dev.7677 239 9/20/2022
4.6.0-dev.7650 231 9/16/2022
4.6.0-dev.7626 204 9/14/2022
4.6.0-dev.7618 186 9/14/2022
4.6.0-dev.7574 135 9/13/2022
4.6.0-dev.7572 118 9/13/2022
4.6.0-dev.7528 268 9/12/2022
4.6.0-dev.7502 163 9/9/2022
4.6.0-dev.7479 193 9/8/2022
4.6.0-dev.7471 138 9/8/2022
4.6.0-dev.7447 194 9/7/2022
4.6.0-dev.7425 131 9/7/2022
4.6.0-dev.7395 156 9/6/2022
4.6.0-dev.7344 336 8/31/2022
4.6.0-dev.7329 119 8/31/2022
4.6.0-dev.7292 134 8/30/2022
4.6.0-dev.7240 318 8/29/2022
4.5.0 63,868 8/29/2022
4.5.0-dev.7216 148 8/27/2022
4.5.0-dev.7147 306 8/22/2022
4.5.0-dev.7134 344 8/17/2022
4.5.0-dev.7096 182 8/15/2022
4.5.0-dev.7070 279 8/11/2022
4.5.0-dev.7040 192 8/10/2022
4.5.0-dev.7011 242 8/3/2022
4.5.0-dev.6987 148 8/1/2022
4.5.0-dev.6962 160 7/29/2022
4.4.0 49,479 7/29/2022
4.4.0-dev.6901 341 7/25/2022
4.4.0-dev.6843 381 7/19/2022
4.4.0-dev.6804 146 7/19/2022
4.4.0-dev.6789 138 7/19/2022
4.4.0-dev.6760 136 7/19/2022
4.4.0-dev.6705 225 7/14/2022
4.4.0-dev.6663 1,121 6/24/2022
4.4.0-dev.6655 157 6/24/2022
4.3.0 175,817 6/24/2022
4.3.0-dev.multiple.buckets3 294 6/21/2022
4.3.0-dev.multiple.buckets2 268 6/17/2022
4.3.0-dev.multiple.buckets1 137 6/17/2022
4.3.0-dev.6631 148 6/22/2022
4.3.0-dev.6623 133 6/22/2022
4.3.0-dev.6374 459 6/13/2022
4.3.0-dev.6286 991 5/20/2022
4.2.0 71,897 5/20/2022
4.2.0-dev.6257 612 5/13/2022
4.2.0-dev.6248 150 5/12/2022
4.2.0-dev.6233 239 5/12/2022
4.2.0-dev.6194 246 5/10/2022
4.2.0-dev.6193 161 5/10/2022
4.2.0-dev.6158 3,057 5/6/2022
4.2.0-dev.6135 202 5/6/2022
4.2.0-dev.6091 532 4/28/2022
4.2.0-dev.6048 171 4/28/2022
4.2.0-dev.6047 150 4/28/2022
4.2.0-dev.5966 501 4/25/2022
4.2.0-dev.5938 398 4/19/2022
4.1.0 47,177 4/19/2022
4.1.0-dev.5910 363 4/13/2022
4.1.0-dev.5888 159 4/13/2022
4.1.0-dev.5887 165 4/13/2022
4.1.0-dev.5794 855 4/6/2022
4.1.0-dev.5725 573 3/18/2022
4.0.0 59,097 3/18/2022
4.0.0-rc3 994 3/4/2022
4.0.0-rc2 721 2/25/2022
4.0.0-rc1 2,202 2/18/2022
4.0.0-dev.5709 156 3/18/2022
4.0.0-dev.5684 168 3/15/2022
4.0.0-dev.5630 153 3/4/2022
4.0.0-dev.5607 163 3/3/2022
4.0.0-dev.5579 168 2/25/2022
4.0.0-dev.5556 166 2/24/2022
4.0.0-dev.5555 162 2/24/2022
4.0.0-dev.5497 167 2/23/2022
4.0.0-dev.5489 153 2/23/2022
4.0.0-dev.5460 160 2/23/2022
4.0.0-dev.5444 165 2/22/2022
4.0.0-dev.5333 179 2/17/2022
4.0.0-dev.5303 171 2/16/2022
4.0.0-dev.5280 165 2/16/2022
4.0.0-dev.5279 163 2/16/2022
4.0.0-dev.5241 348 2/15/2022
4.0.0-dev.5225 171 2/15/2022
4.0.0-dev.5217 153 2/15/2022
4.0.0-dev.5209 155 2/15/2022
4.0.0-dev.5200 170 2/14/2022
4.0.0-dev.5188 718 2/10/2022
4.0.0-dev.5180 380 2/10/2022
4.0.0-dev.5172 380 2/10/2022
4.0.0-dev.5130 388 2/10/2022
4.0.0-dev.5122 397 2/9/2022
4.0.0-dev.5103 395 2/9/2022
4.0.0-dev.5097 394 2/9/2022
4.0.0-dev.5091 374 2/9/2022
4.0.0-dev.5084 368 2/8/2022
3.4.0-dev.5263 167 2/15/2022
3.4.0-dev.4986 402 2/7/2022
3.4.0-dev.4968 431 2/4/2022
3.3.0 145,956 2/4/2022
3.3.0-dev.4889 424 2/3/2022
3.3.0-dev.4865 421 2/1/2022
3.3.0-dev.4823 334 1/19/2022
3.3.0-dev.4691 1,182 1/7/2022
3.3.0-dev.4557 2,221 11/26/2021
3.2.0 97,138 11/26/2021
3.2.0-dev.4533 5,083 11/24/2021
3.2.0-dev.4484 368 11/11/2021
3.2.0-dev.4475 229 11/10/2021
3.2.0-dev.4387 294 10/26/2021
3.2.0-dev.4363 256 10/22/2021
3.2.0-dev.4356 204 10/22/2021
3.1.0 94,687 10/22/2021
3.1.0-dev.4303 451 10/18/2021
3.1.0-dev.4293 228 10/15/2021
3.1.0-dev.4286 209 10/15/2021
3.1.0-dev.4240 263 10/12/2021
3.1.0-dev.4202 219 10/11/2021
3.1.0-dev.4183 229 10/11/2021
3.1.0-dev.4131 203 10/8/2021
3.1.0-dev.3999 225 10/5/2021
3.1.0-dev.3841 338 9/29/2021
3.1.0-dev.3798 418 9/17/2021
3.0.0 60,828 9/17/2021
3.0.0-dev.3726 2,550 8/31/2021
3.0.0-dev.3719 182 8/31/2021
3.0.0-dev.3671 430 8/20/2021
2.2.0-dev.3652 187 8/20/2021
2.1.0 283,941 8/20/2021
2.1.0-dev.3605 226 8/17/2021
2.1.0-dev.3584 539 8/16/2021
2.1.0-dev.3558 192 8/16/2021
2.1.0-dev.3527 331 7/29/2021
2.1.0-dev.3519 251 7/29/2021
2.1.0-dev.3490 321 7/20/2021
2.1.0-dev.3445 276 7/12/2021
2.1.0-dev.3434 261 7/9/2021
2.0.0 65,994 7/9/2021
2.0.0-dev.3401 7,629 6/25/2021
2.0.0-dev.3368 262 6/23/2021
2.0.0-dev.3361 240 6/23/2021
2.0.0-dev.3330 272 6/17/2021
2.0.0-dev.3291 260 6/16/2021
1.20.0-dev.3218 535 6/4/2021
1.19.0 133,768 6/4/2021
1.19.0-dev.3204 229 6/3/2021
1.19.0-dev.3160 220 6/2/2021
1.19.0-dev.3159 191 6/2/2021
1.19.0-dev.3084 2,515 5/7/2021
1.19.0-dev.3051 271 5/5/2021
1.19.0-dev.3044 225 5/5/2021
1.19.0-dev.3008 260 4/30/2021
1.18.0 36,208 4/30/2021
1.18.0-dev.2973 250 4/27/2021
1.18.0-dev.2930 1,205 4/16/2021
1.18.0-dev.2919 246 4/13/2021
1.18.0-dev.2893 245 4/12/2021
1.18.0-dev.2880 213 4/12/2021
1.18.0-dev.2856 243 4/7/2021
1.18.0-dev.2830 1,844 4/1/2021
1.18.0-dev.2816 207 4/1/2021
1.17.0 46,331 4/1/2021
1.17.0-dev.linq.17 886 3/18/2021
1.17.0-dev.linq.16 256 3/16/2021
1.17.0-dev.linq.15 238 3/15/2021
1.17.0-dev.linq.14 254 3/12/2021
1.17.0-dev.linq.13 289 3/11/2021
1.17.0-dev.linq.12 211 3/10/2021
1.17.0-dev.linq.11 257 3/8/2021
1.17.0-dev.2776 227 3/26/2021
1.17.0-dev.2713 194 3/25/2021
1.17.0-dev.2707 197 3/25/2021
1.17.0-dev.2652 256 3/19/2021
1.17.0-dev.2619 194 3/18/2021
1.17.0-dev.2566 197 3/16/2021
1.17.0-dev.2549 203 3/15/2021
1.17.0-dev.2505 238 3/12/2021
1.17.0-dev.2446 223 3/11/2021
1.17.0-dev.2402 219 3/8/2021
1.17.0-dev.2371 216 3/5/2021
1.16.0 19,361 3/5/2021
1.16.0-dev.linq.10 1,649 2/4/2021
1.16.0-dev.linq.9 235 2/4/2021
1.16.0-dev.2359 249 3/4/2021
1.16.0-dev.2273 209 2/12/2021
1.16.0-dev.2255 215 2/11/2021
1.16.0-dev.2228 224 2/5/2021
1.16.0-dev.2147 256 1/29/2021
1.15.0 32,791 1/29/2021
1.15.0-dev.linq.8 220 1/28/2021
1.15.0-dev.linq.7 210 1/27/2021
1.15.0-dev.linq.6 281 1/20/2021
1.15.0-dev.linq.5 259 1/19/2021
1.15.0-dev.linq.4 394 1/15/2021
1.15.0-dev.linq.3 209 1/14/2021
1.15.0-dev.linq.2 222 1/13/2021
1.15.0-dev.linq.1 238 1/12/2021
1.15.0-dev.2135 212 1/28/2021
1.15.0-dev.2009 220 1/19/2021
1.15.0-dev.1793 229 1/11/2021
1.15.0-dev.1753 265 1/7/2021
1.15.0-dev.1752 253 1/7/2021
1.15.0-dev.1705 872 12/16/2020
1.15.0-dev.1677 577 12/4/2020
1.14.0 45,700 12/4/2020
1.14.0-dev.1665 269 12/3/2020
1.14.0-dev.1648 270 12/2/2020
1.14.0-dev.1632 331 11/27/2020
1.14.0-dev.1577 464 10/30/2020
1.14.0-dev.1571 327 10/30/2020
1.13.0 15,169 10/30/2020
1.13.0-dev.1545 417 10/15/2020
1.13.0-dev.1516 477 10/8/2020
1.13.0-dev.1489 580 10/2/2020
1.13.0-dev.1478 317 10/2/2020
1.12.0 37,237 10/2/2020
1.12.0-dev.1466 263 10/1/2020
1.12.0-dev.1421 564 9/23/2020
1.12.0-dev.1345 330 9/18/2020
1.12.0-dev.1306 333 9/15/2020
1.12.0-dev.1251 344 9/2/2020
1.12.0-dev.1216 1,955 8/14/2020
1.11.0 24,296 8/14/2020
1.11.0-dev.1205 301 8/14/2020
1.11.0-dev.1185 301 8/10/2020
1.11.0-dev.1166 355 7/28/2020
1.11.0-dev.1150 301 7/28/2020
1.11.0-dev.1144 316 7/28/2020
1.11.0-dev.1125 298 7/20/2020
1.11.0-dev.1111 297 7/17/2020
1.10.0 17,130 7/17/2020
1.10.0-dev.1098 285 7/15/2020
1.10.0-dev.1077 397 7/10/2020
1.10.0-dev.1049 411 6/29/2020
1.10.0-dev.1022 328 6/23/2020
1.10.0-dev.1021 313 6/23/2020
1.10.0-dev.990 314 6/19/2020
1.9.0 20,844 6/19/2020
1.9.0-dev.984 330 6/19/2020
1.9.0-dev.971 287 6/17/2020
1.9.0-dev.955 290 6/17/2020
1.9.0-dev.886 311 6/10/2020
1.9.0-dev.848 331 6/8/2020
1.9.0-dev.842 285 6/8/2020
1.9.0-dev.836 287 6/8/2020
1.9.0-dev.786 1,262 5/27/2020
1.9.0-dev.762 596 5/15/2020
1.8.0 18,552 5/15/2020
1.8.0-dev.748 303 5/12/2020
1.8.0-dev.669 557 4/22/2020
1.8.0-dev.668 292 4/21/2020
1.8.0-dev.661 289 4/20/2020
1.8.0-dev.650 287 4/20/2020
1.8.0-dev.639 301 4/20/2020
1.8.0-dev.620 290 4/17/2020
1.7.0 14,551 4/17/2020
1.7.0-dev.608 324 4/16/2020
1.7.0-dev.574 290 4/14/2020
1.7.0-dev.563 289 4/14/2020
1.7.0-dev.534 305 4/6/2020
1.7.0-dev.528 304 4/6/2020
1.7.0-dev.512 342 4/3/2020
1.7.0-dev.495 309 3/30/2020
1.7.0-dev.469 1,156 3/13/2020
1.6.0 2,931 3/13/2020
1.6.0-dev.458 330 3/13/2020
1.6.0-dev.443 323 3/9/2020
1.6.0-dev.422 333 2/28/2020
1.6.0-dev.410 337 2/27/2020
1.6.0-dev.404 339 2/27/2020
1.6.0-dev.356 333 2/14/2020
1.5.0 1,573 2/14/2020
1.5.0-dev.349 312 2/14/2020
1.5.0-dev.341 315 2/12/2020
1.5.0-dev.312 327 1/22/2020
1.4.0 4,062 1/17/2020
1.3.0 2,036 12/6/2019
1.2.0 6,196 11/8/2019
1.1.0 941 10/11/2019
1.0.0 3,211 8/23/2019