Skip to content

Commit

Permalink
feat: default tags (#66)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sciator authored Dec 8, 2023
1 parent b7dac41 commit 0688621
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## 0.4.0 [unreleased]

### Features

1. [#66](https://github.com/InfluxCommunity/influxdb3-csharp/pull/66): Default Tags for Writes

## 0.3.0 [2023-10-02]

### Features
Expand Down
34 changes: 34 additions & 0 deletions Client.Test/InfluxDBClientWriteTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,40 @@ public async Task NotSpecifiedOrg()
Assert.That(requests[0].RequestMessage.Query, Does.Not.ContainKey("org"));
}

[Test]
public async Task DefaultTags()
{
MockServer
.Given(Request.Create().WithPath("/api/v2/write").UsingPost())
.RespondWith(Response.Create().WithStatusCode(204));

_client = new InfluxDBClient(new ClientConfig
{
Host = MockServerUrl,
Token = "my-token",
Organization = "my-org",
Database = "my-database",
WriteOptions = new WriteOptions
{
DefaultTags = new Dictionary<string, string>()
{
{ "tag1", "default" },
{ "tag2", "default" },
}
}
});

await _client.WritePointAsync(PointData
.Measurement("cpu")
.SetTag("tag", "c")
.SetTag("tag2", "c")
.SetField("field", 1)
);

var requests = MockServer.LogEntries.ToList();
Assert.That(requests[0].RequestMessage.BodyData?.BodyAsString, Is.EqualTo("cpu,tag=c,tag1=default,tag2=c field=1i"));
}

[Test]
public async Task DatabaseCustom()
{
Expand Down
18 changes: 18 additions & 0 deletions Client.Test/Write/PointDataTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,24 @@ public void TagEmptyKey()
Assert.That(point.ToLineProtocol(), Is.EqualTo("h2o,location=europe level=2i"));
}

[Test]
public void DefaultTags()
{
var point = PointData.Measurement("h2o")
.SetTag("tag2", "val")
.SetField("field", 1);

var defaultTags = new Dictionary<string, string>() {
{"tag1", "default"},
{"tag2", "--"},
{"a", "b"},
};

Assert.That(point.ToLineProtocol(defaultTags: defaultTags), Is.EqualTo("h2o,a=b,tag1=default,tag2=val field=1i"));
Assert.That(point.ToLineProtocol(defaultTags: null), Is.EqualTo("h2o,tag2=val field=1i"));
Assert.That(point.ToLineProtocol(defaultTags: new Dictionary<string, string>()), Is.EqualTo("h2o,tag2=val field=1i"));
}

[Test]
public void TagEmptyValue()
{
Expand Down
28 changes: 28 additions & 0 deletions Client/Config/WriteOptions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using InfluxDB3.Client.Write;

namespace InfluxDB3.Client.Config;
Expand Down Expand Up @@ -33,6 +34,33 @@ public class WriteOptions : ICloneable
/// </summary>
public WritePrecision? Precision { get; set; }

/// <summary>
/// Tags added to each point during writing. If a point already has a tag with the same key, it is left unchanged.
/// <example>
/// <code>
/// <![CDATA[
/// var _client = new InfluxDBClient(new InfluxDBClientConfigs
/// {
/// HostUrl = "some-url",
/// Organization = "org",
/// Database = "database",
/// DefaultTags = new Dictionary \<string, string ()
/// {
/// { "rack", "main" },
/// }
/// });
///
/// // Writes with rack=main tag
/// await _client.WritePointAsync(PointData
/// .Measurement("cpu")
/// .SetField("field", 1)
/// );
/// ]]>
/// </code>
/// </example>
/// </summary>
public Dictionary<string, string>? DefaultTags { get; set; }

/// <summary>
/// The threshold in bytes for gzipping the body.
/// </summary>
Expand Down
6 changes: 3 additions & 3 deletions Client/InfluxDBClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ private async Task WriteData(IEnumerable<object> data, string? database = null,
}

var precisionNotNull = precision ?? _config.WritePrecision;
var sb = ToLineProtocolBody(data, precisionNotNull);
var sb = ToLineProtocolBody(data, precisionNotNull, _config.WriteOptions?.DefaultTags);
if (sb.Length == 0)
{
Trace.WriteLine($"The writes: {data} doesn't contains any Line Protocol, skipping");
Expand Down Expand Up @@ -437,15 +437,15 @@ public void Dispose()
_disposed = true;
}

private static StringBuilder ToLineProtocolBody(IEnumerable<object?> data, WritePrecision precision)
private static StringBuilder ToLineProtocolBody(IEnumerable<object?> data, WritePrecision precision, Dictionary<string, string>? defaultTags = null)
{
var sb = new StringBuilder("");

foreach (var item in data)
{
var lineProtocol = item switch
{
PointData pointData => pointData.ToLineProtocol(precision),
PointData pointData => pointData.ToLineProtocol(precision, defaultTags),
_ => item?.ToString()
};

Expand Down
24 changes: 19 additions & 5 deletions Client/Write/PointData.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Numerics;
using System.Text;

Expand Down Expand Up @@ -433,13 +434,14 @@ public PointData Copy()
/// Transform to Line Protocol.
/// </summary>
/// <param name="timeUnit">the timestamp precision</param>
/// <param name="defaultTags">Tags added to point</param>
/// <returns>Line Protocol</returns>
public string ToLineProtocol(WritePrecision? timeUnit = null)
public string ToLineProtocol(WritePrecision? timeUnit = null, Dictionary<string, string>? defaultTags = null)
{
var sb = new StringBuilder();

EscapeKey(sb, _values.GetMeasurement()!, false);
AppendTags(sb);
AppendTags(sb, defaultTags);
var appendedFields = AppendFields(sb);
if (!appendedFields)
{
Expand All @@ -455,11 +457,23 @@ public string ToLineProtocol(WritePrecision? timeUnit = null)
/// Appends the tags.
/// </summary>
/// <param name="writer">The writer.</param>
private void AppendTags(StringBuilder writer)
/// <param name="defaultTags">Tags added to point</param>
private void AppendTags(StringBuilder writer, Dictionary<string, string>? defaultTags = null)
{
foreach (var name in _values.GetTagNames())
var allNames = defaultTags == null
? _values.GetTagNames()
: _values.GetTagNames().Concat(defaultTags.Keys).ToArray()
;
Array.Sort(allNames);
var lastName = "" == allNames.FirstOrDefault() ? "_" : "";

foreach (var name in allNames)
{
var value = _values.GetTag(name);
if (name == lastName) continue;
lastName = name;

var value = _values.GetTag(name)
?? defaultTags.First(kv => kv.Key == name).Value;

if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(value))
{
Expand Down

0 comments on commit 0688621

Please sign in to comment.