1/********************************************************************
2 * Copyright (c) 2013 - 2014, Pivotal Inc.
3 * All rights reserved.
4 *
5 * Author: Zhanwei Wang
6 ********************************************************************/
7/********************************************************************
8 * 2014 -
9 * open source under Apache License Version 2.0
10 ********************************************************************/
11/**
12 * Licensed to the Apache Software Foundation (ASF) under one
13 * or more contributor license agreements. See the NOTICE file
14 * distributed with this work for additional information
15 * regarding copyright ownership. The ASF licenses this file
16 * to you under the Apache License, Version 2.0 (the
17 * "License"); you may not use this file except in compliance
18 * with the License. You may obtain a copy of the License at
19 *
20 * http://www.apache.org/licenses/LICENSE-2.0
21 *
22 * Unless required by applicable law or agreed to in writing, software
23 * distributed under the License is distributed on an "AS IS" BASIS,
24 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25 * See the License for the specific language governing permissions and
26 * limitations under the License.
27 */
28#include "platform.h"
29
30#include "Logger.h"
31
32#include <cassert>
33#include <cstdarg>
34#include <cstdio>
35#include <cstring>
36#include <sstream>
37#include <sys/time.h>
38#include <unistd.h>
39#include <vector>
40
41#include "DateTime.h"
42#include "Thread.h"
43
44namespace Hdfs {
45namespace Internal {
46
47Logger RootLogger;
48
49static mutex LoggerMutex;
50static THREAD_LOCAL once_flag Once;
51static THREAD_LOCAL char ProcessId[64];
52
53const char * SeverityName[] = { "FATAL", "ERROR", "WARNING", "INFO", "DEBUG1",
54 "DEBUG2", "DEBUG3"
55 };
56
57static void InitProcessId() {
58 std::stringstream ss;
59 ss.imbue(std::locale::classic());
60 ss << "p" << getpid() << ", th" << pthread_self();
61 snprintf(ProcessId, sizeof(ProcessId), "%s", ss.str().c_str());
62}
63
64Logger::Logger() :
65 fd(STDERR_FILENO), severity(DEFAULT_LOG_LEVEL) {
66}
67
68Logger::~Logger() {
69}
70
71void Logger::setOutputFd(int f) {
72 fd = f;
73}
74
75void Logger::setLogSeverity(LogSeverity l) {
76 severity = l;
77}
78
79void Logger::printf(LogSeverity s, const char * fmt, ...) {
80 va_list ap;
81
82 if (s > severity || fd < 0) {
83 return;
84 }
85
86 try {
87 call_once(Once, InitProcessId);
88 std::vector<char> buffer;
89 struct tm tm_time;
90 struct timeval tval;
91 memset(&tval, 0, sizeof(tval));
92 gettimeofday(&tval, NULL);
93 localtime_r(&tval.tv_sec, &tm_time);
94 //determine buffer size
95 va_start(ap, fmt);
96 int size = vsnprintf(&buffer[0], buffer.size(), fmt, ap);
97 va_end(ap);
98 //100 is enough for prefix
99 buffer.resize(size + 100);
100 size = snprintf(&buffer[0], buffer.size(), "%04d-%02d-%02d %02d:%02d:%02d.%06ld, %s, %s ", tm_time.tm_year + 1900,
101 1 + tm_time.tm_mon, tm_time.tm_mday, tm_time.tm_hour,
102 tm_time.tm_min, tm_time.tm_sec, static_cast<long>(tval.tv_usec), ProcessId, SeverityName[s]);
103 va_start(ap, fmt);
104 size += vsnprintf(&buffer[size], buffer.size() - size, fmt, ap);
105 va_end(ap);
106 lock_guard<mutex> lock(LoggerMutex);
107 dprintf(fd, "%s\n", &buffer[0]);
108 return;
109 } catch (const std::exception & e) {
110 dprintf(fd, "%s:%d %s %s", __FILE__, __LINE__,
111 "FATAL: get an unexpected exception:", e.what());
112 throw;
113 }
114}
115
116}
117}
118
119