/// <summary>
        /// This method writes the incoming event data to the data collectors.
        /// </summary>
        /// <param name="eventData">The event data.</param>
        /// <param name="support">The event data type.</param>
        /// <param name="sync">Specifies whether the data should be written out immediately.</param>
        /// <param name="claims">The optional claims of the calling party. If not set explicitly, then this
        /// will be populated from the current thread. If you don't want this then pass an empty claims object.</param>
        public void Write(EventBase eventData, DataCollectionSupport support, bool sync = false, ClaimsPrincipal claims = null)
        {
            if (eventData == null)
            {
                throw new ArgumentNullException("eventData", "eventData cannot be null for Write");
            }

            if (!Active)
            {
                throw new ServiceNotStartedException();
            }

            //Create the event holder and set the identity based on the claims passed or if null,
            //picked up from the current thread.
            var item = new EventHolder(support, claims ?? Thread.CurrentPrincipal as ClaimsPrincipal)
            {
                Data        = eventData
                , Sync      = sync
                , Timestamp = StatisticsInternal.ActiveIncrement()
            };

            //Do we have to write this straight away, or can we push it on to an async thread.
            if (item.Sync)
            {
                //Process the item immediately.
                ProcessItem(item);
            }
            else
            {
                mQueue.Enqueue(item);
                //Signal to the logging thread that there is more data waiting.
                mReset.Set();
            }
        }
Пример #2
0
        /// <summary>
        /// This method marshals the RepositoryHolder and transmits it to the remote Microservice.
        /// </summary>
        /// <typeparam Name="KT">The key type.</typeparam>
        /// <typeparam Name="ET">The entity type.</typeparam>
        /// <param name="actionType">The action type.</param>
        /// <param name="rq">The repository holder request.</param>
        /// <param name="routing"></param>
        /// <returns>Returns an async task that will be signalled when the request completes or times out.</returns>
        protected override async Task <RepositoryHolder <KT, ET> > TransmitInternal <KT, ET>(string actionType, RepositoryHolder <KT, ET> rq, ProcessOptions?routing = null, IPrincipal principal = null)
        {
            StatisticsInternal.ActiveIncrement();

            var payloadRq = TransmissionPayload.Create(mPolicy.TransmissionPayloadTraceEnabled);

            // Set the originator key to the correlation id if passed through the rq settings
            if (!string.IsNullOrEmpty(rq.Settings?.CorrelationId))
            {
                payloadRq.Message.ProcessCorrelationKey = rq.Settings.CorrelationId;
            }

            bool processAsync = rq.Settings?.ProcessAsync ?? false;

            payloadRq.Options = ProcessOptions.RouteInternal;
            var message = payloadRq.Message;

            payloadRq.MaxProcessingTime = rq.Settings?.WaitTime ?? mDefaultRequestTimespan;
            payloadRq.MessageObject     = rq;
            message.ChannelId           = ChannelId;
            message.ChannelPriority     = processAsync ? 0:-1;
            message.MessageType         = mMessageType;
            message.ActionType          = actionType;

            message.ResponseChannelId       = mResponseChannel;
            message.ResponseChannelPriority = -1; //Always internal

            message.Blob = PayloadSerializer.PayloadSerialize(rq);

            return(await OutgoingRequestOut(payloadRq, ProcessResponse <KT, ET>, processAsync : processAsync));
        }
        protected async Task Output(string id, string directory, byte[] blob, string contentType, string contentEncoding = null)
        {
            int  start   = StatisticsInternal.ActiveIncrement();
            Guid traceId = ProfileStart(id, directory);
            var  result  = ResourceRequestResult.Unknown;

            try
            {
                await mStorage.CreateOrUpdate(id, blob
                                              , directory : directory
                                              , contentType : contentType
                                              , contentEncoding : contentEncoding
                                              , createSnapshot : false);

                result = ResourceRequestResult.Success;
            }
            catch (StorageThrottlingException)
            {
                result = ResourceRequestResult.Exception;
                throw;
            }
            catch (Exception ex)
            {
                result = ResourceRequestResult.Exception;
                Collector?.LogException(string.Format("Unable to output {0} to {1} for {2}", id, directory, contentType), ex);
                StatisticsInternal.ErrorIncrement();
                throw;
            }
            finally
            {
                ProfileEnd(traceId, start, result);
                StatisticsInternal.ActiveDecrement(start);
            }
        }
        /// <summary>
        /// This method will write the current items in the queue to the stream processor.
        /// </summary>
        protected virtual int ProcessQueue(int?timespaninms = null)
        {
            ActionQueueContainer <D> logEvent;

            DateTime start = DateTime.UtcNow;

            int items = 0;

            do
            {
                while (mQueue.TryDequeue(out logEvent))
                {
                    EventWrite(logEvent.Data);

                    items++;

                    StatisticsInternal.ActiveDecrement(logEvent.Timestamp);

                    //Kick out every 100 loops if there is a timer limit.
                    if (timespaninms.HasValue && (items % 100 == 0))
                    {
                        break;
                    }
                }
            }while (mQueue.Count > 0 && (!timespaninms.HasValue || (DateTime.UtcNow - start).TotalMilliseconds < timespaninms));

            return(items);
        }
