chromium_logger.h revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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#ifndef THIRD_PARTY_LEVELDATABASE_CHROMIUM_LOGGER_H_
6#define THIRD_PARTY_LEVELDATABASE_CHROMIUM_LOGGER_H_
7
8#include <stdio.h>
9
10#include <algorithm>
11
12#include "base/format_macros.h"
13#include "base/strings/string_util.h"
14#include "base/time/time.h"
15#include "third_party/leveldatabase/src/include/leveldb/env.h"
16
17namespace leveldb {
18
19class ChromiumLogger : public Logger {
20 public:
21  explicit ChromiumLogger(FILE* f) : file_(f) {}
22  virtual ~ChromiumLogger() {
23    fclose(file_);
24  }
25  virtual void Logv(const char* format, va_list ap) {
26    const base::PlatformThreadId thread_id =
27        ::base::PlatformThread::CurrentId();
28
29    // We try twice: the first time with a fixed-size stack allocated buffer,
30    // and the second time with a much larger dynamically allocated buffer.
31    char buffer[500];
32    for (int iter = 0; iter < 2; iter++) {
33      char* base;
34      int bufsize;
35      if (iter == 0) {
36        bufsize = sizeof(buffer);
37        base = buffer;
38      } else {
39        bufsize = 30000;
40        base = new char[bufsize];
41      }
42      char* p = base;
43      char* limit = base + bufsize;
44
45      ::base::Time::Exploded t;
46      ::base::Time::Now().LocalExplode(&t);
47
48      p += ::base::snprintf(p, limit - p,
49                    "%04d/%02d/%02d-%02d:%02d:%02d.%03d %" PRIu64 " ",
50                    t.year,
51                    t.month,
52                    t.day_of_month,
53                    t.hour,
54                    t.minute,
55                    t.second,
56                    t.millisecond,
57                    static_cast<uint64>(thread_id));
58
59      // Print the message
60      if (p < limit) {
61        va_list backup_ap;
62        GG_VA_COPY(backup_ap, ap);
63        p += vsnprintf(p, limit - p, format, backup_ap);
64        va_end(backup_ap);
65      }
66
67      // Truncate to available space if necessary
68      if (p >= limit) {
69        if (iter == 0) {
70          continue;       // Try again with larger buffer
71        } else {
72          p = limit - 1;
73        }
74      }
75
76      // Add newline if necessary
77      if (p == base || p[-1] != '\n') {
78        *p++ = '\n';
79      }
80
81      assert(p <= limit);
82      fwrite(base, 1, p - base, file_);
83      fflush(file_);
84      if (base != buffer) {
85        delete[] base;
86      }
87      break;
88    }
89  }
90
91 private:
92  FILE* file_;
93};
94
95}  // namespace leveldb
96
97#endif  // THIRD_PARTY_LEVELDATABASE_CHROMIUM_LOGGER_H_
98