InfluxDB.Client 4.19.0-dev.15189

This is a prerelease version of InfluxDB.Client.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package InfluxDB.Client --version 4.19.0-dev.15189
                    
NuGet\Install-Package InfluxDB.Client -Version 4.19.0-dev.15189
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="InfluxDB.Client" Version="4.19.0-dev.15189" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="InfluxDB.Client" Version="4.19.0-dev.15189" />
                    
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.19.0-dev.15189
                    
#r "nuget: InfluxDB.Client, 4.19.0-dev.15189"
                    
#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.
#addin nuget:?package=InfluxDB.Client&version=4.19.0-dev.15189&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=InfluxDB.Client&version=4.19.0-dev.15189&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");
        }
    }
}

Filter trace verbose

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

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

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

      // My code ...
    }
  }
}

Management API

The client has following management API:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Advanced Usage

Monitoring & Alerting

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

Create Threshold Check

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

var org = ...;

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

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

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

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

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

Custom mapping of DomainObject to/from InfluxDB

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

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

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

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

            public DateTimeOffset Timestamp { get; set; }

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

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

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

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

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

                return point;
            }
        }

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

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

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

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

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

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

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

Client configuration file

A client can be configured via App.config file.

The following options are supported:

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

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

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

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

and then:

var client = InfluxDBClientFactory.Create();

Client connection string

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

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

The following options are supported:

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

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

Gzip support

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

influxDBClient.EnableGzip();

How to use WebProxy

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

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

var client = new InfluxDBClient(options);

Redirects configuration

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

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

using var client = new InfluxDBClient(options);

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

Log HTTP Request and Response

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

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

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

Version

The latest package for .NET CLI:

dotnet add package InfluxDB.Client

Or when using with Package Manager:

