Beispiel #1
0
 /// <summary>
 /// Construct an <see cref="AdministrationController"/>
 /// </summary>
 /// <param name="databaseContext">The <see cref="IDatabaseContext"/> for the <see cref="ApiController"/></param>
 /// <param name="authenticationContextFactory">The <see cref="IAuthenticationContextFactory"/> for the <see cref="ApiController"/></param>
 /// <param name="gitHubClientFactory">The value of <see cref="gitHubClientFactory"/></param>
 /// <param name="serverUpdater">The value of <see cref="serverUpdater"/></param>
 /// <param name="assemblyInformationProvider">The value of <see cref="assemblyInformationProvider"/></param>
 /// <param name="ioManager">The value of <see cref="ioManager"/></param>
 /// <param name="platformIdentifier">The value of <see cref="platformIdentifier"/></param>
 /// <param name="logger">The <see cref="ILogger"/> for the <see cref="ApiController"/></param>
 /// <param name="updatesConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing value of <see cref="updatesConfiguration"/></param>
 /// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing value of <see cref="generalConfiguration"/></param>
 /// <param name="fileLoggingConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing value of <see cref="fileLoggingConfiguration"/></param>
 public AdministrationController(
     IDatabaseContext databaseContext,
     IAuthenticationContextFactory authenticationContextFactory,
     IGitHubClientFactory gitHubClientFactory,
     IServerControl serverUpdater,
     IAssemblyInformationProvider assemblyInformationProvider,
     IIOManager ioManager,
     IPlatformIdentifier platformIdentifier,
     ILogger <AdministrationController> logger,
     IOptions <UpdatesConfiguration> updatesConfigurationOptions,
     IOptions <GeneralConfiguration> generalConfigurationOptions,
     IOptions <FileLoggingConfiguration> fileLoggingConfigurationOptions)
     : base(
         databaseContext,
         authenticationContextFactory,
         logger,
         false)
 {
     this.gitHubClientFactory         = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory));
     this.serverUpdater               = serverUpdater ?? throw new ArgumentNullException(nameof(serverUpdater));
     this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider));
     this.ioManager           = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
     this.platformIdentifier  = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
     updatesConfiguration     = updatesConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(updatesConfigurationOptions));
     generalConfiguration     = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions));
     fileLoggingConfiguration = fileLoggingConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(fileLoggingConfigurationOptions));
 }
Beispiel #2
0
        public void FileLoggerMinLevelWarn_LogsInfo_FileDoesntExist()
        {
            var message = "Some entry";
            var config  = new FileLoggingConfiguration();

            config.MinimumLevel = LogLevel.Warn;

            Aspects.Logging.ILogger logger = new NLogger(config);

            logger.Info(message);

            var fileName = $@"{DateTime.Today.ToString("yyyy-MM-dd")}.log";
            var filePath = $@"{Environment.CurrentDirectory}\{fileName}";

            Assert.False(File.Exists(filePath));
        }
Beispiel #3
0
        /// <summary>
        /// Initiate logging in file
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="levels"></param>
        public NLogger(FileLoggingConfiguration configuration, params LogLevel[] levels)
        {
            LoggingConfiguration = configuration;

            InitTarget(new FileTarget("file")
            {
                CreateDirs       = true,
                ArchiveNumbering = ArchiveNumberingMode.Date,
                ArchiveEvery     = FileArchivePeriod.Day,

                MaxArchiveFiles = configuration.MaxArchiveFiles,
                FileName        = $"{configuration.LogFileDirectory}/${{shortdate}}.log",
                ArchiveFileName = $"{configuration.LogFileDirectory}/${{shortdate}}.log",
                Layout          = configuration.MessageTemplate
            }, levels?.ToList());
        }
        public void ApplyLoggingConfiguration(bool isUsed, bool isActive, bool wasApplied)
        {
            // arrange
            ApplicationConfigurationHelper.AdjustKeys("log.file", isUsed.ToString());
            var serilogConfigurationDummy = new Mock <LoggerConfiguration>();
            var sut = new FileLoggingConfiguration();

            // act
            sut.Apply(serilogConfigurationDummy.Object);

            // assert
            sut.LogFilePath.Should().Be(FilePath);
            sut.LogToFile.Should().Be(isUsed);
            sut.IsActive.Should().Be(isActive);
            sut.WasApplied.Should().Be(wasApplied);
        }