Пример #5
0
        /// <summary>
        /// This method is called to process an incoming message.
        /// </summary>
        /// <param name="request">The message to process.</param>
        /// <param name="responses">The return path for the message.</param>
        public virtual async Task ProcessMessage(TransmissionPayload requestPayload, List <TransmissionPayload> responses)
        {
            int start = StatisticsInternal.ActiveIncrement();

            try
            {
                var header = requestPayload.Message.ToServiceMessageHeader();

                H handler;
                if (!SupportedResolve(header, out handler))
                {
                    throw new NotSupportedException(string.Format("This command is not supported: '{0}' in {1}", header, GetType().Name));
                }

                //Call the registered command.
                await handler.Execute(requestPayload, responses);
            }
            catch (Exception)
            {
                StatisticsInternal.ErrorIncrement();
                throw;
            }
            finally
            {
                StatisticsInternal.ActiveDecrement(start);
            }
        }
Пример #6
0
        /// <summary>
        /// This method is called to process an incoming payload.
        /// </summary>
        /// <param name="rq">The message to process.</param>
        /// <param name="responses">The return path for the message.</param>
        public virtual async Task ProcessRequest(TransmissionPayload rq, List <TransmissionPayload> responses)
        {
            var header = rq.Message.ToServiceMessageHeader();
            H   handler;

            if (!SupportedResolve(header, out handler))
            {
                var ex = new CommandNotSupportedException(rq.Id, header, GetType());
                FireAndDecorateEventArgs(OnRequestUnresolved, () => new ProcessRequestEventArgs(rq, ex));
                throw ex;
            }

            FireAndDecorateEventArgs(OnRequest, () => new ProcessRequestEventArgs(rq));

            int start = StatisticsInternal.ActiveIncrement();

            try
            {
                //Call the registered command. This should not throw an exception if a hander has been registered.
                await handler.Execute(rq, responses);
            }
            catch (Exception ex)
            {
                StatisticsInternal.ErrorIncrement();
                FireAndDecorateEventArgs(OnRequestUnhandledException, () => new ProcessRequestEventArgs(rq, ex));
                //Handler has not caught the exception, so we default to the default policy behaviour.
                await ProcessRequestException(ex, rq, responses);
            }
            finally
            {
                StatisticsInternal.ActiveDecrement(start);
            }
        }
Пример #7
0
        /// <summary>
        /// This method marshals the RepositoryHolder and transmits it to the remote Microservice.
        /// </summary>
        /// <typeparam Name="KT">The key type.</typeparam>
        /// <typeparam Name="ET">The entity type.</typeparam>
        /// <param name="actionType">The action type.</param>
        /// <param name="rq">The repository holder request.</param>
        /// <param name="routing"></param>
        /// <returns>Returns an async task that will be signalled when the request completes or times out.</returns>
        protected override async Task <RepositoryHolder <KT, ET> > TransmitInternal <KT, ET>(string actionType, RepositoryHolder <KT, ET> rq, ProcessOptions?routing = null)
        {
            StatisticsInternal.ActiveIncrement();

            var payloadRq = TransmissionPayload.Create();

            bool processAsync = rq.Settings?.ProcessAsync ?? false;

            payloadRq.Options = ProcessOptions.RouteInternal;
            var message = payloadRq.Message;

            payloadRq.MaxProcessingTime = rq.Settings?.WaitTime ?? mDefaultRequestTimespan;
            payloadRq.MessageObject     = rq;
            message.ChannelId           = ChannelId;
            message.ChannelPriority     = processAsync ? 0:-1;
            message.MessageType         = mMessageType;
            message.ActionType          = actionType;

            message.ResponseChannelId       = mResponseChannel;
            message.ResponseChannelPriority = -1; //Always internal

            message.Blob = PayloadSerializer.PayloadSerialize(rq);

            return(await TransmitAsync(payloadRq, ProcessResponse <KT, ET>, processAsync : processAsync));
        }
