[4095] in BarnOwl Developers

home help back first fref pref prev next nref lref last post

Re: [barnowl/barnowl] Defer failed log messages (#109)

daemon@ATHENA.MIT.EDU (Alex Dehnert)
Sat Aug 5 21:49:19 2017

Date: Sun, 06 Aug 2017 01:49:17 +0000 (UTC)
From: Alex Dehnert <notifications@github.com>
Reply-To: barnowl/barnowl <reply+004448c9bfd795878da6b5d87261712375e76ce8b0f3591c92cf00000001159e379c92a169ce009427d1@reply.github.com>
To: barnowl/barnowl <barnowl@noreply.github.com>
Cc: Subscribed <subscribed@noreply.github.com>
In-Reply-To: <barnowl/barnowl/pull/109@github.com>

----==_mimepart_5986759c9337f_5fb73fa578401c3c90888
Content-Type: text/plain;
 charset=UTF-8
Content-Transfer-Encoding: 7bit

adehnert requested changes on this pull request.



> @@ -180,13 +226,108 @@ static void owl_log_entry_free(void *data)
   }
 }
 
+#if GLIB_CHECK_VERSION(2, 32, 0)
+#else
+static void owl_log_entry_free_gfunc(gpointer data, gpointer user_data)
+{
+  owl_log_entry_free(data);
+}
+#endif
+
+static void owl_log_file_error(owl_log_entry *msg, int ret)

I'd prefer this were called "errnum", which matches GLib and is a little clearer what it is. (I guess errno is taken by the global.)

> +  owl_log_entry_free(data);
+}
+#endif
+
+static void owl_log_file_error(owl_log_entry *msg, int ret)
+{
+  owl_log_error("Unable to open file for logging: %s (file %s)",
+                g_strerror(ret),
+                msg->filename);
+}
+
+/* If we are deferring log messages, enqueue this entry for writing.
+ * Otherwise, try to write this log message, and, if it fails with
+ * EPERM, EACCES, or ETIMEDOUT, go into deferred logging mode and
+ * queue an admin message.  If it fails with anything else, display an
+ * error message, but do not go into deferred logging mode. */

I *think* this means "and drop it on the floor", but clarifying that in the comment would be nice.

> +    } else if (ret != 0) {
+      owl_log_file_error(msg, ret);
+    }
+  }
+}
+
+/* tries to write the deferred log entries */
+static void owl_log_write_deferred_entries(gpointer data)
+{
+  owl_log_entry *entry;
+  bool drop_failed_logs = *(bool *)data;
+  int ret;
+  int logged_message_count = 0;
+  bool all_succeeded = true;
+
+  defer_logs = false;

Is this racey? It's written and read from two functions -- are they the same thread? Jason says in person that they are, but it'd be good to add a comment about that.

> +      /* Attempt to write the log entry.  If it fails, re-queue the entry at
+       * the head of the queue. */
+      owl_log_eventually_write_entry(entry);
+    } else {
+      /* Attempt to write the log entry. If it fails, print an error message,
+       * drop the log, and keep going through the queue. */
+      ret = owl_log_try_write_entry(entry);
+      if (ret != 0) {
+        all_succeeded = false;
+        owl_log_file_error(entry, ret);
+      }
+    }
+    owl_log_entry_free(entry);
+  }
+  if (all_succeeded && logged_message_count > 0 && !defer_logs) {
+    owl_log_adminmsg("Logs have been flushed and logging has resumed.");

It would be nice to report how many logs got flushed.

>    log_loop = g_main_loop_new(log_context, FALSE);
   g_main_loop_run(log_loop);
   return NULL;
 }
 
-void owl_log_init(void) 
+void owl_log_init(void)

:+1: 