Beispiel #5
0
        public void FileLogger_LogsError_FileExists()
        {
            var message = "Some entry";
            var config  = new FileLoggingConfiguration();

            Aspects.Logging.ILogger logger = new NLogger(config);

            logger.Error(new Exception(message));

            var fileName = $@"{DateTime.Today.ToString("yyyy-MM-dd")}.log";
            var filePath = $@"{Environment.CurrentDirectory}\{fileName}";

            Assert.True(File.Exists(filePath));

            var fileText = File.ReadAllText(filePath);

            Assert.Contains(message, fileText);
            Assert.Contains("Error", fileText);

            File.Delete(filePath);
        }
Beispiel #6
0
        /// <summary>
        /// Saves a given <see cref="Configuration"/> set to <paramref name="userConfigFileName"/>
        /// </summary>
        /// <param name="userConfigFileName">The file to save the <see cref="Configuration"/> to</param>
        /// <param name="hostingPort">The hosting port to save</param>
        /// <param name="databaseConfiguration">The <see cref="DatabaseConfiguration"/> to save</param>
        /// <param name="newGeneralConfiguration">The <see cref="GeneralConfiguration"/> to save</param>
        /// <param name="fileLoggingConfiguration">The <see cref="FileLoggingConfiguration"/> to save</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
        /// <returns>A <see cref="Task"/> representing the running operation</returns>
        async Task SaveConfiguration(string userConfigFileName, ushort?hostingPort, DatabaseConfiguration databaseConfiguration, GeneralConfiguration newGeneralConfiguration, FileLoggingConfiguration fileLoggingConfiguration, CancellationToken cancellationToken)
        {
            await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "Configuration complete! Saving to {0}", userConfigFileName), true, cancellationToken).ConfigureAwait(false);

            var map = new Dictionary <string, object>()
            {
                { DatabaseConfiguration.Section, databaseConfiguration },
                { GeneralConfiguration.Section, newGeneralConfiguration },
                { FileLoggingConfiguration.Section, fileLoggingConfiguration }
            };

            if (hostingPort.HasValue)
            {
                map.Add("Kestrel", new
                {
                    EndPoints = new
                    {
                        Http = new
                        {
                            Url = String.Format(CultureInfo.InvariantCulture, "http://0.0.0.0:{0}", hostingPort)
                        }
                    }
                });
            }

            var json        = JsonConvert.SerializeObject(map, Formatting.Indented);
            var configBytes = Encoding.UTF8.GetBytes(json);

            try
            {
                await ioManager.WriteAllBytes(userConfigFileName, configBytes, cancellationToken).ConfigureAwait(false);
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception e)
            {
                await console.WriteAsync(e.Message, true, cancellationToken).ConfigureAwait(false);

                await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);

                await console.WriteAsync("For your convienence, here's the json we tried to write out:", true, cancellationToken).ConfigureAwait(false);

                await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);

                await console.WriteAsync(json, true, cancellationToken).ConfigureAwait(false);

                await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);

                await console.WriteAsync("Press any key to exit...", true, cancellationToken).ConfigureAwait(false);

                await console.PressAnyKeyAsync(cancellationToken).ConfigureAwait(false);

                throw new OperationCanceledException();
            }

            await console.WriteAsync("Waiting for configuration changes to reload...", true, cancellationToken).ConfigureAwait(false);

            //we need to wait for the configuration's file system watcher to read and reload the changes
            await Task.Delay(TimeSpan.FromSeconds(5), cancellationToken).ConfigureAwait(false);
        }
