コード例 #1
0
        /// <summary>
        /// Execute an <paramref name="asyncMethod"/> in the background.
        /// </summary>
        /// <param name="asyncMethod">The action to run in the background.</param>
        /// <param name="token">Propagates notification that operations should be canceled</param>
        /// <returns>The created thread.</returns>
        public static Thread FireAndForget(Func <CancellationToken, Task> asyncMethod, CancellationToken token = default)
        {
            FulcrumApplication.ValidateButNotInProduction();
            var messageIfException = $"Background thread failed.";

            return(FulcrumApplication.Setup.ThreadHandler.FireAndForget(ct => CallAsyncFromSync(asyncMethod, messageIfException, ct), token));
        }
コード例 #2
0
        /// <summary>
        /// Execute an <paramref name="asyncMethod"/> in the background.
        /// </summary>
        /// <param name="asyncMethod">The action to run in the background.</param>
        /// <param name="token">Propagates notification that operations should be canceled</param>
        /// <returns>The created thread.</returns>
        public static Thread FireAndForgetWithExpensiveStackTracePreservation(Func <CancellationToken, Task> asyncMethod, CancellationToken token = default)
        {
            FulcrumApplication.ValidateButNotInProduction();
            var context = new StackTracePreservation();

            return(FireAndForget(ct => context.ExecuteActionFailSafeAsync(asyncMethod, ct), token));
        }
コード例 #3
0
        /// <summary>
        /// Execute an <paramref name="action"/> in the background.
        /// </summary>
        /// <param name="action">The action to run in the background.</param>
        /// <returns>The created thread.</returns>
        public static Thread FireAndForget(Action action)
        {
            FulcrumApplication.ValidateButNotInProduction();
            var messageIfException = $"Background thread failed.";

            return(FulcrumApplication.Setup.ThreadHandler.FireAndForget(ct => ExecuteActionFailSafe(action, messageIfException)));
        }
コード例 #4
0
        /// <summary>
        /// Execute an <paramref name="asyncMethod"/> in the background.
        /// </summary>
        /// <param name="asyncMethod">The action to run in the background.</param>
        /// <returns>The created thread.</returns>
        public static Thread FireAndForgetWithExpensiveStackTracePreservation(Func <Task> asyncMethod)
        {
            FulcrumApplication.ValidateButNotInProduction();
            var context = new StackTracePreservation();

            return(FireAndForget(() => context.ExecuteActionFailSafeAsync(asyncMethod)));
        }
コード例 #5
0
        /// <summary>
        /// Execute an <paramref name="action"/> in the background.
        /// </summary>
        /// <param name="action">The action to run in the background.</param>
        /// <returns>The created thread.</returns>
        public static Thread FireAndForgetWithExpensiveStackTracePreservation(Action action)
        {
            FulcrumApplication.ValidateButNotInProduction();
            var context = new StackTracePreservation();

            return(FireAndForget(() => context.ExecuteActionFailSafe(action)));
        }
