public void FileCanBeOpenedTests(string testPath, bool expectSuccess) { var result = TableauLogsExtractor.FileCanBeOpened(testPath, new NullLogger <TableauLogsExtractor>()); result.FileCanBeOpened.Should().Be(expectSuccess); string.IsNullOrWhiteSpace(result.ErrorMessage).Should().Be(expectSuccess); }
public void FileIsAZipWithLogsTests(string testPath, bool validZip, bool containsLogs) { var result = TableauLogsExtractor.FileIsAZipWithLogs(testPath, new NullLogger <TableauLogsExtractor>()); result.ValidZip.Should().Be(validZip); result.ContainsLogFiles.Should().Be(containsLogs); string.IsNullOrWhiteSpace(result.ErrorMessage).Should().Be(validZip); }
public void EvaluateUnzipped() { Directory.Exists(TempDir).Should().Be(false); using (var extractor = new TableauLogsExtractor(UnzippedTestSet, TempDir, _processingNotificationsCollector, _logger)) { var expectedParts = new HashSet <LogSetInfo> { new LogSetInfo(UnzippedTestSet, string.Empty, false, UnzippedTestSet), new LogSetInfo($"{UnzippedTestSet}/worker1.zip", "worker1", true, UnzippedTestSet), new LogSetInfo($"{UnzippedTestSet}/localhost/tabadminagent_0.20181.18.0404.16052600117725665315795.zip", "localhost/tabadminagent_0.20181.18.0404.16052600117725665315795", true, UnzippedTestSet) }; extractor.LogSetParts.Should().BeEquivalentTo(expectedParts); Directory.Exists(TempDir).Should().Be(false); } _processingNotificationsCollector.TotalErrorsReported.Should().Be(0); }
public ProcessLogSetResult ProcessLogSet() { _logger.LogInformation("Using temp folder `{tempDir}`", _config.TempDir); using var logsExtractor = new TableauLogsExtractor(_config.LogSetLocation, _config.TempDir, _processingNotificationsCollector, _loggerFactory.CreateLogger <TableauLogsExtractor>()); if (!_pluginManager.IsValidPluginConfiguration(out var badPluginNames)) { return(ProcessLogSetResult.Failed(FailureReasonMessageGenerator.BadPluginNamesSpecified(badPluginNames), ExitReason.IncorrectConfiguration)); } var loadedPlugins = _pluginManager.CreatePlugins(_writerFactory, _processingNotificationsCollector).ToList(); var requiredLogTypes = _pluginManager.GetRequiredLogTypes().ToList(); var processedLogTypes = string.Join(", ", requiredLogTypes.OrderBy(name => name)); _logger.LogInformation("Based on requested plugins, the following log types will be processed: {processedLogTypes}", processedLogTypes); var logProcessingStatistics = new Dictionary <LogType, ProcessLogTypeResult>(); var pluginsReceivedAnyData = new HashSet <string>(); ProcessLogTypeResult failedLogTypeResult = null; foreach (var logType in requiredLogTypes) { _logger.LogInformation("Starting to process {logType} logs", logType); var logTypeInfo = _logTypeDetails.GetInfoForLogType(logType); var applicablePlugins = loadedPlugins .Where(plugin => plugin.ConsumedLogTypes.Contains(logType)) .ToList(); try { var logTypeProcessingResult = ProcessLogType(logsExtractor.LogSetParts, logTypeInfo, applicablePlugins); logProcessingStatistics.Add(logType, logTypeProcessingResult); if (!logTypeProcessingResult.IsSuccessful) { failedLogTypeResult = logTypeProcessingResult; break; } _logger.LogInformation("Done processing {logType} logs. {processingResult}", logType, logTypeProcessingResult); if (logTypeProcessingResult.FilesProcessed > 0) { foreach (var plugin in applicablePlugins) { pluginsReceivedAnyData.Add(plugin.Name); } } } catch (Exception ex) { var unhandledExceptionMessage = $"Unhandled exception occurred while processing log type {logType}. Exception: {ex.Message}"; _logger.LogError(ex, unhandledExceptionMessage); var fakeProcessingFileResult = new ProcessFileResult(0, unhandledExceptionMessage, ExitReason.UnclassifiedError); var fakeProcessingTypeResults = new ProcessLogTypeResult(); fakeProcessingTypeResults.AddProcessingInfo(TimeSpan.Zero, 0, fakeProcessingFileResult); failedLogTypeResult = fakeProcessingTypeResults; break; } } _logger.LogInformation("Telling all plugins to complete processing of any cached data"); var pluginsExecutionResults = _pluginManager.SendCompleteProcessingSignalToPlugins(failedLogTypeResult != null); _logger.LogInformation("Completed reading log set and generating data"); var(errorMessage, existReason) = GetExitReasonAndErrorMessageIfApplicable(failedLogTypeResult, logProcessingStatistics); var loadedPluginNames = loadedPlugins.Select(plugin => plugin.Name).ToHashSet(); return(new ProcessLogSetResult( errorMessage, existReason, logsExtractor.LogSetSizeBytes, logsExtractor.IsDirectory, loadedPluginNames, logProcessingStatistics, pluginsExecutionResults, pluginsReceivedAnyData)); }
private async Task <RunSummary> ProcessLog(IWriterFactory customWriterFactory) { _logger.LogInformation("Starting to process Log set {logSetPath}", _config.LogSetLocation); var totalElapsedTimer = Stopwatch.StartNew(); if (_config.OutputDirMaxResultsToKeep != null) { OutputDirTrimmer.TrimOldResults(_config.OutputDir, _config.OutputDirMaxResultsToKeep.Value, _loggerFactory.CreateLogger(nameof(OutputDirTrimmer))); } var runId = GetRunId(_config.ForceRunId); var fileCheckResult = TableauLogsExtractor.FileCanBeOpened(_config.LogSetLocation, _logger); if (!fileCheckResult.FileCanBeOpened) { var error = $"Path `{_config.LogSetLocation}` does not exist or LogShark cannot open it. Make sure `LogSetLocation` parameter points to the valid zip files with Tableau logs or unzipped copy of it. Exception message was: {fileCheckResult.ErrorMessage ?? "(null)"}"; _logger.LogInformation(error); return(RunSummary.FailedRunSummary(runId, error, ExitReason.BadLogSet, _processingNotificationsCollector, totalElapsedTimer.Elapsed)); } IWriterFactory writerFactory; try { writerFactory = customWriterFactory ?? GetWriterFactory(runId); } catch (Exception ex) { if (ex.Message.Contains("Context: 0x86a93465")) { _logger.LogError("Microsoft Visual C++ Runtime required to run LogShark. Please download and install it from 'https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads' and rerun application"); } var error = $"Exception occurred while initializing writer factory for writer '{_config.RequestedWriter ?? "null"}'. Exception message: {ex.Message}"; _logger.LogError(ex, error); return(RunSummary.FailedRunSummary(runId, error, ExitReason.UnclassifiedError, _processingNotificationsCollector, totalElapsedTimer.Elapsed)); } using (_logger.BeginScope(runId)) using (writerFactory) { ProcessLogSetResult logSetProcessingResults; using (var pluginManager = new PluginManager(_config, _loggerFactory)) { var logTypeDetails = new LogTypeDetails(_processingNotificationsCollector); var tableauLogsReader = new TableauLogsProcessor(_config, pluginManager, writerFactory, logTypeDetails, _processingNotificationsCollector, _loggerFactory); logSetProcessingResults = tableauLogsReader.ProcessLogSet(); } if (logSetProcessingResults.IsSuccessful) { var pluginsReceivedAnyDataForLogs = string.Join(", ", logSetProcessingResults.PluginsReceivedAnyData.OrderBy(name => name)); _logger.LogInformation("Plugins that had any data sent to them: {pluginsReceivedAnyData}", pluginsReceivedAnyDataForLogs); } else { _logger.LogDebug($"Log processing failed with error: {logSetProcessingResults.ErrorMessage}"); return(RunSummary.FailedRunSummary(runId, logSetProcessingResults.ErrorMessage, logSetProcessingResults.ExitReason, _processingNotificationsCollector, totalElapsedTimer.Elapsed, logSetProcessingResults)); } var workbookGenerator = writerFactory.GetWorkbookGenerator(); var generatorResults = workbookGenerator.CompleteWorkbooksWithResults(logSetProcessingResults.PluginsExecutionResults.GetWritersStatistics()); if (!GeneratedAnyWorkbooks(generatorResults.CompletedWorkbooks) && workbookGenerator.GeneratesWorkbooks) { const string errorMessage = "No workbooks were generated successfully."; _logger.LogError(errorMessage); return(RunSummary.FailedRunSummary(runId, errorMessage, ExitReason.UnclassifiedError, _processingNotificationsCollector, totalElapsedTimer.Elapsed, logSetProcessingResults, generatorResults)); } PublisherResults publisherResults = null; if (_config.PublishWorkbooks) { var projectDescription = GetProjectDescription(); var workbookPublisher = writerFactory.GetWorkbookPublisher(_publisherSettings); publisherResults = await workbookPublisher.PublishWorkbooks( runId, projectDescription, generatorResults.CompletedWorkbooks, logSetProcessingResults.PluginsExecutionResults.GetSortedTagsFromAllPlugins()); if (!publisherResults.CreatedProjectSuccessfully) { var errorMessage = $"Workbook publisher failed to connect to the Tableau Server or create project for the results. Exception message: {publisherResults.ExceptionCreatingProject.Message}"; _logger.LogError(errorMessage); return(RunSummary.FailedRunSummary(runId, errorMessage, ExitReason.UnclassifiedError, _processingNotificationsCollector, totalElapsedTimer.Elapsed, logSetProcessingResults, generatorResults, publisherResults)); } } _logger.LogInformation("Done processing {logSetPath}. Whole run took {fullRunElapsedTime}", _config.LogSetLocation, totalElapsedTimer.Elapsed); return(RunSummary.SuccessfulRunSummary(runId, totalElapsedTimer.Elapsed, _processingNotificationsCollector, logSetProcessingResults, generatorResults, publisherResults)); } }