Beispiel #7
0
        /// <summary>
        /// Prompts the user to create a <see cref="FileLoggingConfiguration"/>
        /// </summary>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
        /// <returns>A <see cref="Task{TResult}"/> resulting in the new <see cref="FileLoggingConfiguration"/></returns>
        async Task <FileLoggingConfiguration> ConfigureLogging(CancellationToken cancellationToken)
        {
            var fileLoggingConfiguration = new FileLoggingConfiguration();
            await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);

            fileLoggingConfiguration.Disable = !await PromptYesNo("Enable file logging? (y/n): ", cancellationToken).ConfigureAwait(false);

            if (!fileLoggingConfiguration.Disable)
            {
                do
                {
                    await console.WriteAsync("Log file directory path (leave blank for default): ", false, cancellationToken).ConfigureAwait(false);

                    fileLoggingConfiguration.Directory = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);

                    if (String.IsNullOrWhiteSpace(fileLoggingConfiguration.Directory))
                    {
                        fileLoggingConfiguration.Directory = null;
                        break;
                    }
                    //test a write of it
                    await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);

                    await console.WriteAsync("Testing directory access...", true, cancellationToken).ConfigureAwait(false);

                    try
                    {
                        await ioManager.CreateDirectory(fileLoggingConfiguration.Directory, cancellationToken).ConfigureAwait(false);

                        var testFile = ioManager.ConcatPath(fileLoggingConfiguration.Directory, String.Format(CultureInfo.InvariantCulture, "WizardAccesTest.{0}.deleteme", Guid.NewGuid()));
                        await ioManager.WriteAllBytes(testFile, Array.Empty <byte>(), cancellationToken).ConfigureAwait(false);

                        try
                        {
                            await ioManager.DeleteFile(testFile, cancellationToken).ConfigureAwait(false);
                        }
                        catch (OperationCanceledException)
                        {
                            throw;
                        }
                        catch (Exception e)
                        {
                            await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "Error deleting test log file: {0}", testFile), true, cancellationToken).ConfigureAwait(false);

                            await console.WriteAsync(e.Message, true, cancellationToken).ConfigureAwait(false);

                            await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
                        }
                        break;
                    }
                    catch (OperationCanceledException)
                    {
                        throw;
                    }
                    catch (Exception e)
                    {
                        await console.WriteAsync(e.Message, true, cancellationToken).ConfigureAwait(false);

                        await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);

                        await console.WriteAsync("Please verify the path is valid and you have access to it!", true, cancellationToken).ConfigureAwait(false);
                    }
                } while (true);

                async Task <LogLevel?> PromptLogLevel(string question)
                {
                    do
                    {
                        await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);

                        await console.WriteAsync(question, true, cancellationToken).ConfigureAwait(false);

                        await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "Enter one of {0}/{1}/{2}/{3}/{4}/{5} (leave blank for default): ", nameof(LogLevel.Trace), nameof(LogLevel.Debug), nameof(LogLevel.Information), nameof(LogLevel.Warning), nameof(LogLevel.Error), nameof(LogLevel.Critical)), false, cancellationToken).ConfigureAwait(false);

                        var responseString = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);

                        if (String.IsNullOrWhiteSpace(responseString))
                        {
                            return(null);
                        }
                        if (Enum.TryParse <LogLevel>(responseString, out var logLevel) && logLevel != LogLevel.None)
                        {
                            return(logLevel);
                        }
                        await console.WriteAsync("Invalid log level!", true, cancellationToken).ConfigureAwait(false);
                    } while (true);
                }

                fileLoggingConfiguration.LogLevel = await PromptLogLevel(String.Format(CultureInfo.InvariantCulture, "Enter the level limit for normal logs (default {0}).", fileLoggingConfiguration.LogLevel)).ConfigureAwait(false) ?? fileLoggingConfiguration.LogLevel;

                fileLoggingConfiguration.MicrosoftLogLevel = await PromptLogLevel(String.Format(CultureInfo.InvariantCulture, "Enter the level limit for Microsoft logs (VERY verbose, default {0}).", fileLoggingConfiguration.MicrosoftLogLevel)).ConfigureAwait(false) ?? fileLoggingConfiguration.MicrosoftLogLevel;
            }
            return(fileLoggingConfiguration);
        }
Beispiel #8
0
        /// <summary>
        /// Saves a given <see cref="Configuration"/> set to <paramref name="userConfigFileName"/>
        /// </summary>
        /// <param name="userConfigFileName">The file to save the <see cref="Configuration"/> to</param>
        /// <param name="hostingPort">The hosting port to save</param>
        /// <param name="databaseConfiguration">The <see cref="DatabaseConfiguration"/> to save</param>
        /// <param name="newGeneralConfiguration">The <see cref="GeneralConfiguration"/> to save</param>
        /// <param name="fileLoggingConfiguration">The <see cref="FileLoggingConfiguration"/> to save</param>
        /// <param name="controlPanelConfiguration">The <see cref="ControlPanelConfiguration"/> to save</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
        /// <returns>A <see cref="Task"/> representing the running operation</returns>
        async Task SaveConfiguration(string userConfigFileName, ushort?hostingPort, DatabaseConfiguration databaseConfiguration, GeneralConfiguration newGeneralConfiguration, FileLoggingConfiguration fileLoggingConfiguration, ControlPanelConfiguration controlPanelConfiguration, CancellationToken cancellationToken)
        {
            await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "Configuration complete! Saving to {0}", userConfigFileName), true, cancellationToken).ConfigureAwait(false);

            newGeneralConfiguration.ApiPort       = hostingPort ?? GeneralConfiguration.DefaultApiPort;
            newGeneralConfiguration.ConfigVersion = GeneralConfiguration.CurrentConfigVersion;
            var map = new Dictionary <string, object>()
            {
                { DatabaseConfiguration.Section, databaseConfiguration },
                { GeneralConfiguration.Section, newGeneralConfiguration },
                { FileLoggingConfiguration.Section, fileLoggingConfiguration },
                { ControlPanelConfiguration.Section, controlPanelConfiguration }
            };

            var json        = JsonConvert.SerializeObject(map, Formatting.Indented);
            var configBytes = Encoding.UTF8.GetBytes(json);

            try
            {
                await ioManager.WriteAllBytes(userConfigFileName, configBytes, cancellationToken).ConfigureAwait(false);
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception e)
            {
                await console.WriteAsync(e.Message, true, cancellationToken).ConfigureAwait(false);

                await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);

                await console.WriteAsync("For your convienence, here's the json we tried to write out:", true, cancellationToken).ConfigureAwait(false);

                await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);

                await console.WriteAsync(json, true, cancellationToken).ConfigureAwait(false);

                await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);

                await console.WriteAsync("Press any key to exit...", true, cancellationToken).ConfigureAwait(false);

                await console.PressAnyKeyAsync(cancellationToken).ConfigureAwait(false);

                throw new OperationCanceledException();
            }
        }