Пример #8
0
        /// <summary>
        /// This method is called to process an incoming payload.
        /// </summary>
        /// <param name="rq">The message to process.</param>
        /// <param name="responses">The return path for the message.</param>
        public virtual async Task ProcessRequest(TransmissionPayload rq, List <TransmissionPayload> responses)
        {
            int start = StatisticsInternal.ActiveIncrement();

            try
            {
                var header = rq.Message.ToServiceMessageHeader();

                H handler;
                if (!SupportedResolve(header, out handler))
                {
                    OnRequestUnresolved?.Invoke(this, rq);
                    throw new CommandNotSupportedException(rq.Id, header, GetType());
                }

                OnRequest?.Invoke(this, rq);
                //Call the registered command.
                await handler.Execute(rq, responses);
            }
            catch (Exception)
            {
                StatisticsInternal.ErrorIncrement();
                //throw any errors back out to the dispatcher.
                throw;
            }
            finally
            {
                StatisticsInternal.ActiveDecrement(start);
            }
        }
        /// <summary>
        /// This method writes the event data to the underlying storage.
        /// </summary>
        /// <param name="connector">The generic connector.</param>
        /// <param name="e">The event to write.</param>
        /// <returns>This is an async process.</returns>
        protected virtual async Task WriteConnector(IAzureStorageConnectorBase connector, EventHolder e)
        {
            int start = StatisticsInternal.ActiveIncrement(connector.Support);

            Guid?traceId = connector.Options.ShouldProfile ? (ProfileStart($"Azure{connector.Support}_{e.Data.TraceId}")) : default(Guid?);

            var result = ResourceRequestResult.Unknown;

            try
            {
                await connector.Write(e, OriginatorId);

                result = ResourceRequestResult.Success;
            }
            catch (StorageThrottlingException)
            {
                result = ResourceRequestResult.Exception;
                throw;
            }
            catch (Exception ex)
            {
                result = ResourceRequestResult.Exception;
                //Collector?.LogException(string.Format("Unable to output {0} to {1} for {2}", id, directory, typeof(E).Name), ex);
                StatisticsInternal.ErrorIncrement(connector.Support);
                throw;
            }
            finally
            {
                StatisticsInternal.ActiveDecrement(connector.Support, start);
                if (traceId.HasValue)
                {
                    ProfileEnd(traceId.Value, start, result);
                }
            }
        }
Пример #10
0
        /// <summary>
        /// This is called when the request is retried due to an underlying storage issue.
        /// </summary>
        /// <typeparam name="KT">The key type.</typeparam>
        /// <typeparam name="ET">The entity type.</typeparam>
        /// <param name="holder">The request holder.</param>
        /// <param name="retryStart">The tick count of the retry point.</param>
        protected virtual void ProfileRetry <KT, ET>(PersistenceRequestHolder <KT, ET> holder, int retryStart)
        {
            mPolicy.ResourceConsumer?.Retry(holder.ProfileId, retryStart, holder.Rs.ShouldRetry ? ResourceRetryReason.Other : ResourceRetryReason.Timeout);

            holder.Retry(retryStart);

            StatisticsInternal.RetryIncrement();
        }
        /// <summary>
        /// This method processes the incoming event by looping through the collectors for the particular type.
        /// </summary>
        /// <param name="eventData">The event data holder.</param>
        protected void ProcessItem(EventHolder eventData)
        {
            mCollectorSupported[eventData.DataType]?
            .ForEach((l) => ProcessItem(l, eventData));

            //Decrement the active count with the time needed to process.
            StatisticsInternal.ActiveDecrement(eventData.Timestamp);
        }
