InfluxDB.Client 4.14.0-dev.12437

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.14.0-dev.12437                
NuGet\Install-Package InfluxDB.Client -Version 4.14.0-dev.12437                
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.14.0-dev.12437" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add InfluxDB.Client --version 4.14.0-dev.12437                
#r "nuget: InfluxDB.Client, 4.14.0-dev.12437"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install InfluxDB.Client as a Cake Addin
#addin nuget:?package=InfluxDB.Client&version=4.14.0-dev.12437&prerelease

// Install InfluxDB.Client as a Cake Tool
#tool nuget:?package=InfluxDB.Client&version=4.14.0-dev.12437&prerelease                

InfluxDB.Client

CircleCI

The reference client that allows query, write and management (bucket, organization, users) for the InfluxDB 2.x.

Documentation

This section contains links to the client library documentation.

Features

Queries

For querying data we use QueryApi that allow perform asynchronous, streaming, synchronous and also use raw query response.

Asynchronous Query

The asynchronous query is not intended for large query results because the Flux response can be potentially unbound.

using System;
using System.Threading.Tasks;
using InfluxDB.Client;

namespace Examples
{
    public static class AsynchronousQuery
    {
        private static readonly string Token = "";

        public static async Task Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", Token);

            var flux = "from(bucket:\"temperature-sensors\") |> range(start: 0)";
            
            var queryApi = client.GetQueryApi();

            //
            // QueryData
            //
            var tables = await queryApi.QueryAsync(flux, "org_id");
            tables.ForEach(table =>
            {
                table.Records.ForEach(record =>
                {
                    Console.WriteLine($"{record.GetTime()}: {record.GetValueByKey("_value")}");
                });
            });
        }        
    }
}

The asynchronous query offers a possibility map FluxRecords to POCO:

using System;
using System.Threading.Tasks;
using InfluxDB.Client;
using InfluxDB.Client.Core;

namespace Examples
{
    public static class AsynchronousQuery
    {
        private static readonly string Token = "";

        public static async Task Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", Token);

            var flux = "from(bucket:\"temperature-sensors\") |> range(start: 0)";
            
            var queryApi = client.GetQueryApi();

            //
            // QueryData
            //
            var temperatures = await queryApi.QueryAsync<Temperature>(flux, "org_id");
            temperatures.ForEach(temperature =>
            {
                Console.WriteLine($"{temperature.Location}: {temperature.Value} at {temperature.Time}");
            });
        }  
        
        [Measurement("temperature")]
        private class Temperature
        {
            [Column("location", IsTag = true)] public string Location { get; set; }

            [Column("value")] public double Value { get; set; }

            [Column(IsTimestamp = true)] public DateTime Time { get; set; }
        }
    }
}

Streaming Query

The Streaming query offers possibility to process unbound query and allow user to handle exceptions, stop receiving more results and notify that all data arrived.

using System;
using System.Threading.Tasks;
using InfluxDB.Client;

namespace Examples
{
    public static class StreamingQuery
    {
        private static readonly string Token = "";

        public static async Task Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", Token);

            var flux = "from(bucket:\"temperature-sensors\") |> range(start: 0)";

            var queryApi = client.GetQueryApi();

            //
            // QueryData
            //
            await queryApi.QueryAsync(flux, record =>
            {
                //
                // The callback to consume a FluxRecord.
                //
                Console.WriteLine($"{record.GetTime()}: {record.GetValueByKey("_value")}");
            }, exception =>
            {
                //
                // The callback to consume any error notification.
                //
                Console.WriteLine($"Error occurred: {exception.Message}");
            }, () =>
            {
                //
                // The callback to consume a notification about successfully end of stream.
                //
                Console.WriteLine("Query completed");
            }, "org_id");
        }
    }
}

And there is also a possibility map FluxRecords to POCO:

using System;
using System.Threading.Tasks;
using InfluxDB.Client;
using InfluxDB.Client.Core;

namespace Examples
{
    public static class StreamingQuery
    {
        private static readonly string Token = "";

        public static async Task Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", Token);

            var flux = "from(bucket:\"temperature-sensors\") |> range(start: 0)";
            
            var queryApi = client.GetQueryApi();

            //
            // QueryData
            //
            await queryApi.QueryAsync<Temperature>(flux, temperature =>
            {
                //
                // The callback to consume a FluxRecord mapped to POCO.
                //
                Console.WriteLine($"{temperature.Location}: {temperature.Value} at {temperature.Time}");
            }, org: "org_id");
        }  
        
        [Measurement("temperature")]
        private class Temperature
        {
            [Column("location", IsTag = true)] public string Location { get; set; }

            [Column("value")] public double Value { get; set; }

            [Column(IsTimestamp = true)] public DateTime Time { get; set; }
        }
    }
}

Raw Query

The Raw query allows direct processing original CSV response:

using System;
using System.Threading.Tasks;
using InfluxDB.Client;

namespace Examples
{
    public static class RawQuery
    {
        private static readonly string Token = "";

        public static async Task Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", Token);

            var flux = "from(bucket:\"temperature-sensors\") |> range(start: 0)";

            var queryApi = client.GetQueryApi();

            //
            // QueryData
            //
            var csv = await queryApi.QueryRawAsync(flux, org: "org_id");
            
            Console.WriteLine($"CSV response: {csv}");
        }
    }
}

The Streaming version allows processing line by line:

using System;
using System.Threading.Tasks;
using InfluxDB.Client;

namespace Examples
{
    public static class RawQueryAsynchronous
    {
        private static readonly string Token = "";

        public static async Task Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", Token);

