diff --git a/Graphite.Test/Graphite.Test.csproj b/Graphite.Test/Graphite.Test.csproj index f928e4b..d2a77d1 100644 --- a/Graphite.Test/Graphite.Test.csproj +++ b/Graphite.Test/Graphite.Test.csproj @@ -1,7 +1,7 @@  - netcoreapp2.1 + net6.0 false ahd.Graphite.Test ahd.Graphite.Test @@ -20,10 +20,10 @@ - - - - + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Graphite/AbstractCarbonClient.cs b/Graphite/AbstractCarbonClient.cs new file mode 100644 index 0000000..0d1c946 --- /dev/null +++ b/Graphite/AbstractCarbonClient.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace ahd.Graphite +{ + /// + /// Base class for clients for submitting data to carbon + /// + public abstract class AbstractCarbonClient + { + /// + /// Send a single datapoint + /// + /// metric path + /// metric value + /// The token to monitor for cancellation requests. The default value is . + /// + public Task SendAsync(string series, double value, CancellationToken cancellationToken = default(CancellationToken)) + { + return SendAsync(series, value, DateTime.Now, cancellationToken); + } + + /// + /// Send a single datapoint + /// + /// metric path + /// metric value + /// metric timestamp + /// The token to monitor for cancellation requests. The default value is . + /// + public Task SendAsync(string series, double value, DateTime timestamp, CancellationToken cancellationToken = default(CancellationToken)) + { + return SendAsync(new []{new Datapoint(series, value, timestamp)}, cancellationToken); + } + + /// + /// Send a list of datapoints + /// + /// + /// + public Task SendAsync(params Datapoint[] datapoints) + { + return SendAsync(datapoints, CancellationToken.None); + } + + /// + /// Send a list of datapoints + /// + /// The token to monitor for cancellation requests. The default value is . + /// + /// + public Task SendAsync(CancellationToken cancellationToken, params Datapoint[] datapoints) + { + return SendAsync(datapoints, cancellationToken); + } + + /// + /// Send a list of datapoints + /// + /// + /// The token to monitor for cancellation requests. + /// + public Task SendAsync(Datapoint[] datapoints, CancellationToken cancellationToken) + { + ICollection points = datapoints; + return SendAsync(points, cancellationToken); + } + + /// + /// Send a list of datapoints + /// + /// + /// The token to monitor for cancellation requests. The default value is . + /// + public abstract Task SendAsync(ICollection datapoints, CancellationToken cancellationToken = default(CancellationToken)); + + } +} \ No newline at end of file diff --git a/Graphite/CarbonClient.cs b/Graphite/CarbonClient.cs index 02577a9..5f41694 100644 --- a/Graphite/CarbonClient.cs +++ b/Graphite/CarbonClient.cs @@ -9,7 +9,7 @@ namespace ahd.Graphite /// /// Client for submitting data to carbon /// - public class CarbonClient + public class CarbonClient:AbstractCarbonClient { private readonly CarbonConnectionPool _carbonPool; @@ -27,6 +27,7 @@ public CarbonClient():this("localhost") public CarbonClient(string host):this(host, new PlaintextGraphiteFormatter()) { } + /// /// Creates a client with the specified host and formatter /// @@ -63,64 +64,6 @@ public CarbonClient(string host, IGraphiteFormatter formatter) /// Use ip dual stack for sending metrics. Defaults to true. /// public bool UseDualStack { get; set; } - - /// - /// Send a single datapoint - /// - /// metric path - /// metric value - /// The token to monitor for cancellation requests. The default value is . - /// - public Task SendAsync(string series, double value, CancellationToken cancellationToken = default(CancellationToken)) - { - return SendAsync(series, value, DateTime.Now, cancellationToken); - } - - /// - /// Send a single datapoint - /// - /// metric path - /// metric value - /// metric timestamp - /// The token to monitor for cancellation requests. The default value is . - /// - public Task SendAsync(string series, double value, DateTime timestamp, CancellationToken cancellationToken = default(CancellationToken)) - { - return SendAsync(new []{new Datapoint(series, value, timestamp)}, cancellationToken); - } - - /// - /// Send a list of datapoints in up to batches - /// - /// - /// - public Task SendAsync(params Datapoint[] datapoints) - { - return SendAsync(datapoints, CancellationToken.None); - } - - /// - /// Send a list of datapoints in up to batches - /// - /// The token to monitor for cancellation requests. The default value is . - /// - /// - public Task SendAsync(CancellationToken cancellationToken, params Datapoint[] datapoints) - { - return SendAsync(datapoints, cancellationToken); - } - - /// - /// Send a list of datapoints in up to batches - /// - /// - /// The token to monitor for cancellation requests. - /// - public Task SendAsync(Datapoint[] datapoints, CancellationToken cancellationToken) - { - ICollection points = datapoints; - return SendAsync(points, cancellationToken); - } /// /// Send a list of datapoints in up to batches @@ -128,7 +71,7 @@ public Task SendAsync(Datapoint[] datapoints, CancellationToken cancellationToke /// /// The token to monitor for cancellation requests. The default value is . /// - public async Task SendAsync(ICollection datapoints, CancellationToken cancellationToken = default(CancellationToken)) + public override async Task SendAsync(ICollection datapoints, CancellationToken cancellationToken = default(CancellationToken)) { if (datapoints == null || datapoints.Count == 0) throw new ArgumentNullException(nameof(datapoints)); var batches = GetBatches(datapoints); diff --git a/Graphite/CarbonHttpClient.cs b/Graphite/CarbonHttpClient.cs new file mode 100644 index 0000000..82e6ddd --- /dev/null +++ b/Graphite/CarbonHttpClient.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading; +using System.Threading.Tasks; +using ahd.Graphite.Exceptions; +using Razorvine.Pickle; + +namespace ahd.Graphite +{ + /// + /// Client for submitting data to carbon via HTTP using the pickle protocol + /// + public class CarbonHttpClient:AbstractCarbonClient + { + private readonly HttpClient _client; + + /// + /// Creates a client for localhost:2007 + /// + public CarbonHttpClient():this("http://localhost:2007") + { + } + + /// + /// Creates a client with the specified endpoint + /// + /// carbon http endpoint + public CarbonHttpClient(string baseAddress):this(new Uri(baseAddress)) + { + } + + /// + /// Creates a client with the specified endpoint + /// + /// carbon http endpoint + public CarbonHttpClient(Uri baseAddress):this(new HttpClient{BaseAddress = baseAddress}) + { + } + + /// + /// Creates a client using the supplied http client + /// + /// preconfigured http client + public CarbonHttpClient(HttpClient client) + { + _client = client; + } + + /// + public override async Task SendAsync(ICollection datapoints, CancellationToken cancellationToken = default(CancellationToken)) + { + var response = await _client.PostAsync("/", Serialize(datapoints), cancellationToken).ConfigureAwait(false); + await response.EnsureSuccessStatusCodeAsync().ConfigureAwait(false); + } + + private HttpContent Serialize(ICollection datapoints) + { + using (var pickler = new Pickler()) + { + var data = datapoints.Select(x => new object[] { x.Series, new object[] { x.UnixTimestamp, x.Value } }); + var pickled = pickler.dumps(data); + return new ByteArrayContent(pickled) + { + Headers = + { + ContentType = new MediaTypeHeaderValue("application/python-pickle") + } + }; + } + } + } +} \ No newline at end of file diff --git a/Graphite/Graphite.csproj b/Graphite/Graphite.csproj index b165682..69218e0 100644 --- a/Graphite/Graphite.csproj +++ b/Graphite/Graphite.csproj @@ -53,9 +53,9 @@ - - - + + +