/// <summary>
        /// Start the service, and stop the service if there were any errors found.
        /// </summary>
        /// <param name="Arguments">Command line arguments (unused).</param>
        protected override void OnStart(string[] Arguments)
        {
            // Create a log file for any start-up messages
            Log = new LogWriter("CrashReportProcess", LogFolder);

            Config.LoadConfig();

            Slack = new SlackWriter
            {
                WebhookUrl = Config.Default.SlackWebhookUrl,
                Channel    = Config.Default.SlackChannel,
                Username   = Config.Default.SlackUsername,
                IconEmoji  = Config.Default.SlackEmoji
            };

            Symbolicator = new Symbolicator();

            StatusReporter = new StatusReporting();

            ReportIndex = new ReportIndex
            {
                IsEnabled = !string.IsNullOrWhiteSpace(Config.Default.ProcessedReportsIndexPath),
                Filepath  = Config.Default.ProcessedReportsIndexPath,
                Retention = TimeSpan.FromDays(Config.Default.ReportsIndexRetentionDays)
            };

            ReportIndex.ReadFromFile();

            WriteEvent("Initializing AWS");
            string          AWSError;
            AWSCredentials  AWSCredentialsForDataRouter = new StoredProfileAWSCredentials(Config.Default.AWSProfileInputName, Config.Default.AWSCredentialsFilepath);
            AmazonSQSConfig SqsConfigForDataRouter      = new AmazonSQSConfig
            {
                ServiceURL = Config.Default.AWSSQSServiceInputURL
            };
            AmazonS3Config S3ConfigForDataRouter = new AmazonS3Config
            {
                ServiceURL = Config.Default.AWSS3ServiceInputURL
            };

            DataRouterAWS = new AmazonClient(AWSCredentialsForDataRouter, SqsConfigForDataRouter, S3ConfigForDataRouter, out AWSError);
            if (!DataRouterAWS.IsSQSValid || !DataRouterAWS.IsS3Valid)
            {
                WriteFailure("AWS failed to initialize profile for DataRouter access. Error:" + AWSError);
                StatusReporter.Alert("AWSFailInput", "AWS failed to initialize profile for DataRouter access", 0);
            }
            AWSCredentials AWSCredentialsForOutput = new StoredProfileAWSCredentials(Config.Default.AWSProfileOutputName, Config.Default.AWSCredentialsFilepath);
            AmazonS3Config S3ConfigForOutput       = new AmazonS3Config
            {
                ServiceURL = Config.Default.AWSS3ServiceOutputURL
            };

            OutputAWS = new AmazonClient(AWSCredentialsForOutput, null, S3ConfigForOutput, out AWSError);
            if (!OutputAWS.IsS3Valid)
            {
                WriteFailure("AWS failed to initialize profile for output S3 bucket access. Error:" + AWSError);
                StatusReporter.Alert("AWSFailOutput", "AWS failed to initialize profile for output S3 bucket access", 0);
            }

            // Add directory watchers
            WriteEvent("Creating ReportWatcher");
            Watcher = new ReportWatcher();

            WriteEvent("Creating ReportProcessors");
            for (int ProcessorIndex = 0; ProcessorIndex < Config.Default.ProcessorThreadCount; ProcessorIndex++)
            {
                var Processor = new ReportProcessor(Watcher, ProcessorIndex);
                Processors.Add(Processor);
            }

            // Init events by enumerating event names
            WriteEvent("Initializing Event Counters");
            FieldInfo[] EventNameFields = typeof(StatusReportingEventNames).GetFields(BindingFlags.Static | BindingFlags.Public);
            StatusReporter.InitCounters(EventNameFields.Select(EventNameField => (string)EventNameField.GetValue(null)));

            WriteEvent("Initializing Performance Mean Counters");
            FieldInfo[] MeanNameFields = typeof(StatusReportingPerfMeanNames).GetFields(BindingFlags.Static | BindingFlags.Public);
            StatusReporter.InitMeanCounters(MeanNameFields.Select(MeanNameField => (string)MeanNameField.GetValue(null)));

            WriteEvent("Initializing Folder Monitors");
            Dictionary <string, string> FoldersToMonitor = new Dictionary <string, string>();

            FoldersToMonitor.Add(Config.Default.ProcessedReports, "Processed Reports");
            FoldersToMonitor.Add(Config.Default.ProcessedVideos, "Processed Videos");
            FoldersToMonitor.Add(Config.Default.DepotRoot, "P4 Workspace");
            FoldersToMonitor.Add(Config.Default.InternalLandingZone, "CRR Landing Zone");
            FoldersToMonitor.Add(Config.Default.DataRouterLandingZone, "Data Router Landing Zone");
            FoldersToMonitor.Add(Config.Default.PS4LandingZone, "PS4 Landing Zone");
            FoldersToMonitor.Add(Assembly.GetExecutingAssembly().Location, "CRP Binaries and Logs");
            FoldersToMonitor.Add(Config.Default.MDDPDBCachePath, "MDD PDB Cache");
            StatusReporter.InitFolderMonitors(FoldersToMonitor);

            WriteEvent("Starting StatusReporter");
            StatusReporter.Start();

            // Start the threads now
            Watcher.Start();
            foreach (var Processor in Processors)
            {
                Processor.Start();
            }

            DateTime StartupTime = DateTime.UtcNow;

            WriteEvent("Successfully started at " + StartupTime);
        }
