コード例 #1
0
ファイル: EventPostsJob.cs プロジェクト: caesay/Exceptionless
        private async Task RetryEvents(QueueEntryContext <EventPost> context, List <PersistentEvent> eventsToRetry, EventPostInfo ep, IQueueEntry <EventPost> queueEntry)
        {
            await _metricsClient.GaugeAsync(MetricNames.EventsRetryCount, eventsToRetry.Count).AnyContext();

            foreach (var ev in eventsToRetry)
            {
                try {
                    string contentEncoding = null;
                    byte[] data            = ev.GetBytes(_jsonSerializerSettings);
                    if (data.Length > 1000)
                    {
                        data = await data.CompressAsync().AnyContext();

                        contentEncoding = "gzip";
                    }

                    // Put this single event back into the queue so we can retry it separately.
                    await _queue.Value.EnqueueAsync(new EventPostInfo {
                        ApiVersion      = ep.ApiVersion,
                        CharSet         = ep.CharSet,
                        ContentEncoding = contentEncoding,
                        Data            = data,
                        IpAddress       = ep.IpAddress,
                        MediaType       = ep.MediaType,
                        ProjectId       = ep.ProjectId,
                        UserAgent       = ep.UserAgent
                    }, _storage, false, context.CancellationToken).AnyContext();
                } catch (Exception ex) {
                    _logger.Error()
                    .Exception(ex)
                    .Critical()
                    .Message("Error while requeuing event post \"{0}\": {1}", queueEntry.Value.FilePath, ex.Message)
                    .Property("Event", new { ev.Date, ev.StackId, ev.Type, ev.Source, ev.Message, ev.Value, ev.Geo, ev.ReferenceId, ev.Tags })
                    .Project(ep.ProjectId)
                    .Write();

                    await _metricsClient.CounterAsync(MetricNames.EventsRetryErrors).AnyContext();
                }
            }
        }
コード例 #2
0
 public Task <EventContext> RunAsync(PersistentEvent ev, Organization organization, Project project, EventPostInfo epi = null)
 {
     return(RunAsync(new EventContext(ev, organization, project, epi)));
 }
コード例 #3
0
 public Task <ICollection <EventContext> > RunAsync(IEnumerable <PersistentEvent> events, Organization organization, Project project, EventPostInfo epi = null)
 {
     return(RunAsync(events.Select(ev => new EventContext(ev, organization, project, epi)).ToList()));
 }
コード例 #4
0
 public EventContext(PersistentEvent ev, Organization organization, Project project, EventPostInfo epi = null)
 {
     Organization         = organization;
     Project              = project;
     Event                = ev;
     Event.OrganizationId = organization.Id;
     Event.ProjectId      = project.Id;
     EventPostInfo        = epi;
     StackSignatureData   = new Dictionary <string, string>();
 }
