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