예제 #1
0
        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;
            }
        }
예제 #2
0
        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;
            }
        }