From: Fabian Keil <fk@fabiankeil.de>
Date: Fri, 7 Aug 2020 09:08:23 +0000 (+0200)
Subject: Gather statistics for block reasons
X-Git-Tag: v_3_0_29~228
X-Git-Url: http://www.privoxy.org/gitweb/%22https:/@default-cgi@/faq/static/user-manual/@default-cgi@show-url-info?a=commitdiff_plain;h=92d54bfa51701a0b2b96a1b929bd9b7279b89fab;p=privoxy.git

Gather statistics for block reasons

... if FEATURE_EXTENDED_STATISTICS is enabled.

Sponsored by: Robert Klemme
---

diff --git a/actions.c b/actions.c
index a1c00f98..087f59db 100644
--- a/actions.c
+++ b/actions.c
@@ -547,6 +547,12 @@ jb_err get_actions(char *line,
                         return JB_ERR_PARSE;
                      }
                   }
+#ifdef FEATURE_EXTENDED_STATISTICS
+                  if (0 == strcmpic(action->name, "+block"))
+                  {
+                     register_block_reason_for_statistics(value);
+                  }
+#endif
                   /* FIXME: should validate option string here */
                   freez (cur_action->string[action->index]);
                   cur_action->string[action->index] = strdup(value);
diff --git a/cgisimple.c b/cgisimple.c
index 3428d81e..e738a605 100644
--- a/cgisimple.c
+++ b/cgisimple.c
@@ -1032,6 +1032,76 @@ jb_err cgi_send_user_manual(struct client_state *csp,
 
 
 #ifdef FEATURE_EXTENDED_STATISTICS
+/*********************************************************************
+ *
+ * Function    :  get_block_reason_statistics_table
+ *
+ * Description :  Produces the block reason statistic table content.
+ *
+ * Parameters  :
+ *          1  :  csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns     :  Pointer to the HTML statistic table content or
+ *                NULL on out of memory
+ *
+ *********************************************************************/
+static char *get_block_reason_statistics_table(const struct client_state *csp)
+{
+   char buf[BUFFER_SIZE];
+   char *statistics;
+   int i;
+   struct file_list *fl;
+   jb_err err = JB_ERR_OK;
+
+   statistics = strdup_or_die("");
+
+   /* Run through all action files. */
+   for (i = 0; i < MAX_AF_FILES; i++)
+   {
+      struct url_actions *b;
+      struct action_spec *last_action = NULL;
+
+      if (((fl = csp->actions_list[i]) == NULL) || ((b = fl->f) == NULL))
+      {
+         /* Skip empty files */
+         continue;
+      }
+
+      /* Go through all the actions. */
+      for (b = b->next; NULL != b; b = b->next)
+      {
+         if (last_action == b->action)
+         {
+            continue;
+         }
+         if ((b->action->add & ACTION_BLOCK))
+         {
+            unsigned long long count;
+            const char *block_reason = b->action->string[ACTION_STRING_BLOCK];
+            const char *encoded_block_reason = html_encode(block_reason);
+
+            if (encoded_block_reason == NULL)
+            {
+               freez(statistics);
+               return NULL;
+            }
+            get_block_reason_count(block_reason, &count);
+            snprintf(buf, sizeof(buf),
+               "<tr><td>%s</td><td style=\"text-align: right\">%llu</td>",
+               encoded_block_reason, count);
+            freez(encoded_block_reason);
+
+            if (!err) err = string_append(&statistics, buf);
+         }
+         last_action = b->action;
+      }
+   }
+
+   return statistics;
+
+}
+
+
 /*********************************************************************
  *
  * Function    :  get_filter_statistics_table
@@ -1094,7 +1164,7 @@ static char *get_filter_statistics_table(const struct client_state *csp)
    return statistics;
 
 }
-#endif
+#endif /* def FEATURE_EXTENDED_STATISTICS */
 
 
 /*********************************************************************
@@ -1210,6 +1280,17 @@ jb_err cgi_show_status(struct client_state *csp,
 #endif /* ndef FEATURE_STATISTICS */
 
 #ifdef FEATURE_EXTENDED_STATISTICS
+   {
+      char *block_reason_statistics = get_block_reason_statistics_table(csp);
+      if (block_reason_statistics != NULL)
+      {
+         if (!err) err = map(exports, "block-reason-statistics", 1, block_reason_statistics, 0);
+      }
+      else
+      {
+         if (!err) err = map_block_killer(exports, "extended-statistics");
+      }
+   }
    {
       char *filter_statistics = get_filter_statistics_table(csp);
       if (filter_statistics != NULL)
diff --git a/filters.c b/filters.c
index 82f79db4..0c338907 100644
--- a/filters.c
+++ b/filters.c
@@ -87,6 +87,10 @@ static void apply_url_actions(struct current_action_spec *action,
 #endif
                               struct url_actions *b);
 
+#ifdef FEATURE_EXTENDED_STATISTICS
+static void increment_block_reason_counter(const char *block_reason);
+#endif
+
 #ifdef FEATURE_ACL
 #ifdef HAVE_RFC2553
 /*********************************************************************
@@ -557,6 +561,13 @@ struct http_response *block_url(struct client_state *csp)
       return cgi_error_memory();
    }
 
+#ifdef FEATURE_EXTENDED_STATISTICS
+   if (csp->action->string[ACTION_STRING_BLOCK] != NULL)
+   {
+      increment_block_reason_counter(csp->action->string[ACTION_STRING_BLOCK]);
+   }
+#endif
+
    /*
     * If it's an image-url, send back an image or redirect
     * as specified by the relevant +image action
@@ -2897,6 +2908,136 @@ void get_filter_statistics(const char *filter, unsigned long long *executions,
 
 }
 
+
+struct block_statistics_entry
+{
+   char *block_reason;
+   unsigned long long count;
+
+   struct block_statistics_entry *next;
+};
+
+static struct block_statistics_entry *block_statistics = NULL;
+
+/*********************************************************************
+ *
+ * Function    :  register_block_reason_for_statistics
+ *
+ * Description :  Registers a block reason so we can gather statistics
+ *                for it unless the block reason has already been
+ *                registered before.
+ *
+ * Parameters  :
+ *          1  :  block_reason = Block reason to register
+ *
+ * Returns     :  void
+ *
+ *********************************************************************/
+void register_block_reason_for_statistics(const char *block_reason)
+{
+   struct block_statistics_entry *entry;
+
+   privoxy_mutex_lock(&block_statistics_mutex);
+
+   if (block_statistics == NULL)
+   {
+      block_statistics = zalloc_or_die(sizeof(struct block_statistics_entry));
+      entry = block_statistics;
+      entry->block_reason = strdup_or_die(block_reason);
+      privoxy_mutex_unlock(&block_statistics_mutex);
+      return;
+   }
+   entry = block_statistics;
+   while (entry != NULL)
+   {
+      if (!strcmp(entry->block_reason, block_reason))
+      {
+         /* Already registered, nothing to do. */
+         break;
+      }
+      if (entry->next == NULL)
+      {
+         entry->next = zalloc_or_die(sizeof(struct block_statistics_entry));
+         entry->next->block_reason = strdup_or_die(block_reason);
+         break;
+      }
+      entry = entry->next;
+   }
+
+   privoxy_mutex_unlock(&block_statistics_mutex);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function    :  increment_block_reason_counter
+ *
+ * Description :  Updates the counter for a block reason.
+ *
+ * Parameters  :
+ *          1  :  block_reason = Block reason to count
+ *
+ * Returns     :  void
+ *
+ *********************************************************************/
+static void increment_block_reason_counter(const char *block_reason)
+{
+   struct block_statistics_entry *entry;
+
+   privoxy_mutex_lock(&block_statistics_mutex);
+
+   entry = block_statistics;
+   while (entry != NULL)
+   {
+      if (!strcmp(entry->block_reason, block_reason))
+      {
+         entry->count++;
+         break;
+      }
+      entry = entry->next;
+   }
+
+   privoxy_mutex_unlock(&block_statistics_mutex);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function    :  get_block_reason_count
+ *
+ * Description :  Gets number of times a block reason was used.
+ *
+ * Parameters  :
+ *          1  :  block_reason = Block reason to get statistics for.
+ *          2  :  count = Storage for the number of times the block
+ *                        reason was used.
+ *
+ * Returns     :  void
+ *
+ *********************************************************************/
+void get_block_reason_count(const char *block_reason, unsigned long long *count)
+{
+   struct block_statistics_entry *entry;
+
+   privoxy_mutex_lock(&block_statistics_mutex);
+
+   entry = block_statistics;
+   while (entry != NULL)
+   {
+      if (!strcmp(entry->block_reason, block_reason))
+      {
+         *count = entry->count;
+         break;
+      }
+      entry = entry->next;
+   }
+
+   privoxy_mutex_unlock(&block_statistics_mutex);
+
+}
+
 #endif /* def FEATURE_EXTENDED_STATISTICS */
 
 /*
diff --git a/filters.h b/filters.h
index dcd58e21..b8004fec 100644
--- a/filters.h
+++ b/filters.h
@@ -111,6 +111,10 @@ extern void get_filter_statistics(const char *filter,
                                   unsigned long long *executions,
                                   unsigned long long *pages_modified,
                                   unsigned long long *hits);
+
+extern void register_block_reason_for_statistics(const char *block_reason);
+extern void get_block_reason_count(const char *block_reason,
+                                   unsigned long long *count);
 #endif
 
 #endif /* ndef FILTERS_H_INCLUDED */
diff --git a/jcc.c b/jcc.c
index 5846f8a2..1380100a 100644
--- a/jcc.c
+++ b/jcc.c
@@ -206,6 +206,7 @@ privoxy_mutex_t client_tags_mutex;
 #endif
 #ifdef FEATURE_EXTENDED_STATISTICS
 privoxy_mutex_t filter_statistics_mutex;
+privoxy_mutex_t block_statistics_mutex;
 #endif
 
 #if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R)
@@ -4572,6 +4573,7 @@ static void initialize_mutexes(void)
 #endif
 #ifdef FEATURE_EXTENDED_STATISTICS
    privoxy_mutex_init(&filter_statistics_mutex);
+   privoxy_mutex_init(&block_statistics_mutex);
 #endif
 
    /*
diff --git a/jcc.h b/jcc.h
index 3412ab29..ad68f42f 100644
--- a/jcc.h
+++ b/jcc.h
@@ -88,6 +88,7 @@ extern privoxy_mutex_t client_tags_mutex;
 
 #ifdef FEATURE_EXTENDED_STATISTICS
 extern privoxy_mutex_t filter_statistics_mutex;
+extern privoxy_mutex_t block_statistics_mutex;
 #endif
 
 #ifndef HAVE_GMTIME_R
diff --git a/templates/show-status b/templates/show-status
index 39f906bd..fe34b4f9 100644
--- a/templates/show-status
+++ b/templates/show-status
@@ -93,7 +93,9 @@
 #    There haven't any statistics been collected yet
 #  extended-statistics:
 #    Privoxy was compiled with extended statistiscs support.
-#    In this case the following symbol is available:
+#    In this case the following symbols are available:
+#    block-reason-statistics:
+#      Table content of block reasons and how often they were used.
 #    filter-statistics:
 #      Table content of content filter statistics.
 #  pcrs-support:
@@ -220,6 +222,14 @@
 <!-- if-statistics-end@ -->
 
 <!-- @if-extended-statistics-start -->
+    <tr>
+      <td class="box">
+        <h2>Block Reason Statistics:</h2>
+        <table summary="Statistics for block reasons" border="1">
+         <tr><th>Block reason</th><th>Count</th></tr>
+@block-reason-statistics@        </table>
+      </td>
+    </tr>
     <tr>
       <td class="box">
         <h2>Content Filter Statistics:</h2>