codemod 2010-2016 to 2010-present
[hiphop-php.git] / hphp / runtime / server / access-log.cpp
blob908554a4265bd38b1443a4cf9c8d2239120ee635
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
16 #include "hphp/runtime/server/access-log.h"
18 #include <sstream>
19 #include <string>
20 #include <cctype>
21 #include <cstdio>
22 #include <cstdlib>
24 #include <signal.h>
25 #include <time.h>
26 #include <stdio.h>
28 #include "hphp/runtime/base/datetime.h"
29 #include "hphp/runtime/base/timestamp.h"
30 #include "hphp/runtime/base/runtime-option.h"
31 #include "hphp/runtime/server/log-writer.h"
32 #include "hphp/runtime/server/server-note.h"
33 #include "hphp/runtime/server/server-stats.h"
34 #include "hphp/runtime/server/request-uri.h"
35 #include "hphp/util/process.h"
36 #include "hphp/util/atomic.h"
37 #include "hphp/util/compatibility.h"
38 #include "hphp/util/hardware-counter.h"
39 #include "hphp/util/timer.h"
41 namespace HPHP {
42 ///////////////////////////////////////////////////////////////////////////////
43 Mutex AccessLogFileData::m_lock;
44 std::unordered_map<std::string, AccessLogFileData::factory_t>
45 AccessLogFileData::m_factories;
47 AccessLogFileData::AccessLogFileData(const std::string& fil,
48 const std::string& lnk,
49 const std::string& fmt,
50 int mpl)
51 : file(fil)
52 , symLink(lnk)
53 , format(fmt)
54 , periodMultiplier(mpl)
57 * a LogWriter with it's format can be selected between colons like:
58 * Format = :thrift: [["%{%s}t", "out-name", "STRING"], ...]
60 m_logOutputType = ClassicWriter::handle;
61 auto fmt_ = folly::StringPiece(fmt);
62 while (!fmt_.empty() && std::isspace(fmt_.front())) fmt_.pop_front();
63 if (fmt_.removePrefix(':')) {
64 size_t close = fmt_.find(':');
65 if (close != fmt_.npos) {
66 m_logOutputType = fmt_.subpiece(0, close).str();
67 fmt_.advance(close + 1);
68 format = folly::trimWhitespace(fmt_).str();
73 std::unique_ptr<LogWriter> AccessLogFileData::Writer(LogChannel chan) const {
74 Lock l(m_lock);
75 auto ifactory = m_factories.find(m_logOutputType);
76 if (ifactory != m_factories.end()) {
77 return ifactory->second(*this, chan);
79 throw std::runtime_error(
80 ("LogWriter not registered: " + m_logOutputType).c_str());
83 void AccessLogFileData::registerWriter(const std::string& handle,
84 factory_t factory) {
85 Lock l(m_lock);
86 m_factories[handle] = factory;
89 AccessLog::~AccessLog() {
90 signal(SIGCHLD, SIG_DFL);
93 void AccessLog::init(const std::string &defaultFormat,
94 std::vector<AccessLogFileData> &files,
95 const std::string &username) {
96 Lock l(m_lock);
97 if (m_initialized) return;
98 m_initialized = true;
99 m_defaultWriter =
100 AccessLogFileData("", "", defaultFormat, 0).Writer(LogChannel::THREADLOCAL);
101 m_defaultWriter->init(username, m_fGetThreadData);
102 for (auto const& file : files) {
103 auto ch = Logger::UseCronolog ? LogChannel::CRONOLOG : LogChannel::REGULAR;
104 auto writer = std::shared_ptr<LogWriter>(file.Writer(ch));
105 writer->init(username, m_fGetThreadData);
106 m_files.push_back(writer);
110 void AccessLog::init(const std::string &defaultFormat,
111 std::map<std::string, AccessLogFileData> &files,
112 const std::string &username) {
113 Lock l(m_lock);
114 if (m_initialized) return;
115 m_initialized = true;
116 m_defaultWriter =
117 AccessLogFileData("", "", defaultFormat, 0).Writer(LogChannel::THREADLOCAL);
118 m_defaultWriter->init(username, m_fGetThreadData);
119 for (auto const& file : files) {
120 auto ch = Logger::UseCronolog ? LogChannel::CRONOLOG : LogChannel::REGULAR;
121 auto writer = std::shared_ptr<LogWriter>(file.second.Writer(ch));
122 writer->init(username, m_fGetThreadData);
123 m_files.push_back(writer);
127 void AccessLog::init(const std::string &format,
128 const std::string &symLink,
129 const std::string &file,
130 const std::string &username) {
131 Lock l(m_lock);
132 if (m_initialized) return;
133 m_initialized = true;
134 m_defaultWriter =
135 AccessLogFileData("", "", format, 0).Writer(LogChannel::THREADLOCAL);
136 m_defaultWriter->init(username, m_fGetThreadData);
137 if (!file.empty() && !format.empty()) {
138 auto ch = Logger::UseCronolog ? LogChannel::CRONOLOG : LogChannel::REGULAR;
139 auto writer = std::shared_ptr<LogWriter>(
140 AccessLogFileData(file, symLink, format, 0).Writer(ch));
141 writer->init(username, m_fGetThreadData);
142 m_files.push_back(writer);
146 void AccessLog::log(Transport *transport, const VirtualHost *vhost) {
147 assert(transport);
148 if (!m_initialized) return;
149 m_defaultWriter->write(transport, vhost);
150 for (auto& file : m_files) file->write(transport, vhost);
153 void AccessLog::onNewRequest() {
154 if (!m_initialized) return;
155 ThreadData *threadData = m_fGetThreadData();
156 threadData->startTime = TimeStamp::Current();
159 void AccessLog::flushAllWriters() {
160 if (!m_initialized) return;
161 m_defaultWriter->flush();
162 for (auto& file : m_files) file->flush();
165 bool AccessLog::setThreadLog(const char *file) {
166 return (m_fGetThreadData()->log = fopen(file, "a")) != nullptr;
168 void AccessLog::clearThreadLog() {
169 FILE* &threadLog = m_fGetThreadData()->log;
170 if (threadLog) {
171 fclose(threadLog);
173 threadLog = nullptr;
176 FILE* LogWriter::getOutputFile() const {
177 FILE* outfile = nullptr;
178 switch (m_channel) {
179 case LogChannel::THREADLOCAL:
181 auto tData = (m_threadDataFn ? m_threadDataFn() : nullptr);
182 outfile = (tData ? tData->log : nullptr);
184 break;
185 case LogChannel::CRONOLOG:
186 outfile = (m_cronolog.get() ? m_cronolog->getOutputFile() : nullptr);
187 break;
188 case LogChannel::REGULAR:
189 outfile = m_filelog;
190 break;
192 return outfile;
195 void LogWriter::recordWriteAndMaybeDropCaches(FILE* out, int bytes) {
196 switch (m_channel) {
197 case LogChannel::THREADLOCAL:
199 auto tData = (m_threadDataFn ? m_threadDataFn() : nullptr);
200 if (tData) tData->flusher.recordWriteAndMaybeDropCaches(out, bytes);
202 break;
203 case LogChannel::CRONOLOG:
204 case LogChannel::REGULAR:
205 m_flusher.recordWriteAndMaybeDropCaches(out, bytes);
206 break;
210 ///////////////////////////////////////////////////////////////////////////////