OSSL_TRACE: enhance documentation and fix doc-nit errors
[openssl.git] / doc / man3 / OSSL_trace_enabled.pod
index db3f99c89b8b6ba8e236ba14774db0c1e40601ed..958e8b063b0127cd5db70103402fb64c0a9d2cc8 100644 (file)
@@ -2,11 +2,18 @@
 
 =head1 NAME
 
-OSSL_trace_enabled, OSSL_trace_begin, OSSL_trace_end
+OSSL_trace_enabled, OSSL_trace_begin, OSSL_trace_end,
+OSSL_TRACE_BEGIN, OSSL_TRACE_END, OSSL_TRACE_CANCEL,
+OSSL_TRACE, OSSL_TRACE1, OSSL_TRACE2, OSSL_TRACE3, OSSL_TRACE4,
+OSSL_TRACE5, OSSL_TRACE6, OSSL_TRACE7, OSSL_TRACE8, OSSL_TRACE9,
+OSSL_TRACEV,
+OSSL_TRACE_ENABLED
 - OpenSSL Tracing API
 
 =head1 SYNOPSIS
 
+=for comment generic
+
  #include <openssl/trace.h>
 
  int OSSL_trace_enabled(int category);
@@ -14,6 +21,28 @@ OSSL_trace_enabled, OSSL_trace_begin, OSSL_trace_end
  BIO *OSSL_trace_begin(int category);
  void OSSL_trace_end(int category, BIO *channel);
 
+ /* trace group macros */
+ OSSL_TRACE_BEGIN(category) {
+     ...
+     if (some_error) {
+         /* Leave trace group prematurely in case of an error */
+         OSSL_TRACE_CANCEL(category);
+         goto err;
+     }
+     ...
+ } OSSL_TRACE_END(category);
+
+ /* one-shot trace macros */
+ OSSL_TRACE1(category, format, arg1)
+ OSSL_TRACE2(category, format, arg1, arg2)
+ ...
+ OSSL_TRACE9(category, format, arg1, ..., arg9)
+
+ /* check whether a trace category is enabled */
+ if (OSSL_TRACE_ENABLED(category)) {
+     ...
+ }
+
 =head1 DESCRIPTION
 
 The functions described here are mainly interesting for those who provide
@@ -27,9 +56,33 @@ The tracing output is divided into types which are enabled
 individually by the application.
 The tracing types are described in detail in
 L<OSSL_trace_set_callback(3)/Trace types>.
-The fallback type C<OSSL_TRACE_CATEGORY_ANY> should I<not> be used
+The fallback type C<OSSL_TRACE_CATEGORY_ALL> should I<not> be used
 with the functions described here.
 
+Tracing for a specific category is enabled if a so called
+I<trace channel> is attached to it. A trace channel is simply a
+BIO object to which the application can write its trace output.
+
+The application has two different ways of registering a trace channel,
+either by directly providing a BIO object using OSSL_trace_set_channel(),
+or by providing a callback routine using OSSL_trace_set_callback().
+The latter is wrapped internally by a dedicated BIO object, so for the
+tracing code both channel types are effectively indistinguishable.
+We call them a I<simple trace channel> and a I<callback trace channel>,
+respectively.
+
+To produce trace output, it is necessary to obtain a pointer to the
+trace channel (i.e., the BIO object) using OSSL_trace_begin(), write
+to it using arbitrary BIO output routines, and finally releases the
+channel using OSSL_trace_end(). The OSSL_trace_begin()/OSSL_trace_end()
+calls surrounding the trace output create a group, which acts as a
+critical section (guarded by a mutex) to ensure that the trace output
+of different threads does not get mixed up.
+
+The tracing code normally does not call OSSL_trace_{begin,end}() directly,
+but rather uses a set of convenience macros, see the L</Macros> section below.
+
+
 =head2 Functions
 
 OSSL_trace_enabled() can be used to check if tracing for the given
@@ -46,7 +99,7 @@ is I<mandatory>.
 The result of trying to produce tracing output outside of such
 sections is undefined.
 
-=head2 Convenience Macros
+=head2 Macros
 
 There are a number of convenience macros defined, to make tracing
 easy and consistent.
@@ -60,7 +113,7 @@ the B<BIO> C<trc_out> and are used as follows to wrap a trace section:
 
  } OSSL_TRACE_END(TLS);
 
