protected virtual void Dispose(bool disposing)
        {
            if (disposed)
            {
                return;
            }
            disposed = true;

            if (disposing)
            {
                if (this.newReportFileTrigger != null)
                {
                    this.newReportFileTrigger.NewReportFileRequested -= OnNewReportFileRequested;
                    this.newReportFileTrigger = null;
                }

                // Mark report collection as complete adding. When the collection is empty, it will dispose the stream writers.
                this.reportCollection.CompleteAdding();

                try
                {
                    // Make sure that when Dispose() returns, the reporter is fully disposed (streams are closed etc.)
                    this.writingTask?.Wait(DisposalTimeout);
                }
                catch
                {
                    // We are reporting writing task errors from ReportXxx() methods, to no need to pass the task exception up here.
                }
            }
        }
Beispiel #2
0
 // Constructor for testing purpose.
 internal CsvHealthReporter(
     CsvHealthReporterConfiguration configuration,
     INewReportFileTrigger newReportTrigger = null,
     int flushPeriodMsec = 5000)
 {
     this.flushPeriodMsec = flushPeriodMsec;
     Initialize(configuration, newReportTrigger);
 }
 // Constructor for testing purpose.
 internal CsvHealthReporter(
     CsvHealthReporterConfiguration configuration,
     INewReportFileTrigger newReportTrigger = null,
     int flushPeriodMsec = 5000,
     Func <DateTime> currentTimeProvider = null)
 {
     this.flushPeriodMsec = flushPeriodMsec;
     if (currentTimeProvider != null)
     {
         this.getCurrentTime = currentTimeProvider;
     }
     Initialize(configuration, newReportTrigger);
 }
        private void Initialize(CsvHealthReporterConfiguration configuration, INewReportFileTrigger newReportTrigger = null)
        {
            Requires.NotNull(configuration, nameof(configuration));

            this.reportCollection = new BlockingCollection <string>();

            this.EnsureOutputCanBeSaved = configuration.EnsureOutputCanBeSaved;

            this.innerReportWriter = this.ReportText;

            if (configuration.AssumeSharedLogFolder)
            {
                var          random = new Random();
                const string chars  = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
                this.logFileNameRandomizer = new string(Enumerable.Range(1, 12).Select(i => chars[random.Next(chars.Length)]).ToArray());
            }
            else
            {
                this.logFileNameRandomizer = string.Empty;
            }

            // Prepare the configuration, set default values, handle invalid values.
            this.Configuration = configuration;

            // Create a default throttle.
            this.throttle = new TimeSpanThrottle(TimeSpan.FromMilliseconds(DefaultThrottlingPeriodMsec));

            // Set the file size for csv health report. Minimum is 1MB. Default is 8192MB.
            this.SingleLogFileMaximumSizeInBytes = (long)(configuration.SingleLogFileMaximumSizeInMBytes > 0 ? configuration.SingleLogFileMaximumSizeInMBytes : 8192) * 1024 * 1024;

            // Log retention days has a minimum of 1 day. Set to the default value of 30 days.
            if (configuration.LogRetentionInDays <= 0)
            {
                configuration.LogRetentionInDays = 30;
            }

            HealthReportLevel logLevel;
            string            logLevelString = this.Configuration.MinReportLevel;

            if (string.IsNullOrWhiteSpace(logLevelString))
            {
                this.minReportLevel = HealthReportLevel.Error;
            }
            else if (Enum.TryParse(logLevelString, out logLevel))
            {
                this.minReportLevel = logLevel;
            }
            else
            {
                this.minReportLevel = HealthReportLevel.Error;
                // The severity has to be at least the same as the default level of error.
                ReportProblem($"Failed to parse log level. Please check the value of: {logLevelString}. Falling back to default value: {this.minReportLevel.ToString()}", TraceTag);
            }
            this.Configuration.MinReportLevel = this.minReportLevel.ToString();

            if (this.Configuration.ThrottlingPeriodMsec == null || !this.Configuration.ThrottlingPeriodMsec.HasValue)
            {
                this.Configuration.ThrottlingPeriodMsec = DefaultThrottlingPeriodMsec;
                ReportHealthy($"{nameof(this.Configuration.ThrottlingPeriodMsec)} is not specified. Falling back to default value: {this.Configuration.ThrottlingPeriodMsec}.", TraceTag);
            }
            else if (this.Configuration.ThrottlingPeriodMsec.Value == DefaultThrottlingPeriodMsec)
            {
                // Keep using the default throttle created before.
            }
            else if (this.Configuration.ThrottlingPeriodMsec.Value < 0)
            {
                ReportWarning($"{nameof(this.Configuration.ThrottlingPeriodMsec)}: {this.Configuration.ThrottlingPeriodMsec.Value} specified in the configuration file is invalid. Falling back to default value: {DefaultThrottlingPeriodMsec}", TraceTag);
                this.Configuration.ThrottlingPeriodMsec = DefaultThrottlingPeriodMsec;
            }
            else if (this.Configuration.ThrottlingPeriodMsec.Value >= 0)
            {
                this.throttle = new TimeSpanThrottle(TimeSpan.FromMilliseconds(this.Configuration.ThrottlingPeriodMsec.Value));
            }

            // Set default value for health report file prefix
            if (string.IsNullOrWhiteSpace(this.Configuration.LogFilePrefix))
            {
                this.Configuration.LogFilePrefix = DefaultLogFilePrefix;
                ReportHealthy($"{nameof(this.Configuration.LogFilePrefix)} is not specified in configuration file. Falling back to default value: {this.Configuration.LogFilePrefix}", TraceTag);
            }

            // Set target folder for health report files.
            if (string.IsNullOrWhiteSpace(this.Configuration.LogFileFolder))
            {
                this.Configuration.LogFileFolder = ".";
                ReportHealthy($"{nameof(this.Configuration.LogFileFolder)} is not specified in configuration file. Falling back to default value: {this.Configuration.LogFileFolder}", TraceTag);
            }
            ProcessLogFileFolder();

            this.newReportFileTrigger = newReportTrigger ?? UtcMidnightNotifier.Instance;
            this.newReportFileTrigger.NewReportFileRequested += OnNewReportFileRequested;

            // Clean up existing logging files per retention policy
            CleanupExistingLogs();
        }