            var flux = "from(bucket:\"temperature-sensors\") |> range(start: 0)";

            var queryApi = client.GetQueryApi();

            //
            // QueryData
            //
            await queryApi.QueryRawAsync(flux, line =>
            {
                //
                // The callback to consume a line of CSV response
                //
                Console.WriteLine($"Response: {line}");
            }, org: "org_id");
        }
    }
}

Synchronous query

The synchronous query is not intended for large query results because the response can be potentially unbound.

using System;
using InfluxDB.Client;

namespace Examples
{
    public static class SynchronousQuery
    {
        public static void Main()
        {
            using var client = new InfluxDBClient("http://localhost:9999", "my-token");

            const string query = "from(bucket:\"my-bucket\") |> range(start: 0)";
           
            //
            // QueryData
            //
            var queryApi = client.GetQueryApiSync();
            var tables = queryApi.QuerySync(query, "my-org");
            
            //
            // Process results
            //
            tables.ForEach(table =>
            {
                table.Records.ForEach(record =>
                {
                    Console.WriteLine($"{record.GetTime()}: {record.GetValueByKey("_value")}");
                });
            });
        }
    }
}

Writes

For writing data we use WriteApi or WriteApiAsync which is simplified version of WriteApi without batching support.

WriteApi supports:

  1. writing data using InfluxDB Line Protocol, Data Point, POCO
  2. use batching for writes
  3. produces events that allow user to be notified and react to this events
    • WriteSuccessEvent - published when arrived the success response from server
    • WriteErrorEvent - published when occurs a unhandled exception from server
    • WriteRetriableErrorEvent - published when occurs a retriable error from server
    • WriteRuntimeExceptionEvent - published when occurs a runtime exception in background batch processing
  4. use GZIP compression for data

The writes are processed in batches which are configurable by WriteOptions:

Property Description Default Value
BatchSize the number of data point to collect in batch 1000
FlushInterval the number of milliseconds before the batch is written 1000
JitterInterval the number of milliseconds to increase the batch flush interval by a random amount 0
RetryInterval the number of milliseconds to retry unsuccessful write. The retry interval is used when the InfluxDB server does not specify "Retry-After" header. 5000
MaxRetries the number of max retries when write fails 3
MaxRetryDelay the maximum delay between each retry attempt in milliseconds 125_000
ExponentialBase the base for the exponential retry delay, the next delay is computed using random exponential backoff as a random value within the interval retryInterval * exponentialBase^(attempts-1) and retryInterval * exponentialBase^(attempts). Example for retryInterval=5_000, exponentialBase=2, maxRetryDelay=125_000, maxRetries=5 Retry delays are random distributed values within the ranges of [5_000-10_000, 10_000-20_000, 20_000-40_000, 40_000-80_000, 80_000-125_000] 2

Writing data

By POCO

Write Measurement into specified bucket:

using System;
using InfluxDB.Client;
using InfluxDB.Client.Api.Domain;
using InfluxDB.Client.Core;

namespace Examples
{
    public static class WritePoco
    {
        private static readonly string Token = "";

        public static void Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", Token);

            //
            // Write Data
            //
            using (var writeApi = client.GetWriteApi())
            {
                //
                // Write by POCO
                //
                var temperature = new Temperature {Location = "south", Value = 62D, Time = DateTime.UtcNow};

                writeApi.WriteMeasurement(temperature, WritePrecision.Ns, "bucket_name", "org_id");
            }
        }
        
        [Measurement("temperature")]
        private class Temperature
        {
            [Column("location", IsTag = true)] public string Location { get; set; }

            [Column("value")] public double Value { get; set; }

            [Column(IsTimestamp = true)] public DateTime Time { get; set; }
        }
    }
}
By Data Point

Write Data point into specified bucket:

using System;
using InfluxDB.Client;
using InfluxDB.Client.Api.Domain;
using InfluxDB.Client.Writes;

namespace Examples
{
    public static class WriteDataPoint
    {
        private static readonly string Token = "";

        public static void Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", Token);

            //
            // Write Data
            //
            using (var writeApi = client.GetWriteApi())
            {
                //
                // Write by Data Point
                
                var point = PointData.Measurement("temperature")
                    .Tag("location", "west")
                    .Field("value", 55D)
                    .Timestamp(DateTime.UtcNow.AddSeconds(-10), WritePrecision.Ns);
                
                writeApi.WritePoint(point, "bucket_name", "org_id");
            }
        }
    }
}

DataPoint Builder Immutability: The builder is immutable therefore won't have side effect when using for building multiple point with single builder.

using System;
using InfluxDB.Client;
using InfluxDB.Client.Api.Domain;
using InfluxDB.Client.Writes;

namespace Examples
{
    public static class WriteDataPoint
    {
        private static readonly string Token = "";

        public static void Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", Token);

            //
            // Write Data
            //
            using (var writeApi = client.GetWriteApi())
            {
                //
                // Write by Data Point
                
                var builder = PointData.Measurement("temperature")
                    .Tag("location", "west");
                
                var pointA = builder
                    .Field("value", 55D)
                    .Timestamp(DateTime.UtcNow.AddSeconds(-10), WritePrecision.Ns);
                
                writeApi.WritePoint(pointA, "bucket_name", "org_id");
                
                var pointB = builder
                    .Field("age", 32)
                    .Timestamp(DateTime.UtcNow, WritePrecision.Ns);
                
                writeApi.WritePoint(pointB, "bucket_name", "org_id");
            }
        }
    }
}
By LineProtocol

Write Line Protocol record into specified bucket:

