null+****@clear*****
null+****@clear*****
2010年 12月 13日 (月) 22:54:54 JST
Tasuku SUENAGA a.k.a. gunyarakun 2010-12-13 13:54:54 +0000 (Mon, 13 Dec 2010)
New Revision: c0970b057757f3997a8087cd5b95737daeb8baff
Log:
Added a logging function to groonga-suggest-httpd.
Modified files:
src/suggest/groonga_suggest_httpd.c
Modified: src/suggest/groonga_suggest_httpd.c (+62 -10)
===================================================================
--- src/suggest/groonga_suggest_httpd.c 2010-12-09 10:21:53 +0000 (40b463a)
+++ src/suggest/groonga_suggest_httpd.c 2010-12-13 13:54:54 +0000 (5b042e4)
@@ -47,6 +47,8 @@ grn_rc grn_ctx_close(grn_ctx *ctx);
#define LISTEN_BACKLOG 756
#define MIN_MAX_FDS 2048
+#define LOG_SPLIT_LINES 1000000
+#define MAX_THREADS 128 /* max 256 */
typedef struct {
grn_ctx *ctx;
@@ -54,9 +56,13 @@ typedef struct {
void *zmq_sock;
grn_obj cmd_buf;
pthread_t thd;
+ uint32_t thread_id;
struct event_base *base;
struct evhttp *httpd;
struct event pulse;
+ const char *log_path;
+ FILE *log_file;
+ uint32_t log_count;
} thd_data;
typedef struct {
@@ -231,6 +237,9 @@ log_send(struct evbuffer *res_buf, thd_data *thd, struct evkeyvalq *get_args)
static void
cleanup_httpd_thread(thd_data *thd) {
+ if (thd->log_file) {
+ fclose(thd->log_file);
+ }
if (thd->httpd) {
evhttp_free(thd->httpd);
}
@@ -282,6 +291,37 @@ generic_handler(struct evhttp_request *req, void *arg)
}
evhttp_send_reply(req, HTTP_OK, "OK", res_buf);
evbuffer_free(res_buf);
+ /* logging */
+ {
+ if (thd->log_path) {
+ if (!thd->log_file) {
+ time_t n;
+ struct tm *t_st;
+ char p[PATH_MAX + 1];
+
+ time(&n);
+ t_st = localtime(&n);
+
+ snprintf(p, PATH_MAX, "%s%04d%02d%02d%02d%02d%02d-%02d",
+ thd->log_path,
+ t_st->tm_year + 1900, t_st->tm_mon + 1, t_st->tm_mday,
+ t_st->tm_hour, t_st->tm_min, t_st->tm_sec, thd->thread_id);
+
+ if (!(thd->log_file = fopen(p, "a"))) {
+ print_error("cannot open log_file %s.", p);
+ } else {
+ thd->log_count = 0;
+ }
+ }
+ if (thd->log_file) {
+ fprintf(thd->log_file, "%s\n", req->uri);
+ if (++thd->log_count > LOG_SPLIT_LINES) {
+ fclose(thd->log_file);
+ thd->log_file = NULL;
+ }
+ }
+ }
+ }
}
evhttp_clear_headers(&args);
}
@@ -493,15 +533,18 @@ recv_from_learner(void *arg)
static int
serve_threads(int nthreads, int port, const char *db_path, void *zmq_ctx,
- const char *send_endpoint, const char *recv_endpoint)
+ const char *send_endpoint, const char *recv_endpoint,
+ const char *log_path)
{
- int i, nfd;
+ int nfd;
+ uint32_t i;
+ thd_data thds[nthreads];
+
if ((nfd = bind_socket(port)) < 0) {
print_error("cannot bind socket. please check port number with netstat.");
return -1;
}
- thd_data thds[nthreads];
for (i = 0; i < nthreads; i++) {
memset(&thds[i], 0, sizeof(thds[i]));
if (!(thds[i].base = event_init())) {
@@ -532,6 +575,8 @@ serve_threads(int nthreads, int port, const char *db_path, void *zmq_ctx,
print_error("error in grn_db_open() on thread %d.", i);
} else {
GRN_TEXT_INIT(&(thds[i].cmd_buf), 0);
+ thds[i].log_path = log_path;
+ thds[i].thread_id = i;
evhttp_set_gencb(thds[i].httpd, generic_handler, &thds[i]);
evhttp_set_timeout(thds[i].httpd, 10);
{
@@ -607,7 +652,8 @@ usage(FILE *output)
" -p <port number> : http server port number (default: %d)\n"
" -c <thread number> : server thread number (default: %d)\n"
" -s <send endpoint> : send endpoint (ex. tcp://example.com:1234)\n"
- " -r <recv endpoint> : recv endpoint (ex. tcp://example.com:1235)\n",
+ " -r <recv endpoint> : recv endpoint (ex. tcp://example.com:1235)\n"
+ " -l <path prefix> : log path prefix\n",
DEFAULT_PORT, default_max_threads);
}
@@ -615,14 +661,14 @@ int
main(int argc, char **argv)
{
int port_no = DEFAULT_PORT;
- const char *send_endpoint = NULL, *recv_endpoint = NULL;
+ const char *send_endpoint = NULL, *recv_endpoint = NULL, *log_path = NULL;
/* check environment */
{
struct rlimit rlim;
if (!getrlimit(RLIMIT_NOFILE, &rlim)) {
if (rlim.rlim_max < MIN_MAX_FDS) {
- print_error("too small max fds. `ulimit -n`");
+ print_error("too small max fds. %d required.", MIN_MAX_FDS);
return -1;
}
rlim.rlim_cur = rlim.rlim_cur;
@@ -636,13 +682,15 @@ main(int argc, char **argv)
/* parse options */
{
int ch;
- extern char *optarg;
- extern int optind, opterr;
- while ((ch = getopt(argc, argv, "c:p:s:r:")) != -1) {
+ while ((ch = getopt(argc, argv, "c:p:s:r:l:")) != -1) {
switch(ch) {
case 'c':
default_max_threads = atoi(optarg);
+ if (default_max_threads > MAX_THREADS) {
+ print_error("too many threads. limit to %d.", MAX_THREADS);
+ default_max_threads = MAX_THREADS;
+ }
break;
case 'p':
port_no = atoi(optarg);
@@ -653,6 +701,9 @@ main(int argc, char **argv)
case 'r':
recv_endpoint = optarg;
break;
+ case 'l':
+ log_path = optarg;
+ break;
}
}
argc -= optind; argv += optind;
@@ -676,7 +727,8 @@ main(int argc, char **argv)
signal(SIGINT, signal_handler);
signal(SIGQUIT, signal_handler);
- serve_threads(default_max_threads, port_no, argv[0], zmq_ctx, send_endpoint, recv_endpoint);
+ serve_threads(default_max_threads, port_no, argv[0], zmq_ctx,
+ send_endpoint, recv_endpoint, log_path);
zmq_term(zmq_ctx);
}
grn_ctx_fin(&ctx);