|
@@ -1,4 +1,6 @@
|
|
-using System;
|
|
|
|
|
|
+using Newtonsoft.Json;
|
|
|
|
+
|
|
|
|
+using System;
|
|
using System.Net.Http;
|
|
using System.Net.Http;
|
|
using System.Net.Http.Headers;
|
|
using System.Net.Http.Headers;
|
|
|
|
|
|
@@ -8,17 +10,43 @@ namespace Vit.Core.Module.Log.LogCollector
|
|
{
|
|
{
|
|
public class SplunkCollector : ILogCollector
|
|
public class SplunkCollector : ILogCollector
|
|
{
|
|
{
|
|
|
|
+ private static DateTimeOffset Epoch = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
|
|
|
|
+ public static double ToEpoch(DateTime value)
|
|
|
|
+ {
|
|
|
|
+ // From Splunk HTTP Collector Protocol
|
|
|
|
+ // The default time format is epoch time format, in the format <sec>.<ms>.
|
|
|
|
+ // For example, 1433188255.500 indicates 1433188255 seconds and 500 milliseconds after epoch,
|
|
|
|
+ // or Monday, June 1, 2015, at 7:50:55 PM GMT.
|
|
|
|
+ // See: http://dev.splunk.com/view/SP-CAAAE6P
|
|
|
|
+ return value.ToTimeStamp() / 1000.0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
|
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
|
public void Write(LogMessage msg)
|
|
public void Write(LogMessage msg)
|
|
{
|
|
{
|
|
- var msgBody = new
|
|
|
|
|
|
+ if (msg.metadata != null && msg.metadata.Length == 0) msg.metadata = null;
|
|
|
|
+
|
|
|
|
+ var msgBody = new Message
|
|
{
|
|
{
|
|
|
|
+ time = ToEpoch(DateTime.UtcNow),
|
|
index = message?.index,
|
|
index = message?.index,
|
|
- level = msg.level,
|
|
|
|
- message = msg.message,
|
|
|
|
- metadata = msg.metadata,
|
|
|
|
- time = DateTime.Now,
|
|
|
|
- source = message?.source
|
|
|
|
|
|
+ host = message?.host ?? Environment.MachineName,
|
|
|
|
+ source = message?.source,
|
|
|
|
+ sourcetype = message?.sourcetype,
|
|
|
|
+
|
|
|
|
+ @event = new Message.Event
|
|
|
|
+ {
|
|
|
|
+ level = msg.level.ToString(),
|
|
|
|
+ message = msg.message,
|
|
|
|
+ metadata = msg.metadata,
|
|
|
|
+
|
|
|
|
+ @namespace = message?.@event?.@namespace,
|
|
|
|
+ app = message?.@event?.app
|
|
|
|
+ }
|
|
};
|
|
};
|
|
|
|
|
|
var request = new HttpRequestMessage(HttpMethod.Post, url);
|
|
var request = new HttpRequestMessage(HttpMethod.Post, url);
|
|
@@ -26,18 +54,67 @@ namespace Vit.Core.Module.Log.LogCollector
|
|
|
|
|
|
// TODO: retry when fail.
|
|
// TODO: retry when fail.
|
|
// batch: batchIntervalInSeconds, batchSizeLimit, queueLimit
|
|
// batch: batchIntervalInSeconds, batchSizeLimit, queueLimit
|
|
- var response = httpClient.SendAsync(request);
|
|
|
|
|
|
+ httpClient.SendAsync(request);
|
|
|
|
+
|
|
|
|
+ //var strMsg = msgBody.Serialize();
|
|
|
|
+ //var response = httpClient.SendAsync(request).Result;
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+
|
|
public class Message
|
|
public class Message
|
|
- {
|
|
|
|
- /// <summary>
|
|
|
|
- ///
|
|
|
|
- /// </summary>
|
|
|
|
|
|
+ {
|
|
|
|
+ public double time;
|
|
|
|
+
|
|
|
|
+ [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
|
public string index;
|
|
public string index;
|
|
|
|
|
|
- public object source;
|
|
|
|
|
|
+ [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
|
|
|
+ public string host;
|
|
|
|
+
|
|
|
|
+ [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
|
|
|
+ public string source;
|
|
|
|
+
|
|
|
|
+ [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
|
|
|
+ public string sourcetype;
|
|
|
|
+
|
|
|
|
+ [JsonProperty("event")]
|
|
|
|
+ public Event @event;
|
|
|
|
+
|
|
|
|
+ public class Event
|
|
|
|
+ {
|
|
|
|
+
|
|
|
|
+ [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
|
|
|
+ public string level;
|
|
|
|
|
|
|
|
+ [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
|
|
|
+ public string message;
|
|
|
|
+
|
|
|
|
+ [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
|
|
|
+ public object metadata;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
|
|
|
+ public string @namespace;
|
|
|
|
+
|
|
|
|
+ [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
|
|
|
+ public string app;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ {
|
|
|
|
+ "time": 1426279439,
|
|
|
|
+ "host": "localhost",
|
|
|
|
+ "source": "random-data-generator",
|
|
|
|
+ "sourcetype": "my_sample_data",
|
|
|
|
+ "index": "index_prod",
|
|
|
|
+ "event": {
|
|
|
|
+ "message": "Something happened",
|
|
|
|
+ "severity": "INFO"
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ */
|
|
}
|
|
}
|
|
public Message message;
|
|
public Message message;
|
|
|
|
|