protected virtual void GenerateHTMLReport(ICoverageParserTool tool)
        {
            if (_configuration.GenerateHTMLReport)
            {
                try
                {
                    using (new SimpleTimer("Parser", "ReportGeneration", _telemetry))
                    {
                        // Generate report
                        tool.GenerateHTMLReport();

                        // Copy coverage input files to report directory in a unique folder
                        if (Directory.Exists(_configuration.ReportDirectory))
                        {
                            string summaryFilesSubDir;

                            // Create a unique folder
                            do
                            {
                                summaryFilesSubDir = Path.Combine(_configuration.ReportDirectory, "Summary_" + Guid.NewGuid().ToString().Substring(0, 8));
                            } while (Directory.Exists(summaryFilesSubDir));

                            TraceLogger.Debug("Parser.GenerateHTMLReport: Creating summary file directory: " + summaryFilesSubDir);

                            Directory.CreateDirectory(summaryFilesSubDir);

                            // Copy the files
                            foreach (var summaryFile in _configuration.CoverageFiles)
                            {
                                var summaryFileName        = Path.GetFileName(summaryFile);
                                var destinationSummaryFile = Path.Combine(summaryFilesSubDir, summaryFileName);

                                TraceLogger.Debug("Parser.GenerateHTMLReport: Copying summary file " + summaryFile);
                                File.Copy(summaryFile, destinationSummaryFile, true);
                            }
                        }
                        else
                        {
                            TraceLogger.Debug("Parser.GenerateHTMLReport: Directory " + _configuration.ReportDirectory + " doesn't exist, skipping copying of coverage input files.");
                        }
                    }
                }
                catch (Exception e)
                {
                    _telemetry.AddFailure(e);
                    TraceLogger.Error(string.Format(Resources.HTMLReportError, e.Message));
                }
            }
        }
        public async Task ParseAndPublishCoverage(PublisherConfiguration config, CancellationToken token, Parser parser)
        {
            if (_publisher != null)
            {
                try
                {
                    _telemetry.AddOrUpdate("PublisherConfig", () =>
                    {
                        return("{" +
                               $"\"InputFilesCount\": {config.CoverageFiles.Count}," +
                               $"\"SourceDirectoryProvided\": {config.SourceDirectory != ""}," +
                               $"\"GenerateHtmlReport\": {config.GenerateHTMLReport}," +
                               $"\"GenerateHtmlReport\": {config.TimeoutInSeconds}" +
                               "}");
                    });

                    var supportsFileCoverageJson = _publisher.IsFileCoverageJsonSupported();

                    if (supportsFileCoverageJson)
                    {
                        TraceLogger.Debug("Publishing file json coverage is supported.");
                        var fileCoverage = parser.GetFileCoverageInfos();

                        _telemetry.AddOrUpdate("UniqueFilesCovered", fileCoverage.Count);

                        if (fileCoverage.Count == 0)
                        {
                            TraceLogger.Warning(Resources.NoCoverageFilesGenerated);
                        }
                        else
                        {
                            using (new SimpleTimer("CoverageProcesser", "PublishFileCoverage", _telemetry))
                            {
                                await _publisher.PublishFileCoverage(fileCoverage, token);
                            }
                        }
                    }
                    else
                    {
                        TraceLogger.Debug("Publishing file json coverage is not supported.");
                        var summary = parser.GetCoverageSummary();

                        if (summary == null || summary.CodeCoverageData.CoverageStats.Count == 0)
                        {
                            TraceLogger.Warning(Resources.NoSummaryStatisticsGenerated);
                        }
                        else
                        {
                            using (new SimpleTimer("CoverageProcesser", "PublishCoverageSummary", _telemetry))
                            {
                                await _publisher.PublishCoverageSummary(summary, token);
                            }
                        }
                    }

                    if (config.GenerateHTMLReport)
                    {
                        if (!Directory.Exists(config.ReportDirectory))
                        {
                            TraceLogger.Warning(Resources.NoReportDirectoryGenerated);
                        }
                        else
                        {
                            using (new SimpleTimer("CoverageProcesser", "PublishHTMLReport", _telemetry))
                            {
                                await _publisher.PublishHTMLReport(config.ReportDirectory, token);
                            }
                        }
                    }
                }
                // Only catastrophic failures should trickle down to these catch blocks
                catch (ParsingException ex)
                {
                    _telemetry.AddFailure(ex);
                    TraceLogger.Error($"{ex.Message} {ex.InnerException}");
                }
                catch (Exception ex)
                {
                    _telemetry.AddFailure(ex);
                    TraceLogger.Error(string.Format(Resources.ErrorOccuredWhilePublishing, ex));
                }
            }
        }