-This will normally expands to:
+This will normally expand to:
 
  do {
      BIO *trc_out = OSSL_trace_begin(OSSL_TRACE_CATEGORY_TLS);
@@ -76,7 +129,7 @@ jumping out of a trace section:
 
  OSSL_TRACE_BEGIN(TLS) {
 
-     if (condition) {
+     if (some_error) {
          OSSL_TRACE_CANCEL(TLS);
          goto err;
      }
@@ -89,7 +142,7 @@ This will normally expand to:
  do {
      BIO *trc_out = OSSL_trace_begin(OSSL_TRACE_CATEGORY_TLS);
      if (trc_out != NULL) {
-         if (condition) {
+         if (some_error) {
              OSSL_trace_end(OSSL_TRACE_CATEGORY_TLS, trc_out);
              goto err;
          }
@@ -98,17 +151,72 @@ This will normally expand to:
      OSSL_trace_end(OSSL_TRACE_CATEGORY_TLS, trc_out);
  } while (0);
 
+
+C<OSSL_TRACE()> and C<OSSL_TRACE1()>, C<OSSL_TRACE2()>, ... C<OSSL_TRACE9()> are
+so-called one-shot macros:
+
+The macro call C<OSSL_TRACE(category, text)>, produces literal text trace output.
+
+The macro call C<OSSL_TRACEn(category, format, arg1, ..., argn)> produces
+printf-style trace output with n format field arguments (n=1,...,9).
+It expands to:
+
+ OSSL_TRACE_BEGIN(category) {
+     BIO_printf(trc_out, format, arg1, ..., argN)
+ } OSSL_TRACE_END(category)
+
+Internally, all one-shot macros are implemented using a generic C<OSSL_TRACEV()>
+macro, since C90 does not support variadic macros. This helper macro has a rather
+weird synopsis and should not be used directly.
+
+The C<OSSL_TRACE_ENABLED(category)> macro can be used to conditionally execute
+some code only if a specific trace category is enabled.
+In some situations this is simpler than entering a trace section using
+C<OSSL_TRACE_BEGIN(category)> and C<OSSL_TRACE_END(category)>.
+For example, the code
+
+ if (OSSL_TRACE_ENABLED(TLS)) {
+     ...
+ }
+
+expands to
+
+ if (OSSL_trace_enabled(OSSL_TRACE_CATEGORY_TLS) {
+     ...
+ }
+
 =head1 NOTES
 
-It is advisable to always check that a trace type is enabled with
-OSSL_trace_enabled() before generating any output, for example:
+If producing the trace output requires carrying out auxiliary calculations,
+this auxiliary code should be placed inside a conditional block which is
+executed only if the trace category is enabled.
+
+The most natural way to do this is to place the code inside the trace section
+itself because it already introduces such a conditional block.
+
+ OSSL_TRACE_BEGIN(TLS) {
+     int var = do_some_auxiliary_calculation();
+
+     BIO_printf(trc_out, "var = %d\n", var);
+
+ } OSSL_TRACE_END(TLS);
+
+In some cases it is more advantageous to use a simple conditional group instead
+of a trace section. This is the case if calculations and tracing happen in
+different locations of the code, or if the calculations are so time consuming
+that placing them inside a (critical) trace section would create too much
+contention.
+
+ if (OSSL_TRACE_ENABLED(TLS)) {
+     int var = do_some_auxiliary_calculation();
+
+     OSSL_TRACE1("var = %d\n", var);
+ }
 
-    if (OSSL_trace_enabled(OSSL_TRACE_CATEGORY_TLS)) {
-        BIO *trace = OSSL_trace_begin(OSSL_TRACE_CATEGORY_TLS);
-        BIO_printf(trace, "FOO %d\n", somevalue);
-        BIO_dump(trace, somememory, somememory_l);
-        OSSL_trace_end(OSSL_TRACE_CATEGORY_TLS, trace);
-    }
+Note however that premature optimization of tracing code is in general futile
+and it's better to keep the tracing code as simple as possible.
+Because most often the limiting factor for the application's speed is the time
+it takes to print the trace output, not to calculate it.
 
 =head2 Configure Tracing
 
@@ -133,7 +241,7 @@ nothing.
 =item *
 
 the convenience macros are defined to produce dead code.
-For example, take this example from L</Convenience Macros> above:
+For example, take this example from L</Macros> section above:
 
  OSSL_TRACE_BEGIN(TLS) {