blob: 2ed9862b2d8941cdae35f171deeca6de7a722349 [file] [log] [blame]
// Copyright 2016 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 <limits>
#include <memory>
#include "base/callback.h"
#include "base/files/file.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/optional.h"
#include "net/base/net_export.h"
#include "net/log/net_log.h"
namespace base {
class Value;
class FilePath;
class SequencedTaskRunner;
} // namespace base
namespace net {
// FileNetLogObserver watches the NetLog event stream and sends all entries to
// a file.
// Consumers must call StartObserving before calling StopObserving, and must
// call each method exactly once in the lifetime of the observer.
// The log will not be completely written until StopObserving is called.
// When a file size limit is given, FileNetLogObserver will create temporary
// directory containing chunks of events. This is used to drop older events in
// favor of newer ones.
class NET_EXPORT FileNetLogObserver : public NetLog::ThreadSafeObserver {
// Special value meaning "can use an unlimited number of bytes".
static constexpr uint64_t kNoLimit = std::numeric_limits<uint64_t>::max();
// Creates an instance of FileNetLogObserver that writes observed netlog
// events to |log_path|.
// |log_path| is where the final log file will be written to. If a file
// already exists at this path it will be overwritten. While logging is in
// progress, events may be written to a like-named directory.
// |max_total_size| is the limit on how many bytes logging may consume on
// disk. This is an approximate limit, and in practice FileNetLogObserver may
// (slightly) exceed it. This may be set to kNoLimit to remove any size
// restrictions.
// |constants| is an optional legend for decoding constant values used in
// the log. It should generally be a modified version of GetNetConstants().
// If not present, the output of GetNetConstants() will be used.
static std::unique_ptr<FileNetLogObserver> CreateBounded(
const base::FilePath& log_path,
uint64_t max_total_size,
NetLogCaptureMode capture_mode,
std::unique_ptr<base::Value> constants);
// Shortcut for calling CreateBounded() with kNoLimit.
static std::unique_ptr<FileNetLogObserver> CreateUnbounded(
const base::FilePath& log_path,
NetLogCaptureMode capture_mode,
std::unique_ptr<base::Value> constants);
// Creates a bounded log that writes to a pre-existing file (truncating
// it to start with, and closing it upon completion). |inprogress_dir_path|
// will be used as a scratch directory, for temporary files (with predictable
// names).
static std::unique_ptr<FileNetLogObserver> CreateBoundedPreExisting(
const base::FilePath& inprogress_dir_path,
base::File output_file,
uint64_t max_total_size,
NetLogCaptureMode capture_mode,
std::unique_ptr<base::Value> constants);
// Creates an unbounded log that writes to a pre-existing file (truncating
// it to start with, and closing it upon completion).
static std::unique_ptr<FileNetLogObserver> CreateUnboundedPreExisting(
base::File output_file,
NetLogCaptureMode capture_mode,
std::unique_ptr<base::Value> constants);
~FileNetLogObserver() override;
// Attaches this observer to |net_log| and begins observing events.
void StartObserving(NetLog* net_log);
// Stops observing net_log() and closes the output file(s). Must be called
// after StartObserving. Should be called before destruction of the
// FileNetLogObserver and the NetLog, or the NetLog files (except for an
// externally provided output_file) will be deleted when the observer is
// destroyed. Note that it is OK to destroy |this| immediately after calling
// StopObserving() - the callback will still be called once the file writing
// has completed.
// |polled_data| is an optional argument used to add additional network stack
// state to the log.
// If non-null, |optional_callback| will be run on whichever thread
// StopObserving() was called on once all file writing is complete and the
// netlog files can be accessed safely.
void StopObserving(std::unique_ptr<base::Value> polled_data,
base::OnceClosure optional_callback);
// NetLog::ThreadSafeObserver
void OnAddEntry(const NetLogEntry& entry) override;
// Same as CreateBounded() but you can additionally specify
// |total_num_event_files|.
static std::unique_ptr<FileNetLogObserver> CreateBoundedForTests(
const base::FilePath& log_path,
uint64_t max_total_size,
size_t total_num_event_files,
NetLogCaptureMode capture_mode,
std::unique_ptr<base::Value> constants);
class WriteQueue;
class FileWriter;
static std::unique_ptr<FileNetLogObserver> CreateInternal(
const base::FilePath& log_path,
const base::FilePath& inprogress_dir_path,
base::Optional<base::File> pre_existing_out_file,
uint64_t max_total_size,
size_t total_num_event_files,
NetLogCaptureMode capture_mode,
std::unique_ptr<base::Value> constants);
FileNetLogObserver(scoped_refptr<base::SequencedTaskRunner> file_task_runner,
std::unique_ptr<FileWriter> file_writer,
scoped_refptr<WriteQueue> write_queue,
NetLogCaptureMode capture_mode,
std::unique_ptr<base::Value> constants);
static std::string CaptureModeToString(NetLogCaptureMode mode);
scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
// The |write_queue_| object is shared between the file task runner and the
// main thread, and should be alive for the entirety of the observer's
// lifetime. It should be destroyed once both the observer has been destroyed
// and all tasks posted to the file task runner have completed.
scoped_refptr<WriteQueue> write_queue_;
// The FileNetLogObserver is shared between the main thread and
// |file_task_runner_|.
// Conceptually FileNetLogObserver owns it, however on destruction its
// deletion is deferred until outstanding tasks on |file_task_runner_| have
// finished (since it is posted using base::Unretained()).
std::unique_ptr<FileWriter> file_writer_;
const NetLogCaptureMode capture_mode_;
// Serializes |value| to a JSON string used when writing to a file.
NET_EXPORT_PRIVATE std::string SerializeNetLogValueToJson(
const base::Value& value);
} // namespace net