コード例 #5
0
        protected override async Task <JobResult> ProcessQueueEntryAsync(QueueEntryContext <EventPost> context)
        {
            var      queueEntry = context.QueueEntry;
            FileSpec fileInfo   = null;
            await _metricsClient.TimeAsync(async() => fileInfo = await _storage.GetFileInfoAsync(queueEntry.Value.FilePath).AnyContext(), MetricNames.PostsFileInfoTime).AnyContext();

            if (fileInfo == null)
            {
                await _metricsClient.TimeAsync(() => queueEntry.AbandonAsync(), MetricNames.PostsAbandonTime).AnyContext();

                return(JobResult.FailedWithMessage($"Unable to retrieve post data info '{queueEntry.Value.FilePath}'."));
            }

            await _metricsClient.GaugeAsync(MetricNames.PostsMessageSize, fileInfo.Size).AnyContext();

            if (fileInfo.Size > GetMaximumEventPostFileSize())
            {
                await _metricsClient.TimeAsync(() => queueEntry.CompleteAsync(), MetricNames.PostsCompleteTime).AnyContext();

                return(JobResult.FailedWithMessage($"Unable to process post data '{queueEntry.Value.FilePath}' ({fileInfo.Size} bytes): Maximum event post size limit ({Settings.Current.MaximumEventPostSize} bytes) reached."));
            }

            EventPostInfo ep = null;
            await _metricsClient.TimeAsync(async() => ep = await _storage.GetEventPostAsync(queueEntry.Value.FilePath, _logger, context.CancellationToken).AnyContext(), MetricNames.PostsMarkFileActiveTime).AnyContext();

            if (ep == null)
            {
                await AbandonEntryAsync(queueEntry).AnyContext();

                return(JobResult.FailedWithMessage($"Unable to retrieve post data '{queueEntry.Value.FilePath}'."));
            }

            await _metricsClient.GaugeAsync(MetricNames.PostsCompressedSize, ep.Data.Length).AnyContext();

            bool isInternalProject = ep.ProjectId == Settings.Current.InternalProjectId;

            _logger.Info()
            .Message("Processing post: id={0} path={1} project={2} ip={3} v={4} agent={5}", queueEntry.Id, queueEntry.Value.FilePath, ep.ProjectId, ep.IpAddress, ep.ApiVersion, ep.UserAgent)
            .Property("Id", queueEntry.Id)
            .Property("ApiVersion", ep.ApiVersion)
            .Property("IpAddress", ep.IpAddress)
            .Property("Client", ep.UserAgent)
            .Tag("processing", "compressed", ep.ContentEncoding)
            .Value(ep.Data.Length)
            .Project(ep.ProjectId)
            .WriteIf(!isInternalProject);

            var project = await _projectRepository.GetByIdAsync(ep.ProjectId, o => o.Cache()).AnyContext();

            if (project == null)
            {
                _logger.Error().Message("Unable to process EventPost \"{0}\": Unable to load project: {1}", queueEntry.Value.FilePath, ep.ProjectId).Property("Id", queueEntry.Id).Project(ep.ProjectId).WriteIf(!isInternalProject);
                await CompleteEntryAsync(queueEntry, ep, SystemClock.UtcNow).AnyContext();

                return(JobResult.Success);
            }

            long maxEventPostSize = Settings.Current.MaximumEventPostSize;

            byte[] uncompressedData = ep.Data;
            if (!String.IsNullOrEmpty(ep.ContentEncoding))
            {
                _logger.Debug().Message("Decompressing EventPost: {0} ({1} bytes)", queueEntry.Id, ep.Data.Length).Property("Id", queueEntry.Id).Tag("decompressing", ep.ContentEncoding).Project(ep.ProjectId).WriteIf(!isInternalProject);
                maxEventPostSize = GetMaximumUncompressedEventPostSize();
                try {
                    await _metricsClient.TimeAsync(async() => {
                        uncompressedData = await uncompressedData.DecompressAsync(ep.ContentEncoding).AnyContext();
                    }, MetricNames.PostsDecompressionTime).AnyContext();
                } catch (Exception ex) {
                    await _metricsClient.CounterAsync(MetricNames.PostsDecompressionErrors).AnyContext();
                    await CompleteEntryAsync(queueEntry, ep, SystemClock.UtcNow).AnyContext();

                    return(JobResult.FailedWithMessage($"Unable to decompress EventPost data '{queueEntry.Value.FilePath}' ({ep.Data.Length} bytes compressed): {ex.Message}"));
                }
            }

            await _metricsClient.GaugeAsync(MetricNames.PostsUncompressedSize, fileInfo.Size).AnyContext();

            if (uncompressedData.Length > maxEventPostSize)
            {
                await CompleteEntryAsync(queueEntry, ep, SystemClock.UtcNow).AnyContext();

                return(JobResult.FailedWithMessage($"Unable to process decompressed EventPost data '{queueEntry.Value.FilePath}' ({ep.Data.Length} bytes compressed, {uncompressedData.Length} bytes): Maximum uncompressed event post size limit ({maxEventPostSize} bytes) reached."));
            }

            _logger.Debug().Message("Processing uncompressed EventPost: {0}  ({1} bytes)", queueEntry.Id, uncompressedData.Length).Property("Id", queueEntry.Id).Tag("uncompressed").Value(uncompressedData.Length).Project(ep.ProjectId).WriteIf(!isInternalProject);
            var createdUtc = SystemClock.UtcNow;
            var events     = await ParseEventPostAsync(ep, createdUtc, uncompressedData, queueEntry.Id, isInternalProject).AnyContext();

            if (events == null || events.Count == 0)
            {
                await CompleteEntryAsync(queueEntry, ep, createdUtc).AnyContext();

                return(JobResult.Success);
            }

            if (context.CancellationToken.IsCancellationRequested)
            {
                await AbandonEntryAsync(queueEntry).AnyContext();

                return(JobResult.Cancelled);
            }

            bool isSingleEvent = events.Count == 1;

            if (!isSingleEvent)
            {
                await _metricsClient.TimeAsync(async() => {
                    // Don't process all the events if it will put the account over its limits.
                    int eventsToProcess = await _organizationRepository.GetRemainingEventLimitAsync(project.OrganizationId).AnyContext();

                    // Add 1 because we already counted 1 against their limit when we received the event post.
                    if (eventsToProcess < Int32.MaxValue)
                    {
                        eventsToProcess += 1;
                    }

                    // Discard any events over there limit.
                    events = events.Take(eventsToProcess).ToList();

                    // Increment the count if greater than 1, since we already incremented it by 1 in the OverageHandler.
                    if (events.Count > 1)
                    {
                        await _organizationRepository.IncrementUsageAsync(project.OrganizationId, false, events.Count - 1, applyHourlyLimit: false).AnyContext();
                    }
                }, MetricNames.PostsUpdateEventLimitTime).AnyContext();
            }

            int errorCount    = 0;
            var eventsToRetry = new List <PersistentEvent>();

            try {
                var contexts = await _eventPipeline.RunAsync(events, ep).AnyContext();

                _logger.Debug().Message(() => $"Ran {contexts.Count} events through the pipeline: id={queueEntry.Id} success={contexts.Count(r => r.IsProcessed)} error={contexts.Count(r => r.HasError)}").Property("Id", queueEntry.Id).Value(contexts.Count).Project(ep.ProjectId).WriteIf(!isInternalProject);
                foreach (var ctx in contexts)
                {
                    if (ctx.IsCancelled)
                    {
                        continue;
                    }

                    if (!ctx.HasError)
                    {
                        continue;
                    }

                    _logger.Error().Exception(ctx.Exception).Message("Error processing EventPost \"{0}\": {1}", queueEntry.Value.FilePath, ctx.ErrorMessage).Property("Id", queueEntry.Id).Project(ep.ProjectId).WriteIf(!isInternalProject);
                    if (ctx.Exception is ValidationException)
                    {
                        continue;
                    }

                    errorCount++;
                    if (!isSingleEvent)
                    {
                        // Put this single event back into the queue so we can retry it separately.
                        eventsToRetry.Add(ctx.Event);
                    }
                }
            } catch (Exception ex) {
                _logger.Error().Exception(ex).Message("Error processing EventPost \"{0}\": {1}", queueEntry.Value.FilePath, ex.Message).Property("Id", queueEntry.Id).Project(ep.ProjectId).WriteIf(!isInternalProject);
                if (ex is ArgumentException || ex is DocumentNotFoundException)
                {
                    await CompleteEntryAsync(queueEntry, ep, createdUtc).AnyContext();

                    return(JobResult.Success);
                }

                errorCount++;
                if (!isSingleEvent)
                {
                    eventsToRetry.AddRange(events);
                }
            }

            if (eventsToRetry.Count > 0)
            {
                await _metricsClient.TimeAsync(() => RetryEvents(context, eventsToRetry, ep, queueEntry), MetricNames.PostsRetryTime).AnyContext();
            }

            if (isSingleEvent && errorCount > 0)
            {
                await AbandonEntryAsync(queueEntry).AnyContext();
            }
            else
            {
                await CompleteEntryAsync(queueEntry, ep, createdUtc).AnyContext();
            }

            return(JobResult.Success);
        }