Beispiel #5
0
        private void Initialize(CsvHealthReporterConfiguration configuration, INewReportFileTrigger newReportTrigger = null)
        {
            Requires.NotNull(configuration, nameof(configuration));

            this.reportCollection = new BlockingCollection <string>();

            // Prepare the configuration, set default values, handle invalid values.
            this.Configuration = configuration;

            // Create a default throttle
            this.throttle = new TimeSpanThrottle(TimeSpan.FromMilliseconds(DefaultThrottlingPeriodMsec));

            HealthReportLevel logLevel;
            string            logLevelString = this.Configuration.MinReportLevel;

            if (string.IsNullOrWhiteSpace(logLevelString))
            {
                this.minReportLevel = HealthReportLevel.Error;
            }
            else if (Enum.TryParse(logLevelString, out logLevel))
            {
                this.minReportLevel = logLevel;
            }
            else
            {
                this.minReportLevel = HealthReportLevel.Error;
                // The severity has to be at least the same as the default level of error.
                ReportProblem($"Failed to parse log level. Please check the value of: {logLevelString}. Falling back to default value: {this.minReportLevel.ToString()}", TraceTag);
            }
            this.Configuration.MinReportLevel = this.minReportLevel.ToString();

            if (this.Configuration.ThrottlingPeriodMsec == null || !this.Configuration.ThrottlingPeriodMsec.HasValue)
            {
                this.Configuration.ThrottlingPeriodMsec = DefaultThrottlingPeriodMsec;
                ReportHealthy($"{nameof(this.Configuration.ThrottlingPeriodMsec)} is not specified. Falling back to default value: {this.Configuration.ThrottlingPeriodMsec}.", TraceTag);
            }
            else if (this.Configuration.ThrottlingPeriodMsec.Value == DefaultThrottlingPeriodMsec)
            {
                // Keep using the default throttle created before.
            }
            else if (this.Configuration.ThrottlingPeriodMsec.Value < 0)
            {
                ReportWarning($"{nameof(this.Configuration.ThrottlingPeriodMsec)}: {this.Configuration.ThrottlingPeriodMsec.Value} specified in the configuration file is invalid. Falling back to default value: {DefaultThrottlingPeriodMsec}", TraceTag);
                this.Configuration.ThrottlingPeriodMsec = DefaultThrottlingPeriodMsec;
            }
            else if (this.Configuration.ThrottlingPeriodMsec.Value >= 0)
            {
                this.throttle = new TimeSpanThrottle(TimeSpan.FromMilliseconds(this.Configuration.ThrottlingPeriodMsec.Value));
            }

            // Set default value for health report file prefix
            if (string.IsNullOrWhiteSpace(this.Configuration.LogFilePrefix))
            {
                this.Configuration.LogFilePrefix = DefaultLogFilePrefix;
                ReportHealthy($"{nameof(this.Configuration.LogFilePrefix)} is not specified in configuration file. Falling back to default value: {this.Configuration.LogFilePrefix}", TraceTag);
            }

            // Set target folder for health report files.
            if (string.IsNullOrWhiteSpace(this.Configuration.LogFileFolder))
            {
                this.Configuration.LogFileFolder = ".";
                ReportHealthy($"{nameof(this.Configuration.LogFileFolder)} is not specified in configuration file. Falling back to default value: {this.Configuration.LogFileFolder}", TraceTag);
            }
            ProcessLogFileFolder();

            this.newReportFileTrigger = newReportTrigger ?? UtcMidnightNotifier.Instance;
            this.newReportFileTrigger.NewReportFileRequested += OnNewReportFileRequested;
        }
Beispiel #6
0
 public CustomHealthReporter(CsvHealthReporterConfiguration configuration, INewReportFileTrigger newReportTrigger)
     : base(configuration, newReportTrigger)
 {
 }