Skip to content

Commit 32820d6

Browse files
committed
Merge branch 'release/3.0.0'
2 parents 7ab0db8 + c164b67 commit 32820d6

19 files changed

+791
-367
lines changed

Source/Picton.Messaging.IntegrationTests/ColoredConsoleLogProvider.cs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ public ColoredConsoleLogProvider(LogLevel minLevel = LogLevel.Trace)
2323
_minLevel = minLevel;
2424
}
2525

26+
27+
/// <summary>
28+
/// Gets the specified named logger.
29+
/// </summary>
30+
/// <param name="name">Name of the logger.</param>
31+
/// <returns>The logger reference.</returns>
2632
public Logger GetLogger(string name)
2733
{
2834
return (logLevel, messageFunc, exception, formatParameters) =>
@@ -36,8 +42,7 @@ public Logger GetLogger(string name)
3642
{
3743
if (logLevel >= _minLevel)
3844
{
39-
ConsoleColor consoleColor;
40-
if (Colors.TryGetValue(logLevel, out consoleColor))
45+
if (Colors.TryGetValue(logLevel, out ConsoleColor consoleColor))
4146
{
4247
var originalForground = Console.ForegroundColor;
4348
try
@@ -76,12 +81,25 @@ private static void WriteMessage(
7681
Console.WriteLine("{0} | {1} | {2} | {3}", DateTime.UtcNow, logLevel, name, message);
7782
}
7883

84+
85+
/// <summary>
86+
/// Opens a nested diagnostics context. Not supported in EntLib logging.
87+
/// </summary>
88+
/// <param name="message">The message to add to the diagnostics context.</param>
89+
/// <returns>A disposable that when disposed removes the message from the context.</returns>
7990
public IDisposable OpenNestedContext(string message)
8091
{
8192
return NullDisposable.Instance;
8293
}
8394

84-
public IDisposable OpenMappedContext(string key, string value)
95+
96+
/// <summary>
97+
/// Opens a mapped diagnostics context. Not supported in EntLib logging.
98+
/// </summary>
99+
/// <param name="key">A key.</param>
100+
/// <param name="value">A value.</param>
101+
/// <returns>A disposable that when disposed removes the map from the context.</returns>
102+
public IDisposable OpenMappedContext(string key, object value, bool destructure = false)
85103
{
86104
return NullDisposable.Instance;
87105
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using App.Metrics;
2+
using App.Metrics.Formatters;
3+
using App.Metrics.Serialization;
4+
using System.IO;
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
8+
namespace Picton.Messaging.IntegrationTests.Datadog
9+
{
10+
/// <summary>
11+
/// Formatter for encoding Metrics in Datadog JSON
12+
/// </summary>
13+
public class DatadogFormatter : IMetricsOutputFormatter
14+
{
15+
private readonly DatadogFormatterOptions _options;
16+
17+
/// <summary>
18+
/// Constructor
19+
/// </summary>
20+
public DatadogFormatter(DatadogFormatterOptions options)
21+
{
22+
_options = options;
23+
}
24+
25+
/// <inheritdoc />
26+
public Task WriteAsync(Stream output, MetricsDataValueSource metricsData, CancellationToken cancellationToken = new CancellationToken())
27+
{
28+
var serializer = new MetricSnapshotSerializer();
29+
using (var streamWriter = new StreamWriter(output))
30+
{
31+
using (var writer = new MetricSnapshotDatadogWriter(streamWriter, _options))
32+
serializer.Serialize(writer, metricsData);
33+
}
34+
35+
return Task.CompletedTask;
36+
}
37+
38+
/// <inheritdoc />
39+
public MetricsMediaTypeValue MediaType => new MetricsMediaTypeValue("application", "com.datadoghq.metrics", "v1", "json");
40+
}
41+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+

2+
namespace Picton.Messaging.IntegrationTests.Datadog
3+
{
4+
/// <summary>
5+
/// Options for data reported to Datadog
6+
/// </summary>
7+
public class DatadogFormatterOptions
8+
{
9+
/// <summary>
10+
/// The Hostname that is reported. Usually Environment.MachineName
11+
/// </summary>
12+
public string Hostname { get; set; }
13+
}
14+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
namespace Picton.Messaging.IntegrationTests.Datadog
2+
{
3+
/// <summary>
4+
/// For serializing http://docs.datadoghq.com/api/?lang=console#metrics
5+
/// </summary>
6+
class MetricJson
7+
{
8+
public string Metric { get; set; }
9+
public object[][] Points { get; set; }
10+
public string Host { get; set; }
11+
public string[] Tags { get; set; }
12+
}
13+
}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
using App.Metrics;
2+
using App.Metrics.Serialization;
3+
using Newtonsoft.Json;
4+
using Newtonsoft.Json.Serialization;
5+
using System;
6+
using System.Collections.Generic;
7+
using System.IO;
8+
using System.Linq;
9+
10+
namespace Picton.Messaging.IntegrationTests.Datadog
11+
{
12+
class MetricSnapshotDatadogWriter : IMetricSnapshotWriter
13+
{
14+
private StreamWriter _streamWriter;
15+
private readonly DatadogFormatterOptions _options;
16+
private readonly List<MetricJson> _metrics = new List<MetricJson>();
17+
18+
static readonly JsonSerializerSettings JsonSettings = new JsonSerializerSettings
19+
{
20+
ContractResolver = new LowercaseContractResolver()
21+
};
22+
23+
private class LowercaseContractResolver : DefaultContractResolver
24+
{
25+
protected override string ResolvePropertyName(string propertyName)
26+
{
27+
return propertyName.ToLower();
28+
}
29+
}
30+
31+
public MetricSnapshotDatadogWriter(StreamWriter streamWriter, DatadogFormatterOptions options)
32+
{
33+
_streamWriter = streamWriter;
34+
_options = options;
35+
}
36+
37+
public void Dispose()
38+
{
39+
if (_streamWriter != null)
40+
{
41+
Flush();
42+
43+
_streamWriter?.Dispose();
44+
_streamWriter = null;
45+
}
46+
}
47+
48+
/// <inheritdoc />
49+
public void Write(string context, string name, object value, MetricTags tags, DateTime timestamp)
50+
{
51+
Write(context, name, new[] { "value" }, new[] { value }, tags, timestamp);
52+
}
53+
54+
/// <inheritdoc />
55+
public void Write(string context, string name, IEnumerable<string> columns, IEnumerable<object> values, MetricTags tags, DateTime timestamp)
56+
{
57+
var posixTimestamp = (timestamp - new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero)).TotalSeconds; //TODO: Check this
58+
59+
var dict = columns.Zip(values, (column, value) => new { column, value }).ToDictionary(p => p.column, p => p.value);
60+
61+
switch (tags.Values[Array.IndexOf(tags.Keys, "mtype")])
62+
{
63+
case "apdex":
64+
Write(posixTimestamp, context, name, "count", dict["samples"]);
65+
Write(posixTimestamp, context, name, "score", dict["score"]);
66+
Write(posixTimestamp, context, name, "satisfied", dict["satisfied"]);
67+
Write(posixTimestamp, context, name, "tolerating", dict["tolerating"]);
68+
Write(posixTimestamp, context, name, "frustrating", dict["frustrating"]);
69+
break;
70+
case "gauge":
71+
Write(posixTimestamp, context, name, dict["value"]);
72+
break;
73+
case "counter":
74+
if (dict.ContainsKey("value"))
75+
Write(posixTimestamp, context, name, dict["value"]);
76+
break;
77+
case "meter":
78+
Write(posixTimestamp, context, name, "count", dict["count.meter"]);
79+
Write(posixTimestamp, context, name, "15m", dict["rate15m"]);
80+
Write(posixTimestamp, context, name, "5m", dict["rate5m"]);
81+
Write(posixTimestamp, context, name, "1m", dict["rate1m"]);
82+
Write(posixTimestamp, context, name, "avg", dict["rate.mean"]);
83+
break;
84+
case "timer":
85+
Write(posixTimestamp, context, name, "1mrate", dict["rate1m"]);
86+
Write(posixTimestamp, context, name, "5mrate", dict["rate5m"]);
87+
Write(posixTimestamp, context, name, "15mrate", dict["rate15m"]);
88+
WriteHistogram(posixTimestamp, context, name, dict);
89+
break;
90+
case "histogram":
91+
WriteHistogram(posixTimestamp, context, name, dict);
92+
break;
93+
}
94+
}
95+
96+
private void WriteHistogram(double posixTimestamp, string context, string name, Dictionary<string, object> dict)
97+
{
98+
Write(posixTimestamp, context, name, "count", dict["count.hist"]);
99+
100+
Write(posixTimestamp, context, name, "max", dict["max"]);
101+
Write(posixTimestamp, context, name, "avg", dict["mean"]);
102+
Write(posixTimestamp, context, name, "median", dict["median"]);
103+
Write(posixTimestamp, context, name, "min", dict["min"]);
104+
Write(posixTimestamp, context, name, "stdDev", dict["stddev"]);
105+
106+
Write(posixTimestamp, context, name, "75percentile", dict["p75"]);
107+
Write(posixTimestamp, context, name, "95percentile", dict["p95"]);
108+
Write(posixTimestamp, context, name, "98percentile", dict["p98"]);
109+
Write(posixTimestamp, context, name, "99percentile", dict["p99"]);
110+
Write(posixTimestamp, context, name, "999percentile", dict["p999"]);
111+
}
112+
113+
private void Write(double timestamp, string context, string name, string subname, object value)
114+
{
115+
Write(timestamp, context, name + "." + subname, value);
116+
}
117+
118+
private void Write(double timestamp, string context, string name, object value)
119+
{
120+
_metrics.Add(new MetricJson
121+
{
122+
Host = _options.Hostname,
123+
Metric = context + "." + name,
124+
//Tags = tags.Values,
125+
Points = new[]
126+
{
127+
new[] { timestamp, value }
128+
}
129+
});
130+
}
131+
132+
private void Flush()
133+
{
134+
_streamWriter.Write(JsonConvert.SerializeObject(new SeriesJson { Series = _metrics.ToArray() }, JsonSettings));
135+
}
136+
137+
public GeneratedMetricNameMapping MetricNameMapping { get; } = new GeneratedMetricNameMapping();
138+
}
139+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace Picton.Messaging.IntegrationTests.Datadog
2+
{
3+
class SeriesJson
4+
{
5+
public MetricJson[] Series { get; set; }
6+
}
7+
}

Source/Picton.Messaging.IntegrationTests/Picton.Messaging.IntegrationTests.csproj

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@
33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
55
<TargetFramework>netcoreapp1.1</TargetFramework>
6-
<AssemblyName>Picton.Mesaging.IntegrationTests</AssemblyName>
7-
<RootNamespace>Picton.Mesaging.IntegrationTests</RootNamespace>
6+
<AssemblyName>Picton.Messaging.IntegrationTests</AssemblyName>
7+
<RootNamespace>Picton.Messaging.IntegrationTests</RootNamespace>
88
</PropertyGroup>
99

10+
<ItemGroup>
11+
<PackageReference Include="App.Metrics.Reporting.Http" Version="2.0.0-preview1" />
12+
</ItemGroup>
13+
1014
<ItemGroup>
1115
<ProjectReference Include="..\Picton.Messaging\Picton.Messaging.csproj" />
1216
</ItemGroup>

0 commit comments

Comments
 (0)