> +
+use BarnOwl::Timer;
+use Exporter;
+
+our @EXPORT_OK = qw();
+
+our %EXPORT_TAGS = (all => [@EXPORT_OK]);
+
+$BarnOwl::Hooks::startup->add("BarnOwl::DeferredLogging::_register_variables");
+
+sub _register_variables {
+    my $flush_logs_interval = -1;
+    my $flush_logs_timer;
+    BarnOwl::new_variable_full('flush-logs-interval',
+        {
+            default        => -1,

I kinda wish we we could have a positive default (60 minutes? 360?), but I'm not sure how I feel about the "drop anything that fails for not-EACCES/EPERM/ETIMEDOUT" rule. I guess the prior rule was "drop anything that fails", so not so bad...?

> +    BarnOwl::new_variable_full('flush-logs-interval',
+        {
+            default        => -1,
+            summary        => 'how often should logs be flushed, in minutes',
+            description    => "If this is set to a positive value n, deferred logs \n"
+                            . "are flushed every n minutes.  If set to a negative or \n"
+                            . "zero values, deferred logs are only flushed when the \n"
+                            . "command :flush-logs is used.",
+            get_tostring   => sub { "$flush_logs_interval" },
+            set_fromstring => sub {
+                die "Expected integer" unless $_[0] =~ /^-?[0-9]+$/;
+                $flush_logs_interval = 0 + $_[0];
+                $flush_logs_timer->stop if defined $flush_logs_timer;
+                undef $flush_logs_timer;
+                if ($flush_logs_interval > 0) {
+                    $flush_logs_timer = BarnOwl::Timer->new({

I guess this is new_variable_full instead of new_variable_int because of the timer. It'd be good to note this in a comment, I think.

> +
+sub _register_variables {
+    my $flush_logs_interval = -1;
+    my $flush_logs_timer;
+    BarnOwl::new_variable_full('flush-logs-interval',
+        {
+            default        => -1,
+            summary        => 'how often should logs be flushed, in minutes',
+            description    => "If this is set to a positive value n, deferred logs \n"
+                            . "are flushed every n minutes.  If set to a negative or \n"
+                            . "zero values, deferred logs are only flushed when the \n"
+                            . "command :flush-logs is used.",
+            get_tostring   => sub { "$flush_logs_interval" },
+            set_fromstring => sub {
+                die "Expected integer" unless $_[0] =~ /^-?[0-9]+$/;
+                $flush_logs_interval = 0 + $_[0];

Is that seriously how one converts a string to an int in Perl? *sigh*

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/barnowl/barnowl/pull/109#pullrequestreview-54525291
----==_mimepart_5986759c9337f_5fb73fa578401c3c90888
Content-Type: text/html;
 charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<p><b>@adehnert</b> requested changes on this pull request.</p>

<hr>

<p>In <a href=3D"https://github.com/barnowl/barnowl/pull/109#discussion_r13=
1532257">logging.c</a>:</p>
<pre style=3D'color:#555'>&gt; @@ -180,13 +226,108 @@ static void owl_log_e=
ntry_free(void *data)
   }
 }
=20
+#if GLIB_CHECK_VERSION(2, 32, 0)
+#else
+static void owl_log_entry_free_gfunc(gpointer data, gpointer user_data)
+{
+  owl_log_entry_free(data);
+}
+#endif
+
+static void owl_log_file_error(owl_log_entry *msg, int ret)
</pre>
<p>I'd prefer this were called "errnum", which matches GLib and is a little=
 clearer what it is. (I guess errno is taken by the global.)</p>

<hr>

<p>In <a href=3D"https://github.com/barnowl/barnowl/pull/109#discussion_r13=
1532293">logging.c</a>:</p>
<pre style=3D'color:#555'>&gt; +  owl_log_entry_free(data);
+}
+#endif
+
+static void owl_log_file_error(owl_log_entry *msg, int ret)
+{
+  owl_log_error(&quot;Unable to open file for logging: %s (file %s)&quot;,
+                g_strerror(ret),
+                msg-&gt;filename);
+}
+
+/* If we are deferring log messages, enqueue this entry for writing.
+ * Otherwise, try to write this log message, and, if it fails with
+ * EPERM, EACCES, or ETIMEDOUT, go into deferred logging mode and
+ * queue an admin message.  If it fails with anything else, display an
+ * error message, but do not go into deferred logging mode. */
</pre>
<p>I <em>think</em> this means "and drop it on the floor", but clarifying t=
hat in the comment would be nice.</p>

<hr>

<p>In <a href=3D"https://github.com/barnowl/barnowl/pull/109#discussion_r13=
1532473">logging.c</a>:</p>
<pre style=3D'color:#555'>&gt; +    } else if (ret !=3D 0) {
+      owl_log_file_error(msg, ret);
+    }
+  }
+}
+
+/* tries to write the deferred log entries */
+static void owl_log_write_deferred_entries(gpointer data)
+{
+  owl_log_entry *entry;
+  bool drop_failed_logs =3D *(bool *)data;
+  int ret;
+  int logged_message_count =3D 0;
+  bool all_succeeded =3D true;
+
+  defer_logs =3D false;
</pre>
<p>Is this racey? It's written and read from two functions -- are they the =
same thread? Jason says in person that they are, but it'd be good to add a =
comment about that.</p>

<hr>

<p>In <a href=3D"https://github.com/barnowl/barnowl/pull/109#discussion_r13=
1532562">logging.c</a>:</p>
<pre style=3D'color:#555'>&gt; +      /* Attempt to write the log entry.  I=
f it fails, re-queue the entry at
+       * the head of the queue. */
+      owl_log_eventually_write_entry(entry);
+    } else {
+      /* Attempt to write the log entry. If it fails, print an error messa=
ge,
+       * drop the log, and keep going through the queue. */
+      ret =3D owl_log_try_write_entry(entry);
+      if (ret !=3D 0) {
+        all_succeeded =3D false;
+        owl_log_file_error(entry, ret);
+      }
+    }
+    owl_log_entry_free(entry);
+  }
+  if (all_succeeded &amp;&amp; logged_message_count &gt; 0 &amp;&amp; !def=
er_logs) {
+    owl_log_adminmsg(&quot;Logs have been flushed and logging has resumed.=
&quot;);
</pre>
<p>It would be nice to report how many logs got flushed.</p>

<hr>

<p>In <a href=3D"https://github.com/barnowl/barnowl/pull/109#discussion_r13=
1532615">logging.c</a>:</p>
<pre style=3D'color:#555'>&gt;    log_loop =3D g_main_loop_new(log_context,=
 FALSE);
   g_main_loop_run(log_loop);
   return NULL;
 }
=20
-void owl_log_init(void)=20
+void owl_log_init(void)
</pre>
<p><g-emoji alias=3D"+1" fallback-src=3D"https://assets-cdn.github.com/imag=
es/icons/emoji/unicode/1f44d.png" ios-version=3D"6.0">=F0=9F=91=8D</g-emoji=
></p>

<hr>

<p>In <a href=3D"https://github.com/barnowl/barnowl/pull/109#discussion_r13=
1532707">perl/lib/BarnOwl/DeferredLogging.pm</a>:</p>
<pre style=3D'color:#555'>&gt; +
+use BarnOwl::Timer;
+use Exporter;
+
+our @EXPORT_OK =3D qw();
+
+our %EXPORT_TAGS =3D (all =3D&gt; [@EXPORT_OK]);
+
+$BarnOwl::Hooks::startup-&gt;add(&quot;BarnOwl::DeferredLogging::_register=
_variables&quot;);
+
+sub _register_variables {
+    my $flush_logs_interval =3D -1;
+    my $flush_logs_timer;
+    BarnOwl::new_variable_full(&#39;flush-logs-interval&#39;,
+        {
+            default        =3D&gt; -1,
</pre>
<p>I kinda wish we we could have a positive default (60 minutes? 360?), but=
 I'm not sure how I feel about the "drop anything that fails for not-EACCES=
/EPERM/ETIMEDOUT" rule. I guess the prior rule was "drop anything that fail=
s", so not so bad...?</p>

<hr>

<p>In <a href=3D"https://github.com/barnowl/barnowl/pull/109#discussion_r13=
1532750">perl/lib/BarnOwl/DeferredLogging.pm</a>:</p>
<pre style=3D'color:#555'>&gt; +    BarnOwl::new_variable_full(&#39;flush-l=
ogs-interval&#39;,
+        {
+            default        =3D&gt; -1,
+            summary        =3D&gt; &#39;how often should logs be flushed, =
in minutes&#39;,
+            description    =3D&gt; &quot;If this is set to a positive valu=
e n, deferred logs \n&quot;
+                            . &quot;are flushed every n minutes.  If set t=
o a negative or \n&quot;
+                            . &quot;zero values, deferred logs are only fl=
ushed when the \n&quot;
+                            . &quot;command :flush-logs is used.&quot;,
+            get_tostring   =3D&gt; sub { &quot;$flush_logs_interval&quot; =
},
+            set_fromstring =3D&gt; sub {
+                die &quot;Expected integer&quot; unless $_[0] =3D~ /^-?[0-=
9]+$/;
+                $flush_logs_interval =3D 0 + $_[0];
+                $flush_logs_timer-&gt;stop if defined $flush_logs_timer;
+                undef $flush_logs_timer;
+                if ($flush_logs_interval &gt; 0) {
+                    $flush_logs_timer =3D BarnOwl::Timer-&gt;new({
</pre>
<p>I guess this is new_variable_full instead of new_variable_int because of=
 the timer. It'd be good to note this in a comment, I think.</p>

<hr>

<p>In <a href=3D"https://github.com/barnowl/barnowl/pull/109#discussion_r13=
1532755">perl/lib/BarnOwl/DeferredLogging.pm</a>:</p>
<pre style=3D'color:#555'>&gt; +
+sub _register_variables {
+    my $flush_logs_interval =3D -1;
+    my $flush_logs_timer;
+    BarnOwl::new_variable_full(&#39;flush-logs-interval&#39;,
+        {
+            default        =3D&gt; -1,
+            summary        =3D&gt; &#39;how often should logs be flushed, =
in minutes&#39;,
+            description    =3D&gt; &quot;If this is set to a positive valu=
e n, deferred logs \n&quot;
+                            . &quot;are flushed every n minutes.  If set t=
o a negative or \n&quot;
+                            . &quot;zero values, deferred logs are only fl=
ushed when the \n&quot;
+                            . &quot;command :flush-logs is used.&quot;,
+            get_tostring   =3D&gt; sub { &quot;$flush_logs_interval&quot; =
},
+            set_fromstring =3D&gt; sub {
+                die &quot;Expected integer&quot; unless $_[0] =3D~ /^-?[0-=
9]+$/;
+                $flush_logs_interval =3D 0 + $_[0];
</pre>
<p>Is that seriously how one converts a string to an int in Perl? <em>sigh<=
/em></p>

<p style=3D"font-size:small;-webkit-text-size-adjust:none;color:#666;">&mda=
sh;<br />You are receiving this because you are subscribed to this thread.<=
br />Reply to this email directly, <a href=3D"https://github.com/barnowl/ba=
rnowl/pull/109#pullrequestreview-54525291">view it on GitHub</a>, or <a hre=
f=3D"https://github.com/notifications/unsubscribe-auth/AERIyVkN6gIl5vNHPFTH=
ShD-jzQRostiks5sVRucgaJpZM4AWArI">mute the thread</a>.<img alt=3D"" height=
=3D"1" src=3D"https://github.com/notifications/beacon/AERIyRYgUFYKb9LoRfhf2=
RbV89gI708Fks5sVRucgaJpZM4AWArI.gif" width=3D"1" /></p>
<div itemscope itemtype=3D"http://schema.org/EmailMessage">
<div itemprop=3D"action" itemscope itemtype=3D"http://schema.org/ViewAction=
">
  <link itemprop=3D"url" href=3D"https://github.com/barnowl/barnowl/pull/10=
9#pullrequestreview-54525291"></link>
  <meta itemprop=3D"name" content=3D"View Pull Request"></meta>
</div>
<meta itemprop=3D"description" content=3D"View this Pull Request on GitHub"=
></meta>
</div>

<script type=3D"application/json" data-scope=3D"inboxmarkup">{"api_version"=
:"1.0","publisher":{"api_key":"05dde50f1d1a384dd78767c55493e4bb","name":"Gi=
tHub"},"entity":{"external_key":"github/barnowl/barnowl","title":"barnowl/b=
arnowl","subtitle":"GitHub repository","main_image_url":"https://cloud.gith=
ubusercontent.com/assets/143418/17495839/a5054eac-5d88-11e6-95fc-7290892c7b=
b5.png","avatar_image_url":"https://cloud.githubusercontent.com/assets/1434=
18/15842166/7c72db34-2c0b-11e6-9aed-b52498112777.png","action":{"name":"Ope=
n in GitHub","url":"https://github.com/barnowl/barnowl"}},"updates":{"snipp=
ets":[{"icon":"PERSON","message":"@adehnert requested changes on #109"}],"a=
ction":{"name":"View Pull Request","url":"https://github.com/barnowl/barnow=
l/pull/109#pullrequestreview-54525291"}}}</script>=

----==_mimepart_5986759c9337f_5fb73fa578401c3c90888--

home help back first fref pref prev next nref lref last post