コード例 #6
0
        protected async override Task <JobResult> RunInternalAsync(CancellationToken token)
        {
            QueueEntry <EventPost> queueEntry = null;

            try {
                queueEntry = _queue.Dequeue(TimeSpan.FromSeconds(1));
            } catch (Exception ex) {
                if (!(ex is TimeoutException))
                {
                    Log.Error().Exception(ex).Message("An error occurred while trying to dequeue the next EventPost: {0}", ex.Message).Write();
                    return(JobResult.FromException(ex));
                }
            }

            if (queueEntry == null)
            {
                return(JobResult.Success);
            }

            if (token.IsCancellationRequested)
            {
                queueEntry.Abandon();
                return(JobResult.Cancelled);
            }

            EventPostInfo eventPostInfo = _storage.GetEventPostAndSetActive(queueEntry.Value.FilePath);

            if (eventPostInfo == null)
            {
                queueEntry.Abandon();
                _storage.SetNotActive(queueEntry.Value.FilePath);
                return(JobResult.FailedWithMessage(String.Format("Unable to retrieve post data '{0}'.", queueEntry.Value.FilePath)));
            }

            bool isInternalProject = eventPostInfo.ProjectId == Settings.Current.InternalProjectId;

            _statsClient.Counter(MetricNames.PostsDequeued);
            Log.Info().Message("Processing post: id={0} path={1} project={2} ip={3} v={4} agent={5}", queueEntry.Id, queueEntry.Value.FilePath, eventPostInfo.ProjectId, eventPostInfo.IpAddress, eventPostInfo.ApiVersion, eventPostInfo.UserAgent).WriteIf(!isInternalProject);

            List <PersistentEvent> events = null;

            try {
                _statsClient.Time(() => {
                    events = ParseEventPost(eventPostInfo);
                    Log.Info().Message("Parsed {0} events for post: id={1}", events.Count, queueEntry.Id).WriteIf(!isInternalProject);
                }, MetricNames.PostsParsingTime);
                _statsClient.Counter(MetricNames.PostsParsed);
                _statsClient.Gauge(MetricNames.PostsEventCount, events.Count);
            } catch (Exception ex) {
                _statsClient.Counter(MetricNames.PostsParseErrors);
                queueEntry.Abandon();
                _storage.SetNotActive(queueEntry.Value.FilePath);

                Log.Error().Exception(ex).Message("An error occurred while processing the EventPost '{0}': {1}", queueEntry.Id, ex.Message).Write();
                return(JobResult.FromException(ex, String.Format("An error occurred while processing the EventPost '{0}': {1}", queueEntry.Id, ex.Message)));
            }

            if (token.IsCancellationRequested)
            {
                queueEntry.Abandon();
                return(JobResult.Cancelled);
            }

            if (events == null)
            {
                queueEntry.Abandon();
                _storage.SetNotActive(queueEntry.Value.FilePath);
                return(JobResult.Success);
            }

            int  eventsToProcess = events.Count;
            bool isSingleEvent   = events.Count == 1;

            if (!isSingleEvent)
            {
                var project = _projectRepository.GetById(eventPostInfo.ProjectId, true);
                // Don't process all the events if it will put the account over its limits.
                eventsToProcess = _organizationRepository.GetRemainingEventLimit(project.OrganizationId);

                // Add 1 because we already counted 1 against their limit when we received the event post.
                if (eventsToProcess < Int32.MaxValue)
                {
                    eventsToProcess += 1;
                }

                // Increment by count - 1 since we already incremented it by 1 in the OverageHandler.
                _organizationRepository.IncrementUsage(project.OrganizationId, false, events.Count - 1);
            }

            if (events == null)
            {
                queueEntry.Abandon();
                _storage.SetNotActive(queueEntry.Value.FilePath);
                return(JobResult.Success);
            }

            var errorCount = 0;
            var created    = DateTime.UtcNow;

            try {
                events.ForEach(e => e.CreatedUtc = created);
                var results = _eventPipeline.Run(events.Take(eventsToProcess).ToList());
                Log.Info().Message("Ran {0} events through the pipeline: id={1} project={2} success={3} error={4}", results.Count, queueEntry.Id, eventPostInfo.ProjectId, results.Count(r => r.IsProcessed), results.Count(r => r.HasError)).WriteIf(!isInternalProject);
                foreach (var eventContext in results)
                {
                    if (eventContext.IsCancelled)
                    {
                        continue;
                    }

                    if (!eventContext.HasError)
                    {
                        continue;
                    }

                    Log.Error().Exception(eventContext.Exception).Project(eventPostInfo.ProjectId).Message("Error while processing event post \"{0}\": {1}", queueEntry.Value.FilePath, eventContext.ErrorMessage).Write();
                    if (eventContext.Exception is ValidationException)
                    {
                        continue;
                    }

                    errorCount++;

                    if (!isSingleEvent)
                    {
                        // Put this single event back into the queue so we can retry it separately.
                        _queue.Enqueue(new EventPostInfo {
                            ApiVersion = eventPostInfo.ApiVersion,
                            CharSet    = eventPostInfo.CharSet,
                            Data       = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(eventContext.Event)),
                            IpAddress  = eventPostInfo.IpAddress,
                            MediaType  = eventPostInfo.MediaType,
                            ProjectId  = eventPostInfo.ProjectId,
                            UserAgent  = eventPostInfo.UserAgent
                        }, _storage, false);
                    }
                }
            } catch (ArgumentException ex) {
                Log.Error().Exception(ex).Project(eventPostInfo.ProjectId).Message("Error while processing event post \"{0}\": {1}", queueEntry.Value.FilePath, ex.Message).Write();
                queueEntry.Complete();
            } catch (Exception ex) {
                Log.Error().Exception(ex).Project(eventPostInfo.ProjectId).Message("Error while processing event post \"{0}\": {1}", queueEntry.Value.FilePath, ex.Message).Write();
                errorCount++;
            }

            if (isSingleEvent && errorCount > 0)
            {
                queueEntry.Abandon();
                _storage.SetNotActive(queueEntry.Value.FilePath);
            }
            else
            {
                queueEntry.Complete();
                if (queueEntry.Value.ShouldArchive)
                {
                    _storage.CompleteEventPost(queueEntry.Value.FilePath, eventPostInfo.ProjectId, created, queueEntry.Value.ShouldArchive);
                }
                else
                {
                    _storage.DeleteFile(queueEntry.Value.FilePath);
                    _storage.SetNotActive(queueEntry.Value.FilePath);
                }
            }

            return(JobResult.Success);
        }