using InfluxDB.Client;
using InfluxDB.Client.Api.Domain;

namespace Examples
{
    public static class WriteLineProtocol
    {
        private static readonly string Token = "";

        public static void Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", Token);

            //
            // Write Data
            //
            using (var writeApi = client.GetWriteApi())
            {
                //
                //
                // Write by LineProtocol
                //
                writeApi.WriteRecord("temperature,location=north value=60.0", WritePrecision.Ns,"bucket_name", "org_id");
            }
        }
    }
}
Using WriteApiAsync
using System;
using System.Threading.Tasks;
using InfluxDB.Client;
using InfluxDB.Client.Api.Domain;
using InfluxDB.Client.Core;
using InfluxDB.Client.Writes;

namespace Examples
{
    public static class WriteApiAsyncExample
    {   
        [Measurement("temperature")]
        private class Temperature
        {
            [Column("location", IsTag = true)] public string Location { get; set; }

            [Column("value")] public double Value { get; set; }

            [Column(IsTimestamp = true)] public DateTime Time { get; set; }
        }
        
        public static async Task Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", 
                            "my-user", "my-password");

            //
            // Write Data
            //
            var writeApiAsync = client.GetWriteApiAsync();

            //
            //
            // Write by LineProtocol
            //
            await writeApiAsync.WriteRecordAsync("temperature,location=north value=60.0", WritePrecision.Ns,
                "my-bucket", "my-org");

            //
            //
            // Write by Data Point
            //               
            var point = PointData.Measurement("temperature")
                            .Tag("location", "west")
                            .Field("value", 55D)
                            .Timestamp(DateTime.UtcNow.AddSeconds(-10), WritePrecision.Ns);

            await writeApiAsync.WritePointAsync(point, "my-bucket", "my-org");

            //
            // Write by POCO
            //
            var temperature = new Temperature {Location = "south", Value = 62D, Time = DateTime.UtcNow};

            await writeApiAsync.WriteMeasurementAsync(temperature, WritePrecision.Ns, "my-bucket", "my-org");

            //
            // Check written data
            //
            var tables = await influxDbClient.GetQueryApi()
                            .QueryAsync("from(bucket:\"my-bucket\") |> range(start: 0)", "my-org");
            
            tables.ForEach(table =>
            {
                var fluxRecords = table.Records;
                fluxRecords.ForEach(record =>
                {
                    Console.WriteLine($"{record.GetTime()}: {record.GetValue()}");
                });
            });
        }
    }
}
Default Tags

Sometimes is useful to store same information in every measurement e.g. hostname, location, customer. The client is able to use static value, app settings or env variable as a tag value.

The expressions:

  • California Miner - static value
  • ${version} - application settings
  • ${env.hostname} - environment property
Via Configuration file

In a configuration file you are able to specify default tags by tags element.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
        <section name="influx2" type="InfluxDB.Client.Configurations.Influx2, InfluxDB.Client" />
    </configSections>
    <appSettings>
        <add key="SensorVersion" value="v1.00"/>
    </appSettings>
    <influx2 url="http://localhost:8086"
             org="my-org"
             bucket="my-bucket"
             token="my-token"
             logLevel="BODY"
             timeout="10s">
        <tags>
            <tag name="id" value="132-987-655"/>
            <tag name="customer" value="California Miner"/>
            <tag name="hostname" value="${env.Hostname}"/>
            <tag name="sensor-version" value="${SensorVersion}"/>
        </tags>
    </influx2>
</configuration>
Via API
var options = new InfluxDBClientOptions(Url)
{
    Token = token,
    DefaultTags = new Dictionary<string, string>
    {
        {"id", "132-987-655"},
        {"customer", "California Miner"},
    }
};   
options.AddDefaultTag("hostname", "${env.Hostname}")
options.AddDefaultTags(new Dictionary<string, string>{{ "sensor-version", "${SensorVersion}" }})

Both of configurations will produce the Line protocol:

mine-sensor,id=132-987-655,customer="California Miner",hostname=example.com,sensor-version=v1.00 altitude=10

Handle the Events

Events that can be handle by WriteAPI EventHandler are:

  • WriteSuccessEvent - for success response from server
  • WriteErrorEvent - for unhandled exception from server
  • WriteRetriableErrorEvent - for retriable error from server
  • WriteRuntimeExceptionEvent - for runtime exception in background batch processing

Number of events depends on number of data points to collect in batch. The batch size is configured by BatchSize option (default size is 1000) - in case of one data point, event is handled for each point, independently on used writing method (even for mass writing of data like WriteMeasurements, WritePoints and WriteRecords).

Events can be handled by register writeApi.EventHandler or by creating custom EventListener:

Register EventHandler
writeApi.EventHandler += (sender, eventArgs) =>
{
    switch (eventArgs)
    {
        case WriteSuccessEvent successEvent:
            string data = @event.LineProtocol;
            //
            // handle success response from server
            // Console.WriteLine($"{data}");
            //
            break;
        case WriteErrorEvent error:
            string data = @error.LineProtocol;
            string errorMessage = @error.Exception.Message;
            //
            // handle unhandled exception from server
            //
            // Console.WriteLine($"{data}");
            // throw new Exception(errorMessage);
            //
            break;
        case WriteRetriableErrorEvent error:
            string data = @error.LineProtocol;
            string errorMessage = @error.Exception.Message;
            //
            // handle retrievable error from server
            //
            // Console.WriteLine($"{data}");
            // throw new Exception(errorMessage);
            //
            break;
        case WriteRuntimeExceptionEvent error:
            string errorMessage = @error.Exception.Message;
            //
            // handle runtime exception in background batch processing
            // throw new Exception(errorMessage);
            //
            break;
    }
};

