1 #include <u.h> 2 #include <libc.h> 3 #include "httpd.h" 4 #include "httpsrv.h" 5 6 int logall[3]; /* logall[2] is in "Common Log Format" */ 7 8 static char * 9 monname[12] = 10 { 11 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 12 }; 13 14 void 15 logit(HConnect *c, char *fmt, ...) 16 { 17 char buf[4096]; 18 va_list arg; 19 HSPriv *p; 20 21 va_start(arg, fmt); 22 vseprint(buf, buf+sizeof(buf), fmt, arg); 23 va_end(arg); 24 p = nil; 25 if(c != nil) 26 p = c->private; 27 if(p != nil && p->remotesys != nil) 28 syslog(0, HTTPLOG, "%s %s", p->remotesys, buf); 29 else 30 syslog(0, HTTPLOG, "%s", buf); 31 } 32 33 void 34 writelog(HConnect *c, char *fmt, ...) 35 { 36 HSPriv *p; 37 char buf[HBufSize+500], *bufp, *bufe; 38 char statuscode[4]; 39 vlong objectsize; 40 ulong now, today; 41 int logfd; 42 va_list arg; 43 Tm *tm; 44 45 if(c == nil) 46 return; 47 p = c->private; 48 bufe = buf + sizeof(buf); 49 now = time(nil); 50 tm = gmtime(now); 51 today = now / (24*60*60); 52 53 /* verbose logfile, for research on web traffic */ 54 logfd = logall[today & 1]; 55 if(logfd > 0){ 56 if(c->hstop == c->header || c->hstop[-1] != '\n') 57 *c->hstop = '\n'; 58 *c->hstop = '\0'; 59 bufp = seprint(buf, bufe, "==========\n"); 60 bufp = seprint(bufp, bufe, "LogTime: %D\n", now); 61 bufp = seprint(bufp, bufe, "ConnTime: %D\n", c->reqtime); 62 bufp = seprint(bufp, bufe, "RemoteIP: %s\n", p->remotesys); 63 bufp = seprint(bufp, bufe, "Port: %s\n", p->remoteserv); 64 va_start(arg, fmt); 65 bufp = vseprint(bufp, bufe, fmt, arg); 66 va_end(arg); 67 if(c->req.uri != nil && c->req.uri[0] != 0) 68 bufp = seprint(bufp, bufe, "FinalURI: %s\n", c->req.uri); 69 bufp = seprint(bufp, bufe, "----------\n%s\n", (char*)c->header); 70 write(logfd, buf, bufp-buf); /* append-only file */ 71 } 72 73 /* another log, with less information but formatted for common analysis tools */ 74 if(logall[2] > 0 && strncmp(fmt, "Reply: ", 7) == 0){ 75 objectsize = 0; 76 strecpy(statuscode, statuscode+4, fmt+7); 77 if( fmt[7] == '%'){ 78 va_start(arg, fmt); 79 vseprint(statuscode, statuscode+4, fmt+7, arg); 80 va_end(arg); 81 }else if( 82 strcmp(fmt+7, "200 file %lld %lld\n") == 0 || 83 strcmp(fmt+7, "206 partial content %lld %lld\n") == 0 || 84 strcmp(fmt+7, "206 partial content, early termination %lld %lld\n") == 0){ 85 va_start(arg, fmt); 86 objectsize = va_arg(arg, vlong); /* length in sendfd.c */ 87 objectsize = va_arg(arg, vlong); /* wrote in sendfd.c */ 88 va_end(arg); 89 } 90 bufp = seprint(buf, bufe, "%s - -", p->remotesys); 91 bufp = seprint(bufp, bufe, " [%.2d/%s/%d:%.2d:%.2d:%.2d +0000]", tm->mday, monname[tm->mon], tm->year+1900, tm->hour, tm->min, tm->sec); 92 if(c->req.uri == nil || c->req.uri[0] == 0){ 93 bufp = seprint(bufp, bufe, " \"%.*s\"", 94 (int)utfnlen((char*)c->header, strcspn((char*)c->header, "\r\n")), 95 (char*)c->header); 96 }else{ 97 /* use more canonical form of URI, if available */ 98 bufp = seprint(bufp, bufe, " \"%s %s HTTP/%d.%d\"", c->req.meth, c->req.uri, c->req.vermaj, c->req.vermin); 99 } 100 bufp = seprint(bufp, bufe, " %s %lld\n", statuscode, objectsize); 101 write(logall[2], buf, bufp-buf); /* append-only file */ 102 } 103 } 104