InfluxDB.Client 4.18.0

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

InfluxDB.Client

CircleCI

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

Documentation

This section contains links to the client library documentation.

Features

Queries

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

Asynchronous Query

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

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

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

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

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

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

The asynchronous query offers a possibility map FluxRecords to POCO:

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

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

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

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

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

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

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

Streaming Query

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

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

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

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

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

            var queryApi = client.GetQueryApi();

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

And there is also a possibility map FluxRecords to POCO:

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

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

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

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

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

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

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

Raw Query

The Raw query allows direct processing original CSV response:

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

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

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

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

            var queryApi = client.GetQueryApi();

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

The Streaming version allows processing line by line:

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

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

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

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

            var queryApi = client.GetQueryApi();

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

Synchronous query

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

using System;
using InfluxDB.Client;

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

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

Writes

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

WriteApi supports:

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

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

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

Writing data

By POCO

Write Measurement into specified bucket:

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

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

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

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

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

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

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

Write Data point into specified bucket:

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

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

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

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

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

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

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

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

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

Write Line Protocol record into specified bucket:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

The expressions:

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

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

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

Both of configurations will produce the Line protocol:

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

Handle the Events

Events that can be handle by WriteAPI EventHandler are:

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

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

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

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

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

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

Delete Data

Delete data from specified bucket:

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

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

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

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

Filter trace verbose

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

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

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

      // My code ...
    }
  }
}

Management API

The client has following management API:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Advanced Usage

Monitoring & Alerting

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

Create Threshold Check

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

var org = ...;

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

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

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

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

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

Custom mapping of DomainObject to/from InfluxDB

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

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

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

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

            public DateTimeOffset Timestamp { get; set; }

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

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

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

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

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

                return point;
            }
        }

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

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

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

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

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

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

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

Client configuration file

A client can be configured via App.config file.

The following options are supported:

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

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

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

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

and then:

var client = InfluxDBClientFactory.Create();

Client connection string

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

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

The following options are supported:

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

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

Gzip support

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

influxDBClient.EnableGzip();

How to use WebProxy

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

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

var client = new InfluxDBClient(options);

Redirects configuration

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

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

using var client = new InfluxDBClient(options);

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

Log HTTP Request and Response

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

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

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

Version

The latest package for .NET CLI:

dotnet add package InfluxDB.Client

Or when using with Package Manager:

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

NuGet packages (35)

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

Package Downloads
InfluxDB.Client.Linq

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

NBomber.Sinks.InfluxDB

NBomber sink that writes stats data to InfluxDB.

Serilog.Sinks.InfluxDB.Syslog

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

OpenTelemetry.Exporter.InfluxDB

An OpenTelemetry .NET exporter that exports to InfluxDB.

AspNetCore.HealthChecks.InfluxDB

HealthChecks.InfluxDB is the health check package for InfluxDB.

GitHub repositories (10)

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