Beispiel #9
0
        public ILogger Build()
        {
            _loggerConfiguration = _loggerConfiguration ?? new LoggerConfiguration();

            var jgLoggingConfiguration = new JgLoggingConfiguration();

            var enrichLoggingConfig = new EnrichLoggingConfiguration();

            _configuration?.Bind("JG-Logging:Enrich", enrichLoggingConfig);

            _configuration?.Bind("JG-Logging:Serilog", jgLoggingConfiguration);

            if (jgLoggingConfiguration.WriteToSeq)
            {
                var seqLoggingConfig = new SeqLoggingConfiguration();

                _configuration?.Bind("JG-Logging:Serilog:Seq", seqLoggingConfig);

                _loggerConfiguration
                .Destructure.JsonNetTypes()
                .WriteTo.Seq(
                    seqLoggingConfig.ServerUrl,
                    seqLoggingConfig.RestrictedToMinimumLevel,
                    seqLoggingConfig.BatchPostingLimit,
                    seqLoggingConfig.Period,
                    seqLoggingConfig.ApiKey,
                    seqLoggingConfig.BufferBaseFilename,
                    seqLoggingConfig.BufferSizeLimitBytes,
                    seqLoggingConfig.EventBodyLimitBytes,
                    seqLoggingConfig.ControlLevelSwitch,
                    null,
                    seqLoggingConfig.RetainedInvalidPayloadsLimitBytes,
                    seqLoggingConfig.Compact,
                    seqLoggingConfig.QueueSizeLimit);
            }

            if (jgLoggingConfiguration.WriteToColoredConsole)
            {
                _loggerConfiguration.WriteTo.ColoredConsole();
            }

            if (jgLoggingConfiguration.WriteToFile)
            {
                var fileLoggingConfig = new FileLoggingConfiguration();

                _loggerConfiguration.WriteTo.File(
                    // Note: IIS requires write access
                    Path.Combine(Environment.CurrentDirectory, fileLoggingConfig.Path),
                    fileLoggingConfig.RestrictedToMinimumLevel,
                    fileLoggingConfig.OutputTemplate,
                    null,
                    fileLoggingConfig.FileSizeLimitBytes,
                    fileLoggingConfig.LevelSwitch,
                    fileLoggingConfig.Buffered,
                    fileLoggingConfig.Shared,
                    fileLoggingConfig.FlushToDiskInterval,
                    fileLoggingConfig.RollingInterval,
                    fileLoggingConfig.RollOnFileSizeLimit,
                    fileLoggingConfig.RetainedFileCountLimit);
            }


            _loggerConfiguration
            .Enrich.FromLogContext()
            .Enrich.WithExceptionDetails()
            .Enrich.WithMachineName()
            .Enrich.WithEnvironmentUserName()
            .Enrich.WithProcessName()
            .Enrich.WithProcessId()
            .Enrich.WithProperty(LogProps.APPLICATION, "JG.FinTechTest")
            .Enrich.WithProperty(LogProps.ENVIRONMENT, _environment)
            .Enrich.WithProperty(LogProps.ENV_NAME, enrichLoggingConfig.EnvName);

            _loggerConfiguration.MinimumLevel.Debug()
            .MinimumLevel.Override("Microsoft", LogEventLevel.Error)
            .MinimumLevel.Override("System", LogEventLevel.Error);

            _loggerConfiguration.Enrich.With(new CorrelationEnricher(new CorrelationContextAccessor()));

            // TODO: Revisit this, although Props is shorter, how much does it cost us to clone the dictionary?
            _loggerConfiguration.Destructure.ByTransformingWhere <Props>(type => type == typeof(Props), value =>
                                                                         value.ToDictionary(entry => entry.Key,
                                                                                            entry => entry.Value));

            return(_loggerConfiguration.CreateLogger());
        }