Exemplo n.º 1
0
static void
print_html_summary (FILE * fp, GLog * logger)
{
  char *bw, *size;
  off_t log_size;

  print_html_h2 (fp, T_HEAD, 0);
  print_html_begin_table (fp);
  print_html_begin_tbody (fp);

  print_html_begin_tr (fp, 0);
  print_html_summary_field (fp, logger->process, T_REQUESTS);
  print_html_summary_field (fp, get_ht_size (ht_unique_visitors), T_UNIQUE_VIS);
  print_html_summary_field (fp, get_ht_size (ht_referrers), T_REFERRER);

  if (!logger->piping) {
    log_size = file_size (conf.ifile);
    size = filesize_str (log_size);
  } else {
    size = alloc_string ("N/A");
  }

  bw = filesize_str ((float) logger->resp_size);
  if (conf.ifile == NULL)
    conf.ifile = (char *) "STDIN";

  fprintf (fp, "<td>%s</td><td>%s</td>", T_LOG, size);
  print_html_end_tr (fp);

  print_html_begin_tr (fp, 0);
  print_html_summary_field (fp, logger->invalid, T_F_REQUESTS);
  print_html_summary_field (fp, get_ht_size (ht_requests), T_UNIQUE_FIL);
  print_html_summary_field (fp, get_ht_size (ht_not_found_requests),
                            T_UNIQUE404);
  fprintf (fp, "<td>%s</td><td>%s</td>", T_BW, bw);
  print_html_end_tr (fp);

  print_html_begin_tr (fp, 0);
  fprintf (fp, "<td>%s</td>", T_GEN_TIME);
  fprintf (fp, "<td>%llu</td>", ((long long) end_proc - start_proc));

  print_html_summary_field (fp, get_ht_size (ht_requests_static), T_STATIC_FIL);
  fprintf (fp, "<td colspan=\"4\">%s</td>", conf.ifile);

  print_html_end_tr (fp);
  print_html_end_tbody (fp);
  print_html_end_table (fp);
  free (bw);
  free (size);
}
Exemplo n.º 2
0
/* add a first level item to dashboard */
static void
add_item_to_dash (GDash ** dash, GHolderItem item, GModule module)
{
  GDashData *idata;
  int *idx = &(*dash)->module[module].idx_data;

  idata = &(*dash)->module[module].data[(*idx)];
  idata->metrics = new_gmetrics ();

  idata->metrics->bw.sbw = filesize_str (item.metrics->bw.nbw);
  idata->metrics->data = xstrdup (item.metrics->data);
  idata->metrics->hits = item.metrics->hits;
  idata->metrics->visitors = item.metrics->visitors;

  if (conf.append_method && item.metrics->method)
    idata->metrics->method = item.metrics->method;
  if (conf.append_protocol && item.metrics->protocol)
    idata->metrics->protocol = item.metrics->protocol;
  if (conf.serve_usecs) {
    idata->metrics->avgts.sts = usecs_to_str (item.metrics->avgts.nts);
    idata->metrics->cumts.sts = usecs_to_str (item.metrics->cumts.nts);
    idata->metrics->maxts.sts = usecs_to_str (item.metrics->maxts.nts);
  }

  (*idx)++;
}
Exemplo n.º 3
0
static char *
get_str_filesize (GLog * logger, const char *ifile)
{
  if (!logger->piping && ifile != NULL)
    return filesize_str (file_size (ifile));
  else
    return alloc_string ("N/A");
}
Exemplo n.º 4
0
/* get user-agent string for given key */
char *
ht_bw_str (GHashTable * ht, const char *key)
{
   gpointer value_ptr;

   value_ptr = g_hash_table_lookup (ht, key);
   if (value_ptr != NULL)
      return filesize_str (*(unsigned long long *) value_ptr);
   else
      return alloc_string ("-");
}
Exemplo n.º 5
0
/* add a first level item to dashboard */
static void
add_item_to_dash (GDash ** dash, GHolderItem item, GModule module)
{
   int *idx = &(*dash)->module[module].idx_data;

   (*dash)->module[module].data[(*idx)].bandwidth = filesize_str (item.bw);
   (*dash)->module[module].data[(*idx)].bw = item.bw;
   (*dash)->module[module].data[(*idx)].data = xstrdup (item.data);
   (*dash)->module[module].data[(*idx)].hits = item.hits;
   if (conf.serve_usecs) {
      (*dash)->module[module].data[(*idx)].usecs = item.usecs;
      (*dash)->module[module].data[(*idx)].serve_time =
         usecs_to_str (item.usecs);
   }
   (*idx)++;
}
Exemplo n.º 6
0
/* add an item from a sub_list to the dashboard */
static void
add_sub_item_to_dash (GDash ** dash, GHolderItem item, GModule module, int *i)
{
  GSubList *sub_list = item.sub_list;
  GSubItem *iter;
  GDashData *idata;

  char *entry;
  int *idx;
  idx = &(*dash)->module[module].idx_data;

  if (sub_list == NULL)
    return;

  for (iter = sub_list->head; iter; iter = iter->next, (*i)++) {
    entry = render_child_node (iter->metrics->data);
    if (!entry)
      continue;

    idata = &(*dash)->module[module].data[(*idx)];
    idata->metrics = new_gmetrics ();

    idata->metrics->visitors = iter->metrics->visitors;
    idata->metrics->bw.sbw = filesize_str (iter->metrics->bw.nbw);
    idata->metrics->data = xstrdup (entry);
    idata->metrics->hits = iter->metrics->hits;
    if (conf.serve_usecs) {
      idata->metrics->avgts.sts = usecs_to_str (iter->metrics->avgts.nts);
      idata->metrics->cumts.sts = usecs_to_str (iter->metrics->cumts.nts);
      idata->metrics->maxts.sts = usecs_to_str (iter->metrics->maxts.nts);
    }

    idata->is_subitem = 1;
    (*idx)++;
    free (entry);
  }
}
Exemplo n.º 7
0
/* add an item from a sub_list to the dashboard */
static void
add_sub_item_to_dash (GDash ** dash, GHolderItem item, GModule module, int *i)
{
   GSubList *sub_list = item.sub_list;
   GSubItem *iter;

   char *entry;
   int *idx;
   idx = &(*dash)->module[module].idx_data;

   for (iter = sub_list->head; iter; iter = iter->next) {
      entry = render_child_node (iter->data);
      if (entry) {
         (*dash)->module[module].data[(*idx)].bandwidth =
            filesize_str (iter->bw);
         (*dash)->module[module].data[(*idx)].bw = iter->bw;
         (*dash)->module[module].data[(*idx)].data = xstrdup (entry);
         (*dash)->module[module].data[(*idx)].hits = iter->hits;
         (*dash)->module[module].data[(*idx)++].is_subitem = 1;
         free (entry);
      }
      (*i)++;
   }
}
Exemplo n.º 8
0
/* render general statistics */
void
display_general (WINDOW * win, char *ifile, GLog * logger)
{
  char *bw, *size, *log_file;
  char *failed, *not_found, *process, *ref, *req;
  char *static_files, *now, *visitors, *exclude_ip;

  int x_field = 2, x_value = 0;
  size_t n, i, j, max_field = 0, max_value = 0, mod_val, y;

  typedef struct Field_
  {
    const char *field;
    char *value;                /* char due to log, bw, log_file */
    int color;
  } Field;

  Field fields[] = {
    {T_REQUESTS, NULL, COL_CYAN},
    {T_UNIQUE_VIS, NULL, COL_CYAN},
    {T_REFERRER, NULL, COL_CYAN},
    {T_LOG, NULL, COL_CYAN},
    {T_F_REQUESTS, NULL, COL_CYAN},
    {T_UNIQUE_FIL, NULL, COL_CYAN},
    {T_UNIQUE404, NULL, COL_CYAN},
    {T_BW, NULL, COL_CYAN},
    {T_GEN_TIME, NULL, COL_CYAN},
    {T_EXCLUDE_IP, NULL, COL_CYAN},
    {T_STATIC_FIL, NULL, COL_CYAN},
    {T_LOG_PATH, NULL, COL_YELLOW}
  };

  werase (win);
  draw_header (win, T_HEAD, " %s", 0, 0, getmaxx (stdscr), 1, 0);

  if (!logger->piping && ifile != NULL) {
    size = filesize_str (file_size (ifile));
    log_file = alloc_string (ifile);
  } else {
    size = alloc_string ("N/A");
    log_file = alloc_string ("STDIN");
  }
  bw = filesize_str ((float) logger->resp_size);

  /* *INDENT-OFF* */
  failed       = int_to_str (logger->invalid);
  not_found    = int_to_str (get_ht_size (ht_not_found_requests));
  process      = int_to_str (logger->process);
  ref          = int_to_str (get_ht_size (ht_referrers));
  req          = int_to_str (get_ht_size(ht_requests));
  static_files = int_to_str (get_ht_size(ht_requests_static));
  now          = int_to_str (((long long) end_proc - start_proc));
  visitors     = int_to_str (get_ht_size(ht_unique_visitors));
  exclude_ip    = int_to_str (logger->exclude_ip);

  fields[0].value = process;
  fields[1].value = visitors;
  fields[2].value = ref;
  fields[3].value = size;
  fields[4].value = failed;
  fields[5].value = req;
  fields[6].value = not_found;
  fields[7].value = bw;
  fields[8].value = now;
  fields[9].value = exclude_ip;
  fields[10].value = static_files;
  fields[11].value = log_file;

  n = ARRAY_SIZE (fields);

  /* *INDENT-ON* */
  for (i = 0, y = 2; i < n; i++) {
    mod_val = i % 4;
    if (i > 0 && mod_val == 0) {
      max_field = 0;
      max_value = 0;
      x_field = 2;
      x_value = 2;
      y++;
    }

    x_field += max_field;
    mvwprintw (win, y, x_field, "%s", fields[i].field);

    max_field = 0;
    for (j = 0; j < n; j++) {
      size_t len = strlen (fields[j].field);
      if (j % 4 == mod_val && len > max_field)
        max_field = len;
    }

    max_value = 0;
    for (j = 0; j < n; j++) {
      size_t len = strlen (fields[j].value);
      if (j % 4 == mod_val && len > max_value)
        max_value = len;
    }
    x_value = max_field + x_field + 1;
    max_field += max_value + 2;

    wattron (win, A_BOLD | COLOR_PAIR (fields[i].color));
    mvwprintw (win, y, x_value, "%s", fields[i].value);
    wattroff (win, A_BOLD | COLOR_PAIR (fields[i].color));
  }
  for (i = 0; i < n; i++) {
    free (fields[i].value);
  }
}
Exemplo n.º 9
0
static char *
get_str_bandwidth (GLog * logger)
{
  return filesize_str ((float) logger->resp_size);
}
Exemplo n.º 10
0
/* wrapper - get human-readable bandwidth given X bytes */
char *
bandwidth_string (unsigned long long bw)
{
   return filesize_str (bw);
}
Exemplo n.º 11
0
/* render general statistics */
void
display_general (WINDOW * win, char *ifile, int piping, int processed,
                 int invalid, unsigned long long bandwidth)
{
   size_t n, i, j, max_field = 0, max_value = 0, mod_val, y;
   int x_field = 2, x_value = 0;
   char *bw, *size, *log_file;

   werase (win);

   draw_header (win, T_HEAD, 0, 0, getmaxx (stdscr), 1);

   if (!piping && ifile != NULL) {
      size = filesize_str (file_size (ifile));
      log_file = alloc_string (ifile);
   } else {
      size = alloc_string ("N/A");
      log_file = alloc_string ("STDIN");
   }
   bw = filesize_str ((float) bandwidth);

   typedef struct Field_
   {
      char *field;
      char *value;              /* char due to log, bw, log_file */
      int color;
   } Field;

   /* *INDENT-OFF* */
   char *failed       = int_to_str (invalid);
   char *not_found    = int_to_str (g_hash_table_size (ht_not_found_requests));
   char *process      = int_to_str (processed);
   char *ref          = int_to_str (g_hash_table_size (ht_referrers));
   char *req          = int_to_str (g_hash_table_size (ht_requests));
   char *static_files = int_to_str (g_hash_table_size (ht_requests_static));
   char *time         = int_to_str (((int) end_proc - start_proc));
   char *visitors     = int_to_str (g_hash_table_size (ht_unique_visitors));

   Field fields[] = {
      {T_REQUESTS,   process,           COL_CYAN},
      {T_UNIQUE_VIS, visitors,          COL_CYAN},
      {T_REFERRER,   ref,               COL_CYAN},
      {T_LOG,        size,              COL_CYAN},
      {T_F_REQUESTS, failed,            COL_CYAN},
      {T_UNIQUE_FIL, req,               COL_CYAN},
      {T_UNIQUE404,  not_found,         COL_CYAN},
      {T_BW,         bw,                COL_CYAN},
      {T_GEN_TIME,   time,              COL_CYAN},
      {T_STATIC_FIL, static_files,      COL_CYAN},
      {"",           alloc_string (""), COL_CYAN},
      {T_LOG_PATH,   log_file,          COL_YELLOW}
   };
   n = ARRAY_SIZE (fields);

   /* *INDENT-ON* */
   for (i = 0, y = 2; i < n; i++) {
      mod_val = i % 4;
      if (i > 0 && mod_val == 0) {
         max_field = 0;
         max_value = 0;
         x_field = 2;
         x_value = 2;
         y++;
      }

      x_field += max_field;
      mvwprintw (win, y, x_field, "%s", fields[i].field);

      max_field = 0;
      for (j = 0; j < n; j++) {
         size_t len = strlen (fields[j].field);
         if (j % 4 == mod_val && len > max_field)
            max_field = len;
      }

      max_value = 0;
      for (j = 0; j < n; j++) {
         size_t len = strlen (fields[j].value);
         if (j % 4 == mod_val && len > max_value)
            max_value = len;
      }
      x_value = max_field + x_field + 1;
      max_field += max_value + 2;

      wattron (win, A_BOLD | COLOR_PAIR (fields[i].color));
      mvwprintw (win, y, x_value, "%s", fields[i].value);
      wattroff (win, A_BOLD | COLOR_PAIR (fields[i].color));
   }
   for (i = 0; i < n; i++) {
      free (fields[i].value);
   }
}
Exemplo n.º 12
0
/* Get the bandwidth in a human readable format.
 *
 * On success, the bandwidth as a string is returned. */