Пример #12
0
        /// <summary>
        /// This method is used to process the returning message response.
        /// </summary>
        /// <typeparam name="KT"></typeparam>
        /// <typeparam name="ET"></typeparam>
        /// <param name="rType"></param>
        /// <param name="payload"></param>
        /// <param name="processAsync"></param>
        /// <returns></returns>
        protected virtual RepositoryHolder <KT, ET> ProcessResponse <KT, ET>(TaskStatus rType, TransmissionPayload payload, bool processAsync)
        {
            StatisticsInternal.ActiveDecrement(payload != null ? payload.Extent : TimeSpan.Zero);

            if (processAsync)
            {
                return(new RepositoryHolder <KT, ET>(responseCode: 202, responseMessage: "Accepted"));
            }

            try
            {
                switch (rType)
                {
                case TaskStatus.RanToCompletion:
                    if (payload.MessageObject != null)
                    {
                        return(payload.MessageObject as RepositoryHolder <KT, ET>);
                    }

                    if (payload.Message.Blob == null)
                    {
                        return(new RepositoryHolder <KT, ET>(responseCode: 500, responseMessage: "Unexpected response (no payload)"));
                    }

                    try
                    {
                        var response = PayloadSerializer.PayloadDeserialize <RepositoryHolder <KT, ET> >(payload);
                        return(response);
                    }
                    catch (Exception ex)
                    {
                        StatisticsInternal.ErrorIncrement();
                        return(new RepositoryHolder <KT, ET>(responseCode: 500, responseMessage: ex.Message));
                    }

                case TaskStatus.Canceled:
                    StatisticsInternal.ErrorIncrement();
                    return(new RepositoryHolder <KT, ET>(responseCode: 408, responseMessage: "Time out"));

                case TaskStatus.Faulted:
                    StatisticsInternal.ErrorIncrement();
                    return(new RepositoryHolder <KT, ET>()
                    {
                        ResponseCode = (int)PersistenceResponse.GatewayTimeout504, ResponseMessage = "Response timeout."
                    });

                default:
                    StatisticsInternal.ErrorIncrement();
                    return(new RepositoryHolder <KT, ET>(responseCode: 500, responseMessage: rType.ToString()));
                }
            }
            catch (Exception ex)
            {
                Logger.LogException("Error processing response for task status " + rType, ex);
                throw;
            }
        }
Пример #13
0
        /// <summary>
        /// This method enqueues the message.
        /// </summary>
        /// <param name="item">The task tracker to enqueue.</param>
        public void Enqueue(TaskTracker item)
        {
            var wrapper = new QueueTrackerHolder {
                Item = item, Ingress = StatisticsInternal.ActiveIncrement()
            };

            mQueue.Enqueue(wrapper);
            StatisticsInternal.WaitingSet(Count);
        }
        /// <summary>
        /// This method is the default method used to process the returning message response.
        /// </summary>
        /// <typeparam name="RS">The response type.</typeparam>
        /// <param name="rType"></param>
        /// <param name="payloadRs">The incoming response payload.</param>
        /// <param name="processAsync"></param>
        /// <returns>Returns the response wrapper generic object.</returns>
        protected virtual ResponseWrapper <RS> ProcessOutgoingResponse <RS>(TaskStatus rType, TransmissionPayload payloadRs, bool processAsync)
        {
            StatisticsInternal.ActiveDecrement(payloadRs?.Extent ?? TimeSpan.Zero);

            if (processAsync)
            {
                return(new ResponseWrapper <RS>(responseCode: 202, responseMessage: "Accepted"));
            }

            try
            {
                payloadRs?.CompleteSet();

                switch (rType)
                {
                case TaskStatus.RanToCompletion:
                    try
                    {
                        //payload.Message.
                        var response = new ResponseWrapper <RS>(payloadRs);

                        if (payloadRs.Message.Blob.HasObject)
                        {
                            response.Response = (RS)payloadRs.Message.Blob.Object;
                        }
                        else if (payloadRs.Message.Blob != null)
                        {
                            response.Response = PayloadSerializer.PayloadDeserialize <RS>(payloadRs);
                        }

                        return(response);
                    }
                    catch (Exception ex)
                    {
                        StatisticsInternal.ErrorIncrement();
                        return(new ResponseWrapper <RS>(500, ex.Message));
                    }

                case TaskStatus.Canceled:
                    StatisticsInternal.ErrorIncrement();
                    return(new ResponseWrapper <RS>(408, "Time out"));

                case TaskStatus.Faulted:
                    StatisticsInternal.ErrorIncrement();
                    return(new ResponseWrapper <RS>((int)PersistenceResponse.GatewayTimeout504, "Response timeout."));

                default:
                    StatisticsInternal.ErrorIncrement();
                    return(new ResponseWrapper <RS>(500, rType.ToString()));
                }
            }
            catch (Exception ex)
            {
                Collector?.LogException("Error processing response for task status " + rType, ex);
                throw;
            }
        }
        /// <summary>
        /// This is wrapper class that provides generic exception handling support
        /// and retrieves the standard metadata for each request.
        /// </summary>
        /// <param name="rq">The request.</param>
        /// <param name="rs">The response.</param>
        /// <param name="action">The async action task.</param>
        /// <returns>Returns a task with the response.</returns>
        protected async Task <StorageResponseHolder> CallCloudBlockBlob(StorageRequestHolder rq
                                                                        , Func <StorageRequestHolder, StorageResponseHolder, bool, Task> action)
        {
            int start = StatisticsInternal.ActiveIncrement();
            var rs    = new StorageResponseHolder();

            try
            {
                var refEntityDirectory = mEntityContainer.GetDirectoryReference(rq.Directory);
                rq.Blob = refEntityDirectory.GetBlockBlobReference(rq.SafeKey);

                bool exists = await rq.Blob.ExistsAsync(rq.CancelSet);

                if (exists)
                {
                    MetadataGet(rq.Blob, rq);
                    exists ^= rq.IsDeleted;
                }

                await action(rq, rs, exists);
            }
            catch (StorageException sex)
            {
                rs.Ex         = sex;
                rs.IsSuccess  = false;
                rs.StatusCode = sex.RequestInformation.HttpStatusCode;
                rs.IsTimeout  = rs.StatusCode == 500 || rs.StatusCode == 503;
            }
            catch (TaskCanceledException tcex)
            {
                rs.Ex         = tcex;
                rs.IsTimeout  = true;
                rs.IsSuccess  = false;
                rs.StatusCode = 502;
            }
            catch (Exception ex)
            {
                rs.Ex         = ex;
                rs.IsSuccess  = false;
                rs.StatusCode = 500;
            }
            finally
            {
                if (!rs.IsSuccess)
                {
                    StatisticsInternal.ErrorIncrement();
                }
                StatisticsInternal.ActiveDecrement(start);
            }

            return(rs);
        }
 /// <summary>
 /// This method wraps the individual request in a safe wrapper.
 /// </summary>
 /// <param name="eventData">The event data.</param>
 /// <param name="item">The item to process.</param>
 protected virtual void ProcessItem(D eventData, I item)
 {
     try
     {
         Process(eventData, item);
     }
     catch (Exception ex)
     {
         //We don't want unexpected exceptions here and to stop the other loggers working.
         StatisticsInternal.ErrorIncrement();
         StatisticsInternal.Ex = ex;
     }
 }
