internal async Task <int> PublishEventsAsync(IList <EventEntry> collection) { try { string logMessages; using (var serializer = new ElasticsearchEventEntrySerializer(this.index, this.type, this.instanceName, this.flattenPayload, this._jsonGlobalContextExtension)) { logMessages = serializer.Serialize(collection); } var content = new StringContent(logMessages); content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); var response = await client.PostAsync(this.elasticsearchUrl, content, cancellationTokenSource.Token).ConfigureAwait(false); // If there is an exception if (response.StatusCode != HttpStatusCode.OK) { // Check the response for 400 bad request if (response.StatusCode == HttpStatusCode.BadRequest) { var messagesDiscarded = collection.Count(); var errorContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false); string serverErrorMessage; // Try to parse the exception message try { var errorObject = JObject.Parse(errorContent); serverErrorMessage = errorObject["error"].Value <string>(); } catch (Exception) { // If for some reason we cannot extract the server error message log the entire response serverErrorMessage = errorContent; } // We are unable to write the batch of event entries - Possible poison message // I don't like discarding events but we cannot let a single malformed event prevent others from being written // We might want to consider falling back to writing entries individually here SemanticLoggingEventSource.Log.CustomSinkUnhandledFault(string.Format("Elasticsearch sink unhandled exception {0} messages discarded with server error message {1}", messagesDiscarded, serverErrorMessage)); return(messagesDiscarded); } // This will leave the messages in the buffer return(0); } var responseString = await response.Content.ReadAsStringAsync().ConfigureAwait(false); var responseObject = JObject.Parse(responseString); var items = responseObject["items"] as JArray; // If the response return items collection if (items != null) { // NOTE: This only works with Elasticsearch 1.0 // Alternatively we could query ES as part of initialization check results or fall back to trying <1.0 parsing // We should also consider logging errors for individual entries //return items.Count(t => t["create"]["status"].Value<int>().Equals(201)); int count = items.Count(); return(count); // Pre-1.0 Elasticsearch // return items.Count(t => t["create"]["ok"].Value<bool>().Equals(true)); } return(0); } catch (OperationCanceledException) { return(0); } catch (Exception ex) { // Although this is generally considered an anti-pattern this is not logged upstream and we have context SemanticLoggingEventSource.Log.CustomSinkUnhandledFault(ex.ToString()); throw; } }
internal async Task <int> PublishEventsAsync(IList <EventEntry> collection) { try { string logMessages; using (var serializer = new ElasticsearchEventEntrySerializer(this.index, this.type, this.instanceName, this.flattenPayload, this._jsonGlobalContextExtension)) { logMessages = serializer.Serialize(collection); } var content = new StringContent(logMessages); content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); // buiding the basic authorization if (this.userName != null && this.password != null) { string temp = this.userName + ":" + this.password; var byteArray = Encoding.ASCII.GetBytes(temp); var header = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray)); this.client.DefaultRequestHeaders.Authorization = header; } var response = await this.client.PostAsync(this.elasticsearchUrl, content, this.cancellationTokenSource.Token).ConfigureAwait(false); // If there is an exception if (response.StatusCode != HttpStatusCode.OK) { // Check the response for 400 bad request if (response.StatusCode == HttpStatusCode.BadRequest) { var messagesDiscarded = collection.Count(); var errorContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false); string serverErrorMessage; // Try to parse the exception message try { var errorObject = JObject.Parse(errorContent); serverErrorMessage = errorObject["error"].Value <string>(); } catch (Exception) { // If for some reason we cannot extract the server error message log the entire response serverErrorMessage = errorContent; } // We are unable to write the batch of event entries - Possible poison message // I don't like discarding events but we cannot let a single malformed event prevent others from being written // We might want to consider falling back to writing entries individually here SemanticLoggingEventSource.Log.CustomSinkUnhandledFault(string.Format("Elasticsearch sink unhandled exception {0} messages discarded with server error message {1}", messagesDiscarded, serverErrorMessage)); return(messagesDiscarded); } // This will leave the messages in the buffer return(0); } var responseString = await response.Content.ReadAsStringAsync().ConfigureAwait(false); var responseObject = JObject.Parse(responseString); var items = responseObject["items"] as JArray; // If the response return items collection if (items != null) { // NOTE: This only works with Elasticsearch 1.0 // Alternatively we could query ES as part of initialization check results or fall back to trying <1.0 parsing // We should also consider logging errors for individual entries if (this.elasticsearchUrl.Port == 80 || this.elasticsearchUrl.Port == 443) { return(items.Count(t => t["index"]["status"].Value <int>().Equals(201))); } else if (this.elasticsearchUrl.Port == 9200 || this.elasticsearchUrl.Port == 9243) { //return items.Count(t => t["create"]["status"].Value<int>().Equals(201)); // Temporary fix: ES 2.3.1 returns create for bulk index, ES 5.0.2 and ES 5.1.1 return index for buld index. // TODO Introduce version specific constant here. return(items.Count(t => t["index"]["status"].Value <int>().Equals(201))); } // Pre-1.0 Elasticsearch // return items.Count(t => t["create"]["ok"].Value<bool>().Equals(true)); } return(0); } catch (OperationCanceledException) { return(0); } catch (Exception ex) { // Although this is generally considered an anti-pattern this is not logged upstream and we have context Debug.WriteLine("{0} \n {1} \n {2} \n ", ex.Message, ex.InnerException, ex.StackTrace); SemanticLoggingEventSource.Log.CustomSinkUnhandledFault(ex.ToString()); throw; } }