コード例 #7
0
        private async Task CompleteEntryAsync(IQueueEntry <EventPost> queueEntry, EventPostInfo eventPostInfo, DateTime created)
        {
            await queueEntry.CompleteAsync().AnyContext();

            await _storage.CompleteEventPostAsync(queueEntry.Value.FilePath, eventPostInfo.ProjectId, created, _logger, queueEntry.Value.ShouldArchive).AnyContext();
        }
コード例 #8
0
        public static async Task <string> EnqueueAsync(this IQueue <EventPost> queue, EventPostInfo data, IFileStorage storage, bool shouldArchive, CancellationToken cancellationToken = default(CancellationToken))
        {
            string path;

            if (shouldArchive)
            {
                path = $"archive\\{SystemClock.UtcNow:yy\\\\MM\\\\dd\\\\HH}\\{data.ProjectId}\\{Guid.NewGuid():N}.json";
            }
            else
            {
                path = $"q\\{Guid.NewGuid():N}.json";
            }

            if (!await storage.SaveObjectAsync(path, data, cancellationToken).AnyContext())
            {
                return(null);
            }

            return(await queue.EnqueueAsync(new EventPost {
                FilePath = path,
                ShouldArchive = shouldArchive
            }).AnyContext());
        }
コード例 #9
0
        protected override async Task <JobResult> ProcessQueueEntryAsync(JobQueueEntryContext <EventPost> context)
        {
            var           queueEntry    = context.QueueEntry;
            EventPostInfo eventPostInfo = await _storage.GetEventPostAndSetActiveAsync(queueEntry.Value.FilePath, context.CancellationToken).AnyContext();

            if (eventPostInfo == null)
            {
                await queueEntry.AbandonAsync().AnyContext();

                await _storage.SetNotActiveAsync(queueEntry.Value.FilePath).AnyContext();

                return(JobResult.FailedWithMessage($"Unable to retrieve post data '{queueEntry.Value.FilePath}'."));
            }

            bool isInternalProject = eventPostInfo.ProjectId == Settings.Current.InternalProjectId;

            Logger.Info().Message("Processing post: id={0} path={1} project={2} ip={3} v={4} agent={5}", queueEntry.Id, queueEntry.Value.FilePath, eventPostInfo.ProjectId, eventPostInfo.IpAddress, eventPostInfo.ApiVersion, eventPostInfo.UserAgent).WriteIf(!isInternalProject);

            List <PersistentEvent> events = null;

            try {
                _metricsClient.Time(() => {
                    events = ParseEventPost(eventPostInfo);
                    Logger.Info().Message("Parsed {0} events for post: id={1}", events.Count, queueEntry.Id).WriteIf(!isInternalProject);
                }, MetricNames.PostsParsingTime);
                await _metricsClient.CounterAsync(MetricNames.PostsParsed).AnyContext();

                await _metricsClient.GaugeAsync(MetricNames.PostsEventCount, events.Count).AnyContext();
            } catch (Exception ex) {
                await queueEntry.AbandonAsync().AnyContext();

                await _metricsClient.CounterAsync(MetricNames.PostsParseErrors).AnyContext();

                await _storage.SetNotActiveAsync(queueEntry.Value.FilePath).AnyContext();

                Logger.Error().Exception(ex).Message("An error occurred while processing the EventPost '{0}': {1}", queueEntry.Id, ex.Message).Write();
                return(JobResult.FromException(ex, $"An error occurred while processing the EventPost '{queueEntry.Id}': {ex.Message}"));
            }

            if (!events.Any() || context.CancellationToken.IsCancellationRequested)
            {
                await queueEntry.AbandonAsync().AnyContext();

                await _storage.SetNotActiveAsync(queueEntry.Value.FilePath).AnyContext();

                return(!events.Any() ? JobResult.Success : JobResult.Cancelled);
            }

            int  eventsToProcess = events.Count;
            bool isSingleEvent   = events.Count == 1;

            if (!isSingleEvent)
            {
                var project = await _projectRepository.GetByIdAsync(eventPostInfo.ProjectId, true).AnyContext();

                if (project == null)
                {
                    // NOTE: This could archive the data for a project that no longer exists.
                    Logger.Error().Project(eventPostInfo.ProjectId).Message($"Unable to process EventPost \"{queueEntry.Value.FilePath}\": Unable to load project: {eventPostInfo.ProjectId}").Write();
                    await CompleteEntryAsync(queueEntry, eventPostInfo, DateTime.UtcNow).AnyContext();

                    return(JobResult.Success);
                }

                // Don't process all the events if it will put the account over its limits.
                eventsToProcess = await _organizationRepository.GetRemainingEventLimitAsync(project.OrganizationId).AnyContext();

                // Add 1 because we already counted 1 against their limit when we received the event post.
                if (eventsToProcess < Int32.MaxValue)
                {
                    eventsToProcess += 1;
                }

                // Increment by count - 1 since we already incremented it by 1 in the OverageHandler.
                await _organizationRepository.IncrementUsageAsync(project.OrganizationId, false, events.Count - 1).AnyContext();
            }

            var errorCount = 0;
            var created    = DateTime.UtcNow;

            try {
                events.ForEach(e => e.CreatedUtc = created);
                var results = await _eventPipeline.RunAsync(events.Take(eventsToProcess).ToList()).AnyContext();

                Logger.Info().Message("Ran {0} events through the pipeline: id={1} project={2} success={3} error={4}", results.Count, queueEntry.Id, eventPostInfo.ProjectId, results.Count(r => r.IsProcessed), results.Count(r => r.HasError)).WriteIf(!isInternalProject);
                foreach (var eventContext in results)
                {
                    if (eventContext.IsCancelled)
                    {
                        continue;
                    }

                    if (!eventContext.HasError)
                    {
                        continue;
                    }

                    Logger.Error().Exception(eventContext.Exception).Project(eventPostInfo.ProjectId).Message("Error while processing event post \"{0}\": {1}", queueEntry.Value.FilePath, eventContext.ErrorMessage).Write();
                    if (eventContext.Exception is ValidationException)
                    {
                        continue;
                    }

                    errorCount++;

                    if (!isSingleEvent)
                    {
                        // Put this single event back into the queue so we can retry it separately.
                        await _queue.EnqueueAsync(new EventPostInfo {
                            ApiVersion = eventPostInfo.ApiVersion,
                            Data       = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(eventContext.Event)),
                            IpAddress  = eventPostInfo.IpAddress,
                            MediaType  = eventPostInfo.MediaType,
                            CharSet    = eventPostInfo.CharSet,
                            ProjectId  = eventPostInfo.ProjectId,
                            UserAgent  = eventPostInfo.UserAgent
                        }, _storage, false, context.CancellationToken).AnyContext();
                    }
                }
            } catch (Exception ex) {
                Logger.Error().Exception(ex).Project(eventPostInfo.ProjectId).Message("Error while processing event post \"{0}\": {1}", queueEntry.Value.FilePath, ex.Message).Write();
                if (ex is ArgumentException || ex is DocumentNotFoundException)
                {
                    await queueEntry.CompleteAsync().AnyContext();
                }
                else
                {
                    errorCount++;
                }
            }

            if (isSingleEvent && errorCount > 0)
            {
                await queueEntry.AbandonAsync().AnyContext();

                await _storage.SetNotActiveAsync(queueEntry.Value.FilePath).AnyContext();
            }
            else
            {
                await CompleteEntryAsync(queueEntry, eventPostInfo, created).AnyContext();
            }

            return(JobResult.Success);
        }