//
// Write by LineProtocol
//
writeApi.WriteRecord("influxPoint,writeType=lineProtocol value=11.11" +
    $" {DateTime.UtcNow.Subtract(EpochStart).Ticks * 100}", WritePrecision.Ns, "my-bucket", "my-org");
Custom EventListener

Advantage of using custom Event Listener is possibility of waiting on handled event between different writings - for more info see EventListener.

Delete Data

Delete data from specified bucket:

using InfluxDB.Client;
using InfluxDB.Client.Api.Domain;

namespace Examples
{
    public static class WriteLineProtocol
    {
        private static readonly string Token = "";

        public static void Main()
        {
            using var client = new InfluxDBClient("http://localhost:8086", Token);

            //
            // Delete data
            //
            await client.GetDeleteApi().Delete(DateTime.UtcNow.AddMinutes(-1), DateTime.Now, "", "bucket", "org");
        }
    }
}

Filter trace verbose

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

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

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

      // My code ...
    }
  }
}

Management API

The client has following management API:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Advanced Usage

Monitoring & Alerting

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

Create Threshold Check

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

var org = ...;

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

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

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

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

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

Custom mapping of DomainObject to/from InfluxDB

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

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

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

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

            public DateTimeOffset Timestamp { get; set; }

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

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

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

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

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

                return point;
            }
        }

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

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

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

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

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

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

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

Client configuration file

A client can be configured via App.config file.

The following options are supported:

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

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

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

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

and then:

var client = InfluxDBClientFactory.Create();

Client connection string

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

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

The following options are supported:

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

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

Gzip support

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

influxDBClient.EnableGzip();

How to use WebProxy

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

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

var client = new InfluxDBClient(options);

Redirects configuration

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

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

using var client = new InfluxDBClient(options);

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

Log HTTP Request and Response

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

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

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

Version

The latest package for .NET CLI:

dotnet add package InfluxDB.Client

Or when using with Package Manager:

Install-Package InfluxDB.Client
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 is compatible. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (30)

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

Package Downloads
InfluxDB.Client.Linq

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

NBomber.Sinks.InfluxDB

NBomber sink that writes stats data to InfluxDB.

Serilog.Sinks.InfluxDB.Syslog

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

IoTSharp.HealthChecks.InfluxDB

HealthChecks.InfluxDB is the health check package for InfluxDB.

OpenTelemetry.Exporter.InfluxDB

An OpenTelemetry .NET exporter that exports to InfluxDB.

GitHub repositories (8)

Showing the top 5 popular GitHub repositories that depend on InfluxDB.Client:

