InfluxDB.Client 4.19.0-dev.15178

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.15178                
NuGet\Install-Package InfluxDB.Client -Version 4.19.0-dev.15178                
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.15178" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add InfluxDB.Client --version 4.19.0-dev.15178                
#r "nuget: InfluxDB.Client, 4.19.0-dev.15178"                
#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.19.0-dev.15178&prerelease

// Install InfluxDB.Client as a Cake Tool
#tool nuget:?package=InfluxDB.Client&version=4.19.0-dev.15178&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 = 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. 
.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 (31)

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 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.15190 353 12/5/2024
4.19.0-dev.15189 51 12/5/2024
4.19.0-dev.15188 44 12/5/2024
4.19.0-dev.15178 44 12/5/2024
4.19.0-dev.15177 49 12/5/2024
4.19.0-dev.14906 1,314 10/2/2024
4.19.0-dev.14897 51 10/2/2024
4.19.0-dev.14896 58 10/2/2024
4.19.0-dev.14895 74 10/2/2024
4.19.0-dev.14811 231 9/13/2024
4.18.0 121,768 9/13/2024
4.18.0-dev.14769 128 9/4/2024
4.18.0-dev.14743 77 9/3/2024
4.18.0-dev.14694 70 9/3/2024
4.18.0-dev.14693 58 9/3/2024
4.18.0-dev.14692 60 9/3/2024
4.18.0-dev.14618 79 9/2/2024
4.18.0-dev.14609 64 9/2/2024
4.18.0-dev.14592 59 9/2/2024
4.18.0-dev.14446 503 8/19/2024
4.18.0-dev.14414 275 8/12/2024
4.17.0 70,380 8/12/2024
4.17.0-dev.headers.read.1 197 7/22/2024
4.17.0-dev.14350 50 8/5/2024
4.17.0-dev.14333 50 8/5/2024
4.17.0-dev.14300 49 8/5/2024
4.17.0-dev.14291 47 8/5/2024
4.17.0-dev.14189 93 7/23/2024
4.17.0-dev.14179 71 7/22/2024
4.17.0-dev.14101 234 7/1/2024
4.17.0-dev.14100 67 7/1/2024
4.17.0-dev.14044 109 6/24/2024
4.16.0 51,815 6/24/2024
4.16.0-dev.13990 2,022 6/3/2024
4.16.0-dev.13973 69 6/3/2024
4.16.0-dev.13972 63 6/3/2024
4.16.0-dev.13963 75 6/3/2024
4.16.0-dev.13962 67 6/3/2024
4.16.0-dev.13881 66 6/3/2024
4.16.0-dev.13775 174 5/17/2024
4.16.0-dev.13702 79 5/17/2024
4.15.0 44,285 5/17/2024
4.15.0-dev.13674 88 5/14/2024
4.15.0-dev.13567 1,226 4/2/2024
4.15.0-dev.13558 69 4/2/2024
4.15.0-dev.13525 67 4/2/2024
4.15.0-dev.13524 71 4/2/2024
4.15.0-dev.13433 240 3/7/2024
4.15.0-dev.13432 73 3/7/2024
4.15.0-dev.13407 103 3/7/2024
4.15.0-dev.13390 71 3/7/2024
4.15.0-dev.13388 69 3/7/2024
4.15.0-dev.13282 258 3/6/2024
4.15.0-dev.13257 83 3/6/2024
4.15.0-dev.13113 1,137 2/1/2024
4.15.0-dev.13104 75 2/1/2024
4.15.0-dev.13081 75 2/1/2024
4.15.0-dev.13040 139 2/1/2024
4.15.0-dev.13039 76 2/1/2024
4.15.0-dev.12863 2,077 1/8/2024
4.15.0-dev.12846 84 1/8/2024
4.15.0-dev.12837 81 1/8/2024
4.15.0-dev.12726 2,680 12/1/2023
4.15.0-dev.12725 91 12/1/2023
4.15.0-dev.12724 84 12/1/2023
4.15.0-dev.12691 90 12/1/2023
4.15.0-dev.12658 97 12/1/2023
4.15.0-dev.12649 83 12/1/2023
4.15.0-dev.12624 85 12/1/2023
4.15.0-dev.12471 1,039 11/7/2023
4.15.0-dev.12462 88 11/7/2023
4.14.0 474,565 11/7/2023
4.14.0-dev.12437 88 11/7/2023
4.14.0-dev.12343 134 11/2/2023
4.14.0-dev.12310 89 11/2/2023
4.14.0-dev.12284 356 11/1/2023
4.14.0-dev.12235 109 11/1/2023
4.14.0-dev.12226 88 11/1/2023
4.14.0-dev.11972 5,632 8/8/2023
4.14.0-dev.11915 153 7/31/2023
4.14.0-dev.11879 170 7/28/2023
4.13.0 284,427 7/28/2023
4.13.0-dev.11854 109 7/28/2023
4.13.0-dev.11814 364 7/21/2023
4.13.0-dev.11771 155 7/19/2023
4.13.0-dev.11770 114 7/19/2023
4.13.0-dev.11728 134 7/18/2023
4.13.0-dev.11686 211 7/17/2023
4.13.0-dev.11685 101 7/17/2023
4.13.0-dev.11676 112 7/17/2023
4.13.0-dev.11479 2,039 6/27/2023
4.13.0-dev.11478 109 6/27/2023
4.13.0-dev.11477 110 6/27/2023
4.13.0-dev.11396 465 6/19/2023
4.13.0-dev.11395 101 6/19/2023
4.13.0-dev.11342 354 6/15/2023
4.13.0-dev.11330 289 6/12/2023
4.13.0-dev.11305 106 6/12/2023
4.13.0-dev.11296 108 6/12/2023
4.13.0-dev.11217 380 6/6/2023
4.13.0-dev.11089 299 5/30/2023
4.13.0-dev.11064 130 5/30/2023
4.13.0-dev.10998 169 5/29/2023
4.13.0-dev.10989 124 5/29/2023
4.13.0-dev.10871 884 5/8/2023
4.13.0-dev.10870 102 5/8/2023
4.13.0-dev.10819 281 4/28/2023
4.12.0 177,859 4/28/2023
4.12.0-dev.10777 141 4/27/2023
4.12.0-dev.10768 122 4/27/2023
4.12.0-dev.10759 116 4/27/2023
4.12.0-dev.10742 97 4/27/2023
4.12.0-dev.10685 108 4/27/2023
4.12.0-dev.10684 112 4/27/2023
4.12.0-dev.10643 119 4/27/2023
4.12.0-dev.10642 103 4/27/2023
4.12.0-dev.10569 104 4/27/2023
4.12.0-dev.10193 1,755 2/23/2023
4.11.0 114,666 2/23/2023
4.11.0-dev.10176 187 2/23/2023
4.11.0-dev.10059 3,170 1/26/2023
4.10.0 70,433 1/26/2023
4.10.0-dev.10033 150 1/25/2023
4.10.0-dev.10032 129 1/25/2023
4.10.0-dev.10031 140 1/25/2023
4.10.0-dev.9936 3,592 12/26/2022
4.10.0-dev.9935 147 12/26/2022
4.10.0-dev.9881 188 12/21/2022
4.10.0-dev.9880 128 12/21/2022
4.10.0-dev.9818 619 12/16/2022
4.10.0-dev.9773 304 12/12/2022
4.10.0-dev.9756 123 12/12/2022
4.10.0-dev.9693 371 12/6/2022
4.9.0 202,859 12/6/2022
4.9.0-dev.9684 119 12/6/2022
4.9.0-dev.9666 131 12/6/2022
4.9.0-dev.9617 144 12/6/2022
4.9.0-dev.9478 209 12/5/2022
4.9.0-dev.9469 146 12/5/2022
4.9.0-dev.9444 109 12/5/2022
4.9.0-dev.9411 131 12/5/2022
4.9.0-dev.9350 167 12/1/2022
4.8.0 5,731 12/1/2022
4.8.0-dev.9324 211 11/30/2022
4.8.0-dev.9232 191 11/28/2022
4.8.0-dev.9223 128 11/28/2022
4.8.0-dev.9222 123 11/28/2022
4.8.0-dev.9117 413 11/21/2022
4.8.0-dev.9108 131 11/21/2022
4.8.0-dev.9099 131 11/21/2022
4.8.0-dev.9029 203 11/16/2022
4.8.0-dev.8971 133 11/15/2022
4.8.0-dev.8961 138 11/14/2022
4.8.0-dev.8928 141 11/14/2022
4.8.0-dev.8899 141 11/14/2022
4.8.0-dev.8898 151 11/14/2022
4.8.0-dev.8839 140 11/14/2022
4.8.0-dev.8740 252 11/7/2022
4.8.0-dev.8725 129 11/7/2022
4.8.0-dev.8648 369 11/3/2022
4.7.0 104,609 11/3/2022
4.7.0-dev.8625 277 11/2/2022
4.7.0-dev.8594 288 10/31/2022
4.7.0-dev.8579 127 10/31/2022
4.7.0-dev.8557 117 10/31/2022
4.7.0-dev.8540 133 10/31/2022
4.7.0-dev.8518 128 10/31/2022
4.7.0-dev.8517 127 10/31/2022
4.7.0-dev.8509 124 10/31/2022
4.7.0-dev.8377 821 10/26/2022
4.7.0-dev.8360 149 10/25/2022
4.7.0-dev.8350 185 10/24/2022
4.7.0-dev.8335 139 10/24/2022
4.7.0-dev.8334 138 10/24/2022
4.7.0-dev.8223 230 10/19/2022
4.7.0-dev.8178 250 10/17/2022
4.7.0-dev.8170 129 10/17/2022
4.7.0-dev.8148 135 10/17/2022
4.7.0-dev.8133 127 10/17/2022
4.7.0-dev.8097 118 10/17/2022
4.7.0-dev.8034 962 10/11/2022
4.7.0-dev.8025 157 10/11/2022
4.7.0-dev.8009 210 10/10/2022
4.7.0-dev.8001 145 10/10/2022
4.7.0-dev.7959 213 10/4/2022
4.7.0-dev.7905 336 9/30/2022
4.7.0-dev.7875 183 9/29/2022
4.6.0 48,545 9/29/2022
4.6.0-dev.7832 177 9/29/2022
4.6.0-dev.7817 141 9/29/2022
4.6.0-dev.7779 199 9/27/2022
4.6.0-dev.7778 154 9/27/2022
4.6.0-dev.7734 169 9/26/2022
4.6.0-dev.7733 138 9/26/2022
4.6.0-dev.7677 244 9/20/2022
4.6.0-dev.7650 236 9/16/2022
4.6.0-dev.7626 209 9/14/2022
4.6.0-dev.7618 191 9/14/2022
4.6.0-dev.7574 140 9/13/2022
4.6.0-dev.7572 125 9/13/2022
4.6.0-dev.7528 275 9/12/2022
4.6.0-dev.7502 168 9/9/2022
4.6.0-dev.7479 198 9/8/2022
4.6.0-dev.7471 143 9/8/2022
4.6.0-dev.7447 201 9/7/2022
4.6.0-dev.7425 138 9/7/2022
4.6.0-dev.7395 163 9/6/2022
4.6.0-dev.7344 343 8/31/2022
4.6.0-dev.7329 126 8/31/2022
4.6.0-dev.7292 141 8/30/2022
4.6.0-dev.7240 323 8/29/2022
4.5.0 66,027 8/29/2022
4.5.0-dev.7216 155 8/27/2022
4.5.0-dev.7147 313 8/22/2022
4.5.0-dev.7134 351 8/17/2022
4.5.0-dev.7096 187 8/15/2022
4.5.0-dev.7070 284 8/11/2022
4.5.0-dev.7040 197 8/10/2022
4.5.0-dev.7011 247 8/3/2022
4.5.0-dev.6987 155 8/1/2022
4.5.0-dev.6962 167 7/29/2022
4.4.0 49,827 7/29/2022
4.4.0-dev.6901 346 7/25/2022
4.4.0-dev.6843 388 7/19/2022
4.4.0-dev.6804 155 7/19/2022
4.4.0-dev.6789 148 7/19/2022
4.4.0-dev.6760 143 7/19/2022
4.4.0-dev.6705 232 7/14/2022
4.4.0-dev.6663 1,133 6/24/2022
4.4.0-dev.6655 164 6/24/2022
4.3.0 182,461 6/24/2022
4.3.0-dev.multiple.buckets3 301 6/21/2022
4.3.0-dev.multiple.buckets2 273 6/17/2022
4.3.0-dev.multiple.buckets1 144 6/17/2022
4.3.0-dev.6631 155 6/22/2022
4.3.0-dev.6623 140 6/22/2022
4.3.0-dev.6374 464 6/13/2022
4.3.0-dev.6286 999 5/20/2022
4.2.0 73,129 5/20/2022
4.2.0-dev.6257 619 5/13/2022
4.2.0-dev.6248 155 5/12/2022
4.2.0-dev.6233 246 5/12/2022
4.2.0-dev.6194 253 5/10/2022
4.2.0-dev.6193 168 5/10/2022
4.2.0-dev.6158 3,062 5/6/2022
4.2.0-dev.6135 207 5/6/2022
4.2.0-dev.6091 539 4/28/2022
4.2.0-dev.6048 178 4/28/2022
4.2.0-dev.6047 157 4/28/2022
4.2.0-dev.5966 508 4/25/2022
4.2.0-dev.5938 405 4/19/2022
4.1.0 47,492 4/19/2022
4.1.0-dev.5910 368 4/13/2022
4.1.0-dev.5888 164 4/13/2022
4.1.0-dev.5887 172 4/13/2022
4.1.0-dev.5794 864 4/6/2022
4.1.0-dev.5725 598 3/18/2022
4.0.0 59,863 3/18/2022
4.0.0-rc3 1,003 3/4/2022
4.0.0-rc2 730 2/25/2022
4.0.0-rc1 2,212 2/18/2022
4.0.0-dev.5709 163 3/18/2022
4.0.0-dev.5684 175 3/15/2022
4.0.0-dev.5630 160 3/4/2022
4.0.0-dev.5607 170 3/3/2022
4.0.0-dev.5579 173 2/25/2022
4.0.0-dev.5556 171 2/24/2022
4.0.0-dev.5555 169 2/24/2022
4.0.0-dev.5497 172 2/23/2022
4.0.0-dev.5489 160 2/23/2022
4.0.0-dev.5460 167 2/23/2022
4.0.0-dev.5444 172 2/22/2022
4.0.0-dev.5333 184 2/17/2022
4.0.0-dev.5303 178 2/16/2022
4.0.0-dev.5280 172 2/16/2022
4.0.0-dev.5279 170 2/16/2022
4.0.0-dev.5241 353 2/15/2022
4.0.0-dev.5225 180 2/15/2022
4.0.0-dev.5217 158 2/15/2022
4.0.0-dev.5209 162 2/15/2022
4.0.0-dev.5200 175 2/14/2022
4.0.0-dev.5188 725 2/10/2022
4.0.0-dev.5180 387 2/10/2022
4.0.0-dev.5172 387 2/10/2022
4.0.0-dev.5130 393 2/10/2022
4.0.0-dev.5122 404 2/9/2022
4.0.0-dev.5103 402 2/9/2022
4.0.0-dev.5097 401 2/9/2022
4.0.0-dev.5091 383 2/9/2022
4.0.0-dev.5084 375 2/8/2022
3.4.0-dev.5263 174 2/15/2022
3.4.0-dev.4986 407 2/7/2022
3.4.0-dev.4968 438 2/4/2022
3.3.0 151,901 2/4/2022
3.3.0-dev.4889 429 2/3/2022
3.3.0-dev.4865 428 2/1/2022
3.3.0-dev.4823 343 1/19/2022
3.3.0-dev.4691 1,309 1/7/2022
3.3.0-dev.4557 2,229 11/26/2021
3.2.0 98,275 11/26/2021
3.2.0-dev.4533 5,090 11/24/2021
3.2.0-dev.4484 375 11/11/2021
3.2.0-dev.4475 236 11/10/2021
3.2.0-dev.4387 301 10/26/2021
3.2.0-dev.4363 263 10/22/2021
3.2.0-dev.4356 209 10/22/2021
3.1.0 95,356 10/22/2021
3.1.0-dev.4303 458 10/18/2021
3.1.0-dev.4293 233 10/15/2021
3.1.0-dev.4286 216 10/15/2021
3.1.0-dev.4240 270 10/12/2021
3.1.0-dev.4202 226 10/11/2021
3.1.0-dev.4183 236 10/11/2021
3.1.0-dev.4131 210 10/8/2021
3.1.0-dev.3999 230 10/5/2021
3.1.0-dev.3841 343 9/29/2021
3.1.0-dev.3798 425 9/17/2021
3.0.0 61,633 9/17/2021
3.0.0-dev.3726 2,561 8/31/2021
3.0.0-dev.3719 187 8/31/2021
3.0.0-dev.3671 437 8/20/2021
2.2.0-dev.3652 194 8/20/2021
2.1.0 299,310 8/20/2021
2.1.0-dev.3605 233 8/17/2021
2.1.0-dev.3584 546 8/16/2021
2.1.0-dev.3558 197 8/16/2021
2.1.0-dev.3527 338 7/29/2021
2.1.0-dev.3519 256 7/29/2021
2.1.0-dev.3490 328 7/20/2021
2.1.0-dev.3445 283 7/12/2021
2.1.0-dev.3434 268 7/9/2021
2.0.0 66,915 7/9/2021
2.0.0-dev.3401 7,698 6/25/2021
2.0.0-dev.3368 267 6/23/2021
2.0.0-dev.3361 253 6/23/2021
2.0.0-dev.3330 279 6/17/2021
2.0.0-dev.3291 266 6/16/2021
1.20.0-dev.3218 540 6/4/2021
1.19.0 140,951 6/4/2021
1.19.0-dev.3204 236 6/3/2021
1.19.0-dev.3160 226 6/2/2021
1.19.0-dev.3159 198 6/2/2021
1.19.0-dev.3084 2,522 5/7/2021
1.19.0-dev.3051 276 5/5/2021
1.19.0-dev.3044 232 5/5/2021
1.19.0-dev.3008 265 4/30/2021
1.18.0 36,520 4/30/2021
1.18.0-dev.2973 255 4/27/2021
1.18.0-dev.2930 1,210 4/16/2021
1.18.0-dev.2919 255 4/13/2021
1.18.0-dev.2893 250 4/12/2021
1.18.0-dev.2880 224 4/12/2021
1.18.0-dev.2856 250 4/7/2021
1.18.0-dev.2830 1,849 4/1/2021
1.18.0-dev.2816 212 4/1/2021
1.17.0 46,788 4/1/2021
1.17.0-dev.linq.17 891 3/18/2021
1.17.0-dev.linq.16 264 3/16/2021
1.17.0-dev.linq.15 245 3/15/2021
1.17.0-dev.linq.14 261 3/12/2021
1.17.0-dev.linq.13 297 3/11/2021
1.17.0-dev.linq.12 224 3/10/2021
1.17.0-dev.linq.11 262 3/8/2021
1.17.0-dev.2776 234 3/26/2021
1.17.0-dev.2713 207 3/25/2021
1.17.0-dev.2707 202 3/25/2021
1.17.0-dev.2652 263 3/19/2021
1.17.0-dev.2619 201 3/18/2021
1.17.0-dev.2566 205 3/16/2021
1.17.0-dev.2549 210 3/15/2021
1.17.0-dev.2505 243 3/12/2021
1.17.0-dev.2446 232 3/11/2021
1.17.0-dev.2402 226 3/8/2021
1.17.0-dev.2371 223 3/5/2021
1.16.0 19,475 3/5/2021
1.16.0-dev.linq.10 1,661 2/4/2021
1.16.0-dev.linq.9 244 2/4/2021
1.16.0-dev.2359 256 3/4/2021
1.16.0-dev.2273 218 2/12/2021
1.16.0-dev.2255 220 2/11/2021
1.16.0-dev.2228 231 2/5/2021
1.16.0-dev.2147 261 1/29/2021
1.15.0 33,033 1/29/2021
1.15.0-dev.linq.8 227 1/28/2021
1.15.0-dev.linq.7 217 1/27/2021
1.15.0-dev.linq.6 289 1/20/2021
1.15.0-dev.linq.5 266 1/19/2021
1.15.0-dev.linq.4 401 1/15/2021
1.15.0-dev.linq.3 214 1/14/2021
1.15.0-dev.linq.2 229 1/13/2021
1.15.0-dev.linq.1 245 1/12/2021
1.15.0-dev.2135 219 1/28/2021
1.15.0-dev.2009 227 1/19/2021
1.15.0-dev.1793 236 1/11/2021
1.15.0-dev.1753 272 1/7/2021
1.15.0-dev.1752 260 1/7/2021
1.15.0-dev.1705 879 12/16/2020
1.15.0-dev.1677 582 12/4/2020
1.14.0 46,208 12/4/2020
1.14.0-dev.1665 278 12/3/2020
1.14.0-dev.1648 275 12/2/2020
1.14.0-dev.1632 336 11/27/2020
1.14.0-dev.1577 472 10/30/2020
1.14.0-dev.1571 335 10/30/2020
1.13.0 15,211 10/30/2020
1.13.0-dev.1545 422 10/15/2020
1.13.0-dev.1516 483 10/8/2020
1.13.0-dev.1489 585 10/2/2020
1.13.0-dev.1478 324 10/2/2020
1.12.0 38,277 10/2/2020
1.12.0-dev.1466 272 10/1/2020
1.12.0-dev.1421 571 9/23/2020
1.12.0-dev.1345 338 9/18/2020
1.12.0-dev.1306 338 9/15/2020
1.12.0-dev.1251 351 9/2/2020
1.12.0-dev.1216 1,962 8/14/2020
1.11.0 24,350 8/14/2020
1.11.0-dev.1205 306 8/14/2020
1.11.0-dev.1185 308 8/10/2020
1.11.0-dev.1166 362 7/28/2020
1.11.0-dev.1150 307 7/28/2020
1.11.0-dev.1144 322 7/28/2020
1.11.0-dev.1125 306 7/20/2020
1.11.0-dev.1111 308 7/17/2020
1.10.0 17,144 7/17/2020
1.10.0-dev.1098 290 7/15/2020
1.10.0-dev.1077 402 7/10/2020
1.10.0-dev.1049 416 6/29/2020
1.10.0-dev.1022 335 6/23/2020
1.10.0-dev.1021 318 6/23/2020
1.10.0-dev.990 319 6/19/2020
1.9.0 22,019 6/19/2020
1.9.0-dev.984 335 6/19/2020
1.9.0-dev.971 292 6/17/2020
1.9.0-dev.955 295 6/17/2020
1.9.0-dev.886 316 6/10/2020
1.9.0-dev.848 336 6/8/2020
1.9.0-dev.842 292 6/8/2020
1.9.0-dev.836 292 6/8/2020
1.9.0-dev.786 1,267 5/27/2020
1.9.0-dev.762 601 5/15/2020
1.8.0 18,599 5/15/2020
1.8.0-dev.748 309 5/12/2020
1.8.0-dev.669 563 4/22/2020
1.8.0-dev.668 302 4/21/2020
1.8.0-dev.661 297 4/20/2020
1.8.0-dev.650 293 4/20/2020
1.8.0-dev.639 307 4/20/2020
1.8.0-dev.620 300 4/17/2020
1.7.0 14,713 4/17/2020
1.7.0-dev.608 329 4/16/2020
1.7.0-dev.574 295 4/14/2020
1.7.0-dev.563 296 4/14/2020
1.7.0-dev.534 310 4/6/2020
1.7.0-dev.528 315 4/6/2020
1.7.0-dev.512 347 4/3/2020
1.7.0-dev.495 314 3/30/2020
1.7.0-dev.469 1,161 3/13/2020
1.6.0 2,945 3/13/2020
1.6.0-dev.458 335 3/13/2020
1.6.0-dev.443 328 3/9/2020
1.6.0-dev.422 340 2/28/2020
1.6.0-dev.410 342 2/27/2020
1.6.0-dev.404 344 2/27/2020
1.6.0-dev.356 338 2/14/2020
1.5.0 1,724 2/14/2020
1.5.0-dev.349 317 2/14/2020
1.5.0-dev.341 320 2/12/2020
1.5.0-dev.312 333 1/22/2020
1.4.0 4,079 1/17/2020
1.3.0 2,048 12/6/2019
1.2.0 6,213 11/8/2019
1.1.0 955 10/11/2019
1.0.0 3,733 8/23/2019