コード例 #6
0
        /// <summary>
        /// This method will be called indirectly from the program's Main method to configure the services
        /// </summary>
        /// <remarks>
        /// Don't override this method unless you really know what you are doing.
        /// First see if the following methods could be good enough for your needs:
        /// Always override <see cref="GetSynchronousFastLogger"/> to establish your preferred way of logging.
        /// Always override <see cref="DependencyInjectServices(IServiceCollection)"/> to inject your own services.
        /// Override <see cref="ConfigureServicesInitialUrgentPart"/> if you have things that needs to be initialized early.
        /// Override <see cref="ConfigureServicesSwagger"/> if you want to change how swagger is set up.
        /// </remarks>
        public virtual void ConfigureServices(IServiceCollection services)
        {
            try
            {
                FulcrumApplication.Validate();
                ConfigureServicesInitialUrgentPart(services);
                FulcrumApplication.ValidateButNotInProduction();
                InternalContract.RequireValidated(this, GetType().FullName);
                ConfigureServicesSwagger(services);
                DependencyInjectServices(services);
                using (var serviceScope = services.BuildServiceProvider().CreateScope())
                {
                    ValueTranslatorFilter valueTranslatorFilter = null;
                    var serviceProvider = serviceScope.ServiceProvider;
                    DependencyInjectServicesAdvanced(services, serviceProvider);
                    if (IsBusinessApi)
                    {
                        var translatorService = serviceProvider.GetService <ITranslatorService>();
                        if (translatorService == null)
                        {
                            Log.LogWarning($"Could not resolve {nameof(ITranslatorService)}");
                        }
                        else
                        {
                            ValueTranslatorHttpSender.TranslatorService = translatorService;
                            valueTranslatorFilter = new ValueTranslatorFilter(
                                translatorService,
                                () => FulcrumApplication.Context?.ClientPrincipal?.Identity?.Name);
                        }
                    }
                    var mvc = services.AddMvc(opts =>
                    {
                        if (IsBusinessApi && valueTranslatorFilter != null)
                        {
                            opts.Filters.Add(valueTranslatorFilter);
                        }
                        if (!FulcrumApplication.IsInDevelopment)
                        {
                            return;
                        }
                        Log.LogWarning($"Anonymous service usage is allowed, due to development mode.");
                        opts.Filters.Add(new AllowAnonymousFilter());
                    });
                    mvc
                    .SetCompatibilityVersion(CompatibilityVersion)
                    .ConfigureApplicationPartManager(apm =>
                                                     apm.FeatureProviders.Add(new RemoveRedundantControllers(_controllersToKeep)));
                    AddControllersToMvc(services, mvc);
                }

                Log.LogInformation($"{nameof(StartupBase)}.{nameof(ConfigureServices)} succeeded.");
            }
            catch (Exception e)
            {
                Log.LogCritical(
                    $"{nameof(StartupBase)}.{nameof(ConfigureServices)} failed. The application {FulcrumApplication.Setup?.Name} needs to be restarted.: {e.Message}",
                    e);
                throw;
            }
        }
コード例 #7
0
        /// <summary>
        /// This logging is done with simple methods like local logging. The <paramref name="message"/> will be extended with application information and possibly exception information.
        /// </summary>
        /// <param name="severityLevel">The severity level for this log.</param>
        /// <param name="message">The message to log.</param>
        /// <param name="exception">An optional exception that will have it's information incorporated in the message.</param>
        /// <param name="memberName">Method or property name of the caller</param>
        /// <param name="filePath">Full path of the source file that contains the caller. This is the file path at compile time.</param>
        /// <param name="lineNumber">Line number in the source file at which the method is called</param>
        public static void FallbackSafeLog(
            LogSeverityLevel severityLevel,
            string message,
            Exception exception = null,
            [CallerMemberName] string memberName = "",
            [CallerFilePath] string filePath     = "",
            [CallerLineNumber] int lineNumber    = 0)
        {
            try
            {
                var hideStackTrace = severityLevel < LogSeverityLevel.Error;
                // ReSharper disable ExplicitCallerInfoArgument
                var location = LocationToLogString(memberName, filePath, lineNumber);
                // ReSharper restore ExplicitCallerInfoArgument
                var messageWithLogInfo = $"{severityLevel}: {message}";
                messageWithLogInfo += $"\r{FulcrumApplication.ToLogString()}";
                messageWithLogInfo += ContextToLogString();
                messageWithLogInfo += $"\r{location}";
                if (exception != null)
                {
                    messageWithLogInfo += $"\r{exception.ToLogString(hideStackTrace)}";
                }

                FulcrumApplication.Setup.FallbackLogger.SafeLog(severityLevel, messageWithLogInfo);
            }
            catch (Exception)
            {
                // We give up
            }
        }
