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);
        }
Ejemplo n.º 3
0
        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);
        }
Ejemplo n.º 4
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));
        }
Ejemplo n.º 5
0
        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));
                }
        }