Home | History | Annotate | Download | only in tracing
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/browser/tracing/trace_subscriber_stdio.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/debug/trace_event.h"
      9 #include "base/file_util.h"
     10 #include "base/logging.h"
     11 #include "base/threading/sequenced_worker_pool.h"
     12 #include "content/public/browser/browser_thread.h"
     13 
     14 namespace content {
     15 
     16 // All method calls on this class are done on a SequencedWorkerPool thread.
     17 class TraceSubscriberStdioImpl
     18     : public base::RefCountedThreadSafe<TraceSubscriberStdioImpl> {
     19  public:
     20   explicit TraceSubscriberStdioImpl(const base::FilePath& path)
     21       : path_(path),
     22         file_(0) {}
     23 
     24   void OnStart() {
     25     DCHECK(!file_);
     26     trace_buffer_.SetOutputCallback(
     27         base::Bind(&TraceSubscriberStdioImpl::Write, this));
     28     file_ = file_util::OpenFile(path_, "w+");
     29     if (IsValid()) {
     30       LOG(INFO) << "Logging performance trace to file: " << path_.value();
     31       trace_buffer_.Start();
     32     } else {
     33       LOG(ERROR) << "Failed to open performance trace file: " << path_.value();
     34     }
     35   }
     36 
     37   void OnData(const scoped_refptr<base::RefCountedString>& data_ptr) {
     38     trace_buffer_.AddFragment(data_ptr->data());
     39   }
     40 
     41   void OnEnd() {
     42     trace_buffer_.Finish();
     43     CloseFile();
     44   }
     45 
     46  private:
     47   friend class base::RefCountedThreadSafe<TraceSubscriberStdioImpl>;
     48 
     49   ~TraceSubscriberStdioImpl() {
     50     CloseFile();
     51   }
     52 
     53   bool IsValid() const {
     54     return file_ && (0 == ferror(file_));
     55   }
     56 
     57   void CloseFile() {
     58     if (file_) {
     59       fclose(file_);
     60       file_ = 0;
     61     }
     62     // This is important, as it breaks a reference cycle.
     63     trace_buffer_.SetOutputCallback(
     64         base::debug::TraceResultBuffer::OutputCallback());
     65   }
     66 
     67   void Write(const std::string& output_str) {
     68     if (IsValid()) {
     69       size_t written = fwrite(output_str.data(), 1, output_str.size(), file_);
     70       if (written != output_str.size()) {
     71         LOG(ERROR) << "Error " << ferror(file_) << " in fwrite() to trace file";
     72         CloseFile();
     73       }
     74     }
     75   }
     76 
     77   base::FilePath path_;
     78   FILE* file_;
     79   base::debug::TraceResultBuffer trace_buffer_;
     80 };
     81 
     82 TraceSubscriberStdio::TraceSubscriberStdio(const base::FilePath& path)
     83     : impl_(new TraceSubscriberStdioImpl(path)) {
     84   BrowserThread::PostBlockingPoolSequencedTask(
     85       __FILE__, FROM_HERE,
     86       base::Bind(&TraceSubscriberStdioImpl::OnStart, impl_));
     87 }
     88 
     89 TraceSubscriberStdio::~TraceSubscriberStdio() {
     90 }
     91 
     92 void TraceSubscriberStdio::OnEndTracingComplete() {
     93   BrowserThread::PostBlockingPoolSequencedTask(
     94       __FILE__, FROM_HERE,
     95       base::Bind(&TraceSubscriberStdioImpl::OnEnd, impl_));
     96 }
     97 
     98 void TraceSubscriberStdio::OnTraceDataCollected(
     99     const scoped_refptr<base::RefCountedString>& data_ptr) {
    100   BrowserThread::PostBlockingPoolSequencedTask(
    101       __FILE__, FROM_HERE,
    102       base::Bind(&TraceSubscriberStdioImpl::OnData, impl_, data_ptr));
    103 }
    104 
    105 }  // namespace content
    106