Skip to content

Commit

Permalink
[Feature] Add support for %{key}C to access log format string
Browse files Browse the repository at this point in the history
Summary: As title.

Test Plan:
fast_tests TestServer

Also verified expected logs for:

% sudo hphpi -mserver -c sandbox.hdf
-vLog.AccessLogDefaultFormat='::%{c_user}C:: ::%{notpresent}C::'

Reviewers: qigao, myang

Reviewed By: qigao

CC: ps, mwilliams, qigao

Differential Revision: 328579

Task ID: 618949
  • Loading branch information
mwilliams authored and macvicar committed Sep 23, 2011
1 parent 1ab1581 commit c3fbd30
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 38 deletions.
108 changes: 71 additions & 37 deletions src/runtime/base/server/access_log.cpp
Expand Up @@ -223,6 +223,31 @@ void AccessLog::skipField(const char* &format) {
format++;
}

static void escape_data(ostringstream &out, const char *s, int len)
{
static const char digits[] = "0123456789abcdef";

for (int i = 0; i < len; i++) {
unsigned char uc = *s++;
switch (uc) {
case '"': out << "\\\""; break;
case '\\': out << "\\\\"; break;
case '\b': out << "\\b"; break;
case '\f': out << "\\f"; break;
case '\n': out << "\\n"; break;
case '\r': out << "\\r"; break;
case '\t': out << "\\t"; break;
default:
if (uc >= ' ' && (uc & 127) == uc) {
out << (char)uc;
} else {
out << "\\x" << digits[(uc >> 4) & 15] << digits[(uc >> 0) & 15];
}
break;
}
}
}

bool AccessLog::genField(ostringstream &out, const char* &format,
Transport *transport, const VirtualHost *vhost,
const string &arg) {
Expand All @@ -240,6 +265,29 @@ bool AccessLog::genField(ostringstream &out, const char* &format,
case 'B':
out << responseSize;
break;
case 'C':
if (arg.empty()) {
return false;
} else {
string cookie = transport->getCookie(arg);
if (cookie.empty()) return false;
escape_data(out, cookie.c_str(), cookie.size());
}
break;
case 'D':
{
struct timespec now;
gettime(CLOCK_MONOTONIC, &now);
out << gettime_diff_us(transport->getWallTime(), now);
}
break;
case 'd':
{
struct timespec now;
gettime(CLOCK_THREAD_CPUTIME_ID, &now);
out << gettime_diff_us(transport->getCpuTime(), now);
}
break;
case 'h':
out << transport->getRemoteHost();
break;
Expand All @@ -265,6 +313,29 @@ bool AccessLog::genField(ostringstream &out, const char* &format,
out << note.c_str();
}
break;
case 'r':
{
const char *method = NULL;
switch (transport->getMethod()) {
case Transport::GET: method = "GET"; break;
case Transport::POST: method = "POST"; break;
case Transport::HEAD: method = "HEAD"; break;
default: break;
}
if (!method) return false;
out << method << " ";

const char *url = transport->getUrl();
if (vhost && vhost->hasLogFilter()) {
out << vhost->filterUrl(url);
} else {
out << url;
}

string httpVersion = transport->getHTTPVersion();
out << " HTTP/" << httpVersion;
}
break;
case 's':
out << code;
break;
Expand Down Expand Up @@ -296,29 +367,6 @@ bool AccessLog::genField(ostringstream &out, const char* &format,
case 'T':
out << TimeStamp::Current() - m_fGetThreadData()->startTime;
break;
case 'r':
{
const char *method = NULL;
switch (transport->getMethod()) {
case Transport::GET: method = "GET"; break;
case Transport::POST: method = "POST"; break;
case Transport::HEAD: method = "HEAD"; break;
default: break;
}
if (!method) return false;
out << method << " ";

const char *url = transport->getUrl();
if (vhost && vhost->hasLogFilter()) {
out << vhost->filterUrl(url);
} else {
out << url;
}

string httpVersion = transport->getHTTPVersion();
out << " HTTP/" << httpVersion;
}
break;
case 'U':
{
String b, q;
Expand All @@ -337,20 +385,6 @@ bool AccessLog::genField(ostringstream &out, const char* &format,
}
}
break;
case 'D':
{
struct timespec now;
gettime(CLOCK_MONOTONIC, &now);
out << gettime_diff_us(transport->getWallTime(), now);
}
break;
case 'd':
{
struct timespec now;
gettime(CLOCK_THREAD_CPUTIME_ID, &now);
out << gettime_diff_us(transport->getCpuTime(), now);
}
break;
default:
return false;
}
Expand Down
19 changes: 18 additions & 1 deletion src/runtime/base/server/transport.cpp
Expand Up @@ -458,13 +458,30 @@ bool Transport::cookieExists(const char *name) {
if (hasValue) {
if (pos == header.size() || header[pos] == ';') return true;
} else {
if (header[pos] == '=') return true;
if (pos < header.size() && header[pos] == '=') return true;
}
}
}
return false;
}

string Transport::getCookie(const string &name) {
ASSERT(!name.empty());
string header = getHeader("Cookie");
for (size_t pos = header.find(name); pos != string::npos;
pos = header.find(name, pos + 1)) {
if (pos == 0 || isspace(header[pos-1]) || header[pos-1] == ';') {
pos += name.size();
if (pos < header.size() && header[pos] == '=') {
size_t end = header.find(';', pos + 1);
if (end != string::npos) end -= pos + 1;
return header.substr(pos + 1, end);
}
}
}
return "";
}

bool Transport::decideCompression() {
ASSERT(m_compressionDecision == NotDecidedYet);

Expand Down
5 changes: 5 additions & 0 deletions src/runtime/base/server/transport.h
Expand Up @@ -267,6 +267,11 @@ class Transport : public FiberSafe, public IDebuggable {
*/
bool cookieExists(const char *name);

/**
* Get value of cookie "name"
*/
std::string getCookie(const std::string &name);

/**
* Test whether client is okay to accept compressed response.
*/
Expand Down

0 comments on commit c3fbd30

Please sign in to comment.