コード例 #8
0
 /// <summary>
 /// Sets the recommended application setup for a Web Api.
 /// </summary>
 /// <param name="name">The name of the application.</param>
 /// <param name="tenant">The tenant that the application itself runs in.</param>
 /// <param name="level">The run time level for the application itself.</param>
 public static void WebBasicSetup(string name, Tenant tenant, RunTimeLevelEnum level)
 {
     FulcrumApplication.Initialize(name, tenant, level);
     FulcrumApplication.Setup.ThreadHandler         = ThreadHelper.RecommendedForRuntime;
     FulcrumApplication.Setup.SynchronousFastLogger = LogHelper.RecommendedSyncLoggerForRuntime;
     FulcrumApplication.Setup.FallbackLogger        = LogHelper.RecommendedFallbackLoggerForRuntime;
     FulcrumApplication.AppSettings = new AppSettings(new ConfigurationManagerAppSettings());
 }
コード例 #9
0
        /// <summary>
        ///
        /// </summary>
        /// <remarks>See https://docs.microsoft.com/en-us/azure/azure-monitor/app/api-custom-events-metrics</remarks>
        public ApplicationInsightsTelemetryHandler(string contextDeviceId = null, string contextUserId = null)
        {
            FulcrumApplication.ValidateButNotInProduction();

            TelemetryClient = new TelemetryClient();

            if (!string.IsNullOrWhiteSpace(contextDeviceId))
            {
                TelemetryClient.Context.Device.Id = contextDeviceId;
            }
            if (!string.IsNullOrWhiteSpace(contextUserId))
            {
                TelemetryClient.Context.User.Id = contextUserId;
            }
        }
コード例 #10
0
        public void FallbackSafeLog()
        {
            const LogSeverityLevel expectedLevel    = LogSeverityLevel.Error;
            const string           exceptionMessage = "ExceptionMessage";
            const string           message          = "TestMessage";

            try
            {
                throw new TestException(exceptionMessage);
            }
            catch (Exception expectedException)
            {
                // ReSharper disable ExplicitCallerInfoArgument
                LogHelper.FallbackSafeLog(expectedLevel, message, expectedException, "memberName", "filePath", 42);
                // ReSharper restore ExplicitCallerInfoArgument
                UT.Assert.AreEqual(expectedLevel, _loggedSeverityLevel);
                UT.Assert.IsNotNull(_loggedMessage);
                // ReSharper disable ExplicitCallerInfoArgument
                UT.Assert.IsTrue(_loggedMessage.Contains(LogHelper.LocationToLogString("memberName", "filePath", 42)));
                // ReSharper restore ExplicitCallerInfoArgument
                UT.Assert.IsTrue(_loggedMessage.Contains(FulcrumApplication.ToLogString()));
            }
        }
コード例 #11
0
 /// <summary>
 /// Constructor
 /// </summary>
 public LogRequestAndResponse()
 {
     FulcrumApplication.ValidateButNotInProduction();
 }
コード例 #12
0
 /// <summary>
 /// Execute an <paramref name="asyncMethod"/> in the background.
 /// </summary>
 /// <param name="asyncMethod">The action to run in the background.</param>
 /// <param name="token">Propagates notification that operations should be canceled</param>
 /// <returns>The created thread.</returns>
 public static Thread FireAndForgetResetContext(Func <CancellationToken, Task> asyncMethod, CancellationToken token = default)
 {
     FulcrumApplication.ValidateButNotInProduction();
     return(FireAndForget(async() => await ResetBeforeCall(asyncMethod, token)));
 }
コード例 #13
0
 /// <summary>
 /// Execute an <paramref name="asyncMethod"/> in the background.
 /// </summary>
 /// <param name="asyncMethod">The action to run in the background.</param>
 /// <returns>The created thread.</returns>
 public static Thread FireAndForgetResetContext(Func <Task> asyncMethod)
 {
     FulcrumApplication.ValidateButNotInProduction();
     return(FireAndForget(async() => await ResetBeforeCall(asyncMethod)));
 }
コード例 #14
0
 /// <summary>
 /// Execute an <paramref name="action"/> in the background.
 /// </summary>
 /// <param name="action">The action to run in the background.</param>
 /// <returns>The created thread.</returns>
 public static Thread FireAndForgetResetContext(Action action)
 {
     FulcrumApplication.ValidateButNotInProduction();
     return(FireAndForget(() => ResetBeforeCall(action)));
 }