Install-Package InfluxDB.Client
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  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,134 12/5/2024
4.19.0-dev.15189 72 12/5/2024
4.19.0-dev.15188 65 12/5/2024
4.19.0-dev.15178 62 12/5/2024
4.19.0-dev.15177 67 12/5/2024
4.19.0-dev.14906 1,835 10/2/2024
4.19.0-dev.14897 72 10/2/2024
4.19.0-dev.14896 72 10/2/2024
4.19.0-dev.14895 106 10/2/2024
4.19.0-dev.14811 302 9/13/2024
4.18.0 513,079 9/13/2024
4.18.0-dev.14769 147 9/4/2024
4.18.0-dev.14743 87 9/3/2024
4.18.0-dev.14694 83 9/3/2024
4.18.0-dev.14693 74 9/3/2024
4.18.0-dev.14692 74 9/3/2024
4.18.0-dev.14618 96 9/2/2024
4.18.0-dev.14609 83 9/2/2024
4.18.0-dev.14592 75 9/2/2024
4.18.0-dev.14446 923 8/19/2024
4.18.0-dev.14414 382 8/12/2024
4.17.0 117,556 8/12/2024
4.17.0-dev.headers.read.1 231 7/22/2024
4.17.0-dev.14350 64 8/5/2024
4.17.0-dev.14333 64 8/5/2024
4.17.0-dev.14300 59 8/5/2024
4.17.0-dev.14291 60 8/5/2024
4.17.0-dev.14189 112 7/23/2024
4.17.0-dev.14179 86 7/22/2024
4.17.0-dev.14101 283 7/1/2024
4.17.0-dev.14100 79 7/1/2024
4.17.0-dev.14044 123 6/24/2024
4.16.0 148,151 6/24/2024
4.16.0-dev.13990 3,611 6/3/2024
4.16.0-dev.13973 84 6/3/2024
4.16.0-dev.13972 80 6/3/2024
4.16.0-dev.13963 90 6/3/2024
4.16.0-dev.13962 82 6/3/2024
4.16.0-dev.13881 80 6/3/2024
4.16.0-dev.13775 190 5/17/2024
4.16.0-dev.13702 89 5/17/2024
4.15.0 74,033 5/17/2024
4.15.0-dev.13674 97 5/14/2024
4.15.0-dev.13567 1,508 4/2/2024
4.15.0-dev.13558 81 4/2/2024
4.15.0-dev.13525 86 4/2/2024
4.15.0-dev.13524 83 4/2/2024
4.15.0-dev.13433 297 3/7/2024
4.15.0-dev.13432 85 3/7/2024
4.15.0-dev.13407 114 3/7/2024
4.15.0-dev.13390 88 3/7/2024
4.15.0-dev.13388 83 3/7/2024
4.15.0-dev.13282 273 3/6/2024
4.15.0-dev.13257 100 3/6/2024
4.15.0-dev.13113 1,154 2/1/2024
4.15.0-dev.13104 87 2/1/2024
4.15.0-dev.13081 86 2/1/2024
4.15.0-dev.13040 149 2/1/2024
4.15.0-dev.13039 91 2/1/2024
4.15.0-dev.12863 2,090 1/8/2024
4.15.0-dev.12846 93 1/8/2024
4.15.0-dev.12837 97 1/8/2024
4.15.0-dev.12726 2,752 12/1/2023
4.15.0-dev.12725 102 12/1/2023
4.15.0-dev.12724 99 12/1/2023
4.15.0-dev.12691 102 12/1/2023
4.15.0-dev.12658 114 12/1/2023
4.15.0-dev.12649 98 12/1/2023
4.15.0-dev.12624 98 12/1/2023
4.15.0-dev.12471 1,083 11/7/2023
4.15.0-dev.12462 105 11/7/2023
4.14.0 547,368 11/7/2023
4.14.0-dev.12437 104 11/7/2023
4.14.0-dev.12343 143 11/2/2023
4.14.0-dev.12310 103 11/2/2023
4.14.0-dev.12284 373 11/1/2023
4.14.0-dev.12235 120 11/1/2023
4.14.0-dev.12226 101 11/1/2023
4.14.0-dev.11972 5,681 8/8/2023
4.14.0-dev.11915 176 7/31/2023
4.14.0-dev.11879 186 7/28/2023
4.13.0 322,814 7/28/2023
4.13.0-dev.11854 127 7/28/2023
4.13.0-dev.11814 389 7/21/2023
4.13.0-dev.11771 178 7/19/2023
4.13.0-dev.11770 135 7/19/2023
4.13.0-dev.11728 152 7/18/2023
4.13.0-dev.11686 231 7/17/2023
4.13.0-dev.11685 119 7/17/2023
4.13.0-dev.11676 138 7/17/2023
4.13.0-dev.11479 2,104 6/27/2023
4.13.0-dev.11478 129 6/27/2023
4.13.0-dev.11477 131 6/27/2023
4.13.0-dev.11396 487 6/19/2023
4.13.0-dev.11395 121 6/19/2023
4.13.0-dev.11342 379 6/15/2023
4.13.0-dev.11330 322 6/12/2023
4.13.0-dev.11305 137 6/12/2023
4.13.0-dev.11296 134 6/12/2023
4.13.0-dev.11217 408 6/6/2023
4.13.0-dev.11089 329 5/30/2023
4.13.0-dev.11064 157 5/30/2023
4.13.0-dev.10998 191 5/29/2023
4.13.0-dev.10989 146 5/29/2023
4.13.0-dev.10871 916 5/8/2023
4.13.0-dev.10870 124 5/8/2023
4.13.0-dev.10819 306 4/28/2023
4.12.0 196,281 4/28/2023
4.12.0-dev.10777 172 4/27/2023
4.12.0-dev.10768 150 4/27/2023
4.12.0-dev.10759 140 4/27/2023
4.12.0-dev.10742 123 4/27/2023
4.12.0-dev.10685 135 4/27/2023
4.12.0-dev.10684 136 4/27/2023
4.12.0-dev.10643 146 4/27/2023
4.12.0-dev.10642 132 4/27/2023
4.12.0-dev.10569 137 4/27/2023
4.12.0-dev.10193 1,790 2/23/2023
4.11.0 123,947 2/23/2023
4.11.0-dev.10176 220 2/23/2023
4.11.0-dev.10059 3,207 1/26/2023
4.10.0 75,101 1/26/2023
4.10.0-dev.10033 182 1/25/2023
4.10.0-dev.10032 158 1/25/2023
4.10.0-dev.10031 174 1/25/2023
4.10.0-dev.9936 3,711 12/26/2022
4.10.0-dev.9935 177 12/26/2022
4.10.0-dev.9881 215 12/21/2022
4.10.0-dev.9880 156 12/21/2022
4.10.0-dev.9818 644 12/16/2022
4.10.0-dev.9773 344 12/12/2022
4.10.0-dev.9756 154 12/12/2022
4.10.0-dev.9693 404 12/6/2022
4.9.0 231,899 12/6/2022
4.9.0-dev.9684 147 12/6/2022
4.9.0-dev.9666 154 12/6/2022
4.9.0-dev.9617 178 12/6/2022
4.9.0-dev.9478 242 12/5/2022
4.9.0-dev.9469 175 12/5/2022
4.9.0-dev.9444 138 12/5/2022
4.9.0-dev.9411 156 12/5/2022
4.9.0-dev.9350 199 12/1/2022
4.8.0 5,913 12/1/2022
4.8.0-dev.9324 242 11/30/2022
4.8.0-dev.9232 217 11/28/2022
4.8.0-dev.9223 155 11/28/2022
4.8.0-dev.9222 160 11/28/2022
4.8.0-dev.9117 446 11/21/2022
4.8.0-dev.9108 163 11/21/2022
4.8.0-dev.9099 155 11/21/2022
4.8.0-dev.9029 232 11/16/2022
4.8.0-dev.8971 166 11/15/2022
4.8.0-dev.8961 168 11/14/2022
4.8.0-dev.8928 175 11/14/2022
4.8.0-dev.8899 165 11/14/2022
4.8.0-dev.8898 175 11/14/2022
4.8.0-dev.8839 172 11/14/2022
4.8.0-dev.8740 279 11/7/2022
4.8.0-dev.8725 159 11/7/2022
4.8.0-dev.8648 395 11/3/2022
4.7.0 109,889 11/3/2022
4.7.0-dev.8625 309 11/2/2022
4.7.0-dev.8594 322 10/31/2022
4.7.0-dev.8579 157 10/31/2022
4.7.0-dev.8557 148 10/31/2022
4.7.0-dev.8540 168 10/31/2022
4.7.0-dev.8518 154 10/31/2022
4.7.0-dev.8517 153 10/31/2022
4.7.0-dev.8509 155 10/31/2022
4.7.0-dev.8377 848 10/26/2022
4.7.0-dev.8360 177 10/25/2022
4.7.0-dev.8350 215 10/24/2022
4.7.0-dev.8335 165 10/24/2022
4.7.0-dev.8334 172 10/24/2022
4.7.0-dev.8223 259 10/19/2022
4.7.0-dev.8178 280 10/17/2022
4.7.0-dev.8170 163 10/17/2022
4.7.0-dev.8148 166 10/17/2022
4.7.0-dev.8133 160 10/17/2022
4.7.0-dev.8097 148 10/17/2022
4.7.0-dev.8034 1,117 10/11/2022
4.7.0-dev.8025 196 10/11/2022
4.7.0-dev.8009 236 10/10/2022
4.7.0-dev.8001 175 10/10/2022
4.7.0-dev.7959 246 10/4/2022
4.7.0-dev.7905 368 9/30/2022
4.7.0-dev.7875 214 9/29/2022
4.6.0 51,117 9/29/2022
4.6.0-dev.7832 208 9/29/2022
4.6.0-dev.7817 170 9/29/2022
4.6.0-dev.7779 232 9/27/2022
4.6.0-dev.7778 180 9/27/2022
4.6.0-dev.7734 203 9/26/2022
4.6.0-dev.7733 165 9/26/2022
4.6.0-dev.7677 276 9/20/2022
4.6.0-dev.7650 269 9/16/2022
4.6.0-dev.7626 242 9/14/2022
4.6.0-dev.7618 223 9/14/2022
4.6.0-dev.7574 177 9/13/2022
4.6.0-dev.7572 157 9/13/2022
4.6.0-dev.7528 305 9/12/2022
4.6.0-dev.7502 202 9/9/2022
4.6.0-dev.7479 229 9/8/2022
4.6.0-dev.7471 181 9/8/2022
4.6.0-dev.7447 234 9/7/2022
4.6.0-dev.7425 169 9/7/2022
4.6.0-dev.7395 191 9/6/2022
4.6.0-dev.7344 374 8/31/2022
4.6.0-dev.7329 161 8/31/2022
4.6.0-dev.7292 170 8/30/2022
4.6.0-dev.7240 354 8/29/2022
4.5.0 72,539 8/29/2022
4.5.0-dev.7216 193 8/27/2022
4.5.0-dev.7147 341 8/22/2022
4.5.0-dev.7134 382 8/17/2022
4.5.0-dev.7096 220 8/15/2022
4.5.0-dev.7070 315 8/11/2022
4.5.0-dev.7040 230 8/10/2022
4.5.0-dev.7011 283 8/3/2022
4.5.0-dev.6987 190 8/1/2022
4.5.0-dev.6962 199 7/29/2022
4.4.0 51,069 7/29/2022
4.4.0-dev.6901 380 7/25/2022
4.4.0-dev.6843 421 7/19/2022
4.4.0-dev.6804 192 7/19/2022
4.4.0-dev.6789 180 7/19/2022
4.4.0-dev.6760 179 7/19/2022
4.4.0-dev.6705 266 7/14/2022
4.4.0-dev.6663 1,178 6/24/2022
4.4.0-dev.6655 203 6/24/2022
4.3.0 212,118 6/24/2022
4.3.0-dev.multiple.buckets3 335 6/21/2022
4.3.0-dev.multiple.buckets2 307 6/17/2022
4.3.0-dev.multiple.buckets1 180 6/17/2022
4.3.0-dev.6631 191 6/22/2022
4.3.0-dev.6623 174 6/22/2022
4.3.0-dev.6374 502 6/13/2022
4.3.0-dev.6286 1,042 5/20/2022
4.2.0 81,660 5/20/2022
4.2.0-dev.6257 655 5/13/2022
4.2.0-dev.6248 195 5/12/2022
4.2.0-dev.6233 284 5/12/2022
4.2.0-dev.6194 293 5/10/2022
4.2.0-dev.6193 206 5/10/2022
4.2.0-dev.6158 3,101 5/6/2022
4.2.0-dev.6135 246 5/6/2022
4.2.0-dev.6091 585 4/28/2022
4.2.0-dev.6048 221 4/28/2022
4.2.0-dev.6047 197 4/28/2022
4.2.0-dev.5966 550 4/25/2022
4.2.0-dev.5938 448 4/19/2022
4.1.0 48,538 4/19/2022
4.1.0-dev.5910 414 4/13/2022
4.1.0-dev.5888 205 4/13/2022
4.1.0-dev.5887 211 4/13/2022
4.1.0-dev.5794 905 4/6/2022
4.1.0-dev.5725 692 3/18/2022
4.0.0 62,110 3/18/2022
4.0.0-rc3 1,045 3/4/2022
4.0.0-rc2 776 2/25/2022
4.0.0-rc1 2,258 2/18/2022
4.0.0-dev.5709 207 3/18/2022
4.0.0-dev.5684 216 3/15/2022
4.0.0-dev.5630 202 3/4/2022
4.0.0-dev.5607 212 3/3/2022
4.0.0-dev.5579 220 2/25/2022
4.0.0-dev.5556 219 2/24/2022
4.0.0-dev.5555 218 2/24/2022
4.0.0-dev.5497 215 2/23/2022
4.0.0-dev.5489 202 2/23/2022
4.0.0-dev.5460 208 2/23/2022
4.0.0-dev.5444 220 2/22/2022
4.0.0-dev.5333 229 2/17/2022
4.0.0-dev.5303 220 2/16/2022
4.0.0-dev.5280 214 2/16/2022
4.0.0-dev.5279 217 2/16/2022
4.0.0-dev.5241 408 2/15/2022
4.0.0-dev.5225 227 2/15/2022
4.0.0-dev.5217 205 2/15/2022
4.0.0-dev.5209 207 2/15/2022
4.0.0-dev.5200 220 2/14/2022
4.0.0-dev.5188 770 2/10/2022
4.0.0-dev.5180 435 2/10/2022
4.0.0-dev.5172 435 2/10/2022
4.0.0-dev.5130 439 2/10/2022
4.0.0-dev.5122 449 2/9/2022
4.0.0-dev.5103 447 2/9/2022
4.0.0-dev.5097 444 2/9/2022
4.0.0-dev.5091 424 2/9/2022
4.0.0-dev.5084 422 2/8/2022
3.4.0-dev.5263 219 2/15/2022
3.4.0-dev.4986 453 2/7/2022
3.4.0-dev.4968 484 2/4/2022
3.3.0 168,684 2/4/2022
3.3.0-dev.4889 475 2/3/2022
3.3.0-dev.4865 472 2/1/2022
3.3.0-dev.4823 390 1/19/2022
3.3.0-dev.4691 1,493 1/7/2022
3.3.0-dev.4557 2,279 11/26/2021
3.2.0 102,662 11/26/2021
3.2.0-dev.4533 5,135 11/24/2021
3.2.0-dev.4484 425 11/11/2021
3.2.0-dev.4475 284 11/10/2021
3.2.0-dev.4387 348 10/26/2021
3.2.0-dev.4363 311 10/22/2021
3.2.0-dev.4356 255 10/22/2021
3.1.0 97,652 10/22/2021
3.1.0-dev.4303 505 10/18/2021
3.1.0-dev.4293 283 10/15/2021
3.1.0-dev.4286 262 10/15/2021
3.1.0-dev.4240 319 10/12/2021
3.1.0-dev.4202 275 10/11/2021
3.1.0-dev.4183 285 10/11/2021
3.1.0-dev.4131 254 10/8/2021
3.1.0-dev.3999 277 10/5/2021
3.1.0-dev.3841 391 9/29/2021
3.1.0-dev.3798 471 9/17/2021
3.0.0 66,410 9/17/2021
3.0.0-dev.3726 2,606 8/31/2021
3.0.0-dev.3719 233 8/31/2021
3.0.0-dev.3671 484 8/20/2021
2.2.0-dev.3652 242 8/20/2021
2.1.0 346,771 8/20/2021
2.1.0-dev.3605 284 8/17/2021
2.1.0-dev.3584 591 8/16/2021
2.1.0-dev.3558 243 8/16/2021
2.1.0-dev.3527 386 7/29/2021
2.1.0-dev.3519 305 7/29/2021
2.1.0-dev.3490 374 7/20/2021
2.1.0-dev.3445 331 7/12/2021
2.1.0-dev.3434 311 7/9/2021
2.0.0 69,698 7/9/2021
2.0.0-dev.3401 8,132 6/25/2021
2.0.0-dev.3368 316 6/23/2021
2.0.0-dev.3361 304 6/23/2021
2.0.0-dev.3330 327 6/17/2021
2.0.0-dev.3291 312 6/16/2021
1.20.0-dev.3218 588 6/4/2021
1.19.0 174,027 6/4/2021
1.19.0-dev.3204 285 6/3/2021
1.19.0-dev.3160 274 6/2/2021
1.19.0-dev.3159 246 6/2/2021
1.19.0-dev.3084 2,576 5/7/2021
1.19.0-dev.3051 327 5/5/2021
1.19.0-dev.3044 282 5/5/2021
1.19.0-dev.3008 321 4/30/2021
1.18.0 37,993 4/30/2021
1.18.0-dev.2973 310 4/27/2021
1.18.0-dev.2930 1,264 4/16/2021
1.18.0-dev.2919 309 4/13/2021
1.18.0-dev.2893 306 4/12/2021
1.18.0-dev.2880 273 4/12/2021
1.18.0-dev.2856 300 4/7/2021
1.18.0-dev.2830 1,904 4/1/2021
1.18.0-dev.2816 272 4/1/2021
1.17.0 49,280 4/1/2021
1.17.0-dev.linq.17 944 3/18/2021
1.17.0-dev.linq.16 315 3/16/2021
1.17.0-dev.linq.15 296 3/15/2021
1.17.0-dev.linq.14 311 3/12/2021
1.17.0-dev.linq.13 350 3/11/2021
1.17.0-dev.linq.12 282 3/10/2021
1.17.0-dev.linq.11 317 3/8/2021
1.17.0-dev.2776 288 3/26/2021
1.17.0-dev.2713 260 3/25/2021
1.17.0-dev.2707 257 3/25/2021
1.17.0-dev.2652 318 3/19/2021
1.17.0-dev.2619 256 3/18/2021
1.17.0-dev.2566 258 3/16/2021
1.17.0-dev.2549 261 3/15/2021
1.17.0-dev.2505 299 3/12/2021
1.17.0-dev.2446 284 3/11/2021
1.17.0-dev.2402 282 3/8/2021
1.17.0-dev.2371 275 3/5/2021
1.16.0 19,730 3/5/2021
1.16.0-dev.linq.10 1,718 2/4/2021
1.16.0-dev.linq.9 299 2/4/2021
1.16.0-dev.2359 310 3/4/2021
1.16.0-dev.2273 280 2/12/2021
1.16.0-dev.2255 277 2/11/2021
1.16.0-dev.2228 292 2/5/2021
1.16.0-dev.2147 319 1/29/2021
1.15.0 34,263 1/29/2021
1.15.0-dev.linq.8 285 1/28/2021
1.15.0-dev.linq.7 272 1/27/2021
1.15.0-dev.linq.6 347 1/20/2021
1.15.0-dev.linq.5 321 1/19/2021
1.15.0-dev.linq.4 455 1/15/2021
1.15.0-dev.linq.3 272 1/14/2021
1.15.0-dev.linq.2 289 1/13/2021
1.15.0-dev.linq.1 299 1/12/2021
1.15.0-dev.2135 274 1/28/2021
1.15.0-dev.2009 285 1/19/2021
1.15.0-dev.1793 288 1/11/2021
1.15.0-dev.1753 328 1/7/2021
1.15.0-dev.1752 316 1/7/2021
1.15.0-dev.1705 939 12/16/2020
1.15.0-dev.1677 648 12/4/2020
1.14.0 46,556 12/4/2020
1.14.0-dev.1665 333 12/3/2020
1.14.0-dev.1648 336 12/2/2020
1.14.0-dev.1632 396 11/27/2020
1.14.0-dev.1577 536 10/30/2020
1.14.0-dev.1571 391 10/30/2020
1.13.0 15,494 10/30/2020
1.13.0-dev.1545 484 10/15/2020
1.13.0-dev.1516 546 10/8/2020
1.13.0-dev.1489 644 10/2/2020
1.13.0-dev.1478 384 10/2/2020
1.12.0 41,175 10/2/2020
1.12.0-dev.1466 329 10/1/2020
1.12.0-dev.1421 627 9/23/2020
1.12.0-dev.1345 394 9/18/2020
1.12.0-dev.1306 396 9/15/2020
1.12.0-dev.1251 408 9/2/2020
1.12.0-dev.1216 2,019 8/14/2020
1.11.0 24,439 8/14/2020
1.11.0-dev.1205 366 8/14/2020
1.11.0-dev.1185 368 8/10/2020
1.11.0-dev.1166 422 7/28/2020
1.11.0-dev.1150 364 7/28/2020
1.11.0-dev.1144 386 7/28/2020
1.11.0-dev.1125 366 7/20/2020
1.11.0-dev.1111 364 7/17/2020
1.10.0 17,372 7/17/2020
1.10.0-dev.1098 347 7/15/2020
1.10.0-dev.1077 464 7/10/2020
1.10.0-dev.1049 472 6/29/2020
1.10.0-dev.1022 390 6/23/2020
1.10.0-dev.1021 373 6/23/2020
1.10.0-dev.990 376 6/19/2020
1.9.0 26,550 6/19/2020
1.9.0-dev.984 392 6/19/2020
1.9.0-dev.971 355 6/17/2020
1.9.0-dev.955 358 6/17/2020
1.9.0-dev.886 375 6/10/2020
1.9.0-dev.848 393 6/8/2020
1.9.0-dev.842 351 6/8/2020
1.9.0-dev.836 348 6/8/2020
1.9.0-dev.786 1,332 5/27/2020
1.9.0-dev.762 662 5/15/2020
1.8.0 18,769 5/15/2020
1.8.0-dev.748 372 5/12/2020
1.8.0-dev.669 630 4/22/2020
1.8.0-dev.668 364 4/21/2020
1.8.0-dev.661 360 4/20/2020
1.8.0-dev.650 355 4/20/2020
1.8.0-dev.639 368 4/20/2020
1.8.0-dev.620 363 4/17/2020
1.7.0 15,437 4/17/2020
1.7.0-dev.608 393 4/16/2020
1.7.0-dev.574 362 4/14/2020
1.7.0-dev.563 357 4/14/2020
1.7.0-dev.534 372 4/6/2020
1.7.0-dev.528 379 4/6/2020
1.7.0-dev.512 412 4/3/2020
1.7.0-dev.495 378 3/30/2020
1.7.0-dev.469 1,226 3/13/2020
1.6.0 3,015 3/13/2020
1.6.0-dev.458 399 3/13/2020
1.6.0-dev.443 396 3/9/2020
1.6.0-dev.422 407 2/28/2020
1.6.0-dev.410 405 2/27/2020
1.6.0-dev.404 408 2/27/2020
1.6.0-dev.356 401 2/14/2020
1.5.0 2,179 2/14/2020
1.5.0-dev.349 378 2/14/2020
1.5.0-dev.341 382 2/12/2020
1.5.0-dev.312 397 1/22/2020
1.4.0 4,156 1/17/2020
1.3.0 2,116 12/6/2019
1.2.0 6,279 11/8/2019
1.1.0 1,030 10/11/2019
1.0.0 5,798 8/23/2019