log.c 3.0 KB

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