public static async Task <IActionResult> GetCustomerByIdAsync(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "v1/customers/{id}")] HttpRequest req,
            string id,
            [Inject] IMediator mediator,
            [Inject] IMapper mapper,
            [Inject] IServerlessLogger serverlessLogger,
            [Inject] IHttpContextAccessor acessor,
            [Inject] Presenter presenter,
            [Inject] BadRequestPresenter badRequestPresenter,
            ILogger log)
        {
            serverlessLogger.InjectLogger(log);

            var functionMiddleware = new GetCustomerByIdFunctionMiddleware(
                req,
                id,
                mediator,
                mapper,
                presenter,
                badRequestPresenter,
                serverlessLogger);

            return(await functionMiddleware.ExecutePipeline(serverlessLogger, req, acessor, true)
                   .ConfigureAwait(false));
        }
Exemple #2
0
 public CreateCustomerRepository(
     IDatabaseFactory <SqlServerDatabase> sqlDatabase,
     IServerlessLogger logger)
 {
     this.sqlDatabase = sqlDatabase.Create();
     this.logger      = logger;
 }
Exemple #3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="LoggingHandler"/> class.
 /// </summary>
 /// <param name="serverlessLogger">See <see cref="IServerlessLogger"/>.</param>
 /// <param name="transactionFlow">See <see cref="ITransactionFlow"/>.</param>
 public LoggingHandler(
     IServerlessLogger serverlessLogger,
     ITransactionFlow transactionFlow)
 {
     this.serverlessLogger = serverlessLogger;
     this.transactionFlow  = transactionFlow;
 }
        private static List <HttpMiddleware> GetMiddlewares(
            HttpMiddleware functionMiddleware,
            IServerlessLogger serverlessLogger,
            IHttpContextAccessor acessor,
            bool allowAnonymous)
        {
            var exceptionMiddleware = new ExceptionMiddleware(serverlessLogger);
            var loggerMiddleware    = new LoggerMiddleware(serverlessLogger);
            var headerMiddleware    = new HeaderMiddleware();

            List <HttpMiddleware> middlewares = null;

            if (allowAnonymous)
            {
                middlewares = MiddlewaresWithoutAuth(
                    functionMiddleware,
                    exceptionMiddleware,
                    loggerMiddleware,
                    headerMiddleware);
            }
            else
            {
                middlewares = MiddlewaresWithAuth(
                    functionMiddleware,
                    serverlessLogger,
                    acessor,
                    exceptionMiddleware,
                    loggerMiddleware,
                    headerMiddleware);
            }

            return(middlewares);
        }
Exemple #5
0
        /// <summary>
        /// Extract correlationId value from <see cref="EventData"/> properties.
        /// </summary>
        /// <param name="serverlessLogger">Logger to save log with correlationId extracted.</param>
        /// <param name="patternLog">Pattern log.</param>
        /// <returns>CorrelationId value extracted.</returns>
        public static string GetCorrelationId(IServerlessLogger serverlessLogger, string patternLog)
        {
            var correlationId = Guid.NewGuid();

            serverlessLogger.LogInformation($"{patternLog} Processing document with {nameof(correlationId)}: {correlationId}!");

            return(correlationId.ToString());
        }
        /// <summary>
        /// Create pattern log.
        /// </summary>
        /// <param name="className">Name of trigger class.</param>
        /// <param name="serverlessLogger">Logger to save log with pattern created and execution time.</param>
        /// <returns>Pattern log created.</returns>
        public static string CreatePatternLog(string className, IServerlessLogger serverlessLogger)
        {
            var pattern = $"[{Guid.NewGuid()} | {className}] ";

            serverlessLogger.LogInformation($"C# Timer trigger function executed at: {DateTime.UtcNow}");

            return(pattern);
        }
        /// <summary>
        /// Extract correlationId value from <see cref="EventData"/> properties.
        /// </summary>
        /// <param name="eventData">Event data.</param>
        /// <param name="serverlessLogger">Logger to save log with correlationId extracted.</param>
        /// <param name="patternLog">Pattern log.</param>
        /// <returns>CorrelationId value extracted.</returns>
        public static string GetCorrelationId(EventData eventData, IServerlessLogger serverlessLogger, string patternLog)
        {
            var properties = eventData.Properties;

            properties.TryGetValue("correlationId", out var correlationId);

            serverlessLogger.LogInformation($"{patternLog} Processing event with {nameof(correlationId)}: {correlationId}!");

            return((correlationId ?? Guid.NewGuid()).ToString());
        }