Repository Stars
Xabaril/AspNetCore.Diagnostics.HealthChecks
Enterprise HealthChecks for ASP.NET Core Diagnostics Package
testcontainers/testcontainers-dotnet
A library to support tests with throwaway instances of Docker containers for all compatible .NET Standard versions.
IoTSharp/IoTSharp
IoTSharp is an open-source IoT platform for data collection, processing, visualization, and device management.
melanchall/drywetmidi
Swiss knife for everything MIDI related
open-telemetry/opentelemetry-dotnet-contrib
This repository contains set of components extending functionality of the OpenTelemetry .NET SDK. Instrumentation libraries, exporters, and other components can find their home here.
ConcreteMC/Alex
A Minecraft client written in C# aimed at compatibility with MC:Java & MC:Bedrock
nickbabcock/OhmGraphite
Expose hardware sensor data to Graphite / InfluxDB / Prometheus / Postgres / Timescaledb
RapidScada/scada-v6
Contains Rapid SCADA 6 source code.
dotnetcore/mocha
Mocha is an application performance monitor tools based on OpenTelemetry, which also provides a scalable platform for observability data analysis and storage.
Ladder99/fanuc-driver
Configurable Fanuc Focas data collector and post processor.
Version Downloads Last Updated
4.19.0-dev.15190 7,482 12/5/2024
4.19.0-dev.15189 119 12/5/2024
4.19.0-dev.15188 100 12/5/2024
4.19.0-dev.15178 105 12/5/2024
4.19.0-dev.15177 116 12/5/2024
4.19.0-dev.14906 1,914 10/2/2024
4.19.0-dev.14897 92 10/2/2024
4.19.0-dev.14896 106 10/2/2024
4.19.0-dev.14895 147 10/2/2024
4.19.0-dev.14811 341 9/13/2024
4.18.0 948,098 9/13/2024
4.18.0-dev.14769 185 9/4/2024
4.18.0-dev.14743 113 9/3/2024
4.18.0-dev.14694 115 9/3/2024
4.18.0-dev.14693 93 9/3/2024
4.18.0-dev.14692 114 9/3/2024
4.18.0-dev.14618 115 9/2/2024
4.18.0-dev.14609 105 9/2/2024
4.18.0-dev.14592 91 9/2/2024
4.18.0-dev.14446 1,508 8/19/2024
4.18.0-dev.14414 460 8/12/2024
4.17.0 144,668 8/12/2024
4.17.0-dev.headers.read.1 267 7/22/2024
4.17.0-dev.14350 102 8/5/2024
4.17.0-dev.14333 80 8/5/2024
4.17.0-dev.14300 76 8/5/2024
4.17.0-dev.14291 92 8/5/2024
4.17.0-dev.14189 153 7/23/2024
4.17.0-dev.14179 130 7/22/2024
4.17.0-dev.14101 359 7/1/2024
4.17.0-dev.14100 98 7/1/2024
4.17.0-dev.14044 140 6/24/2024
4.16.0 200,129 6/24/2024
4.16.0-dev.13990 4,113 6/3/2024
4.16.0-dev.13973 123 6/3/2024
4.16.0-dev.13972 120 6/3/2024
4.16.0-dev.13963 126 6/3/2024
4.16.0-dev.13962 123 6/3/2024
4.16.0-dev.13881 104 6/3/2024
4.16.0-dev.13775 235 5/17/2024
4.16.0-dev.13702 122 5/17/2024
4.15.0 91,683 5/17/2024
4.15.0-dev.13674 113 5/14/2024
4.15.0-dev.13567 1,547 4/2/2024
4.15.0-dev.13558 123 4/2/2024
4.15.0-dev.13525 121 4/2/2024
4.15.0-dev.13524 106 4/2/2024
4.15.0-dev.13433 346 3/7/2024
4.15.0-dev.13432 120 3/7/2024
4.15.0-dev.13407 148 3/7/2024
4.15.0-dev.13390 121 3/7/2024
4.15.0-dev.13388 100 3/7/2024
4.15.0-dev.13282 292 3/6/2024
4.15.0-dev.13257 121 3/6/2024
4.15.0-dev.13113 1,193 2/1/2024
4.15.0-dev.13104 107 2/1/2024
4.15.0-dev.13081 116 2/1/2024
4.15.0-dev.13040 184 2/1/2024
4.15.0-dev.13039 119 2/1/2024
4.15.0-dev.12863 2,126 1/8/2024
4.15.0-dev.12846 115 1/8/2024
4.15.0-dev.12837 142 1/8/2024
4.15.0-dev.12726 2,886 12/1/2023
4.15.0-dev.12725 136 12/1/2023
4.15.0-dev.12724 142 12/1/2023
4.15.0-dev.12691 130 12/1/2023
4.15.0-dev.12658 158 12/1/2023
4.15.0-dev.12649 136 12/1/2023
4.15.0-dev.12624 118 12/1/2023
4.15.0-dev.12471 1,212 11/7/2023
4.15.0-dev.12462 120 11/7/2023
4.14.0 584,212 11/7/2023
4.14.0-dev.12437 140 11/7/2023
4.14.0-dev.12343 177 11/2/2023
4.14.0-dev.12310 139 11/2/2023
4.14.0-dev.12284 394 11/1/2023
4.14.0-dev.12235 139 11/1/2023
4.14.0-dev.12226 143 11/1/2023
4.14.0-dev.11972 5,766 8/8/2023
4.14.0-dev.11915 240 7/31/2023
4.14.0-dev.11879 222 7/28/2023
4.13.0 351,822 7/28/2023
4.13.0-dev.11854 178 7/28/2023
4.13.0-dev.11814 427 7/21/2023
4.13.0-dev.11771 234 7/19/2023
4.13.0-dev.11770 193 7/19/2023
4.13.0-dev.11728 192 7/18/2023
4.13.0-dev.11686 293 7/17/2023
4.13.0-dev.11685 159 7/17/2023
4.13.0-dev.11676 199 7/17/2023
4.13.0-dev.11479 2,268 6/27/2023
4.13.0-dev.11478 192 6/27/2023
4.13.0-dev.11477 174 6/27/2023
4.13.0-dev.11396 530 6/19/2023
4.13.0-dev.11395 190 6/19/2023
4.13.0-dev.11342 458 6/15/2023
4.13.0-dev.11330 367 6/12/2023
4.13.0-dev.11305 203 6/12/2023
4.13.0-dev.11296 196 6/12/2023
4.13.0-dev.11217 465 6/6/2023
4.13.0-dev.11089 402 5/30/2023
4.13.0-dev.11064 218 5/30/2023
4.13.0-dev.10998 236 5/29/2023
4.13.0-dev.10989 190 5/29/2023
4.13.0-dev.10871 986 5/8/2023
4.13.0-dev.10870 179 5/8/2023
4.13.0-dev.10819 351 4/28/2023
4.12.0 211,839 4/28/2023
4.12.0-dev.10777 258 4/27/2023
4.12.0-dev.10768 218 4/27/2023
4.12.0-dev.10759 214 4/27/2023
4.12.0-dev.10742 195 4/27/2023
4.12.0-dev.10685 187 4/27/2023
4.12.0-dev.10684 206 4/27/2023
4.12.0-dev.10643 193 4/27/2023
4.12.0-dev.10642 203 4/27/2023
4.12.0-dev.10569 206 4/27/2023
4.12.0-dev.10193 1,852 2/23/2023
4.11.0 128,431 2/23/2023
4.11.0-dev.10176 300 2/23/2023
4.11.0-dev.10059 3,275 1/26/2023
4.10.0 78,344 1/26/2023
4.10.0-dev.10033 256 1/25/2023
4.10.0-dev.10032 227 1/25/2023
4.10.0-dev.10031 241 1/25/2023
4.10.0-dev.9936 3,784 12/26/2022
4.10.0-dev.9935 253 12/26/2022
4.10.0-dev.9881 268 12/21/2022
4.10.0-dev.9880 209 12/21/2022
4.10.0-dev.9818 696 12/16/2022
4.10.0-dev.9773 421 12/12/2022
4.10.0-dev.9756 229 12/12/2022
4.10.0-dev.9693 458 12/6/2022
4.9.0 246,473 12/6/2022
4.9.0-dev.9684 212 12/6/2022
4.9.0-dev.9666 223 12/6/2022
4.9.0-dev.9617 227 12/6/2022
4.9.0-dev.9478 290 12/5/2022
4.9.0-dev.9469 244 12/5/2022
4.9.0-dev.9444 203 12/5/2022
4.9.0-dev.9411 208 12/5/2022
4.9.0-dev.9350 248 12/1/2022
4.8.0 6,072 12/1/2022
4.8.0-dev.9324 304 11/30/2022
4.8.0-dev.9232 268 11/28/2022
4.8.0-dev.9223 207 11/28/2022
4.8.0-dev.9222 229 11/28/2022
4.8.0-dev.9117 520 11/21/2022
4.8.0-dev.9108 237 11/21/2022
4.8.0-dev.9099 220 11/21/2022
4.8.0-dev.9029 285 11/16/2022
4.8.0-dev.8971 247 11/15/2022
4.8.0-dev.8961 221 11/14/2022
4.8.0-dev.8928 251 11/14/2022
4.8.0-dev.8899 217 11/14/2022
4.8.0-dev.8898 227 11/14/2022
4.8.0-dev.8839 239 11/14/2022
4.8.0-dev.8740 333 11/7/2022
4.8.0-dev.8725 229 11/7/2022
4.8.0-dev.8648 467 11/3/2022
4.7.0 117,207 11/3/2022
4.7.0-dev.8625 382 11/2/2022
4.7.0-dev.8594 380 10/31/2022
4.7.0-dev.8579 228 10/31/2022
4.7.0-dev.8557 222 10/31/2022
4.7.0-dev.8540 222 10/31/2022
4.7.0-dev.8518 223 10/31/2022
4.7.0-dev.8517 220 10/31/2022
4.7.0-dev.8509 221 10/31/2022
4.7.0-dev.8377 918 10/26/2022
4.7.0-dev.8360 226 10/25/2022
4.7.0-dev.8350 275 10/24/2022
4.7.0-dev.8335 243 10/24/2022
4.7.0-dev.8334 245 10/24/2022
4.7.0-dev.8223 327 10/19/2022
4.7.0-dev.8178 336 10/17/2022
4.7.0-dev.8170 236 10/17/2022
4.7.0-dev.8148 237 10/17/2022
4.7.0-dev.8133 214 10/17/2022
4.7.0-dev.8097 231 10/17/2022
4.7.0-dev.8034 1,185 10/11/2022
4.7.0-dev.8025 270 10/11/2022
4.7.0-dev.8009 307 10/10/2022
4.7.0-dev.8001 256 10/10/2022
4.7.0-dev.7959 299 10/4/2022
4.7.0-dev.7905 436 9/30/2022
4.7.0-dev.7875 292 9/29/2022
4.6.0 52,959 9/29/2022
4.6.0-dev.7832 289 9/29/2022
4.6.0-dev.7817 235 9/29/2022
4.6.0-dev.7779 302 9/27/2022
4.6.0-dev.7778 244 9/27/2022
4.6.0-dev.7734 281 9/26/2022
4.6.0-dev.7733 221 9/26/2022
4.6.0-dev.7677 331 9/20/2022
4.6.0-dev.7650 326 9/16/2022
4.6.0-dev.7626 297 9/14/2022
4.6.0-dev.7618 279 9/14/2022
4.6.0-dev.7574 249 9/13/2022
4.6.0-dev.7572 227 9/13/2022
4.6.0-dev.7528 377 9/12/2022
4.6.0-dev.7502 268 9/9/2022
4.6.0-dev.7479 303 9/8/2022
4.6.0-dev.7471 230 9/8/2022
4.6.0-dev.7447 285 9/7/2022
4.6.0-dev.7425 226 9/7/2022
4.6.0-dev.7395 246 9/6/2022
4.6.0-dev.7344 453 8/31/2022
4.6.0-dev.7329 238 8/31/2022
4.6.0-dev.7292 239 8/30/2022
4.6.0-dev.7240 409 8/29/2022
4.5.0 77,624 8/29/2022
4.5.0-dev.7216 265 8/27/2022
4.5.0-dev.7147 392 8/22/2022
4.5.0-dev.7134 452 8/17/2022
4.5.0-dev.7096 273 8/15/2022
4.5.0-dev.7070 371 8/11/2022
4.5.0-dev.7040 282 8/10/2022
4.5.0-dev.7011 341 8/3/2022
4.5.0-dev.6987 241 8/1/2022
4.5.0-dev.6962 251 7/29/2022
4.4.0 52,369 7/29/2022
4.4.0-dev.6901 437 7/25/2022
4.4.0-dev.6843 477 7/19/2022
4.4.0-dev.6804 269 7/19/2022
4.4.0-dev.6789 236 7/19/2022
4.4.0-dev.6760 256 7/19/2022
4.4.0-dev.6705 339 7/14/2022
4.4.0-dev.6663 1,257 6/24/2022
4.4.0-dev.6655 280 6/24/2022
4.3.0 231,393 6/24/2022
4.3.0-dev.multiple.buckets3 414 6/21/2022
4.3.0-dev.multiple.buckets2 361 6/17/2022
4.3.0-dev.multiple.buckets1 255 6/17/2022
4.3.0-dev.6631 261 6/22/2022
4.3.0-dev.6623 248 6/22/2022
4.3.0-dev.6374 576 6/13/2022
4.3.0-dev.6286 1,119 5/20/2022
4.2.0 84,580 5/20/2022
4.2.0-dev.6257 726 5/13/2022
4.2.0-dev.6248 280 5/12/2022
4.2.0-dev.6233 365 5/12/2022
4.2.0-dev.6194 365 5/10/2022
4.2.0-dev.6193 264 5/10/2022
4.2.0-dev.6158 3,155 5/6/2022
4.2.0-dev.6135 313 5/6/2022
4.2.0-dev.6091 649 4/28/2022
4.2.0-dev.6048 292 4/28/2022
4.2.0-dev.6047 272 4/28/2022
4.2.0-dev.5966 626 4/25/2022
4.2.0-dev.5938 519 4/19/2022
4.1.0 49,323 4/19/2022
4.1.0-dev.5910 487 4/13/2022
4.1.0-dev.5888 286 4/13/2022
4.1.0-dev.5887 284 4/13/2022
4.1.0-dev.5794 960 4/6/2022
4.1.0-dev.5725 773 3/18/2022
4.0.0 64,073 3/18/2022
4.0.0-rc3 1,120 3/4/2022
4.0.0-rc2 914 2/25/2022
4.0.0-rc1 2,357 2/18/2022
4.0.0-dev.5709 285 3/18/2022
4.0.0-dev.5684 284 3/15/2022
4.0.0-dev.5630 275 3/4/2022
4.0.0-dev.5607 282 3/3/2022
4.0.0-dev.5579 290 2/25/2022
4.0.0-dev.5556 288 2/24/2022
4.0.0-dev.5555 290 2/24/2022
4.0.0-dev.5497 293 2/23/2022
4.0.0-dev.5489 277 2/23/2022
4.0.0-dev.5460 263 2/23/2022
4.0.0-dev.5444 298 2/22/2022
4.0.0-dev.5333 310 2/17/2022
4.0.0-dev.5303 296 2/16/2022
4.0.0-dev.5280 267 2/16/2022
4.0.0-dev.5279 287 2/16/2022
4.0.0-dev.5241 490 2/15/2022
4.0.0-dev.5225 287 2/15/2022
4.0.0-dev.5217 285 2/15/2022
4.0.0-dev.5209 257 2/15/2022
4.0.0-dev.5200 292 2/14/2022
4.0.0-dev.5188 841 2/10/2022
4.0.0-dev.5180 487 2/10/2022
4.0.0-dev.5172 492 2/10/2022
4.0.0-dev.5130 521 2/10/2022
4.0.0-dev.5122 527 2/9/2022
4.0.0-dev.5103 511 2/9/2022
4.0.0-dev.5097 515 2/9/2022
4.0.0-dev.5091 477 2/9/2022
4.0.0-dev.5084 480 2/8/2022
3.4.0-dev.5263 275 2/15/2022
3.4.0-dev.4986 530 2/7/2022
3.4.0-dev.4968 550 2/4/2022
3.3.0 176,022 2/4/2022
3.3.0-dev.4889 549 2/3/2022
3.3.0-dev.4865 552 2/1/2022
3.3.0-dev.4823 444 1/19/2022
3.3.0-dev.4691 1,570 1/7/2022
3.3.0-dev.4557 2,358 11/26/2021
3.2.0 106,352 11/26/2021
3.2.0-dev.4533 5,191 11/24/2021
3.2.0-dev.4484 499 11/11/2021
3.2.0-dev.4475 341 11/10/2021
3.2.0-dev.4387 401 10/26/2021
3.2.0-dev.4363 382 10/22/2021
3.2.0-dev.4356 310 10/22/2021
3.1.0 98,564 10/22/2021
3.1.0-dev.4303 579 10/18/2021
3.1.0-dev.4293 363 10/15/2021
3.1.0-dev.4286 335 10/15/2021
3.1.0-dev.4240 397 10/12/2021
3.1.0-dev.4202 349 10/11/2021
3.1.0-dev.4183 366 10/11/2021
3.1.0-dev.4131 314 10/8/2021
3.1.0-dev.3999 349 10/5/2021
3.1.0-dev.3841 450 9/29/2021
3.1.0-dev.3798 529 9/17/2021
3.0.0 74,114 9/17/2021
3.0.0-dev.3726 2,690 8/31/2021
3.0.0-dev.3719 314 8/31/2021
3.0.0-dev.3671 573 8/20/2021
2.2.0-dev.3652 298 8/20/2021
2.1.0 383,647 8/20/2021
2.1.0-dev.3605 364 8/17/2021
2.1.0-dev.3584 649 8/16/2021
2.1.0-dev.3558 299 8/16/2021
2.1.0-dev.3527 459 7/29/2021
2.1.0-dev.3519 387 7/29/2021
2.1.0-dev.3490 449 7/20/2021
2.1.0-dev.3445 406 7/12/2021
2.1.0-dev.3434 378 7/9/2021
2.0.0 70,652 7/9/2021
2.0.0-dev.3401 8,401 6/25/2021
2.0.0-dev.3368 390 6/23/2021
2.0.0-dev.3361 377 6/23/2021
2.0.0-dev.3330 408 6/17/2021
2.0.0-dev.3291 381 6/16/2021
1.20.0-dev.3218 644 6/4/2021
1.19.0 238,059 6/4/2021
1.19.0-dev.3204 358 6/3/2021
1.19.0-dev.3160 359 6/2/2021
1.19.0-dev.3159 299 6/2/2021
1.19.0-dev.3084 2,630 5/7/2021
1.19.0-dev.3051 390 5/5/2021
1.19.0-dev.3044 358 5/5/2021
1.19.0-dev.3008 377 4/30/2021
1.18.0 38,456 4/30/2021
1.18.0-dev.2973 364 4/27/2021
1.18.0-dev.2930 1,342 4/16/2021
1.18.0-dev.2919 380 4/13/2021
1.18.0-dev.2893 379 4/12/2021
1.18.0-dev.2880 326 4/12/2021
1.18.0-dev.2856 376 4/7/2021
1.18.0-dev.2830 1,978 4/1/2021
1.18.0-dev.2816 350 4/1/2021
1.17.0 50,376 4/1/2021
1.17.0-dev.linq.17 1,005 3/18/2021
1.17.0-dev.linq.16 394 3/16/2021
1.17.0-dev.linq.15 357 3/15/2021
1.17.0-dev.linq.14 393 3/12/2021
1.17.0-dev.linq.13 424 3/11/2021
1.17.0-dev.linq.12 363 3/10/2021
1.17.0-dev.linq.11 395 3/8/2021
1.17.0-dev.2776 358 3/26/2021
1.17.0-dev.2713 313 3/25/2021
1.17.0-dev.2707 332 3/25/2021
1.17.0-dev.2652 389 3/19/2021
1.17.0-dev.2619 332 3/18/2021
1.17.0-dev.2566 337 3/16/2021
1.17.0-dev.2549 316 3/15/2021
1.17.0-dev.2505 380 3/12/2021
1.17.0-dev.2446 343 3/11/2021
1.17.0-dev.2402 340 3/8/2021
1.17.0-dev.2371 336 3/5/2021
1.16.0 19,921 3/5/2021
1.16.0-dev.linq.10 1,775 2/4/2021
1.16.0-dev.linq.9 362 2/4/2021
1.16.0-dev.2359 386 3/4/2021
1.16.0-dev.2273 338 2/12/2021
1.16.0-dev.2255 349 2/11/2021
1.16.0-dev.2228 349 2/5/2021
1.16.0-dev.2147 380 1/29/2021
1.15.0 34,914 1/29/2021
1.15.0-dev.linq.8 348 1/28/2021
1.15.0-dev.linq.7 349 1/27/2021
1.15.0-dev.linq.6 407 1/20/2021
1.15.0-dev.linq.5 405 1/19/2021
1.15.0-dev.linq.4 541 1/15/2021
1.15.0-dev.linq.3 355 1/14/2021
1.15.0-dev.linq.2 379 1/13/2021
1.15.0-dev.linq.1 383 1/12/2021
1.15.0-dev.2135 351 1/28/2021
1.15.0-dev.2009 345 1/19/2021
1.15.0-dev.1793 348 1/11/2021
1.15.0-dev.1753 417 1/7/2021
1.15.0-dev.1752 380 1/7/2021
1.15.0-dev.1705 1,012 12/16/2020
1.15.0-dev.1677 726 12/4/2020
1.14.0 46,779 12/4/2020
1.14.0-dev.1665 420 12/3/2020
1.14.0-dev.1648 413 12/2/2020
1.14.0-dev.1632 457 11/27/2020
1.14.0-dev.1577 607 10/30/2020
1.14.0-dev.1571 469 10/30/2020
1.13.0 15,731 10/30/2020
1.13.0-dev.1545 562 10/15/2020
1.13.0-dev.1516 609 10/8/2020
1.13.0-dev.1489 730 10/2/2020
1.13.0-dev.1478 458 10/2/2020
1.12.0 42,501 10/2/2020
1.12.0-dev.1466 389 10/1/2020
1.12.0-dev.1421 705 9/23/2020
1.12.0-dev.1345 455 9/18/2020
1.12.0-dev.1306 474 9/15/2020
1.12.0-dev.1251 490 9/2/2020
1.12.0-dev.1216 2,097 8/14/2020
1.11.0 24,670 8/14/2020
1.11.0-dev.1205 440 8/14/2020
1.11.0-dev.1185 449 8/10/2020
1.11.0-dev.1166 482 7/28/2020
1.11.0-dev.1150 422 7/28/2020
1.11.0-dev.1144 463 7/28/2020
1.11.0-dev.1125 444 7/20/2020
1.11.0-dev.1111 424 7/17/2020
1.10.0 17,759 7/17/2020
1.10.0-dev.1098 425 7/15/2020
1.10.0-dev.1077 524 7/10/2020
1.10.0-dev.1049 535 6/29/2020
1.10.0-dev.1022 447 6/23/2020
1.10.0-dev.1021 430 6/23/2020
1.10.0-dev.990 433 6/19/2020
1.9.0 27,675 6/19/2020
1.9.0-dev.984 455 6/19/2020
1.9.0-dev.971 431 6/17/2020
1.9.0-dev.955 435 6/17/2020
1.9.0-dev.886 435 6/10/2020
1.9.0-dev.848 474 6/8/2020
1.9.0-dev.842 413 6/8/2020
1.9.0-dev.836 410 6/8/2020
1.9.0-dev.786 1,397 5/27/2020
1.9.0-dev.762 722 5/15/2020
1.8.0 19,071 5/15/2020
1.8.0-dev.748 457 5/12/2020
1.8.0-dev.669 706 4/22/2020
1.8.0-dev.668 428 4/21/2020
1.8.0-dev.661 417 4/20/2020
1.8.0-dev.650 415 4/20/2020
1.8.0-dev.639 433 4/20/2020
1.8.0-dev.620 441 4/17/2020
1.7.0 15,772 4/17/2020
1.7.0-dev.608 456 4/16/2020
1.7.0-dev.574 433 4/14/2020
1.7.0-dev.563 446 4/14/2020
1.7.0-dev.534 429 4/6/2020
1.7.0-dev.528 437 4/6/2020
1.7.0-dev.512 491 4/3/2020
1.7.0-dev.495 437 3/30/2020
1.7.0-dev.469 1,305 3/13/2020
1.6.0 3,158 3/13/2020
1.6.0-dev.458 477 3/13/2020
1.6.0-dev.443 457 3/9/2020
1.6.0-dev.422 468 2/28/2020
1.6.0-dev.410 464 2/27/2020
1.6.0-dev.404 488 2/27/2020
1.6.0-dev.356 480 2/14/2020
1.5.0 2,512 2/14/2020
1.5.0-dev.349 459 2/14/2020
1.5.0-dev.341 446 2/12/2020
1.5.0-dev.312 476 1/22/2020
1.4.0 4,500 1/17/2020
1.3.0 2,236 12/6/2019
1.2.0 6,424 11/8/2019
1.1.0 1,158 10/11/2019
1.0.0 6,606 8/23/2019