/* tinyproxy - A fast light-weight HTTP proxy * Copyright (C) 2000 Robert James Kaes * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* This module handles the statistics for tinyproxy. There are only two * public API functions. The reason for the functions, rather than just a * external structure is that tinyproxy is now multi-threaded and we can * not allow more than one child to access the statistics at the same * time. This is prevented by a mutex. If there is a need for more * statistics in the future, just add to the structure, enum (in the header), * and the switch statement in update_stats(). */ #include "main.h" #include "log.h" #include "heap.h" #include "html-error.h" #include "stats.h" #include "utils.h" #include "conf.h" #include struct stat_s { unsigned long int num_reqs; unsigned long int num_badcons; unsigned long int num_open; unsigned long int num_refused; unsigned long int num_denied; }; static struct stat_s *stats; static pthread_mutex_t stats_update_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t stats_file_lock = PTHREAD_MUTEX_INITIALIZER; /* * Initialize the statistics information to zero. */ void init_stats (void) { stats = (struct stat_s *) safemalloc (sizeof (struct stat_s)); if (!stats) return; memset (stats, 0, sizeof (struct stat_s)); } /* * Display the statics of the tinyproxy server. */ int showstats (struct conn_s *connptr) { char *message_buffer; char opens[16], reqs[16], badconns[16], denied[16], refused[16]; FILE *statfile; snprintf (opens, sizeof (opens), "%lu", stats->num_open); snprintf (reqs, sizeof (reqs), "%lu", stats->num_reqs); snprintf (badconns, sizeof (badconns), "%lu", stats->num_badcons); snprintf (denied, sizeof (denied), "%lu", stats->num_denied); snprintf (refused, sizeof (refused), "%lu", stats->num_refused); pthread_mutex_lock(&stats_file_lock); if (!config->statpage || (!(statfile = fopen (config->statpage, "r")))) { message_buffer = (char *) safemalloc (MAXBUFFSIZE); if (!message_buffer) { err_minus_one: pthread_mutex_unlock(&stats_file_lock); return -1; } snprintf (message_buffer, MAXBUFFSIZE, "\n" "\n" "\n" "%s version %s run-time statistics\n" "\n" "

%s version %s run-time statistics

\n" "

\n" "Number of open connections: %lu
\n" "Number of requests: %lu
\n" "Number of bad connections: %lu
\n" "Number of denied connections: %lu
\n" "Number of refused connections due to high load: %lu\n" "

\n" "
\n" "

Generated by %s version %s.

\n" "\n" "\n", PACKAGE, VERSION, PACKAGE, VERSION, stats->num_open, stats->num_reqs, stats->num_badcons, stats->num_denied, stats->num_refused, PACKAGE, VERSION); if (send_http_message (connptr, 200, "OK", message_buffer) < 0) { safefree (message_buffer); goto err_minus_one; } safefree (message_buffer); pthread_mutex_unlock(&stats_file_lock); return 0; } add_error_variable (connptr, "opens", opens); add_error_variable (connptr, "reqs", reqs); add_error_variable (connptr, "badconns", badconns); add_error_variable (connptr, "deniedconns", denied); add_error_variable (connptr, "refusedconns", refused); add_standard_vars (connptr); send_http_headers (connptr, 200, "Statistic requested"); send_html_file (statfile, connptr); fclose (statfile); pthread_mutex_unlock(&stats_file_lock); return 0; } /* * Update the value of the statistics. The update_level is defined in * stats.h */ int update_stats (status_t update_level) { int ret = 0; pthread_mutex_lock(&stats_update_lock); switch (update_level) { case STAT_BADCONN: ++stats->num_badcons; break; case STAT_OPEN: ++stats->num_open; ++stats->num_reqs; break; case STAT_CLOSE: --stats->num_open; break; case STAT_REFUSE: ++stats->num_refused; break; case STAT_DENIED: ++stats->num_denied; break; default: ret = -1; } pthread_mutex_unlock(&stats_update_lock); return ret; }