Пример #17
0
        /// <summary>
        /// This method attemps to dequeue a message.
        /// </summary>
        /// <param name="item">The item dequeued or null</param>
        /// <returns>Returns true if a message was dequeued successfully.</returns>
        public bool TryDequeue(out TaskTracker item)
        {
            item = null;
            QueueTrackerHolder wrapper;

            if (mQueue.TryDequeue(out wrapper))
            {
                item = wrapper.Item;
                StatisticsInternal.ActiveDecrement(wrapper.Ingress);
                return(true);
            }
            return(false);
        }
 /// <summary>
 /// This method wraps the individual request in a safe wrapper.
 /// </summary>
 /// <param name="dataCollector">The data collector component.</param>
 /// <param name="eventData">The event data holder.</param>
 protected virtual void ProcessItem(IDataCollectorComponent dataCollector, EventHolder eventData)
 {
     try
     {
         dataCollector.Write(eventData);
     }
     catch (Exception ex)
     {
         //We don't want unexpected exceptions here and to stop the other loggers working.
         StatisticsInternal.ErrorIncrement();
         StatisticsInternal.Ex = ex;
     }
 }
Пример #19
0
        public bool TryDequeue(out TaskTracker item)
        {
            item = null;
            KeyValuePair <TaskTracker, int> wrapper;

            if (mQueue.TryDequeue(out wrapper))
            {
                item = wrapper.Key;
                StatisticsInternal.ActiveDecrement(wrapper.Value);
                return(true);
            }
            return(false);
        }