Example #2
0
        /// <summary>
        /// Create thread to watch for new crash reports landing.
        /// </summary>
        /// <remarks>The NFS storage does not support file system watchers, so this has to be done laboriously.</remarks>
        void Init()
        {
            CrashReporterProcessServicer.WriteEvent("CrashReportProcessor watching directories:");
            var Settings = Config.Default;

            if (!string.IsNullOrEmpty(Settings.DataRouterLandingZone))
            {
                if (System.IO.Directory.Exists(Settings.DataRouterLandingZone))
                {
                    ReportQueues.Add(new DataRouterReportQueue("DataRouter Crashes", Settings.DataRouterLandingZone, Config.Default.QueueLowerLimitForDiscard, Config.Default.QueueUpperLimitForDiscard));
                    CrashReporterProcessServicer.WriteEvent(string.Format("\t{0} (all crashes from data router)", Settings.DataRouterLandingZone));
                }
                else
                {
                    CrashReporterProcessServicer.WriteFailure(string.Format("\t{0} (all crashes from data router) is not accessible", Settings.DataRouterLandingZone));
                }
            }

            if (!string.IsNullOrEmpty(Settings.InternalLandingZone))
            {
                if (System.IO.Directory.Exists(Settings.InternalLandingZone))
                {
                    ReportQueues.Add(new ReceiverReportQueue("Epic Crashes", Settings.InternalLandingZone, Config.Default.QueueLowerLimitForDiscard, Config.Default.QueueUpperLimitForDiscard));
                    CrashReporterProcessServicer.WriteEvent(string.Format("\t{0} (internal, high priority (legacy))", Settings.InternalLandingZone));
                }
                else
                {
                    CrashReporterProcessServicer.WriteFailure(string.Format("\t{0} (internal, high priority (legacy)) is not accessible", Settings.InternalLandingZone));
                }
            }

#if !DEBUG
            if (!string.IsNullOrEmpty(Settings.ExternalLandingZone))
            {
                if (System.IO.Directory.Exists(Settings.ExternalLandingZone))
                {
                    ReportQueues.Add(new ReceiverReportQueue("External Crashes", Settings.ExternalLandingZone, Config.Default.QueueLowerLimitForDiscard, Config.Default.QueueUpperLimitForDiscard));
                    CrashReporterProcessServicer.WriteEvent(string.Format("\t{0} (legacy)", Settings.ExternalLandingZone));
                }
                else
                {
                    CrashReporterProcessServicer.WriteFailure(string.Format("\t{0} (legacy) is not accessible", Settings.ExternalLandingZone));
                }
            }
#endif //!DEBUG

            // Init queue entries in StatusReporter
            foreach (var Queue in ReportQueues)
            {
                CrashReporterProcessServicer.StatusReporter.InitQueue(Queue.QueueId, Queue.LandingZonePath);
            }

            ReportIndex.Filepath  = Config.Default.ProcessedReportsIndexPath;
            ReportIndex.Retention = TimeSpan.FromDays(Config.Default.ReportsIndexRetentionDays);
            ReportIndex.ReadFromFile();

            var Cancel = CancelSource.Token;
            WatcherTask = new Task(async() =>
            {
                DateTime LastQueueSizeReport = DateTime.MinValue;
                while (!Cancel.IsCancellationRequested)
                {
                    // Check the landing zones for new reports
                    DateTime StartTime = DateTime.Now;

                    foreach (var Queue in ReportQueues)
                    {
                        int QueueSize = Queue.CheckForNewReports();
                        CrashReporterProcessServicer.StatusReporter.SetQueueSize(Queue.QueueId, QueueSize);
                    }

                    TimeSpan TimeTaken = DateTime.Now - StartTime;
                    CrashReporterProcessServicer.WriteEvent(string.Format("Checking Landing Zones took {0:F2} seconds", TimeTaken.TotalSeconds));
                    await Task.Delay(30000, Cancel);
                }
            });
        }