Repository Stars
Xabaril/AspNetCore.Diagnostics.HealthChecks
Enterprise HealthChecks for ASP.NET Core Diagnostics Package
testcontainers/testcontainers-dotnet
A library to support tests with throwaway instances of Docker containers for all compatible .NET Standard versions.
IoTSharp/IoTSharp
IoTSharp is an open-source IoT platform for data collection, processing, visualization, and device management.
ConcreteMC/Alex
A Minecraft client written in C# aimed at compatibility with MC:Java & MC:Bedrock
melanchall/drywetmidi
.NET library to read, write, process MIDI files and to work with MIDI devices
Version Downloads Last updated
4.19.0-dev.14906 347 10/2/2024
4.19.0-dev.14897 46 10/2/2024
4.19.0-dev.14896 53 10/2/2024
4.19.0-dev.14895 66 10/2/2024
4.19.0-dev.14811 176 9/13/2024
4.18.0 53,229 9/13/2024
4.18.0-dev.14769 123 9/4/2024
4.18.0-dev.14743 72 9/3/2024
4.18.0-dev.14694 67 9/3/2024
4.18.0-dev.14693 55 9/3/2024
4.18.0-dev.14692 57 9/3/2024
4.18.0-dev.14618 68 9/2/2024
4.18.0-dev.14609 59 9/2/2024
4.18.0-dev.14592 54 9/2/2024
4.18.0-dev.14446 424 8/19/2024
4.18.0-dev.14414 173 8/12/2024
4.17.0 57,888 8/12/2024
4.17.0-dev.headers.read.1 187 7/22/2024
4.17.0-dev.14350 45 8/5/2024
4.17.0-dev.14333 45 8/5/2024
4.17.0-dev.14300 44 8/5/2024
4.17.0-dev.14291 42 8/5/2024
4.17.0-dev.14189 88 7/23/2024
4.17.0-dev.14179 60 7/22/2024
4.17.0-dev.14101 214 7/1/2024
4.17.0-dev.14100 62 7/1/2024
4.17.0-dev.14044 101 6/24/2024
4.16.0 36,998 6/24/2024
4.16.0-dev.13990 1,663 6/3/2024
4.16.0-dev.13973 62 6/3/2024
4.16.0-dev.13972 60 6/3/2024
4.16.0-dev.13963 70 6/3/2024
4.16.0-dev.13962 64 6/3/2024
4.16.0-dev.13881 63 6/3/2024
4.16.0-dev.13775 166 5/17/2024
4.16.0-dev.13702 70 5/17/2024
4.15.0 36,406 5/17/2024
4.15.0-dev.13674 85 5/14/2024
4.15.0-dev.13567 905 4/2/2024
4.15.0-dev.13558 66 4/2/2024
4.15.0-dev.13525 64 4/2/2024
4.15.0-dev.13524 68 4/2/2024
4.15.0-dev.13433 225 3/7/2024
4.15.0-dev.13432 70 3/7/2024
4.15.0-dev.13407 100 3/7/2024
4.15.0-dev.13390 68 3/7/2024
4.15.0-dev.13388 64 3/7/2024
4.15.0-dev.13282 255 3/6/2024
4.15.0-dev.13257 80 3/6/2024
4.15.0-dev.13113 1,128 2/1/2024
4.15.0-dev.13104 72 2/1/2024
4.15.0-dev.13081 72 2/1/2024
4.15.0-dev.13040 134 2/1/2024
4.15.0-dev.13039 73 2/1/2024
4.15.0-dev.12863 2,074 1/8/2024
4.15.0-dev.12846 81 1/8/2024
4.15.0-dev.12837 78 1/8/2024
4.15.0-dev.12726 2,647 12/1/2023
4.15.0-dev.12725 88 12/1/2023
4.15.0-dev.12724 81 12/1/2023
4.15.0-dev.12691 83 12/1/2023
4.15.0-dev.12658 94 12/1/2023
4.15.0-dev.12649 80 12/1/2023
4.15.0-dev.12624 82 12/1/2023
4.15.0-dev.12471 1,021 11/7/2023
4.15.0-dev.12462 84 11/7/2023
4.14.0 437,659 11/7/2023
4.14.0-dev.12437 84 11/7/2023
4.14.0-dev.12343 130 11/2/2023
4.14.0-dev.12310 85 11/2/2023
4.14.0-dev.12284 352 11/1/2023
4.14.0-dev.12235 105 11/1/2023
4.14.0-dev.12226 84 11/1/2023
4.14.0-dev.11972 5,546 8/8/2023
4.14.0-dev.11915 148 7/31/2023
4.14.0-dev.11879 165 7/28/2023
4.13.0 274,880 7/28/2023
4.13.0-dev.11854 104 7/28/2023
4.13.0-dev.11814 360 7/21/2023
4.13.0-dev.11771 151 7/19/2023
4.13.0-dev.11770 110 7/19/2023
4.13.0-dev.11728 130 7/18/2023
4.13.0-dev.11686 205 7/17/2023
4.13.0-dev.11685 93 7/17/2023
4.13.0-dev.11676 108 7/17/2023
4.13.0-dev.11479 2,021 6/27/2023
4.13.0-dev.11478 103 6/27/2023
4.13.0-dev.11477 106 6/27/2023
4.13.0-dev.11396 457 6/19/2023
4.13.0-dev.11395 95 6/19/2023
4.13.0-dev.11342 346 6/15/2023
4.13.0-dev.11330 282 6/12/2023
4.13.0-dev.11305 100 6/12/2023
4.13.0-dev.11296 102 6/12/2023
4.13.0-dev.11217 374 6/6/2023
4.13.0-dev.11089 293 5/30/2023
4.13.0-dev.11064 124 5/30/2023
4.13.0-dev.10998 163 5/29/2023
4.13.0-dev.10989 118 5/29/2023
4.13.0-dev.10871 874 5/8/2023
4.13.0-dev.10870 96 5/8/2023
4.13.0-dev.10819 275 4/28/2023
4.12.0 173,165 4/28/2023
4.12.0-dev.10777 135 4/27/2023
4.12.0-dev.10768 116 4/27/2023
4.12.0-dev.10759 110 4/27/2023
4.12.0-dev.10742 93 4/27/2023
4.12.0-dev.10685 104 4/27/2023
4.12.0-dev.10684 106 4/27/2023
4.12.0-dev.10643 113 4/27/2023
4.12.0-dev.10642 99 4/27/2023
4.12.0-dev.10569 100 4/27/2023
4.12.0-dev.10193 1,745 2/23/2023
4.11.0 112,158 2/23/2023
4.11.0-dev.10176 181 2/23/2023
4.11.0-dev.10059 3,155 1/26/2023
4.10.0 69,095 1/26/2023
4.10.0-dev.10033 146 1/25/2023
4.10.0-dev.10032 123 1/25/2023
4.10.0-dev.10031 136 1/25/2023
4.10.0-dev.9936 3,570 12/26/2022
4.10.0-dev.9935 143 12/26/2022
4.10.0-dev.9881 182 12/21/2022
4.10.0-dev.9880 122 12/21/2022
4.10.0-dev.9818 613 12/16/2022
4.10.0-dev.9773 292 12/12/2022
4.10.0-dev.9756 119 12/12/2022
4.10.0-dev.9693 365 12/6/2022
4.9.0 192,005 12/6/2022
4.9.0-dev.9684 113 12/6/2022
4.9.0-dev.9666 125 12/6/2022
4.9.0-dev.9617 140 12/6/2022
4.9.0-dev.9478 205 12/5/2022
4.9.0-dev.9469 132 12/5/2022
4.9.0-dev.9444 105 12/5/2022
4.9.0-dev.9411 125 12/5/2022
4.9.0-dev.9350 161 12/1/2022
4.8.0 5,585 12/1/2022
4.8.0-dev.9324 205 11/30/2022
4.8.0-dev.9232 185 11/28/2022
4.8.0-dev.9223 123 11/28/2022
4.8.0-dev.9222 119 11/28/2022
4.8.0-dev.9117 407 11/21/2022
4.8.0-dev.9108 125 11/21/2022
4.8.0-dev.9099 125 11/21/2022
4.8.0-dev.9029 197 11/16/2022
4.8.0-dev.8971 127 11/15/2022
4.8.0-dev.8961 131 11/14/2022
4.8.0-dev.8928 137 11/14/2022
4.8.0-dev.8899 135 11/14/2022
4.8.0-dev.8898 145 11/14/2022
4.8.0-dev.8839 134 11/14/2022
4.8.0-dev.8740 246 11/7/2022
4.8.0-dev.8725 123 11/7/2022
4.8.0-dev.8648 365 11/3/2022
4.7.0 102,635 11/3/2022
4.7.0-dev.8625 271 11/2/2022
4.7.0-dev.8594 284 10/31/2022
4.7.0-dev.8579 121 10/31/2022
4.7.0-dev.8557 111 10/31/2022
4.7.0-dev.8540 129 10/31/2022
4.7.0-dev.8518 122 10/31/2022
4.7.0-dev.8517 121 10/31/2022
4.7.0-dev.8509 118 10/31/2022
4.7.0-dev.8377 817 10/26/2022
4.7.0-dev.8360 137 10/25/2022
4.7.0-dev.8350 179 10/24/2022
4.7.0-dev.8335 133 10/24/2022
4.7.0-dev.8334 130 10/24/2022
4.7.0-dev.8223 224 10/19/2022
4.7.0-dev.8178 244 10/17/2022
4.7.0-dev.8170 125 10/17/2022
4.7.0-dev.8148 131 10/17/2022
4.7.0-dev.8133 121 10/17/2022
4.7.0-dev.8097 114 10/17/2022
4.7.0-dev.8034 948 10/11/2022
4.7.0-dev.8025 150 10/11/2022
4.7.0-dev.8009 202 10/10/2022
4.7.0-dev.8001 139 10/10/2022
4.7.0-dev.7959 206 10/4/2022
4.7.0-dev.7905 332 9/30/2022
4.7.0-dev.7875 177 9/29/2022
4.6.0 47,898 9/29/2022
4.6.0-dev.7832 171 9/29/2022
4.6.0-dev.7817 135 9/29/2022
4.6.0-dev.7779 195 9/27/2022
4.6.0-dev.7778 142 9/27/2022
4.6.0-dev.7734 163 9/26/2022
4.6.0-dev.7733 132 9/26/2022
4.6.0-dev.7677 240 9/20/2022
4.6.0-dev.7650 232 9/16/2022
4.6.0-dev.7626 205 9/14/2022
4.6.0-dev.7618 187 9/14/2022
4.6.0-dev.7574 136 9/13/2022
4.6.0-dev.7572 119 9/13/2022
4.6.0-dev.7528 269 9/12/2022
4.6.0-dev.7502 164 9/9/2022
4.6.0-dev.7479 194 9/8/2022
4.6.0-dev.7471 139 9/8/2022
4.6.0-dev.7447 195 9/7/2022
4.6.0-dev.7425 132 9/7/2022
4.6.0-dev.7395 157 9/6/2022
4.6.0-dev.7344 337 8/31/2022
4.6.0-dev.7329 120 8/31/2022
4.6.0-dev.7292 135 8/30/2022
4.6.0-dev.7240 319 8/29/2022
4.5.0 63,881 8/29/2022
4.5.0-dev.7216 149 8/27/2022
4.5.0-dev.7147 307 8/22/2022
4.5.0-dev.7134 345 8/17/2022
4.5.0-dev.7096 183 8/15/2022
4.5.0-dev.7070 280 8/11/2022
4.5.0-dev.7040 193 8/10/2022
4.5.0-dev.7011 243 8/3/2022
4.5.0-dev.6987 149 8/1/2022
4.5.0-dev.6962 161 7/29/2022
4.4.0 49,481 7/29/2022
4.4.0-dev.6901 342 7/25/2022
4.4.0-dev.6843 382 7/19/2022
4.4.0-dev.6804 147 7/19/2022
4.4.0-dev.6789 139 7/19/2022
4.4.0-dev.6760 137 7/19/2022
4.4.0-dev.6705 226 7/14/2022
4.4.0-dev.6663 1,122 6/24/2022
4.4.0-dev.6655 158 6/24/2022
4.3.0 175,899 6/24/2022
4.3.0-dev.multiple.buckets3 295 6/21/2022
4.3.0-dev.multiple.buckets2 269 6/17/2022
4.3.0-dev.multiple.buckets1 138 6/17/2022
4.3.0-dev.6631 149 6/22/2022
4.3.0-dev.6623 134 6/22/2022
4.3.0-dev.6374 460 6/13/2022
4.3.0-dev.6286 992 5/20/2022
4.2.0 71,919 5/20/2022
4.2.0-dev.6257 613 5/13/2022
4.2.0-dev.6248 151 5/12/2022
4.2.0-dev.6233 240 5/12/2022
4.2.0-dev.6194 247 5/10/2022
4.2.0-dev.6193 162 5/10/2022
4.2.0-dev.6158 3,058 5/6/2022
4.2.0-dev.6135 203 5/6/2022
4.2.0-dev.6091 533 4/28/2022
4.2.0-dev.6048 172 4/28/2022
4.2.0-dev.6047 151 4/28/2022
4.2.0-dev.5966 502 4/25/2022
4.2.0-dev.5938 399 4/19/2022
4.1.0 47,180 4/19/2022
4.1.0-dev.5910 364 4/13/2022
4.1.0-dev.5888 160 4/13/2022
4.1.0-dev.5887 166 4/13/2022
4.1.0-dev.5794 856 4/6/2022
4.1.0-dev.5725 574 3/18/2022
4.0.0 59,106 3/18/2022
4.0.0-rc3 995 3/4/2022
4.0.0-rc2 722 2/25/2022
4.0.0-rc1 2,203 2/18/2022
4.0.0-dev.5709 157 3/18/2022
4.0.0-dev.5684 169 3/15/2022
4.0.0-dev.5630 154 3/4/2022
4.0.0-dev.5607 164 3/3/2022
4.0.0-dev.5579 169 2/25/2022
4.0.0-dev.5556 167 2/24/2022
4.0.0-dev.5555 163 2/24/2022
4.0.0-dev.5497 168 2/23/2022
4.0.0-dev.5489 154 2/23/2022
4.0.0-dev.5460 161 2/23/2022
4.0.0-dev.5444 166 2/22/2022
4.0.0-dev.5333 180 2/17/2022
4.0.0-dev.5303 172 2/16/2022
4.0.0-dev.5280 166 2/16/2022
4.0.0-dev.5279 164 2/16/2022
4.0.0-dev.5241 349 2/15/2022
4.0.0-dev.5225 172 2/15/2022
4.0.0-dev.5217 154 2/15/2022
4.0.0-dev.5209 156 2/15/2022
4.0.0-dev.5200 171 2/14/2022
4.0.0-dev.5188 719 2/10/2022
4.0.0-dev.5180 381 2/10/2022
4.0.0-dev.5172 381 2/10/2022
4.0.0-dev.5130 389 2/10/2022
4.0.0-dev.5122 398 2/9/2022
4.0.0-dev.5103 396 2/9/2022
4.0.0-dev.5097 395 2/9/2022
4.0.0-dev.5091 375 2/9/2022
4.0.0-dev.5084 369 2/8/2022
3.4.0-dev.5263 168 2/15/2022
3.4.0-dev.4986 403 2/7/2022
3.4.0-dev.4968 432 2/4/2022
3.3.0 146,025 2/4/2022
3.3.0-dev.4889 425 2/3/2022
3.3.0-dev.4865 422 2/1/2022
3.3.0-dev.4823 335 1/19/2022
3.3.0-dev.4691 1,183 1/7/2022
3.3.0-dev.4557 2,222 11/26/2021
3.2.0 97,142 11/26/2021
3.2.0-dev.4533 5,084 11/24/2021
3.2.0-dev.4484 369 11/11/2021
3.2.0-dev.4475 230 11/10/2021
3.2.0-dev.4387 295 10/26/2021
3.2.0-dev.4363 257 10/22/2021
3.2.0-dev.4356 205 10/22/2021
3.1.0 94,702 10/22/2021
3.1.0-dev.4303 452 10/18/2021
3.1.0-dev.4293 229 10/15/2021
3.1.0-dev.4286 210 10/15/2021
3.1.0-dev.4240 264 10/12/2021
3.1.0-dev.4202 220 10/11/2021
3.1.0-dev.4183 230 10/11/2021
3.1.0-dev.4131 204 10/8/2021
3.1.0-dev.3999 226 10/5/2021
3.1.0-dev.3841 339 9/29/2021
3.1.0-dev.3798 419 9/17/2021
3.0.0 60,835 9/17/2021
3.0.0-dev.3726 2,551 8/31/2021
3.0.0-dev.3719 183 8/31/2021
3.0.0-dev.3671 431 8/20/2021
2.2.0-dev.3652 188 8/20/2021
2.1.0 284,089 8/20/2021
2.1.0-dev.3605 227 8/17/2021
2.1.0-dev.3584 540 8/16/2021
2.1.0-dev.3558 193 8/16/2021
2.1.0-dev.3527 332 7/29/2021
2.1.0-dev.3519 252 7/29/2021
2.1.0-dev.3490 322 7/20/2021
2.1.0-dev.3445 277 7/12/2021
2.1.0-dev.3434 262 7/9/2021
2.0.0 66,005 7/9/2021
2.0.0-dev.3401 7,630 6/25/2021
2.0.0-dev.3368 263 6/23/2021
2.0.0-dev.3361 241 6/23/2021
2.0.0-dev.3330 273 6/17/2021
2.0.0-dev.3291 261 6/16/2021
1.20.0-dev.3218 536 6/4/2021
1.19.0 133,926 6/4/2021
1.19.0-dev.3204 230 6/3/2021
1.19.0-dev.3160 221 6/2/2021
1.19.0-dev.3159 192 6/2/2021
1.19.0-dev.3084 2,516 5/7/2021
1.19.0-dev.3051 272 5/5/2021
1.19.0-dev.3044 226 5/5/2021
1.19.0-dev.3008 261 4/30/2021
1.18.0 36,209 4/30/2021
1.18.0-dev.2973 251 4/27/2021
1.18.0-dev.2930 1,206 4/16/2021
1.18.0-dev.2919 247 4/13/2021
1.18.0-dev.2893 246 4/12/2021
1.18.0-dev.2880 214 4/12/2021
1.18.0-dev.2856 244 4/7/2021
1.18.0-dev.2830 1,845 4/1/2021
1.18.0-dev.2816 208 4/1/2021
1.17.0 46,333 4/1/2021
1.17.0-dev.linq.17 887 3/18/2021
1.17.0-dev.linq.16 257 3/16/2021
1.17.0-dev.linq.15 239 3/15/2021
1.17.0-dev.linq.14 255 3/12/2021
1.17.0-dev.linq.13 290 3/11/2021
1.17.0-dev.linq.12 212 3/10/2021
1.17.0-dev.linq.11 258 3/8/2021
1.17.0-dev.2776 228 3/26/2021
1.17.0-dev.2713 195 3/25/2021
1.17.0-dev.2707 198 3/25/2021
1.17.0-dev.2652 257 3/19/2021
1.17.0-dev.2619 195 3/18/2021
1.17.0-dev.2566 198 3/16/2021
1.17.0-dev.2549 204 3/15/2021
1.17.0-dev.2505 239 3/12/2021
1.17.0-dev.2446 224 3/11/2021
1.17.0-dev.2402 220 3/8/2021
1.17.0-dev.2371 217 3/5/2021
1.16.0 19,362 3/5/2021
1.16.0-dev.linq.10 1,650 2/4/2021
1.16.0-dev.linq.9 236 2/4/2021
1.16.0-dev.2359 250 3/4/2021
1.16.0-dev.2273 210 2/12/2021
1.16.0-dev.2255 216 2/11/2021
1.16.0-dev.2228 225 2/5/2021
1.16.0-dev.2147 257 1/29/2021
1.15.0 32,793 1/29/2021
1.15.0-dev.linq.8 221 1/28/2021
1.15.0-dev.linq.7 211 1/27/2021
1.15.0-dev.linq.6 282 1/20/2021
1.15.0-dev.linq.5 260 1/19/2021
1.15.0-dev.linq.4 395 1/15/2021
1.15.0-dev.linq.3 210 1/14/2021
1.15.0-dev.linq.2 223 1/13/2021
1.15.0-dev.linq.1 239 1/12/2021
1.15.0-dev.2135 213 1/28/2021
1.15.0-dev.2009 221 1/19/2021
1.15.0-dev.1793 230 1/11/2021
1.15.0-dev.1753 266 1/7/2021
1.15.0-dev.1752 254 1/7/2021
1.15.0-dev.1705 873 12/16/2020
1.15.0-dev.1677 578 12/4/2020
1.14.0 45,701 12/4/2020
1.14.0-dev.1665 270 12/3/2020
1.14.0-dev.1648 271 12/2/2020
1.14.0-dev.1632 332 11/27/2020
1.14.0-dev.1577 465 10/30/2020
1.14.0-dev.1571 328 10/30/2020
1.13.0 15,171 10/30/2020
1.13.0-dev.1545 418 10/15/2020
1.13.0-dev.1516 478 10/8/2020
1.13.0-dev.1489 581 10/2/2020
1.13.0-dev.1478 318 10/2/2020
1.12.0 37,255 10/2/2020
1.12.0-dev.1466 264 10/1/2020
1.12.0-dev.1421 565 9/23/2020
1.12.0-dev.1345 331 9/18/2020
1.12.0-dev.1306 334 9/15/2020
1.12.0-dev.1251 345 9/2/2020
1.12.0-dev.1216 1,956 8/14/2020
1.11.0 24,297 8/14/2020
1.11.0-dev.1205 302 8/14/2020
1.11.0-dev.1185 302 8/10/2020
1.11.0-dev.1166 356 7/28/2020
1.11.0-dev.1150 302 7/28/2020
1.11.0-dev.1144 317 7/28/2020
1.11.0-dev.1125 299 7/20/2020
1.11.0-dev.1111 298 7/17/2020
1.10.0 17,131 7/17/2020
1.10.0-dev.1098 286 7/15/2020
1.10.0-dev.1077 398 7/10/2020
1.10.0-dev.1049 412 6/29/2020
1.10.0-dev.1022 329 6/23/2020
1.10.0-dev.1021 314 6/23/2020
1.10.0-dev.990 315 6/19/2020
1.9.0 20,846 6/19/2020
1.9.0-dev.984 331 6/19/2020
1.9.0-dev.971 288 6/17/2020
1.9.0-dev.955 291 6/17/2020
1.9.0-dev.886 312 6/10/2020
1.9.0-dev.848 332 6/8/2020
1.9.0-dev.842 286 6/8/2020
1.9.0-dev.836 288 6/8/2020
1.9.0-dev.786 1,263 5/27/2020
1.9.0-dev.762 597 5/15/2020
1.8.0 18,554 5/15/2020
1.8.0-dev.748 304 5/12/2020
1.8.0-dev.669 558 4/22/2020
1.8.0-dev.668 293 4/21/2020
1.8.0-dev.661 290 4/20/2020
1.8.0-dev.650 288 4/20/2020
1.8.0-dev.639 302 4/20/2020
1.8.0-dev.620 291 4/17/2020
1.7.0 14,554 4/17/2020
1.7.0-dev.608 325 4/16/2020
1.7.0-dev.574 291 4/14/2020
1.7.0-dev.563 290 4/14/2020
1.7.0-dev.534 306 4/6/2020
1.7.0-dev.528 305 4/6/2020
1.7.0-dev.512 343 4/3/2020
1.7.0-dev.495 310 3/30/2020
1.7.0-dev.469 1,157 3/13/2020
1.6.0 2,932 3/13/2020
1.6.0-dev.458 331 3/13/2020
1.6.0-dev.443 324 3/9/2020
1.6.0-dev.422 334 2/28/2020
1.6.0-dev.410 338 2/27/2020
1.6.0-dev.404 340 2/27/2020
1.6.0-dev.356 334 2/14/2020
1.5.0 1,575 2/14/2020
1.5.0-dev.349 313 2/14/2020
1.5.0-dev.341 316 2/12/2020
1.5.0-dev.312 328 1/22/2020
1.4.0 4,063 1/17/2020
1.3.0 2,037 12/6/2019
1.2.0 6,197 11/8/2019
1.1.0 942 10/11/2019
1.0.0 3,215 8/23/2019