Пример #20
0
        /// <summary>
        /// This method marshals the RepositoryHolder and transmits it to the remote Microservice.
        /// </summary>
        /// <typeparam Name="KT">The key type.</typeparam>
        /// <typeparam Name="ET">The entity type.</typeparam>
        /// <param Name="actionType">The action type.</param>
        /// <param Name="rq">The repository holder request.</param>
        /// <returns>Returns an async task that will be signalled when the request completes or times out.</returns>
        protected override async Task <RepositoryHolder <KT, ET> > TransmitInternal <KT, ET>(
            string actionType, RepositoryHolder <KT, ET> rq, ProcessOptions?routing = null, IPrincipal principal = null)
        {
            try
            {
                StatisticsInternal.ActiveIncrement();

                var payload = TransmissionPayload.Create(Policy.TransmissionPayloadTraceEnabled);

                payload.SecurityPrincipal = TransmissionPayload.ConvertToClaimsPrincipal(principal ?? Thread.CurrentPrincipal);

                // Set the process correlation key to the correlation id if passed through the rq settings
                if (!string.IsNullOrEmpty(rq.Settings?.CorrelationId))
                {
                    payload.Message.ProcessCorrelationKey = rq.Settings.CorrelationId;
                }

                bool processAsync = rq.Settings?.ProcessAsync ?? false;

                payload.Message.ChannelPriority = processAsync ? 0 : 1;

                payload.Options = routing ?? RoutingDefault ?? ProcessOptions.RouteExternal;

                payload.Message.Blob = PayloadSerializer.PayloadSerialize(rq);

                payload.Message.ResponseChannelId = ResponseChannelId;

                payload.Message.ResponseChannelId   = ResponseId.Header.ChannelId;
                payload.Message.ResponseMessageType = ResponseId.Header.MessageType;
                payload.Message.ResponseActionType  = ResponseId.Header.ActionType;

                payload.Message.ResponseChannelPriority = payload.Message.ChannelPriority;

                payload.Message.ChannelId   = ChannelId;
                payload.Message.MessageType = EntityType;
                payload.Message.ActionType  = actionType;

                payload.MaxProcessingTime = rq.Settings?.WaitTime ?? mDefaultRequestTimespan;

                return(await OutgoingRequestOut(payload, ProcessResponse <KT, ET>, processAsync));
            }
            catch (Exception ex)
            {
                string key = rq != null && rq.Key != null?rq.Key.ToString() : string.Empty;

                Collector?.LogException($"Error transmitting {actionType}-{key} internally", ex);
                throw;
            }
        }
        /// <summary>
        /// This method queues the incoming event data to be processed on the queue thread.
        /// </summary>
        /// <param name="eventData">The incoming event</param>
        protected virtual void EventEnqueue(D eventData)
        {
            if (!Active)
            {
                throw new ServiceNotStartedException();
            }

            var item = new ActionQueueContainer <D> {
                Data = eventData, Timestamp = StatisticsInternal.ActiveIncrement()
            };

            mQueue.Enqueue(item);

            mReset.Set();
        }
Пример #22
0
        /// <summary>
        /// Write event source
        /// </summary>
        /// <param name="support"></param>
        /// <param name="eventHolder"></param>
        protected virtual void WriteEvent(DataCollectionSupport support, EventHolder eventHolder)
        {
            var options = mPolicy.Options.FirstOrDefault(o => o.Support == support);

            if (options == null || !options.IsSupported(eventHolder))
            {
                return;
            }

            int  start   = StatisticsInternal.ActiveIncrement(options.Support);
            Guid?traceId = options.ShouldProfile ? (ProfileStart($"AzureEventHub{options.Support}_{eventHolder.Data.TraceId}")) : default(Guid?);

            // Check we have en event hub client
            mEventHubClient = mEventHubClient ?? CreateEventHubClient();

            var result = ResourceRequestResult.Unknown;

            try
            {
                //Serialize the blob.
                var blob = options.SerializerBinary(eventHolder, OriginatorId).Blob;

                //Encrypt the blob is that is the policy.
                if (options.EncryptionPolicy != AzureStorageEncryption.None && mEncryption != null)
                {
                    blob = ServiceHandlers.Encryption[mEncryption].Encrypt(blob);
                }

                mEventHubClient.SendAsync(new EventData(blob)).Wait();
                result = ResourceRequestResult.Success;
            }
            catch (Exception)
            {
                result = ResourceRequestResult.Exception;
                StatisticsInternal.ErrorIncrement(options.Support);
                throw;
            }
            finally
            {
                StatisticsInternal.ActiveDecrement(options.Support, start);
                if (traceId.HasValue)
                {
                    ProfileEnd(traceId.Value, start, result);
                }
            }
        }
Пример #23
0
        /// <summary>
        /// This method invokes the event to simulate transmission of the payload.
        /// </summary>
        /// <param name="payload">The payload to transmit.</param>
        /// <param name="retry">The retry count.</param>
        /// <returns></returns>
        public override async Task Transmit(TransmissionPayload payload, int retry = 0)
        {
            bool tryAgain = false;
            bool fail     = true;

            try
            {
                LastTickCount = Environment.TickCount;

                if (retry > MaxRetries)
                {
                    throw new RetryExceededTransmissionException();
                }

                IncomingAction?.Invoke(payload);

                if (BoundaryLoggingActive)
                {
                    Collector?.BoundaryLog(ChannelDirection.Outgoing, payload, ChannelId, Priority);
                }

                fail = false;
            }
            catch (Exception ex)
            {
                LogException("Unhandled Exception (Transmit)", ex);
                if (BoundaryLoggingActive)
                {
                    Collector?.BoundaryLog(ChannelDirection.Outgoing, payload, ChannelId, Priority, ex);
                }
                throw;
            }
            finally
            {
                if (fail)
                {
                    StatisticsInternal.ExceptionHitIncrement();
                }
            }

            if (tryAgain)
            {
                await Transmit(payload, ++retry);
            }
        }
