InfluxDB.Client 4.8.0-dev.9232

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.8.0-dev.9232
                    
NuGet\Install-Package InfluxDB.Client -Version 4.8.0-dev.9232
                    
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.8.0-dev.9232" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="InfluxDB.Client" Version="4.8.0-dev.9232" />
                    
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.8.0-dev.9232
                    
#r "nuget: InfluxDB.Client, 4.8.0-dev.9232"
                    
#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.8.0-dev.9232
                    
#: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.8.0-dev.9232&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=InfluxDB.Client&version=4.8.0-dev.9232&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 (36)

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

Package Downloads
InfluxDB.Client.Linq

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

NBomber.Sinks.InfluxDB

NBomber sink that writes stats data to InfluxDB.

Serilog.Sinks.InfluxDB.Syslog

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

OpenTelemetry.Exporter.InfluxDB

An OpenTelemetry .NET exporter that exports to InfluxDB.

AspNetCore.HealthChecks.InfluxDB

HealthChecks.InfluxDB is the health check package for InfluxDB.

GitHub repositories (10)

Showing the top 10 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
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.
ConcreteMC/Alex
A Minecraft client written in C# aimed at compatibility with MC:Java & MC:Bedrock
nickbabcock/OhmGraphite
Expose hardware sensor data to Graphite / InfluxDB / Prometheus / Postgres / Timescaledb
RapidScada/scada-v6
Contains Rapid SCADA 6 source code.
dotnetcore/mocha
Mocha is an application performance monitor tools based on OpenTelemetry, which also provides a scalable platform for observability data analysis and storage.
Ladder99/fanuc-driver
Configurable Fanuc Focas data collector and post processor.
Version Downloads Last Updated
4.19.0-dev.15190 8,066 12/5/2024
4.19.0-dev.15189 123 12/5/2024
4.19.0-dev.15188 103 12/5/2024
4.19.0-dev.15178 108 12/5/2024
4.19.0-dev.15177 119 12/5/2024
4.19.0-dev.14906 1,927 10/2/2024
4.19.0-dev.14897 95 10/2/2024
4.19.0-dev.14896 112 10/2/2024
4.19.0-dev.14895 152 10/2/2024
4.19.0-dev.14811 345 9/13/2024
4.18.0 994,494 9/13/2024
4.18.0-dev.14769 188 9/4/2024
4.18.0-dev.14743 117 9/3/2024
4.18.0-dev.14694 118 9/3/2024
4.18.0-dev.14693 95 9/3/2024
4.18.0-dev.14692 117 9/3/2024
4.18.0-dev.14618 119 9/2/2024
4.18.0-dev.14609 113 9/2/2024
4.18.0-dev.14592 96 9/2/2024
4.18.0-dev.14446 1,561 8/19/2024
4.18.0-dev.14414 483 8/12/2024
4.17.0 146,708 8/12/2024
4.17.0-dev.headers.read.1 274 7/22/2024
4.17.0-dev.14350 106 8/5/2024
4.17.0-dev.14333 84 8/5/2024
4.17.0-dev.14300 79 8/5/2024
4.17.0-dev.14291 96 8/5/2024
4.17.0-dev.14189 157 7/23/2024
4.17.0-dev.14179 133 7/22/2024
4.17.0-dev.14101 364 7/1/2024
4.17.0-dev.14100 106 7/1/2024
4.17.0-dev.14044 143 6/24/2024
4.16.0 204,757 6/24/2024
4.16.0-dev.13990 4,144 6/3/2024
4.16.0-dev.13973 127 6/3/2024
4.16.0-dev.13972 123 6/3/2024
4.16.0-dev.13963 131 6/3/2024
4.16.0-dev.13962 128 6/3/2024
4.16.0-dev.13881 107 6/3/2024
4.16.0-dev.13775 240 5/17/2024
4.16.0-dev.13702 127 5/17/2024
4.15.0 92,976 5/17/2024
4.15.0-dev.13674 119 5/14/2024
4.15.0-dev.13567 1,552 4/2/2024
4.15.0-dev.13558 129 4/2/2024
4.15.0-dev.13525 125 4/2/2024
4.15.0-dev.13524 110 4/2/2024
4.15.0-dev.13433 351 3/7/2024
4.15.0-dev.13432 124 3/7/2024
4.15.0-dev.13407 152 3/7/2024
4.15.0-dev.13390 124 3/7/2024
4.15.0-dev.13388 106 3/7/2024
4.15.0-dev.13282 294 3/6/2024
4.15.0-dev.13257 126 3/6/2024
4.15.0-dev.13113 1,197 2/1/2024
4.15.0-dev.13104 112 2/1/2024
4.15.0-dev.13081 119 2/1/2024
4.15.0-dev.13040 188 2/1/2024
4.15.0-dev.13039 124 2/1/2024
4.15.0-dev.12863 2,130 1/8/2024
4.15.0-dev.12846 120 1/8/2024
4.15.0-dev.12837 147 1/8/2024
4.15.0-dev.12726 2,924 12/1/2023
4.15.0-dev.12725 140 12/1/2023
4.15.0-dev.12724 147 12/1/2023
4.15.0-dev.12691 135 12/1/2023
4.15.0-dev.12658 161 12/1/2023
4.15.0-dev.12649 140 12/1/2023
4.15.0-dev.12624 122 12/1/2023
4.15.0-dev.12471 1,215 11/7/2023
4.15.0-dev.12462 123 11/7/2023
4.14.0 587,293 11/7/2023
4.14.0-dev.12437 145 11/7/2023
4.14.0-dev.12343 180 11/2/2023
4.14.0-dev.12310 141 11/2/2023
4.14.0-dev.12284 398 11/1/2023
4.14.0-dev.12235 147 11/1/2023
4.14.0-dev.12226 146 11/1/2023
4.14.0-dev.11972 5,771 8/8/2023
4.14.0-dev.11915 247 7/31/2023
4.14.0-dev.11879 230 7/28/2023
4.13.0 354,118 7/28/2023
4.13.0-dev.11854 184 7/28/2023
4.13.0-dev.11814 432 7/21/2023
4.13.0-dev.11771 238 7/19/2023
4.13.0-dev.11770 196 7/19/2023
4.13.0-dev.11728 196 7/18/2023
4.13.0-dev.11686 297 7/17/2023
4.13.0-dev.11685 162 7/17/2023
4.13.0-dev.11676 204 7/17/2023
4.13.0-dev.11479 2,278 6/27/2023
4.13.0-dev.11478 195 6/27/2023
4.13.0-dev.11477 179 6/27/2023
4.13.0-dev.11396 535 6/19/2023
4.13.0-dev.11395 195 6/19/2023
4.13.0-dev.11342 473 6/15/2023
4.13.0-dev.11330 370 6/12/2023
4.13.0-dev.11305 208 6/12/2023
4.13.0-dev.11296 200 6/12/2023
4.13.0-dev.11217 469 6/6/2023
4.13.0-dev.11089 404 5/30/2023
4.13.0-dev.11064 219 5/30/2023
4.13.0-dev.10998 238 5/29/2023
4.13.0-dev.10989 191 5/29/2023
4.13.0-dev.10871 993 5/8/2023
4.13.0-dev.10870 180 5/8/2023
4.13.0-dev.10819 354 4/28/2023
4.12.0 212,984 4/28/2023
4.12.0-dev.10777 262 4/27/2023
4.12.0-dev.10768 223 4/27/2023
4.12.0-dev.10759 217 4/27/2023
4.12.0-dev.10742 199 4/27/2023
4.12.0-dev.10685 190 4/27/2023
4.12.0-dev.10684 209 4/27/2023
4.12.0-dev.10643 195 4/27/2023
4.12.0-dev.10642 206 4/27/2023
4.12.0-dev.10569 208 4/27/2023
4.12.0-dev.10193 1,854 2/23/2023
4.11.0 128,727 2/23/2023
4.11.0-dev.10176 302 2/23/2023
4.11.0-dev.10059 3,277 1/26/2023
4.10.0 78,678 1/26/2023
4.10.0-dev.10033 258 1/25/2023
4.10.0-dev.10032 230 1/25/2023
4.10.0-dev.10031 243 1/25/2023
4.10.0-dev.9936 3,787 12/26/2022
4.10.0-dev.9935 257 12/26/2022
4.10.0-dev.9881 270 12/21/2022
4.10.0-dev.9880 213 12/21/2022
4.10.0-dev.9818 697 12/16/2022
4.10.0-dev.9773 423 12/12/2022
4.10.0-dev.9756 233 12/12/2022
4.10.0-dev.9693 461 12/6/2022
4.9.0 247,638 12/6/2022
4.9.0-dev.9684 216 12/6/2022
4.9.0-dev.9666 225 12/6/2022
4.9.0-dev.9617 230 12/6/2022
4.9.0-dev.9478 293 12/5/2022
4.9.0-dev.9469 247 12/5/2022
4.9.0-dev.9444 206 12/5/2022
4.9.0-dev.9411 211 12/5/2022
4.9.0-dev.9350 250 12/1/2022
4.8.0 6,077 12/1/2022
4.8.0-dev.9324 307 11/30/2022
4.8.0-dev.9232 270 11/28/2022
4.8.0-dev.9223 209 11/28/2022
4.8.0-dev.9222 231 11/28/2022
4.8.0-dev.9117 522 11/21/2022
4.8.0-dev.9108 241 11/21/2022
4.8.0-dev.9099 221 11/21/2022
4.8.0-dev.9029 287 11/16/2022
4.8.0-dev.8971 252 11/15/2022
4.8.0-dev.8961 223 11/14/2022
4.8.0-dev.8928 252 11/14/2022
4.8.0-dev.8899 218 11/14/2022
4.8.0-dev.8898 228 11/14/2022
4.8.0-dev.8839 242 11/14/2022
4.8.0-dev.8740 348 11/7/2022
4.8.0-dev.8725 232 11/7/2022
4.8.0-dev.8648 469 11/3/2022
4.7.0 118,183 11/3/2022
4.7.0-dev.8625 386 11/2/2022
4.7.0-dev.8594 383 10/31/2022
4.7.0-dev.8579 230 10/31/2022
4.7.0-dev.8557 224 10/31/2022
4.7.0-dev.8540 224 10/31/2022
4.7.0-dev.8518 225 10/31/2022
4.7.0-dev.8517 224 10/31/2022
4.7.0-dev.8509 224 10/31/2022
4.7.0-dev.8377 919 10/26/2022
4.7.0-dev.8360 227 10/25/2022
4.7.0-dev.8350 276 10/24/2022
4.7.0-dev.8335 246 10/24/2022
4.7.0-dev.8334 247 10/24/2022
4.7.0-dev.8223 332 10/19/2022
4.7.0-dev.8178 337 10/17/2022
4.7.0-dev.8170 241 10/17/2022
4.7.0-dev.8148 241 10/17/2022
4.7.0-dev.8133 216 10/17/2022
4.7.0-dev.8097 233 10/17/2022
4.7.0-dev.8034 1,189 10/11/2022
4.7.0-dev.8025 273 10/11/2022
4.7.0-dev.8009 314 10/10/2022
4.7.0-dev.8001 258 10/10/2022
4.7.0-dev.7959 300 10/4/2022
4.7.0-dev.7905 438 9/30/2022
4.7.0-dev.7875 295 9/29/2022
4.6.0 53,120 9/29/2022
4.6.0-dev.7832 290 9/29/2022
4.6.0-dev.7817 238 9/29/2022
4.6.0-dev.7779 306 9/27/2022
4.6.0-dev.7778 247 9/27/2022
4.6.0-dev.7734 286 9/26/2022
4.6.0-dev.7733 223 9/26/2022
4.6.0-dev.7677 341 9/20/2022
4.6.0-dev.7650 327 9/16/2022
4.6.0-dev.7626 302 9/14/2022
4.6.0-dev.7618 281 9/14/2022
4.6.0-dev.7574 251 9/13/2022
4.6.0-dev.7572 229 9/13/2022
4.6.0-dev.7528 380 9/12/2022
4.6.0-dev.7502 271 9/9/2022
4.6.0-dev.7479 305 9/8/2022
4.6.0-dev.7471 233 9/8/2022
4.6.0-dev.7447 287 9/7/2022
4.6.0-dev.7425 228 9/7/2022
4.6.0-dev.7395 249 9/6/2022
4.6.0-dev.7344 455 8/31/2022
4.6.0-dev.7329 241 8/31/2022
4.6.0-dev.7292 240 8/30/2022
4.6.0-dev.7240 411 8/29/2022
4.5.0 78,562 8/29/2022
4.5.0-dev.7216 274 8/27/2022
4.5.0-dev.7147 394 8/22/2022
4.5.0-dev.7134 454 8/17/2022
4.5.0-dev.7096 274 8/15/2022
4.5.0-dev.7070 373 8/11/2022
4.5.0-dev.7040 284 8/10/2022
4.5.0-dev.7011 344 8/3/2022
4.5.0-dev.6987 242 8/1/2022
4.5.0-dev.6962 252 7/29/2022
4.4.0 52,466 7/29/2022
4.4.0-dev.6901 442 7/25/2022
4.4.0-dev.6843 479 7/19/2022
4.4.0-dev.6804 271 7/19/2022
4.4.0-dev.6789 240 7/19/2022
4.4.0-dev.6760 258 7/19/2022
4.4.0-dev.6705 342 7/14/2022
4.4.0-dev.6663 1,263 6/24/2022
4.4.0-dev.6655 283 6/24/2022
4.3.0 233,202 6/24/2022
4.3.0-dev.multiple.buckets3 419 6/21/2022
4.3.0-dev.multiple.buckets2 365 6/17/2022
4.3.0-dev.multiple.buckets1 259 6/17/2022
4.3.0-dev.6631 267 6/22/2022
4.3.0-dev.6623 252 6/22/2022
4.3.0-dev.6374 579 6/13/2022
4.3.0-dev.6286 1,123 5/20/2022
4.2.0 84,815 5/20/2022
4.2.0-dev.6257 732 5/13/2022
4.2.0-dev.6248 284 5/12/2022
4.2.0-dev.6233 369 5/12/2022
4.2.0-dev.6194 370 5/10/2022
4.2.0-dev.6193 266 5/10/2022
4.2.0-dev.6158 3,159 5/6/2022
4.2.0-dev.6135 317 5/6/2022
4.2.0-dev.6091 652 4/28/2022
4.2.0-dev.6048 294 4/28/2022
4.2.0-dev.6047 278 4/28/2022
4.2.0-dev.5966 632 4/25/2022
4.2.0-dev.5938 523 4/19/2022
4.1.0 49,355 4/19/2022
4.1.0-dev.5910 491 4/13/2022
4.1.0-dev.5888 289 4/13/2022
4.1.0-dev.5887 288 4/13/2022
4.1.0-dev.5794 963 4/6/2022
4.1.0-dev.5725 779 3/18/2022
4.0.0 64,223 3/18/2022
4.0.0-rc3 1,125 3/4/2022
4.0.0-rc2 918 2/25/2022
4.0.0-rc1 2,364 2/18/2022
4.0.0-dev.5709 290 3/18/2022
4.0.0-dev.5684 289 3/15/2022
4.0.0-dev.5630 280 3/4/2022
4.0.0-dev.5607 286 3/3/2022
4.0.0-dev.5579 294 2/25/2022
4.0.0-dev.5556 291 2/24/2022
4.0.0-dev.5555 298 2/24/2022
4.0.0-dev.5497 300 2/23/2022
4.0.0-dev.5489 281 2/23/2022
4.0.0-dev.5460 268 2/23/2022
4.0.0-dev.5444 306 2/22/2022
4.0.0-dev.5333 316 2/17/2022
4.0.0-dev.5303 300 2/16/2022
4.0.0-dev.5280 270 2/16/2022
4.0.0-dev.5279 290 2/16/2022
4.0.0-dev.5241 494 2/15/2022
4.0.0-dev.5225 290 2/15/2022
4.0.0-dev.5217 289 2/15/2022
4.0.0-dev.5209 260 2/15/2022
4.0.0-dev.5200 297 2/14/2022
4.0.0-dev.5188 845 2/10/2022
4.0.0-dev.5180 491 2/10/2022
4.0.0-dev.5172 495 2/10/2022
4.0.0-dev.5130 525 2/10/2022
4.0.0-dev.5122 532 2/9/2022
4.0.0-dev.5103 515 2/9/2022
4.0.0-dev.5097 518 2/9/2022
4.0.0-dev.5091 482 2/9/2022
4.0.0-dev.5084 484 2/8/2022
3.4.0-dev.5263 278 2/15/2022
3.4.0-dev.4986 536 2/7/2022
3.4.0-dev.4968 554 2/4/2022
3.3.0 176,664 2/4/2022
3.3.0-dev.4889 555 2/3/2022
3.3.0-dev.4865 559 2/1/2022
3.3.0-dev.4823 450 1/19/2022
3.3.0-dev.4691 1,574 1/7/2022
3.3.0-dev.4557 2,362 11/26/2021
3.2.0 106,641 11/26/2021
3.2.0-dev.4533 5,196 11/24/2021
3.2.0-dev.4484 502 11/11/2021
3.2.0-dev.4475 347 11/10/2021
3.2.0-dev.4387 404 10/26/2021
3.2.0-dev.4363 386 10/22/2021
3.2.0-dev.4356 315 10/22/2021
3.1.0 98,618 10/22/2021
3.1.0-dev.4303 584 10/18/2021
3.1.0-dev.4293 368 10/15/2021
3.1.0-dev.4286 339 10/15/2021
3.1.0-dev.4240 401 10/12/2021
3.1.0-dev.4202 355 10/11/2021
3.1.0-dev.4183 372 10/11/2021
3.1.0-dev.4131 319 10/8/2021
3.1.0-dev.3999 354 10/5/2021
3.1.0-dev.3841 454 9/29/2021
3.1.0-dev.3798 535 9/17/2021
3.0.0 74,719 9/17/2021
3.0.0-dev.3726 2,694 8/31/2021
3.0.0-dev.3719 319 8/31/2021
3.0.0-dev.3671 577 8/20/2021
2.2.0-dev.3652 301 8/20/2021
2.1.0 386,793 8/20/2021
2.1.0-dev.3605 370 8/17/2021
2.1.0-dev.3584 652 8/16/2021
2.1.0-dev.3558 303 8/16/2021
2.1.0-dev.3527 463 7/29/2021
2.1.0-dev.3519 392 7/29/2021
2.1.0-dev.3490 455 7/20/2021
2.1.0-dev.3445 411 7/12/2021
2.1.0-dev.3434 382 7/9/2021
2.0.0 70,691 7/9/2021
2.0.0-dev.3401 8,433 6/25/2021
2.0.0-dev.3368 396 6/23/2021
2.0.0-dev.3361 381 6/23/2021
2.0.0-dev.3330 413 6/17/2021
2.0.0-dev.3291 385 6/16/2021
1.20.0-dev.3218 647 6/4/2021
1.19.0 243,872 6/4/2021
1.19.0-dev.3204 363 6/3/2021
1.19.0-dev.3160 364 6/2/2021
1.19.0-dev.3159 303 6/2/2021
1.19.0-dev.3084 2,634 5/7/2021
1.19.0-dev.3051 394 5/5/2021
1.19.0-dev.3044 364 5/5/2021
1.19.0-dev.3008 382 4/30/2021
1.18.0 38,466 4/30/2021
1.18.0-dev.2973 368 4/27/2021
1.18.0-dev.2930 1,348 4/16/2021
1.18.0-dev.2919 386 4/13/2021
1.18.0-dev.2893 387 4/12/2021
1.18.0-dev.2880 330 4/12/2021
1.18.0-dev.2856 380 4/7/2021
1.18.0-dev.2830 1,985 4/1/2021
1.18.0-dev.2816 357 4/1/2021
1.17.0 50,524 4/1/2021
1.17.0-dev.linq.17 1,011 3/18/2021
1.17.0-dev.linq.16 399 3/16/2021
1.17.0-dev.linq.15 361 3/15/2021
1.17.0-dev.linq.14 398 3/12/2021
1.17.0-dev.linq.13 428 3/11/2021
1.17.0-dev.linq.12 367 3/10/2021
1.17.0-dev.linq.11 399 3/8/2021
1.17.0-dev.2776 363 3/26/2021
1.17.0-dev.2713 317 3/25/2021
1.17.0-dev.2707 337 3/25/2021
1.17.0-dev.2652 393 3/19/2021
1.17.0-dev.2619 337 3/18/2021
1.17.0-dev.2566 343 3/16/2021
1.17.0-dev.2549 320 3/15/2021
1.17.0-dev.2505 383 3/12/2021
1.17.0-dev.2446 347 3/11/2021
1.17.0-dev.2402 343 3/8/2021
1.17.0-dev.2371 341 3/5/2021
1.16.0 19,930 3/5/2021
1.16.0-dev.linq.10 1,779 2/4/2021
1.16.0-dev.linq.9 366 2/4/2021
1.16.0-dev.2359 390 3/4/2021
1.16.0-dev.2273 343 2/12/2021
1.16.0-dev.2255 353 2/11/2021
1.16.0-dev.2228 352 2/5/2021
1.16.0-dev.2147 386 1/29/2021
1.15.0 34,994 1/29/2021
1.15.0-dev.linq.8 354 1/28/2021
1.15.0-dev.linq.7 356 1/27/2021
1.15.0-dev.linq.6 413 1/20/2021
1.15.0-dev.linq.5 411 1/19/2021
1.15.0-dev.linq.4 545 1/15/2021
1.15.0-dev.linq.3 361 1/14/2021
1.15.0-dev.linq.2 385 1/13/2021
1.15.0-dev.linq.1 391 1/12/2021
1.15.0-dev.2135 357 1/28/2021
1.15.0-dev.2009 350 1/19/2021
1.15.0-dev.1793 355 1/11/2021
1.15.0-dev.1753 422 1/7/2021
1.15.0-dev.1752 384 1/7/2021
1.15.0-dev.1705 1,019 12/16/2020
1.15.0-dev.1677 729 12/4/2020
1.14.0 46,783 12/4/2020
1.14.0-dev.1665 429 12/3/2020
1.14.0-dev.1648 425 12/2/2020
1.14.0-dev.1632 463 11/27/2020
1.14.0-dev.1577 614 10/30/2020
1.14.0-dev.1571 474 10/30/2020
1.13.0 15,736 10/30/2020
1.13.0-dev.1545 566 10/15/2020
1.13.0-dev.1516 614 10/8/2020
1.13.0-dev.1489 736 10/2/2020
1.13.0-dev.1478 463 10/2/2020
1.12.0 42,516 10/2/2020
1.12.0-dev.1466 394 10/1/2020
1.12.0-dev.1421 710 9/23/2020
1.12.0-dev.1345 460 9/18/2020
1.12.0-dev.1306 480 9/15/2020
1.12.0-dev.1251 497 9/2/2020
1.12.0-dev.1216 2,102 8/14/2020
1.11.0 24,678 8/14/2020
1.11.0-dev.1205 444 8/14/2020
1.11.0-dev.1185 455 8/10/2020
1.11.0-dev.1166 489 7/28/2020
1.11.0-dev.1150 426 7/28/2020
1.11.0-dev.1144 468 7/28/2020
1.11.0-dev.1125 452 7/20/2020
1.11.0-dev.1111 429 7/17/2020
1.10.0 17,769 7/17/2020
1.10.0-dev.1098 430 7/15/2020
1.10.0-dev.1077 528 7/10/2020
1.10.0-dev.1049 541 6/29/2020
1.10.0-dev.1022 452 6/23/2020
1.10.0-dev.1021 435 6/23/2020
1.10.0-dev.990 439 6/19/2020
1.9.0 27,931 6/19/2020
1.9.0-dev.984 460 6/19/2020
1.9.0-dev.971 435 6/17/2020
1.9.0-dev.955 440 6/17/2020
1.9.0-dev.886 439 6/10/2020
1.9.0-dev.848 479 6/8/2020
1.9.0-dev.842 418 6/8/2020
1.9.0-dev.836 414 6/8/2020
1.9.0-dev.786 1,402 5/27/2020
1.9.0-dev.762 728 5/15/2020
1.8.0 19,082 5/15/2020
1.8.0-dev.748 464 5/12/2020
1.8.0-dev.669 712 4/22/2020
1.8.0-dev.668 433 4/21/2020
1.8.0-dev.661 422 4/20/2020
1.8.0-dev.650 420 4/20/2020
1.8.0-dev.639 438 4/20/2020
1.8.0-dev.620 449 4/17/2020
1.7.0 15,806 4/17/2020
1.7.0-dev.608 460 4/16/2020
1.7.0-dev.574 442 4/14/2020
1.7.0-dev.563 452 4/14/2020
1.7.0-dev.534 436 4/6/2020
1.7.0-dev.528 442 4/6/2020
1.7.0-dev.512 497 4/3/2020
1.7.0-dev.495 441 3/30/2020
1.7.0-dev.469 1,311 3/13/2020
1.6.0 3,164 3/13/2020
1.6.0-dev.458 485 3/13/2020
1.6.0-dev.443 461 3/9/2020
1.6.0-dev.422 472 2/28/2020
1.6.0-dev.410 469 2/27/2020
1.6.0-dev.404 493 2/27/2020
1.6.0-dev.356 485 2/14/2020
1.5.0 2,516 2/14/2020
1.5.0-dev.349 465 2/14/2020
1.5.0-dev.341 452 2/12/2020
1.5.0-dev.312 482 1/22/2020
1.4.0 4,507 1/17/2020
1.3.0 2,240 12/6/2019
1.2.0 6,429 11/8/2019
1.1.0 1,162 10/11/2019
1.0.0 6,661 8/23/2019