Exemple #8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MiddlewarePipeline"/> class.
        /// </summary>
        /// <param name="pipeline">List of <see cref="HttpMiddleware"/> to build a pipeline.</param>
        /// <param name="serverlessLogger">Logger to log error in case of fail.</param>
        public MiddlewarePipeline(List <HttpMiddleware> pipeline, IServerlessLogger serverlessLogger)
        {
            this.serverlessLogger = serverlessLogger ?? throw new ArgumentNullException(nameof(serverlessLogger));

            if (pipeline != null)
            {
                foreach (var httpMiddleware in pipeline)
                {
                    Register(httpMiddleware);
                }
            }
        }
Exemple #9
0
 public static object ConvertToJson(string data, IServerlessLogger serverlessLogger)
 {
     try
     {
         return(string.IsNullOrWhiteSpace(data) ? null : JsonConvert.DeserializeObject(data));
     }
     catch (Exception ex)
     {
         serverlessLogger.LogError(ex, $"{nameof(LoggerHelper)} -> Fail using {nameof(ConvertToJson)}: data -> {data}. message: {ex.Message}");
         return(data);
     }
 }
        /// <summary>
        /// Execute middleware pipeline.
        /// </summary>
        /// <param name="functionMiddleware">Function logic as middleware to be called inside pipeline.</param>
        /// <param name="serverlessLogger">Modal logger.</param>
        /// <param name="request">Function http request.</param>
        /// <param name="acessor">See <see cref="IHttpContextAccessor"/>.</param>
        /// <param name="allowAnonymous">If true, it allows access to the endpoint without authentication.(Default: false)</param>
        /// <returns>Response <see cref="IActionResult"/> after pipeline execution.</returns>
        public static async Task <IActionResult> ExecutePipeline(
            this HttpMiddleware functionMiddleware,
            IServerlessLogger serverlessLogger,
            HttpRequest request,
            IHttpContextAccessor acessor,
            bool allowAnonymous = false)
        {
            var middlewares = GetMiddlewares(functionMiddleware, serverlessLogger, acessor, allowAnonymous);

            return(await new MiddlewarePipeline(middlewares, serverlessLogger)
                   .ExecuteAsync(HttpFunctionContext.Build(request))
                   .ConfigureAwait(false));
        }
 public GetCustomerByIdUseCase(
     IMediator mediator,
     IMapper mapper,
     IServerlessLogger logger,
     ITransactionFlow transactionFlow,
     IGetCustomerByIdRepository getCustomerByIdRepository)
     : base(mediator, logger)
 {
     this.mapper                    = mapper;
     this.logger                    = logger;
     this.transactionFlow           = transactionFlow;
     this.getCustomerByIdRepository = getCustomerByIdRepository;
 }
 public CreateCustomerUseCase(
     IMediator mediator,
     IMapper mapper,
     IServerlessLogger logger,
     ITransactionFlow transactionFlow,
     ICreateCustomerRepository createCustomerRepository)
     : base(mediator, logger)
 {
     this.mapper                   = mapper;
     this.logger                   = logger;
     this.transactionFlow          = transactionFlow;
     this.createCustomerRepository = createCustomerRepository;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="AuthenticationMiddleware"/> class.
 /// </summary>
 /// <param name="serverlessLogger">Modal logger.</param>
 /// <param name="issuer">Authentication issuer.</param>
 /// <param name="audience">Authentication audience.</param>
 /// <param name="metadataAddress">Authentication metadata address.</param>
 /// <param name="acessor">See <see cref="IHttpContextAccessor"/>.</param>
 /// <param name="isDebug">True if environment is debug mode. Otherwise, false.</param>
 public AuthenticationMiddleware(
     IServerlessLogger serverlessLogger,
     string issuer,
     string audience,
     string metadataAddress,
     IHttpContextAccessor acessor,
     bool isDebug = false)
 {
     this.serverlessLogger = serverlessLogger;
     this.issuer           = issuer;
     this.audience         = audience;
     this.metadataAddress  = metadataAddress;
     this.acessor          = acessor;
     this.isDebug          = isDebug;
 }
Exemple #14
0
 public CreateCustomerFunctionMiddleware(
     HttpRequest req,
     IMediator mediator,
     IMapper mapper,
     Presenter presenter,
     BadRequestPresenter badRequestPresenter,
     IServerlessLogger logger)
 {
     this.req                 = req;
     this.mediator            = mediator;
     this.mapper              = mapper;
     this.presenter           = presenter;
     this.badRequestPresenter = badRequestPresenter;
     this.logger              = logger;
 }
Exemple #15
0
        /// <summary>
        /// Start event hub process.
        /// </summary>
        /// <param name="serverlessLogger">Logger to save log.</param>
        /// <param name="logger">Logger to be injected in <paramref name="serverlessLogger"/>.</param>
        /// <param name="patternLog">Pattern log.</param>
        /// <param name="events">Events to be processed.</param>
        /// <param name="processEventAsync">Process with business rules to be processed.</param>
        /// <param name="publishPoisonedEventAsync">Function receiving error parameter to publish poisoned event data.</param>
        /// <param name="eventReliabilitySettings">Event reliability settings.</param>
        /// <returns>Task executed.</returns>
        public static async Task StartEventProcessAsync(
            IServerlessLogger serverlessLogger,
            ILogger logger,
            string patternLog,
            EventData[] events,
            Func <EventData, Task> processEventAsync,
            Func <EventData, Exception, Task> publishPoisonedEventAsync,
            EventReliabilitySettings eventReliabilitySettings)
        {
            try
            {
                serverlessLogger.InjectLogger(logger);

                if (events.Length == 0)
                {
                    serverlessLogger.LogWarning($"{patternLog} No event to process.");
                    return;
                }

                serverlessLogger.LogInformation($"{patternLog} Start processing...");

                var waitAndRetryAsync = GetWaitAndRetry(eventReliabilitySettings);

                var eventCount = events.Length;

                for (int eventIndex = 0; eventIndex < eventCount; eventIndex++)
                {
                    serverlessLogger.LogInformation($"{patternLog} Processing event index {eventIndex}...");

                    var eventData     = events[eventIndex];
                    var fallbackAsync = GetFallback(serverlessLogger, patternLog, eventData, publishPoisonedEventAsync);

                    await Policy
                    .WrapAsync(fallbackAsync, waitAndRetryAsync)
                    .ExecuteAsync(() => processEventAsync(eventData))
                    .ConfigureAwait(false);

                    serverlessLogger.LogInformation($"{patternLog} Event index {eventIndex} processed!");
                }

                serverlessLogger.LogInformation($"{patternLog} Processing completed!");
            }
            catch (Exception ex)
            {
                serverlessLogger.LogError(ex, $"{patternLog} Processing failed!");
                throw;
            }
        }
Exemple #16
0
 private static Polly.Fallback.AsyncFallbackPolicy GetFallback(
     IServerlessLogger serverlessLogger,
     string patternLog,
     EventData eventData,
     Func <EventData, Exception, Task> publishPoisonedEventAsync)
 {
     return(Policy
            .Handle <Exception>()
            .FallbackAsync(
                (exception, context, cancellationToken) => publishPoisonedEventAsync(eventData, exception),
                (exception, context) =>
     {
         serverlessLogger.LogError(exception, $"{patternLog} Processing failed!");
         return Task.CompletedTask;
     }));
 }
Exemple #17
0
 public GetCustomerByIdFunctionMiddleware(
     HttpRequest req,
     string id,
     IMediator mediator,
     IMapper mapper,
     Presenter presenter,
     BadRequestPresenter badRequestPresenter,
     IServerlessLogger logger)
 {
     this.req                 = req;
     this.id                  = id;
     this.mediator            = mediator;
     this.mapper              = mapper;
     this.presenter           = presenter;
     this.badRequestPresenter = badRequestPresenter;
     this.logger              = logger;
 }
        /// <summary>
        /// End event process logging notification messages.
        /// </summary>
        /// <typeparam name="TResult">Type of result data.</typeparam>
        /// <param name="result">Result data. If the object is null, throw exception. Otherwise, the event was processed successfully.</param>
        /// <param name="correlationId">Correlation id.</param>
        /// <param name="notificationUseCase">Use case to extract notifications.</param>
        /// <param name="serverlessLogger">Logger to save log.</param>
        /// <param name="patternLog">Pattern log.</param>
        public static void EndEventProcess <TResult>(
            TResult result,
            string correlationId,
            DomainNotificationUseCase notificationUseCase,
            IServerlessLogger serverlessLogger,
            string patternLog)
            where TResult : IResult
        {
            if (result == null)
            {
                if (notificationUseCase.HasNotifications())
                {
                    var errors = GetAllMessageErrors(correlationId, notificationUseCase, patternLog);

                    throw new Exception(errors);
                }

                throw new Exception($"{patternLog} Event item with {nameof(correlationId)}: {correlationId} processing failed.");
            }

            serverlessLogger.LogInformation($"{patternLog} Event item with {nameof(correlationId)}: {correlationId} successfully processed!");
        }
Exemple #19
0
        /// <summary>
        /// Start cosmosdb process.
        /// </summary>
        /// <param name="serverlessLogger">Logger to save log.</param>
        /// <param name="logger">Logger to be injected in <paramref name="serverlessLogger"/>.</param>
        /// <param name="patternLog">Pattern log.</param>
        /// <param name="documents">Documents to be processed.</param>
        /// <param name="func">Process with business rules to be processed.</param>
        /// <returns>Task executed.</returns>
        public static async Task StartDocumentProcessAsync(
            IServerlessLogger serverlessLogger,
            ILogger logger,
            string patternLog,
            IReadOnlyList <Document> documents,
            Func <Document, Task> func)
        {
            try
            {
                serverlessLogger.InjectLogger(logger);

                if (documents.Count == 0)
                {
                    serverlessLogger.LogWarning($"{patternLog} No document to process.");
                    return;
                }

                serverlessLogger.LogInformation($"{patternLog} Start processing...");

                var documentCount = documents.Count;

                for (int documentIndex = 0; documentIndex < documentCount; documentIndex++)
                {
                    var document = documents[documentIndex];
                    serverlessLogger.LogInformation($"{patternLog} Processing document index: {documentIndex}, id: {document.Id} and resourceId: {document.ResourceId}!");
                    await func(document).ConfigureAwait(false);

                    serverlessLogger.LogInformation($"{patternLog} Document index {documentIndex} processed!");
                }

                serverlessLogger.LogInformation($"{patternLog} Processing completed!");
            }
            catch (Exception ex)
            {
                serverlessLogger.LogError(ex, $"{patternLog} Processing failed!");
                throw;
            }
        }
        /// <summary>
        /// Start event hub process.
        /// </summary>
        /// <param name="serverlessLogger">Logger to save log.</param>
        /// <param name="logger">Logger to be injected in <paramref name="serverlessLogger"/>.</param>
        /// <param name="patternLog">Pattern log.</param>
        /// <param name="events">Events to be processed.</param>
        /// <param name="func">Process with business rules to be processed.</param>
        /// <returns>Task executed.</returns>
        public static async Task StartEventProcessAsync(
            IServerlessLogger serverlessLogger,
            ILogger logger,
            string patternLog,
            EventData[] events,
            Func <EventData, Task> func)
        {
            try
            {
                serverlessLogger.InjectLogger(logger);

                if (events.Length == 0)
                {
                    serverlessLogger.LogWarning($"{patternLog} No event to process.");
                    return;
                }

                serverlessLogger.LogInformation($"{patternLog} Start processing...");

                var eventCount = events.Length;

                for (int eventIndex = 0; eventIndex < eventCount; eventIndex++)
                {
                    serverlessLogger.LogInformation($"{patternLog} Processing event index {eventIndex}...");
                    await func(events[eventIndex]).ConfigureAwait(false);

                    serverlessLogger.LogInformation($"{patternLog} Event index {eventIndex} processed!");
                }

                serverlessLogger.LogInformation($"{patternLog} Processing completed!");
            }
            catch (Exception ex)
            {
                serverlessLogger.LogError(ex, $"{patternLog} Processing failed!");
                throw;
            }
        }
        private static List <HttpMiddleware> MiddlewaresWithAuth(HttpMiddleware functionMiddleware, IServerlessLogger serverlessLogger, IHttpContextAccessor acessor, ExceptionMiddleware exceptionMiddleware, LoggerMiddleware loggerMiddleware, HeaderMiddleware headerMiddleware)
        {
            var authenticationMiddleware = new AuthenticationMiddleware(
                serverlessLogger,
                Environment.GetEnvironmentVariable("AUTH.ISSUER"),
                Environment.GetEnvironmentVariable("AUTH.AUDIENCE"),
                Environment.GetEnvironmentVariable("AUTH.METADATAADDRESS"),
                acessor);

            return(new List <HttpMiddleware>()
            {
                loggerMiddleware,
                headerMiddleware,
                exceptionMiddleware,
                authenticationMiddleware,
                functionMiddleware
            });
        }
        internal void CreateRequestData(HttpContext context, string requestBody, DateTimeOffset start, IServerlessLogger serverlessLogger)
        {
            Request = new LogApiRequest();

            StartTimestamp  = start;
            Request.Body    = LoggerHelper.ConvertToJson(requestBody, serverlessLogger);
            Request.Method  = context?.Request?.Method;
            Request.Url     = $"{context?.Request.Scheme}://{context?.Request.Host}{context?.Request.Path.ToString()}";
            Request.Headers = context?.Request?.Headers?.ToDictionary(h => h.Key, h => h.Value);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="LoggerMiddleware"/> class.
 /// </summary>
 /// <param name="serverlessLogger"></param>
 public LoggerMiddleware(IServerlessLogger serverlessLogger)
 {
     this.serverlessLogger = serverlessLogger;
 }
        internal void CreateResponseData(HttpContext context, string responseBody, DateTimeOffset end, IServerlessLogger serverlessLogger)
        {
            Response = new LogApiResponse();

            EndTimestamp        = end;
            Response.Body       = LoggerHelper.ConvertToJson(responseBody, serverlessLogger);
            Response.StatusCode = (context?.Response?.StatusCode).GetValueOrDefault();
            Response.Headers    = context?.Response?.Headers?.ToDictionary(h => h.Key, h => h.Value);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="HttpMessageHandlerBehavior"/> class.
 /// </summary>
 /// <param name="transactionFlow"></param>
 /// <param name="logger"></param>
 public HttpMessageHandlerBehavior(ITransactionFlow transactionFlow, IServerlessLogger logger)
 {
     this.transactionFlow = transactionFlow;
     this.logger          = logger;
 }
Exemple #26
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ExceptionMiddleware"/> class.
 /// </summary>
 /// <param name="serverlessLogger">Logger to log error.</param>
 public ExceptionMiddleware(IServerlessLogger serverlessLogger)
 {
     this.serverlessLogger = serverlessLogger ?? throw new ArgumentNullException(nameof(serverlessLogger));
 }
Exemple #27
0
 /// <summary>
 /// Initializes a new instance of the <see cref="LogWcf"/> class.
 /// </summary>
 /// <param name="logger"></param>
 /// <param name="transactionFlow"></param>
 public LogWcf(IServerlessLogger logger, ITransactionFlow transactionFlow)
 {
     this.logger          = logger;
     this.transactionFlow = transactionFlow;
 }