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
logit(HConnect * c,char * fmt,...)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
writelog(HConnect * c,char * fmt,...)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 USED(objectsize);
88 objectsize = va_arg(arg, vlong); /* wrote in sendfd.c */
89 va_end(arg);
90 }
91 bufp = seprint(buf, bufe, "%s - -", p->remotesys);
92 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);
93 if(c->req.uri == nil || c->req.uri[0] == 0){
94 bufp = seprint(bufp, bufe, " \"%.*s\"",
95 (int)utfnlen((char*)c->header, strcspn((char*)c->header, "\r\n")),
96 (char*)c->header);
97 }else{
98 /* use more canonical form of URI, if available */
99 bufp = seprint(bufp, bufe, " \"%s %s HTTP/%d.%d\"", c->req.meth, c->req.uri, c->req.vermaj, c->req.vermin);
100 }
101 bufp = seprint(bufp, bufe, " %s %lld\n", statuscode, objectsize);
102 write(logall[2], buf, bufp-buf); /* append-only file */
103 }
104 }
105