Пример #24
0
        /// <summary>
        /// This method creates the necessary task.
        /// </summary>
        /// <param name="tracker">The tracker to create a task.</param>
        /// <returns>Returns a task for the job.</returns>
        private Task ExecuteTaskCreate(TaskTracker tracker)
        {
            //Internal tasks should not block other incoming tasks and they are pass-through requests from another task.
            tracker.ExecuteTickCount = StatisticsInternal.ActiveIncrement();

            var payload = tracker.Context as TransmissionPayload;

            if (payload != null)
            {
                payload.Cancel      = tracker.Cts.Token;
                tracker.ExecuteTask = Dispatcher(payload);
            }
            else
            {
                tracker.ExecuteTask = tracker.Execute(tracker.Cts.Token);
            }

            return(tracker.ExecuteTask);
        }
Пример #25
0
        /// <summary>
        /// This method cancels the specific tracker.
        /// </summary>
        /// <param name="tracker">The tracker to cancel.</param>
        private void TaskCancel(TaskTracker tracker)
        {
            if (tracker.IsCancelled)
            {
                return;
            }

            try
            {
                StatisticsInternal.TimeoutRegister(1);
                tracker.Cancel();
                LoopSet();
            }
            catch (Exception ex)
            {
                Collector?.LogException("TaskCancel exception", ex);
            }

            TaskTrackerEvent(DiagnosticOnExecuteTaskCancelled, tracker);
        }
        /// <summary>
        /// This method marshals the RepositoryHolder and transmits it to the remote Microservice.
        /// </summary>
        /// <typeparam Name="KT">The key type.</typeparam>
        /// <typeparam Name="ET">The entity type.</typeparam>
        /// <param Name="actionType">The action type.</param>
        /// <param Name="rq">The repository holder request.</param>
        /// <returns>Returns an async task that will be signalled when the request completes or times out.</returns>
        protected override async Task <RepositoryHolder <KT, ET> > TransmitInternal <KT, ET>(string actionType, RepositoryHolder <KT, ET> rq, ProcessOptions?routing = null)
        {
            try
            {
                StatisticsInternal.ActiveIncrement();

                var payload = TransmissionPayload.Create();

                // Set the originator key to the correlation id if passed through the rq settings
                if (rq.Settings != null && !string.IsNullOrEmpty(rq.Settings.CorrelationId))
                {
                    payload.Message.OriginatorKey = rq.Settings.CorrelationId;
                }

                bool processAsync = rq.Settings == null ? false : rq.Settings.ProcessAsync;

                payload.Message.ChannelPriority = processAsync ? 0 : 1;

                payload.Options = routing ?? RoutingDefault ?? ProcessOptions.RouteExternal;

                payload.Message.Blob = PayloadSerializer.PayloadSerialize(rq);

                payload.Message.ResponseChannelId       = ResponseChannelId;
                payload.Message.ResponseChannelPriority = payload.Message.ChannelPriority;

                payload.Message.ChannelId   = ChannelId;
                payload.Message.MessageType = EntityType;
                payload.Message.ActionType  = actionType;

                payload.MaxProcessingTime = rq.Settings?.WaitTime ?? mDefaultRequestTimespan;

                return(await TransmitAsync(payload, ProcessResponse <KT, ET>, processAsync));
            }
            catch (Exception ex)
            {
                string key = rq != null && rq.Key != null?rq.Key.ToString() : string.Empty;

                Logger.LogException(string.Format("Error transmitting {0}-{1} internally", actionType, key), ex);
                throw;
            }
        }
Пример #27
0
        /// <summary>
        /// This method executes the message handler and logs the time statistics.
        /// </summary>
        /// <param name="rq">The incoming requests.</param>
        /// <param name="rs">The outgoing responses.</param>
        public async virtual Task Execute(TransmissionPayload rq, List <TransmissionPayload> rs)
        {
            int timerStart = StatisticsInternal.ActiveIncrement();

            mLastAccessed = Environment.TickCount;

            try
            {
                await Action(rq, rs);
            }
            catch (Exception ex)
            {
                StatisticsInternal.ErrorIncrement();
                StatisticsInternal.Ex = ex;
                throw;
            }
            finally
            {
                StatisticsInternal.ActiveDecrement(timerStart);
            }
        }