static char *
get_str_bandwidth (GLog * glog)
{
  return filesize_str ((float) glog->resp_size);
}
Exemplo n.º 13
0
static void
print_html_request_report (FILE * fp, GHolder * h, int process)
{
#ifdef TCB_BTREE
  TCBDB *ht = NULL;
#elif TCB_MEMHASH
  TCMDB *ht = NULL;
#else
  GHashTable *ht;
#endif

  char *data, *bandwidth, *usecs;
  const char *desc = REQUE_DESC;
  const char *head = REQUE_HEAD;
  const char *id = REQUE_ID;
  float percent;
  int hits;
  int i, until = 0;

  if (h->idx == 0)
    return;

  ht = get_ht_by_module (h->module);

  if (ht == ht_requests_static) {
    head = STATI_HEAD;
    id = STATI_ID;
    desc = STATI_DESC;
  } else if (ht == ht_not_found_requests) {
    head = FOUND_HEAD;
    id = FOUND_ID;
    desc = FOUND_DESC;
  }

  print_html_h2 (fp, head, id);
  print_p (fp, desc);
  print_html_begin_table (fp);
  print_html_begin_thead (fp);

  fprintf (fp, "<tr>");
  fprintf (fp, "<th>Hits</th>");
  fprintf (fp, "<th>%%</th>");
  fprintf (fp, "<th>Bandwidth</th>");
  if (conf.serve_usecs)
    fprintf (fp, "<th>Time&nbsp;served</th>");
  if (conf.append_protocol)
    fprintf (fp, "<th>Protocol</th>");
  if (conf.append_method)
    fprintf (fp, "<th>Method</th>");
  fprintf (fp, "<th>URL<span class=\"r\" onclick=\"t(this)\">◀</span>");
  fprintf (fp, "</th>");
  fprintf (fp, "</tr>");

  print_html_end_thead (fp);
  print_html_begin_tbody (fp);

  until = h->idx < MAX_CHOICES ? h->idx : MAX_CHOICES;
  for (i = 0; i < until; i++) {
    hits = h->items[i].hits;
    data = h->items[i].data;
    percent = get_percentage (process, hits);
    percent = percent < 0 ? 0 : percent;
    bandwidth = filesize_str (h->items[i].bw);

    print_html_begin_tr (fp, i > OUTPUT_N ? 1 : 0);

    /* hits */
    fprintf (fp, "<td>%d</td>", hits);
    /* percent */
    fprintf (fp, "<td>%4.2f%%</td>", percent);
    /* bandwidth */
    fprintf (fp, "<td>");
    clean_output (fp, bandwidth);
    fprintf (fp, "</td>");

    /* usecs */
    if (conf.serve_usecs) {
      usecs = usecs_to_str (h->items[i].usecs);
      fprintf (fp, "<td>");
      clean_output (fp, usecs);
      fprintf (fp, "</td>");
      free (usecs);
    }
    /* protocol */
    if (conf.append_protocol) {
      fprintf (fp, "<td>");
      clean_output (fp, h->items[i].protocol);
      fprintf (fp, "</td>");
    }
    /* method */
    if (conf.append_method) {
      fprintf (fp, "<td>");
      clean_output (fp, h->items[i].method);
      fprintf (fp, "</td>");
    }

    /* data */
    fprintf (fp, "<td>");
    clean_output (fp, data);
    fprintf (fp, "</td>");

    print_html_end_tr (fp);

    free (bandwidth);
  }

  print_html_end_tbody (fp);
  print_html_end_table (fp);
}
Exemplo n.º 14
0
static void
print_html_hosts (FILE * fp, GHolder * h, int process)
{
  GAgents *agents;

  char *data, *bandwidth, *usecs, *ag, *ptr_value, *host;
  float percent, l;
  int hits;
  int i, j, max, until = 0, delims = 0, colspan = 6;
  size_t alloc = 0;

#ifdef HAVE_LIBGEOIP
  const char *location = NULL;
  colspan++;
#endif

  if (h->idx == 0)
    return;

  print_html_h2 (fp, HOSTS_HEAD, HOSTS_ID);
  print_p (fp, HOSTS_DESC);
  print_html_begin_table (fp);
  print_html_begin_thead (fp);

  fprintf (fp, "<tr>");
  fprintf (fp, "<th></th>");
  fprintf (fp, "<th>Hits</th>");
  fprintf (fp, "<th>%%</th>");
  fprintf (fp, "<th>Bandwidth</th>");
  if (conf.serve_usecs) {
    colspan++;
    fprintf (fp, "<th>Time&nbsp;served</th>");
  }
  fprintf (fp, "<th>IP</th>");
#ifdef HAVE_LIBGEOIP
  fprintf (fp, "<th>Country</th>");
#endif
  if (conf.enable_html_resolver) {
    colspan++;
    fprintf (fp, "<th>Hostname</th>");
  }

  fprintf (fp, "<th style=\"width:100%%;text-align:right;\">");
  fprintf (fp, "<span class=\"r\" onclick=\"t(this)\">◀</span>");
  fprintf (fp, "</th>");
  fprintf (fp, "</tr>");

  print_html_end_thead (fp);
  print_html_begin_tbody (fp);

  until = h->idx < MAX_CHOICES ? h->idx : MAX_CHOICES;
  max = 0;
  for (i = 0; i < until; i++) {
    if (h->items[i].hits > max)
      max = h->items[i].hits;
  }

  for (i = 0; i < until; i++) {
    hits = h->items[i].hits;
    data = h->items[i].data;
    percent = get_percentage (process, hits);
    percent = percent < 0 ? 0 : percent;
    bandwidth = filesize_str (h->items[i].bw);
    l = get_percentage (max, hits);
    l = l < 1 ? 1 : l;

#ifdef HAVE_LIBTOKYOCABINET
    ag = tc_db_get_str (ht_hosts_agents, data);
#else
    ag = g_hash_table_lookup (ht_hosts_agents, data);
#endif

    print_html_begin_tr (fp, i > OUTPUT_N ? 1 : 0);
    fprintf (fp, "<td>");
    if (ag != NULL)
      fprintf (fp, "<span class=\"s\" onclick=\"a(this)\">▶</span>");
    else
      fprintf (fp, "<span class=\"s\">-</span>");
    fprintf (fp, "</td>");

    fprintf (fp, "<td>%d</td>", hits);
    fprintf (fp, "<td>%4.2f%%</td>", percent);

    fprintf (fp, "<td>");
    clean_output (fp, bandwidth);
    fprintf (fp, "</td>");

    /* usecs */
    if (conf.serve_usecs) {
      usecs = usecs_to_str (h->items[i].usecs);
      fprintf (fp, "<td>");
      clean_output (fp, usecs);
      fprintf (fp, "</td>");
      free (usecs);
    }

    fprintf (fp, "<td>%s</td>", data);

#ifdef HAVE_LIBGEOIP
    location = get_geoip_data (data);
    fprintf (fp, "<td style=\"white-space:nowrap;\">%s</td>", location);
#endif

    if (conf.enable_html_resolver) {
      host = reverse_ip (data);
      fprintf (fp, "<td style=\"white-space:nowrap;\">%s</td>", host);
      free (host);
    }

    fprintf (fp, "<td class=\"graph\">");
    fprintf (fp, "<div class=\"bar\" style=\"width:%f%%\"></div>", l);
    fprintf (fp, "</td>");
    print_html_end_tr (fp);

    /* render agents for each host */
    if (ag != NULL) {
      ptr_value = (char *) ag;

      delims = count_occurrences (ptr_value, '|');
      /* round-up + padding */
      alloc = ((strlen (ptr_value) + 300 - 1) / 300) + delims + 1;
      agents = xmalloc (alloc * sizeof (GAgents));
      memset (agents, 0, alloc * sizeof (GAgents));

      /* split agents into struct */
      split_agent_str (ptr_value, agents, 300);

      fprintf (fp, "<tr class=\"agent-hide\">\n");
      fprintf (fp, "<td colspan=\"%d\">\n", colspan);
      fprintf (fp, "<div>");
      fprintf (fp, "<table class=\"pure-table-striped\">");

      /* output agents from struct */
      for (j = 0; (j < 10) && (agents[j].agents != NULL); j++) {
        print_html_begin_tr (fp, 0);
        fprintf (fp, "<td>");
        clean_output (fp, agents[j].agents);
        fprintf (fp, "</td>");
        print_html_end_tr (fp);
      }

      fprintf (fp, "</table>\n");
      fprintf (fp, "</div>\n");
      fprintf (fp, "</td>\n");
      print_html_end_tr (fp);

      for (j = 0; (agents[j].agents != NULL); j++)
        free (agents[j].agents);
      free (agents);
#ifdef HAVE_LIBTOKYOCABINET
      if (ag)
        free (ag);
#endif
    }

    free (bandwidth);
  }

  print_html_end_tbody (fp);
  print_html_end_table (fp);
}
Exemplo n.º 15
0
static void
print_html_visitors_report (FILE * fp, GHolder * h)
{
  char *data, *bandwidth, buf[DATE_LEN];
  float percent, l;
  int hits, i, max, process = get_ht_size (ht_unique_visitors);

  /* make compiler happy */
  memset (buf, 0, sizeof (buf));

  print_html_h2 (fp, VISIT_HEAD, VISIT_ID);
  print_p (fp, VISIT_DESC);
  print_html_begin_table (fp);
  print_html_begin_thead (fp);

  fprintf (fp, "<tr>");
  fprintf (fp, "<th>Visitors</th>");
  fprintf (fp, "<th>%%</th>");
  fprintf (fp, "<th>Date</th>");
  fprintf (fp, "<th>Bandwidth</th>");
  fprintf (fp, "<th style=\"width:100%%;text-align:right;\">");
  fprintf (fp, "<span class=\"r\" onclick=\"t(this)\">◀</span>");
  fprintf (fp, "</th>");
  fprintf (fp, "</tr>");

  print_html_end_thead (fp);

  print_html_begin_tbody (fp);

  max = 0;
  for (i = 0; i < h->idx; i++) {
    if (h->items[i].hits > max)
      max = h->items[i].hits;
  }
  for (i = 0; i < h->idx; i++) {
    hits = h->items[i].hits;
    data = h->items[i].data;
    percent = get_percentage (process, hits);
    percent = percent < 0 ? 0 : percent;
    bandwidth = filesize_str (h->items[i].bw);

    l = get_percentage (max, hits);
    l = l < 1 ? 1 : l;

    print_html_begin_tr (fp, i > OUTPUT_N ? 1 : 0);

    /* hits */
    fprintf (fp, "<td>%d</td>", hits);
    if (hits == max)
      fprintf (fp, "<td class=\"max\">%4.2f%%</td>", percent);
    else
      fprintf (fp, "<td>%4.2f%%</td>", percent);

    /* date */
    convert_date (buf, data, "%Y%m%d", "%d/%b/%Y", DATE_LEN);
    fprintf (fp, "<td>%s</td>", buf);

    /* bandwidth */
    fprintf (fp, "<td>");
    clean_output (fp, bandwidth);
    fprintf (fp, "</td>");

    /* bars */
    fprintf (fp, "<td class=\"graph\">");
    fprintf (fp, "<div class=\"bar\" style=\"width:%f%%\"></div>", l);
    fprintf (fp, "</td>\n");

    print_html_end_tr (fp);

    free (bandwidth);
  }

  print_html_end_tbody (fp);
  print_html_end_table (fp);
}