InfluxDB.Client 4.13.0-dev.11296

This is a prerelease version of InfluxDB.Client.
There is a newer version of this package available.
See the version list below for details.
dotnet add package InfluxDB.Client --version 4.13.0-dev.11296
                    
NuGet\Install-Package InfluxDB.Client -Version 4.13.0-dev.11296
                    
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.13.0-dev.11296" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="InfluxDB.Client" Version="4.13.0-dev.11296" />
                    
Directory.Packages.props
<PackageReference Include="InfluxDB.Client" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add InfluxDB.Client --version 4.13.0-dev.11296
                    
#r "nuget: InfluxDB.Client, 4.13.0-dev.11296"
                    
#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.
#:package InfluxDB.Client@4.13.0-dev.11296
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=InfluxDB.Client&version=4.13.0-dev.11296&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=InfluxDB.Client&version=4.13.0-dev.11296&prerelease
                    
Install as a Cake Tool

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");
        }
    }
}

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.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.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 (32)

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

AspNetCore.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 8 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.
melanchall/drywetmidi
Swiss knife for everything MIDI related
ConcreteMC/Alex
A Minecraft client written in C# aimed at compatibility with MC:Java & MC:Bedrock
open-telemetry/opentelemetry-dotnet-contrib
This repository contains set of components extending functionality of the OpenTelemetry .NET SDK. Instrumentation libraries, exporters, and other components can find their home here.
nickbabcock/OhmGraphite
Expose hardware sensor data to Graphite / InfluxDB / Prometheus / Postgres / Timescaledb
RapidScada/scada-v6
Contains Rapid SCADA 6 source code.
Version Downloads Last Updated
4.19.0-dev.15190 2,459 12/5/2024
4.19.0-dev.15189 86 12/5/2024
4.19.0-dev.15188 78 12/5/2024
4.19.0-dev.15178 72 12/5/2024
4.19.0-dev.15177 77 12/5/2024
4.19.0-dev.14906 1,843 10/2/2024
4.19.0-dev.14897 77 10/2/2024
4.19.0-dev.14896 81 10/2/2024
4.19.0-dev.14895 116 10/2/2024
4.19.0-dev.14811 311 9/13/2024
4.18.0 590,050 9/13/2024
4.18.0-dev.14769 155 9/4/2024
4.18.0-dev.14743 94 9/3/2024
4.18.0-dev.14694 91 9/3/2024
4.18.0-dev.14693 79 9/3/2024
4.18.0-dev.14692 81 9/3/2024
4.18.0-dev.14618 100 9/2/2024
4.18.0-dev.14609 87 9/2/2024
4.18.0-dev.14592 79 9/2/2024
4.18.0-dev.14446 1,049 8/19/2024
4.18.0-dev.14414 410 8/12/2024
4.17.0 122,481 8/12/2024
4.17.0-dev.headers.read.1 238 7/22/2024
4.17.0-dev.14350 70 8/5/2024
4.17.0-dev.14333 68 8/5/2024
4.17.0-dev.14300 63 8/5/2024
4.17.0-dev.14291 67 8/5/2024
4.17.0-dev.14189 120 7/23/2024
4.17.0-dev.14179 94 7/22/2024
4.17.0-dev.14101 292 7/1/2024
4.17.0-dev.14100 84 7/1/2024
4.17.0-dev.14044 127 6/24/2024
4.16.0 157,552 6/24/2024
4.16.0-dev.13990 3,706 6/3/2024
4.16.0-dev.13973 95 6/3/2024
4.16.0-dev.13972 87 6/3/2024
4.16.0-dev.13963 98 6/3/2024
4.16.0-dev.13962 92 6/3/2024
4.16.0-dev.13881 86 6/3/2024
4.16.0-dev.13775 197 5/17/2024
4.16.0-dev.13702 97 5/17/2024
4.15.0 78,455 5/17/2024
4.15.0-dev.13674 101 5/14/2024
4.15.0-dev.13567 1,514 4/2/2024
4.15.0-dev.13558 90 4/2/2024
4.15.0-dev.13525 93 4/2/2024
4.15.0-dev.13524 90 4/2/2024
4.15.0-dev.13433 311 3/7/2024
4.15.0-dev.13432 91 3/7/2024
4.15.0-dev.13407 119 3/7/2024
4.15.0-dev.13390 93 3/7/2024
4.15.0-dev.13388 86 3/7/2024
4.15.0-dev.13282 276 3/6/2024
4.15.0-dev.13257 103 3/6/2024
4.15.0-dev.13113 1,161 2/1/2024
4.15.0-dev.13104 93 2/1/2024
4.15.0-dev.13081 92 2/1/2024
4.15.0-dev.13040 157 2/1/2024
4.15.0-dev.13039 97 2/1/2024
4.15.0-dev.12863 2,100 1/8/2024
4.15.0-dev.12846 99 1/8/2024
4.15.0-dev.12837 106 1/8/2024
4.15.0-dev.12726 2,758 12/1/2023
4.15.0-dev.12725 110 12/1/2023
4.15.0-dev.12724 106 12/1/2023
4.15.0-dev.12691 104 12/1/2023
4.15.0-dev.12658 117 12/1/2023
4.15.0-dev.12649 105 12/1/2023
4.15.0-dev.12624 100 12/1/2023
4.15.0-dev.12471 1,099 11/7/2023
4.15.0-dev.12462 108 11/7/2023
4.14.0 555,099 11/7/2023
4.14.0-dev.12437 111 11/7/2023
4.14.0-dev.12343 148 11/2/2023
4.14.0-dev.12310 110 11/2/2023
4.14.0-dev.12284 377 11/1/2023
4.14.0-dev.12235 124 11/1/2023
4.14.0-dev.12226 107 11/1/2023
4.14.0-dev.11972 5,698 8/8/2023
4.14.0-dev.11915 194 7/31/2023
4.14.0-dev.11879 199 7/28/2023
4.13.0 327,789 7/28/2023
4.13.0-dev.11854 144 7/28/2023
4.13.0-dev.11814 404 7/21/2023
4.13.0-dev.11771 194 7/19/2023
4.13.0-dev.11770 154 7/19/2023
4.13.0-dev.11728 166 7/18/2023
4.13.0-dev.11686 250 7/17/2023
4.13.0-dev.11685 133 7/17/2023
4.13.0-dev.11676 158 7/17/2023
4.13.0-dev.11479 2,136 6/27/2023
4.13.0-dev.11478 147 6/27/2023
4.13.0-dev.11477 145 6/27/2023
4.13.0-dev.11396 502 6/19/2023
4.13.0-dev.11395 144 6/19/2023
4.13.0-dev.11342 395 6/15/2023
4.13.0-dev.11330 336 6/12/2023
4.13.0-dev.11305 154 6/12/2023
4.13.0-dev.11296 150 6/12/2023
4.13.0-dev.11217 425 6/6/2023
4.13.0-dev.11089 349 5/30/2023
4.13.0-dev.11064 172 5/30/2023
4.13.0-dev.10998 206 5/29/2023
4.13.0-dev.10989 160 5/29/2023
4.13.0-dev.10871 935 5/8/2023
4.13.0-dev.10870 139 5/8/2023
4.13.0-dev.10819 320 4/28/2023
4.12.0 198,989 4/28/2023
4.12.0-dev.10777 191 4/27/2023
4.12.0-dev.10768 168 4/27/2023
4.12.0-dev.10759 161 4/27/2023
4.12.0-dev.10742 143 4/27/2023
4.12.0-dev.10685 150 4/27/2023
4.12.0-dev.10684 153 4/27/2023
4.12.0-dev.10643 161 4/27/2023
4.12.0-dev.10642 152 4/27/2023
4.12.0-dev.10569 154 4/27/2023
4.12.0-dev.10193 1,808 2/23/2023
4.11.0 125,321 2/23/2023
4.11.0-dev.10176 240 2/23/2023
4.11.0-dev.10059 3,224 1/26/2023
4.10.0 75,690 1/26/2023
4.10.0-dev.10033 203 1/25/2023
4.10.0-dev.10032 174 1/25/2023
4.10.0-dev.10031 192 1/25/2023
4.10.0-dev.9936 3,729 12/26/2022
4.10.0-dev.9935 198 12/26/2022
4.10.0-dev.9881 230 12/21/2022
4.10.0-dev.9880 171 12/21/2022
4.10.0-dev.9818 658 12/16/2022
4.10.0-dev.9773 363 12/12/2022
4.10.0-dev.9756 173 12/12/2022
4.10.0-dev.9693 418 12/6/2022
4.9.0 234,790 12/6/2022
4.9.0-dev.9684 165 12/6/2022
4.9.0-dev.9666 178 12/6/2022
4.9.0-dev.9617 194 12/6/2022
4.9.0-dev.9478 256 12/5/2022
4.9.0-dev.9469 191 12/5/2022
4.9.0-dev.9444 155 12/5/2022
4.9.0-dev.9411 171 12/5/2022
4.9.0-dev.9350 213 12/1/2022
4.8.0 5,940 12/1/2022
4.8.0-dev.9324 259 11/30/2022
4.8.0-dev.9232 231 11/28/2022
4.8.0-dev.9223 169 11/28/2022
4.8.0-dev.9222 178 11/28/2022
4.8.0-dev.9117 463 11/21/2022
4.8.0-dev.9108 183 11/21/2022
4.8.0-dev.9099 173 11/21/2022
4.8.0-dev.9029 249 11/16/2022
4.8.0-dev.8971 189 11/15/2022
4.8.0-dev.8961 184 11/14/2022
4.8.0-dev.8928 192 11/14/2022
4.8.0-dev.8899 181 11/14/2022
4.8.0-dev.8898 190 11/14/2022
4.8.0-dev.8839 191 11/14/2022
4.8.0-dev.8740 294 11/7/2022
4.8.0-dev.8725 177 11/7/2022
4.8.0-dev.8648 414 11/3/2022
4.7.0 110,751 11/3/2022
4.7.0-dev.8625 327 11/2/2022
4.7.0-dev.8594 338 10/31/2022
4.7.0-dev.8579 178 10/31/2022
4.7.0-dev.8557 166 10/31/2022
4.7.0-dev.8540 182 10/31/2022
4.7.0-dev.8518 169 10/31/2022
4.7.0-dev.8517 174 10/31/2022
4.7.0-dev.8509 171 10/31/2022
4.7.0-dev.8377 867 10/26/2022
4.7.0-dev.8360 192 10/25/2022
4.7.0-dev.8350 233 10/24/2022
4.7.0-dev.8335 187 10/24/2022
4.7.0-dev.8334 194 10/24/2022
4.7.0-dev.8223 279 10/19/2022
4.7.0-dev.8178 295 10/17/2022
4.7.0-dev.8170 180 10/17/2022
4.7.0-dev.8148 185 10/17/2022
4.7.0-dev.8133 175 10/17/2022
4.7.0-dev.8097 172 10/17/2022
4.7.0-dev.8034 1,135 10/11/2022
4.7.0-dev.8025 214 10/11/2022
4.7.0-dev.8009 256 10/10/2022
4.7.0-dev.8001 198 10/10/2022
4.7.0-dev.7959 261 10/4/2022
4.7.0-dev.7905 386 9/30/2022
4.7.0-dev.7875 232 9/29/2022
4.6.0 51,302 9/29/2022
4.6.0-dev.7832 228 9/29/2022
4.6.0-dev.7817 189 9/29/2022
4.6.0-dev.7779 251 9/27/2022
4.6.0-dev.7778 199 9/27/2022
4.6.0-dev.7734 224 9/26/2022
4.6.0-dev.7733 180 9/26/2022
4.6.0-dev.7677 292 9/20/2022
4.6.0-dev.7650 286 9/16/2022
4.6.0-dev.7626 258 9/14/2022
4.6.0-dev.7618 238 9/14/2022
4.6.0-dev.7574 195 9/13/2022
4.6.0-dev.7572 174 9/13/2022
4.6.0-dev.7528 328 9/12/2022
4.6.0-dev.7502 218 9/9/2022
4.6.0-dev.7479 249 9/8/2022
4.6.0-dev.7471 196 9/8/2022
4.6.0-dev.7447 250 9/7/2022
4.6.0-dev.7425 185 9/7/2022
4.6.0-dev.7395 206 9/6/2022
4.6.0-dev.7344 392 8/31/2022
4.6.0-dev.7329 179 8/31/2022
4.6.0-dev.7292 188 8/30/2022
4.6.0-dev.7240 370 8/29/2022
4.5.0 73,030 8/29/2022
4.5.0-dev.7216 210 8/27/2022
4.5.0-dev.7147 356 8/22/2022
4.5.0-dev.7134 403 8/17/2022
4.5.0-dev.7096 235 8/15/2022
4.5.0-dev.7070 331 8/11/2022
4.5.0-dev.7040 246 8/10/2022
4.5.0-dev.7011 298 8/3/2022
4.5.0-dev.6987 204 8/1/2022
4.5.0-dev.6962 214 7/29/2022
4.4.0 51,364 7/29/2022
4.4.0-dev.6901 397 7/25/2022
4.4.0-dev.6843 438 7/19/2022
4.4.0-dev.6804 214 7/19/2022
4.4.0-dev.6789 196 7/19/2022
4.4.0-dev.6760 203 7/19/2022
4.4.0-dev.6705 288 7/14/2022
4.4.0-dev.6663 1,201 6/24/2022
4.4.0-dev.6655 224 6/24/2022
4.3.0 215,307 6/24/2022
4.3.0-dev.multiple.buckets3 358 6/21/2022
4.3.0-dev.multiple.buckets2 323 6/17/2022
4.3.0-dev.multiple.buckets1 199 6/17/2022
4.3.0-dev.6631 208 6/22/2022
4.3.0-dev.6623 191 6/22/2022
4.3.0-dev.6374 522 6/13/2022
4.3.0-dev.6286 1,066 5/20/2022
4.2.0 82,308 5/20/2022
4.2.0-dev.6257 675 5/13/2022
4.2.0-dev.6248 218 5/12/2022
4.2.0-dev.6233 308 5/12/2022
4.2.0-dev.6194 314 5/10/2022
4.2.0-dev.6193 223 5/10/2022
4.2.0-dev.6158 3,118 5/6/2022
4.2.0-dev.6135 264 5/6/2022
4.2.0-dev.6091 602 4/28/2022
4.2.0-dev.6048 240 4/28/2022
4.2.0-dev.6047 218 4/28/2022
4.2.0-dev.5966 571 4/25/2022
4.2.0-dev.5938 468 4/19/2022
4.1.0 48,652 4/19/2022
4.1.0-dev.5910 432 4/13/2022
4.1.0-dev.5888 224 4/13/2022
4.1.0-dev.5887 232 4/13/2022
4.1.0-dev.5794 920 4/6/2022
4.1.0-dev.5725 712 3/18/2022
4.0.0 62,407 3/18/2022
4.0.0-rc3 1,059 3/4/2022
4.0.0-rc2 795 2/25/2022
4.0.0-rc1 2,276 2/18/2022
4.0.0-dev.5709 228 3/18/2022
4.0.0-dev.5684 235 3/15/2022
4.0.0-dev.5630 221 3/4/2022
4.0.0-dev.5607 230 3/3/2022
4.0.0-dev.5579 242 2/25/2022
4.0.0-dev.5556 239 2/24/2022
4.0.0-dev.5555 234 2/24/2022
4.0.0-dev.5497 240 2/23/2022
4.0.0-dev.5489 225 2/23/2022
4.0.0-dev.5460 224 2/23/2022
4.0.0-dev.5444 239 2/22/2022
4.0.0-dev.5333 251 2/17/2022
4.0.0-dev.5303 240 2/16/2022
4.0.0-dev.5280 230 2/16/2022
4.0.0-dev.5279 237 2/16/2022
4.0.0-dev.5241 428 2/15/2022
4.0.0-dev.5225 246 2/15/2022
4.0.0-dev.5217 227 2/15/2022
4.0.0-dev.5209 221 2/15/2022
4.0.0-dev.5200 238 2/14/2022
4.0.0-dev.5188 788 2/10/2022
4.0.0-dev.5180 450 2/10/2022
4.0.0-dev.5172 449 2/10/2022
4.0.0-dev.5130 458 2/10/2022
4.0.0-dev.5122 473 2/9/2022
4.0.0-dev.5103 463 2/9/2022
4.0.0-dev.5097 462 2/9/2022
4.0.0-dev.5091 441 2/9/2022
4.0.0-dev.5084 437 2/8/2022
3.4.0-dev.5263 235 2/15/2022
3.4.0-dev.4986 471 2/7/2022
3.4.0-dev.4968 499 2/4/2022
3.3.0 170,604 2/4/2022
3.3.0-dev.4889 492 2/3/2022
3.3.0-dev.4865 490 2/1/2022
3.3.0-dev.4823 406 1/19/2022
3.3.0-dev.4691 1,517 1/7/2022
3.3.0-dev.4557 2,301 11/26/2021
3.2.0 103,428 11/26/2021
3.2.0-dev.4533 5,152 11/24/2021
3.2.0-dev.4484 445 11/11/2021
3.2.0-dev.4475 301 11/10/2021
3.2.0-dev.4387 366 10/26/2021
3.2.0-dev.4363 331 10/22/2021
3.2.0-dev.4356 273 10/22/2021
3.1.0 97,828 10/22/2021
3.1.0-dev.4303 525 10/18/2021
3.1.0-dev.4293 305 10/15/2021
3.1.0-dev.4286 280 10/15/2021
3.1.0-dev.4240 341 10/12/2021
3.1.0-dev.4202 299 10/11/2021
3.1.0-dev.4183 305 10/11/2021
3.1.0-dev.4131 272 10/8/2021
3.1.0-dev.3999 299 10/5/2021
3.1.0-dev.3841 410 9/29/2021
3.1.0-dev.3798 488 9/17/2021
3.0.0 67,891 9/17/2021
3.0.0-dev.3726 2,628 8/31/2021
3.0.0-dev.3719 255 8/31/2021
3.0.0-dev.3671 508 8/20/2021
2.2.0-dev.3652 260 8/20/2021
2.1.0 353,428 8/20/2021
2.1.0-dev.3605 305 8/17/2021
2.1.0-dev.3584 610 8/16/2021
2.1.0-dev.3558 260 8/16/2021
2.1.0-dev.3527 408 7/29/2021
2.1.0-dev.3519 328 7/29/2021
2.1.0-dev.3490 396 7/20/2021
2.1.0-dev.3445 354 7/12/2021
2.1.0-dev.3434 332 7/9/2021
2.0.0 69,875 7/9/2021
2.0.0-dev.3401 8,193 6/25/2021
2.0.0-dev.3368 335 6/23/2021
2.0.0-dev.3361 325 6/23/2021
2.0.0-dev.3330 348 6/17/2021
2.0.0-dev.3291 332 6/16/2021
1.20.0-dev.3218 606 6/4/2021
1.19.0 185,159 6/4/2021
1.19.0-dev.3204 306 6/3/2021
1.19.0-dev.3160 296 6/2/2021
1.19.0-dev.3159 263 6/2/2021
1.19.0-dev.3084 2,593 5/7/2021
1.19.0-dev.3051 346 5/5/2021
1.19.0-dev.3044 305 5/5/2021
1.19.0-dev.3008 338 4/30/2021
1.18.0 38,033 4/30/2021
1.18.0-dev.2973 327 4/27/2021
1.18.0-dev.2930 1,288 4/16/2021
1.18.0-dev.2919 329 4/13/2021
1.18.0-dev.2893 325 4/12/2021
1.18.0-dev.2880 290 4/12/2021
1.18.0-dev.2856 321 4/7/2021
1.18.0-dev.2830 1,927 4/1/2021
1.18.0-dev.2816 292 4/1/2021
1.17.0 49,401 4/1/2021
1.17.0-dev.linq.17 961 3/18/2021
1.17.0-dev.linq.16 335 3/16/2021
1.17.0-dev.linq.15 313 3/15/2021
1.17.0-dev.linq.14 331 3/12/2021
1.17.0-dev.linq.13 370 3/11/2021
1.17.0-dev.linq.12 302 3/10/2021
1.17.0-dev.linq.11 336 3/8/2021
1.17.0-dev.2776 311 3/26/2021
1.17.0-dev.2713 277 3/25/2021
1.17.0-dev.2707 277 3/25/2021
1.17.0-dev.2652 340 3/19/2021
1.17.0-dev.2619 279 3/18/2021
1.17.0-dev.2566 281 3/16/2021
1.17.0-dev.2549 278 3/15/2021
1.17.0-dev.2505 321 3/12/2021
1.17.0-dev.2446 301 3/11/2021
1.17.0-dev.2402 299 3/8/2021
1.17.0-dev.2371 293 3/5/2021
1.16.0 19,766 3/5/2021
1.16.0-dev.linq.10 1,735 2/4/2021
1.16.0-dev.linq.9 317 2/4/2021
1.16.0-dev.2359 331 3/4/2021
1.16.0-dev.2273 299 2/12/2021
1.16.0-dev.2255 296 2/11/2021
1.16.0-dev.2228 309 2/5/2021
1.16.0-dev.2147 337 1/29/2021
1.15.0 34,340 1/29/2021
1.15.0-dev.linq.8 303 1/28/2021
1.15.0-dev.linq.7 294 1/27/2021
1.15.0-dev.linq.6 364 1/20/2021
1.15.0-dev.linq.5 344 1/19/2021
1.15.0-dev.linq.4 479 1/15/2021
1.15.0-dev.linq.3 294 1/14/2021
1.15.0-dev.linq.2 311 1/13/2021
1.15.0-dev.linq.1 321 1/12/2021
1.15.0-dev.2135 293 1/28/2021
1.15.0-dev.2009 302 1/19/2021
1.15.0-dev.1793 305 1/11/2021
1.15.0-dev.1753 351 1/7/2021
1.15.0-dev.1752 336 1/7/2021
1.15.0-dev.1705 959 12/16/2020
1.15.0-dev.1677 670 12/4/2020
1.14.0 46,581 12/4/2020
1.14.0-dev.1665 355 12/3/2020
1.14.0-dev.1648 355 12/2/2020
1.14.0-dev.1632 413 11/27/2020
1.14.0-dev.1577 555 10/30/2020
1.14.0-dev.1571 410 10/30/2020
1.13.0 15,556 10/30/2020
1.13.0-dev.1545 505 10/15/2020
1.13.0-dev.1516 566 10/8/2020
1.13.0-dev.1489 666 10/2/2020
1.13.0-dev.1478 406 10/2/2020
1.12.0 41,422 10/2/2020
1.12.0-dev.1466 347 10/1/2020
1.12.0-dev.1421 648 9/23/2020
1.12.0-dev.1345 412 9/18/2020
1.12.0-dev.1306 419 9/15/2020
1.12.0-dev.1251 431 9/2/2020
1.12.0-dev.1216 2,043 8/14/2020
1.11.0 24,469 8/14/2020
1.11.0-dev.1205 386 8/14/2020
1.11.0-dev.1185 389 8/10/2020
1.11.0-dev.1166 439 7/28/2020
1.11.0-dev.1150 381 7/28/2020
1.11.0-dev.1144 407 7/28/2020
1.11.0-dev.1125 387 7/20/2020
1.11.0-dev.1111 383 7/17/2020
1.10.0 17,555 7/17/2020
1.10.0-dev.1098 369 7/15/2020
1.10.0-dev.1077 481 7/10/2020
1.10.0-dev.1049 489 6/29/2020
1.10.0-dev.1022 407 6/23/2020
1.10.0-dev.1021 391 6/23/2020
1.10.0-dev.990 392 6/19/2020
1.9.0 26,612 6/19/2020
1.9.0-dev.984 409 6/19/2020
1.9.0-dev.971 375 6/17/2020
1.9.0-dev.955 377 6/17/2020
1.9.0-dev.886 395 6/10/2020
1.9.0-dev.848 415 6/8/2020
1.9.0-dev.842 368 6/8/2020
1.9.0-dev.836 365 6/8/2020
1.9.0-dev.786 1,352 5/27/2020
1.9.0-dev.762 679 5/15/2020
1.8.0 18,804 5/15/2020
1.8.0-dev.748 394 5/12/2020
1.8.0-dev.669 652 4/22/2020
1.8.0-dev.668 382 4/21/2020
1.8.0-dev.661 378 4/20/2020
1.8.0-dev.650 373 4/20/2020
1.8.0-dev.639 386 4/20/2020
1.8.0-dev.620 383 4/17/2020
1.7.0 15,502 4/17/2020
1.7.0-dev.608 412 4/16/2020
1.7.0-dev.574 384 4/14/2020
1.7.0-dev.563 384 4/14/2020
1.7.0-dev.534 390 4/6/2020
1.7.0-dev.528 396 4/6/2020
1.7.0-dev.512 433 4/3/2020
1.7.0-dev.495 396 3/30/2020
1.7.0-dev.469 1,249 3/13/2020
1.6.0 3,038 3/13/2020
1.6.0-dev.458 423 3/13/2020
1.6.0-dev.443 414 3/9/2020
1.6.0-dev.422 426 2/28/2020
1.6.0-dev.410 424 2/27/2020
1.6.0-dev.404 434 2/27/2020
1.6.0-dev.356 423 2/14/2020
1.5.0 2,252 2/14/2020
1.5.0-dev.349 399 2/14/2020
1.5.0-dev.341 402 2/12/2020
1.5.0-dev.312 420 1/22/2020
1.4.0 4,176 1/17/2020
1.3.0 2,136 12/6/2019
1.2.0 6,303 11/8/2019
1.1.0 1,055 10/11/2019
1.0.0 5,947 8/23/2019