blob: edade2ff300a6b88ad0cd0dcc4df694866070db3 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/chrome_cleaner/logging/scoped_logging.h"
#include <memory>
#include "base/command_line.h"
#include "base/file_version_info.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging_win.h"
#include "base/strings/string_util.h"
#include "base/win/current_module.h"
#include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h"
#include "chrome/chrome_cleaner/constants/version.h"
#include "chrome/chrome_cleaner/logging/logging_service_api.h"
#include "chrome/chrome_cleaner/os/disk_util.h"
#include "chrome/chrome_cleaner/os/pre_fetched_paths.h"
#include "chrome/chrome_cleaner/settings/settings.h"
namespace chrome_cleaner {
namespace {
// {985388DD-5F6A-40A9-A4D2-86D8547EFB52}
const GUID kChromeCleanerTraceProviderName = {
0x985388DD,
0x5F6A,
0x40A9,
{0xA4, 0xD2, 0x86, 0xD8, 0x54, 0x7E, 0xFB, 0x52}};
// The log file extension.
const wchar_t kLogFileExtension[] = L"log";
base::FilePath GetLoggingDirectory() {
base::FilePath logging_directory =
base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
kTestLoggingPathSwitch);
if (logging_directory.empty()) {
if (!GetAppDataProductDirectory(&logging_directory))
return base::FilePath();
}
return logging_directory;
}
} // namespace
ScopedLogging::ScopedLogging(base::FilePath::StringPieceType suffix) {
// Log to an ETW facility for convenience.
// This swallows all log lines it gets, so we need to initialize it before
// LoggingServiceAPI so LoggingServiceAPI can see the logs first, which it
// then passes on to LogEventProvider.
logging::LogEventProvider::Initialize(kChromeCleanerTraceProviderName);
// Initialize the logging global state.
LoggingServiceAPI* logging_service = LoggingServiceAPI::GetInstance();
logging_service->Initialize(nullptr);
const base::FilePath log_file_path = GetLogFilePath(suffix);
// Truncate log files to 40kB. This should be enough to cover logs of the
// previous run (99th percentile of uploaded raw log line size is 36kB).
TruncateLogFileToTail(log_file_path, 40 * 1000);
logging::LoggingSettings logging_settings;
logging_settings.logging_dest = logging::LOG_TO_FILE;
logging_settings.log_file_path = log_file_path.value().c_str();
bool success = logging::InitLogging(logging_settings);
DCHECK(success);
LOG(INFO) << "Starting logs for version: " << CHROME_CLEANER_VERSION_STRING;
logging_service->EnableUploads(
chrome_cleaner::Settings::GetInstance()->logs_upload_allowed(), nullptr);
}
ScopedLogging::~ScopedLogging() {
// Terminate the service to avoid work being done in the destructor called by
// the AtExitManager.
LoggingServiceAPI::GetInstance()->Terminate();
// Kill our ETW provider.
logging::LogEventProvider::Uninitialize();
}
// static
base::FilePath ScopedLogging::GetLogFilePath(
base::FilePath::StringPieceType suffix) {
// Initialize the logging settings to set a specific log file name.
std::unique_ptr<FileVersionInfo> version(
FileVersionInfo::CreateFileVersionInfoForModule(CURRENT_MODULE()));
// Test executables don't have version resources.
base::FilePath original_filename;
if (version.get()) {
original_filename =
base::FilePath(base::AsWStringPiece(version->original_filename()));
} else {
original_filename =
PreFetchedPaths::GetInstance()->GetExecutablePath().BaseName();
}
if (!suffix.empty())
original_filename = original_filename.InsertBeforeExtension(suffix);
base::FilePath log_file_path =
original_filename.ReplaceExtension(kLogFileExtension);
base::FilePath logging_directory = GetLoggingDirectory();
if (!logging_directory.empty())
log_file_path = logging_directory.Append(log_file_path);
return log_file_path;
}
} // namespace chrome_cleaner