blob: ebd8cd7fb53d7d16bc95ca59c829e5f12fe4205f [file] [log] [blame]
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/trace_event/json_file_outputter.h"
#include <string>
#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
#include "base/command_line.h"
#endif
#include "base/logging.h"
#include "base/platform_file.h"
#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
#include "base/string_piece.h"
#include "cobalt/trace_event/switches.h"
#endif
namespace cobalt {
namespace trace_event {
// Returns true if and only if log_timed_trace == "on", and
// ENABLE_DEBUG_COMMAND_LINE_SWITCHES is set.
bool ShouldLogTimedTrace() {
bool isTimedTraceSet = false;
#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
CommandLine* command_line = CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kLogTimedTrace) &&
command_line->GetSwitchValueASCII(switches::kLogTimedTrace) ==
"on") {
isTimedTraceSet = true;
}
#endif // ENABLE_DEBUG_COMMAND_LINE_SWITCHES
return isTimedTraceSet;
}
JSONFileOutputter::JSONFileOutputter(const FilePath& output_path)
: output_path_(output_path),
output_trace_event_call_count_(0),
file_(base::kInvalidPlatformFileValue) {
file_ = base::CreatePlatformFile(
output_path,
base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE, NULL,
NULL);
if (GetError()) {
DLOG(ERROR) << "Unable to open file for writing: " << output_path.value();
} else {
std::string header_text("{\"traceEvents\": [\n");
Write(header_text.c_str(), header_text.size());
}
}
JSONFileOutputter::~JSONFileOutputter() {
if (GetError()) {
DLOG(ERROR) << "An error occurred while writing to the output file: "
<< output_path_.value();
} else {
const char tail[] = "\n]}";
Write(tail, strlen(tail));
}
Close();
}
void JSONFileOutputter::OutputTraceData(
const scoped_refptr<base::RefCountedString>& event_string) {
DCHECK(!GetError());
// This function is usually called as a callback by
// base::debug::TraceLog::Flush(). It may get called by Flush()
// multiple times.
if (output_trace_event_call_count_ != 0) {
const char text[] = ",\n";
Write(text, strlen(text));
}
const std::string& event_str = event_string->data();
Write(event_str.c_str(), event_str.size());
++output_trace_event_call_count_;
}
void JSONFileOutputter::Write(const char* buffer, size_t length) {
if (GetError()) {
return;
}
if (ShouldLogTimedTrace()) {
// These markers assist in locating the trace data in the log, and can be
// used by scripts to help extract the trace data.
LOG(INFO) << "BEGIN_TRACELOG_MARKER" << base::StringPiece(buffer, length)
<< "END_TRACELOG_MARKER";
return;
}
int count = base::WritePlatformFileAtCurrentPos(file_, buffer, length);
if (count < 0) {
Close();
}
}
void JSONFileOutputter::Close() {
if (GetError()) {
return;
}
base::ClosePlatformFile(file_);
file_ = base::kInvalidPlatformFileValue;
}
} // namespace trace_event
} // namespace cobalt