Пример #28
0
        /// <summary>
        /// This method logs the event to DocumentDb
        /// </summary>
        /// <param name="logEvent">The event to store in the log.</param>
        public async Task Log(LogEvent logEvent)
        {
            int start = StatisticsInternal.ActiveIncrement();

            try
            {
                if (logEvent == null)
                {
                    return;
                }

                if (mLoggingPermitted != null && !mLoggingPermitted.Contains(logEvent.Level))
                {
                    return;
                }

                JObject jObj = JObject.FromObject(logEvent);

                jObj["id"] = mInstance + Guid.NewGuid().ToString("N");

                if (mOriginatorId != null)
                {
                    jObj["$microservice.instance"] = mOriginatorId.ExternalServiceId;
                }

                jObj["$microservice.timestamp"] = DateTime.UtcNow;
                jObj["$microservice.logtype"]   = logEvent.GetType().Name;

                await mDocDb.Collection.Create(jObj.ToString());
            }
            catch (Exception ex)
            {
                StatisticsInternal.ErrorIncrement();
            }
            finally
            {
                StatisticsInternal.ActiveDecrement(start);
            }
        }
Пример #29
0
        /// <summary>
        /// This method executes the message handler and logs the time statistics.
        /// </summary>
        /// <param name="rq">The incoming requests.</param>
        /// <param name="rs">The outgoing responses.</param>
        public async virtual Task Execute(TransmissionPayload rq, List <TransmissionPayload> rs)
        {
            int timerStart = StatisticsInternal.ActiveIncrement();

            mLastAccessed = timerStart;
            bool      error    = false;
            Exception actionEx = null;

            try
            {
                try
                {
                    await Action(rq, rs);
                }
                catch (Exception ex)
                {
                    StatisticsInternal.ErrorIncrement();
                    StatisticsInternal.Ex = ex;
                    error    = true;
                    actionEx = ex;

                    if (ExceptionAction == null)
                    {
                        throw;
                    }
                }

                if (error)
                {
                    await ExceptionAction(actionEx, rq, rs);
                }
            }
            finally
            {
                StatisticsInternal.ActiveDecrement(timerStart);
            }
        }
Пример #30
0
        /// <summary>
        /// This method is called after a task has completed.
        /// </summary>
        /// <param name="tracker">The tracker.</param>
        /// <param name="failed">A boolean value indicating whether the task has failed.</param>
        /// <param name="tex">Any exception that was caught as the task executed.</param>
        private void ExecuteTaskComplete(TaskTracker tracker, bool failed, Exception tex)
        {
            tracker.IsFailure        = failed;
            tracker.FailureException = tex;

            tracker.ToTransmissionPayload()?.TraceWrite("ExecuteTaskComplete", "TaskManager");

            try
            {
                TaskTracker outTracker;
                if (mTaskRequests.TryRemove(tracker.Id, out outTracker))
                {
                    mAvailability.Decrement(outTracker);

                    try
                    {
                        outTracker.ExecuteComplete?.Invoke(outTracker, failed, tex);
                    }
                    catch (Exception ex)
                    {
                        //We shouldn't throw an exception here, but let's check just in case.
                        Collector?.LogException("ExecuteTaskComplete/ExecuteComplete", ex);
                    }

                    if (outTracker.ExecuteTickCount.HasValue)
                    {
                        StatisticsInternal.ActiveDecrement(outTracker.ExecuteTickCount.Value);
                    }
                }
                else
                {
                    tracker.IsFailure = true;
                    TaskTrackerEvent(DiagnosticOnExecuteTaskCompleteOrphan, tracker);
                }
            }
            catch (Exception ex)
            {
                Collector?.LogException($"Task {tracker.Id} has faulted when completing: {ex.Message}", ex);
            }

            try
            {
                //Signal the poll loop to proceed in case it is waiting, this will check for any pending tasks that require processing.
                LoopSet();

                if (failed)
                {
                    TaskTrackerEvent(DiagnosticOnExecuteTaskCompleteFailure, tracker);

                    StatisticsInternal.ErrorIncrement();

                    if (tex != null && tex is AggregateException)
                    {
                        foreach (Exception ex in ((AggregateException)tex).InnerExceptions)
                        {
                            Collector?.LogException(string.Format("Task exception {0}-{1}", tracker.Id, tracker.Caller), ex);
                        }
                    }
                }
                else
                {
                    TaskTrackerEvent(DiagnosticOnExecuteTaskCompleteSuccess, tracker);
                }
            }
            catch { }
        }