コード例 #10
0
 public EventContext(PersistentEvent ev, Organization organization, Project project, EventPostInfo epi = null)
 {
     Organization              = organization;
     Project                   = project;
     Event                     = ev;
     Event.OrganizationId      = organization.Id;
     Event.ProjectId           = project.Id;
     IncludePrivateInformation = project.Configuration.Settings.GetBoolean(SettingsDictionary.KnownKeys.IncludePrivateInformation, true);
     EventPostInfo             = epi;
     StackSignatureData        = new Dictionary <string, string>();
 }
コード例 #11
0
 public static Task <string> EnqueueAsync(this IQueue <EventPost> queue, EventPostInfo data, IFileStorage storage)
 {
     return(EnqueueAsync(queue, data, storage, Settings.Current.EnableArchive));
 }
コード例 #12
0
 public Task <EventContext> RunAsync(PersistentEvent ev, EventPostInfo epi = null)
 {
     return(RunAsync(new EventContext(ev, epi)));
 }
コード例 #13
0
        public static async Task <string> EnqueueAsync(this IQueue <EventPost> queue, EventPostInfo data, IFileStorage storage, bool shouldArchive = true, CancellationToken cancellationToken = default(CancellationToken))
        {
            string path = String.Format("q\\{0}.json", Guid.NewGuid().ToString("N"));

            if (!await storage.SaveObjectAsync(path, data, cancellationToken))
            {
                return(null);
            }

            return(queue.Enqueue(new EventPost {
                FilePath = path,
                ShouldArchive = shouldArchive
            }));
        }
コード例 #14
0
        public static async Task <string> EnqueueAsync(this IQueue <EventPost> queue, EventPostInfo data, IFileStorage storage, bool shouldArchive, CancellationToken cancellationToken)
        {
            string path = $"q\\{Guid.NewGuid():N}.json";

            if (!await storage.SaveObjectAsync(path, data, cancellationToken).AnyContext())
            {
                return(null);
            }

            return(await queue.EnqueueAsync(new EventPost {
                FilePath = path,
                ShouldArchive = shouldArchive
            }).AnyContext());
        }
コード例 #15
0
 public static async Task <string> EnqueueAsync(this IQueue <EventPost> queue, EventPostInfo data, IFileStorage storage, bool shouldArchive)
 {
     return(await EnqueueAsync(queue, data, storage, shouldArchive, default(CancellationToken)).AnyContext());
 }
コード例 #16
0
ファイル: EventContext.cs プロジェクト: zzms/Exceptionless
 public EventContext(PersistentEvent ev, EventPostInfo epi = null)
 {
     Event              = ev;
     EventPostInfo      = epi;
     StackSignatureData = new Dictionary <string, string>();
 }