static async void DoItLogging() { var middleware = new HttpEventCollectorResendMiddleware(100); var ecSender = new HttpEventCollectorSender(new Uri("https://localhost:8088"), "3E712E99-63C5-4C5A-841D-592DD070DA51", null, HttpEventCollectorSender.SendMode.Sequential, 0, 0, 0, middleware.Plugin ); ecSender.OnError += o => Console.WriteLine(o.Message); ecSender.Send(Guid.NewGuid().ToString(), "INFO", null, new { Foo = "Bar" }); dynamic obj = new JObject(); obj.Bar = "Baz"; ecSender.Send(Guid.NewGuid().ToString(), "INFO", null, (JObject)obj); await ecSender.FlushAsync(); }
public void HttpEventCollectorBatchingSizeTest() { // estimate serialized event size HttpEventCollectorEventInfo ei = new HttpEventCollectorEventInfo(null, TraceEventType.Information.ToString(), "info ?", null, null); int size = HttpEventCollectorSender.SerializeEventInfo(ei).Length; var trace = Trace( handler: (token, events) => { Assert.True(events.Count == 4); Assert.True(events[0].Event.Message == "info 1"); Assert.True(events[1].Event.Message == "info 2"); Assert.True(events[2].Event.Message == "info 3"); Assert.True(events[3].Event.Message == "info 4"); return(new Response()); }, batchSizeBytes: 4 * size - size / 2 // 4 events trigger post ); trace.TraceInformation("info 1"); trace.TraceInformation("info 2"); trace.TraceInformation("info 3"); trace.TraceInformation("info 4"); trace.TraceInformation("info 1"); trace.TraceInformation("info 2"); trace.TraceInformation("info 3"); trace.TraceInformation("info 4"); trace.Close(); }
/// <summary> /// Callback that should be used as middleware in HttpEventCollectorSender /// </summary> /// <param name="request"></param> /// <param name="next"></param> /// <returns></returns> public async Task<HttpResponseMessage> Plugin( string token, List<HttpEventCollectorEventInfo> events, HttpEventCollectorSender.HttpEventCollectorHandler next) { HttpResponseMessage response = null; HttpStatusCode statusCode = HttpStatusCode.OK; Exception webException = null; string serverReply = null; int retryDelay = 1000; // start with 1 second // retry sending data until success for (int retriesCount = 0; retriesCount <= retriesOnError; retriesCount++) { try { response = await next(token, events); statusCode = response.StatusCode; if (statusCode == HttpStatusCode.OK) { // the data has been sent successfully webException = null; break; } else if (Array.IndexOf(HttpEventCollectorApplicationErrors, statusCode) >= 0) { // HTTP event collector application error detected - resend wouldn't help // in this case. Record server reply and break. if (response.Content != null) { serverReply = await response.Content.ReadAsStringAsync(); } break; } else { // retry } } catch (Exception e) { // connectivity problem - record exception and retry webException = e; } // wait before next retry await Task.Delay(retryDelay); // increase delay exponentially retryDelay = Math.Min(RetryDelayCeiling, retryDelay * 2); } if (statusCode != HttpStatusCode.OK || webException != null) { throw new HttpEventCollectorException( code: statusCode, webException: webException, reply: serverReply, response: response ); } return response; }
/// <summary> /// HttpEventCollectorEventSink c-or with middleware parameter. /// </summary> /// <param name="uri">Splunk server uri, for example https://localhost:8088.</param> /// <param name="token">HTTP event collector authorization token.</param> /// <param name="formatter">Event formatter converting EventEntry instance into a string.</param> /// <param name="metadata">Logger metadata.</param> /// <param name="sendMode">Send mode of the events.</param> /// <param name="batchInterval">Batch interval in milliseconds.</param> /// <param name="batchSizeBytes">Batch max size.</param> /// <param name="batchSizeCount">MNax number of individual events in batch.</param> /// <param name="middleware"> /// HTTP client middleware. This allows to plug an HttpClient handler that /// intercepts logging HTTP traffic. /// </param> public HttpEventCollectorSink( Uri uri, string token, IEventTextFormatter formatter, HttpEventCollectorEventInfo.Metadata metadata = null, HttpEventCollectorSender.SendMode sendMode = HttpEventCollectorSender.SendMode.Sequential, int batchInterval = HttpEventCollectorSender.DefaultBatchInterval, int batchSizeBytes = HttpEventCollectorSender.DefaultBatchSize, int batchSizeCount = HttpEventCollectorSender.DefaultBatchCount, HttpEventCollectorSender.HttpEventCollectorMiddleware middleware = null) { this.formatter = formatter; sender = new HttpEventCollectorSender( uri, token, metadata, sendMode, batchInterval, batchSizeBytes, batchSizeCount, middleware); }
public void HttpEventCollectorSenderMetadataOverrideTest() { Func <String, List <HttpEventCollectorEventInfo>, Response> noopHandler = (token, events) => { return(new Response()); }; HttpEventCollectorEventInfo.Metadata defaultmetadata = new HttpEventCollectorEventInfo.Metadata(index: "defaulttestindex", source: "defaulttestsource", sourceType: "defaulttestsourcetype", host: "defaulttesthost"); HttpEventCollectorEventInfo.Metadata overridemetadata = new HttpEventCollectorEventInfo.Metadata(index: "overridetestindex", source: "overridetestsource", sourceType: "overridetestsourcetype", host: "overridetesthost"); HttpEventCollectorSender httpEventCollectorSender = new HttpEventCollectorSender(uri, "TOKEN-GUID", defaultmetadata, HttpEventCollectorSender.SendMode.Sequential, 100000, 100000, 3, new HttpEventCollectorSender.HttpEventCollectorMiddleware((token, events, next) => { Assert.True(events.Count == 3); // Id = id1 should have the default meta data values. Assert.True(events[0].Event.Id == "id1"); Assert.True(events[0].Index == defaultmetadata.Index); Assert.True(events[0].Source == defaultmetadata.Source); Assert.True(events[0].SourceType == defaultmetadata.SourceType); Assert.True(events[0].Host == defaultmetadata.Host); // Id = id2 should have the metadataOverride values. Assert.True(events[1].Event.Id == "id2"); Assert.True(events[1].Index == overridemetadata.Index); Assert.True(events[1].Source == overridemetadata.Source); Assert.True(events[1].SourceType == overridemetadata.SourceType); Assert.True(events[1].Host == overridemetadata.Host); // Id = id3 should have the default meta data values. Assert.True(events[2].Event.Id == "id3"); Assert.True(events[2].Index == defaultmetadata.Index); Assert.True(events[2].Source == defaultmetadata.Source); Assert.True(events[2].SourceType == defaultmetadata.SourceType); Assert.True(events[2].Host == defaultmetadata.Host); Response response = noopHandler(token, events); HttpResponseMessage httpResponseMessage = new HttpResponseMessage(); httpResponseMessage.StatusCode = response.Code; byte[] buf = Encoding.UTF8.GetBytes(response.Context); httpResponseMessage.Content = new StringContent(response.Context); var task = new Task <HttpResponseMessage>(() => { return(httpResponseMessage); }); task.RunSynchronously(); return(task); }) ); httpEventCollectorSender.Send(id: "id1"); httpEventCollectorSender.Send(id: "id2", metadataOverride: overridemetadata); httpEventCollectorSender.Send(id: "id3"); httpEventCollectorSender.FlushSync(); httpEventCollectorSender.Dispose(); }
/// <summary> /// HttpEventCollectorTraceListener c-or. Instantiates HttpEventCollectorTraceListener /// when retriesOnError parameter is specified. /// </summary> /// <param name="uri">Splunk server uri, for example https://localhost:8089.</param> /// <param name="token">HTTP event collector authorization token.</param> /// <param name="retriesOnError">Number of retries when network problem is detected</param> /// <param name="metadata">Logger metadata.</param> /// <param name="sendMode">Send mode of the events.</param> /// <param name="batchInterval">Batch interval in milliseconds.</param> /// <param name="batchSizeBytes">Batch max size.</param> /// <param name="batchSizeCount">MNax number of individual events in batch.</param> public HttpEventCollectorTraceListener( Uri uri, string token, int retriesOnError, HttpEventCollectorEventInfo.Metadata metadata = null, HttpEventCollectorSender.SendMode sendMode = HttpEventCollectorSender.SendMode.Sequential, int batchInterval = HttpEventCollectorSender.DefaultBatchInterval, int batchSizeBytes = HttpEventCollectorSender.DefaultBatchSize, int batchSizeCount = HttpEventCollectorSender.DefaultBatchCount) : this(uri, token, metadata, sendMode, batchInterval, batchSizeBytes, batchSizeCount, (new HttpEventCollectorResendMiddleware(retriesOnError)).Plugin) { }
/// <summary> /// HttpEventCollectorTraceListener c-or. /// </summary> /// <param name="uri">Splunk server uri, for example https://localhost:8089.</param> /// <param name="token">HTTP event collector authorization token.</param> /// <param name="metadata">Logger metadata.</param> /// <param name="sendMode">Send mode of the events.</param> /// <param name="batchInterval">Batch interval in milliseconds.</param> /// <param name="batchSizeBytes">Batch max size.</param> /// <param name="batchSizeCount">MNax number of individual events in batch.</param> /// <param name="middleware"> /// HTTP client middleware. This allows to plug an HttpClient handler that /// intercepts logging HTTP traffic. /// </param> public HttpEventCollectorTraceListener( Uri uri, string token, HttpEventCollectorEventInfo.Metadata metadata = null, HttpEventCollectorSender.SendMode sendMode = HttpEventCollectorSender.SendMode.Sequential, int batchInterval = HttpEventCollectorSender.DefaultBatchInterval, int batchSizeBytes = HttpEventCollectorSender.DefaultBatchSize, int batchSizeCount = HttpEventCollectorSender.DefaultBatchCount, HttpEventCollectorSender.HttpEventCollectorMiddleware middleware = null) { sender = new HttpEventCollectorSender( uri, token, metadata, sendMode, batchInterval, batchSizeBytes, batchSizeCount, middleware); }
private SinkTrace TraceSource( RequestHandler handler, HttpEventCollectorEventInfo.Metadata metadata = null, HttpEventCollectorSender.SendMode sendMode = HttpEventCollectorSender.SendMode.Parallel, int batchInterval = 0, int batchSizeBytes = 0, int batchSizeCount = 0, HttpEventCollectorSender.HttpEventCollectorMiddleware middleware = null) { var listener = new ObservableEventListener(); var sink = new HttpEventCollectorSink( uri: uri, token: token, formatter: new TestEventFormatter(), metadata: metadata, sendMode: sendMode, batchInterval: batchInterval, batchSizeBytes: batchSizeBytes, batchSizeCount: batchSizeCount, middleware: MiddlewareInterceptor(handler, middleware)); listener.Subscribe(sink); var eventSource = TestEventSource.GetInstance(); listener.EnableEvents(eventSource, EventLevel.LogAlways, Keywords.All); return new SinkTrace() { Source = eventSource, Sink = sink, Listener = listener }; }
// Input trace listener private TraceSource Trace( RequestHandler handler, HttpEventCollectorEventInfo.Metadata metadata = null, int batchInterval = 0, int batchSizeBytes = 0, int batchSizeCount = 0, HttpEventCollectorSender.SendMode sendMode = HttpEventCollectorSender.SendMode.Parallel, HttpEventCollectorSender.HttpEventCollectorMiddleware middleware = null) { var trace = new TraceSource("HttpEventCollectorLogger"); trace.Switch.Level = SourceLevels.All; trace.Listeners.Add( new HttpEventCollectorTraceListener( uri: uri, token: token, metadata: metadata, sendMode: sendMode, batchInterval: batchInterval, batchSizeBytes: batchSizeBytes, batchSizeCount: batchSizeCount, middleware: MiddlewareInterceptor(handler, middleware)) ); return trace; }
// we inject this method into HTTP event collector middleware chain to mimic a Splunk // server private HttpEventCollectorSender.HttpEventCollectorMiddleware MiddlewareInterceptor( RequestHandler handler, HttpEventCollectorSender.HttpEventCollectorMiddleware middleware) { HttpEventCollectorSender.HttpEventCollectorMiddleware interceptor = (string token, List<HttpEventCollectorEventInfo> events, HttpEventCollectorSender.HttpEventCollectorHandler next) => { Response response = handler(token, events); HttpResponseMessage httpResponseMessage = new HttpResponseMessage(); httpResponseMessage.StatusCode = response.Code; byte[] buf = Encoding.UTF8.GetBytes(response.Context); httpResponseMessage.Content = new StringContent(response.Context); var task = new Task<HttpResponseMessage>(() => { return httpResponseMessage; }); task.RunSynchronously(); return task; }; if (middleware != null) { // chain middleware to interceptor var temp = interceptor; interceptor = (token, events, next) => { return middleware(token, events, (t, e) => { return temp(t, e, next); }); }; } return interceptor; }