Skip to content

Commit

Permalink
Even more wordsmithing on the transcript docs.
Browse files Browse the repository at this point in the history
  • Loading branch information
tshead2 committed Nov 27, 2023
1 parent 82f2112 commit 371e85c
Showing 1 changed file with 22 additions and 22 deletions.
44 changes: 22 additions & 22 deletions docs/user-guide/transcripts.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"Transcripts\n",
"===========\n",
"\n",
"In this section we extend Cicada's basic :ref:`logging` functionality to support advanced use cases including detailed debugging, function tracing, and zero-knowledge proofs. We refer to these more detailed logs as *transcripts*, and generate them using the :mod:`cicada.transcript` module.\n",
"In this section we extend Cicada's basic :ref:`logging` functionality to support advanced use cases including detailed network logging, function tracing, and zero-knowledge proofs. We refer to these more detailed logs as *transcripts*, and generate them using the :mod:`cicada.transcript` module.\n",
"\n",
".. tip::\n",
"\n",
Expand Down Expand Up @@ -161,15 +161,15 @@
"tags": []
},
"source": [
"First, we add a stream handler to the transcript logger; this will direct the transcript outputs to the console. Second, instead of the default log formatter provided by Python, we specify the custom :any:`transcript.Formatter` provided by Cicada, which can handle all of the event types that can be logged by a transcript.\n",
"First, we add a stream handler to the transcript logger; this will direct the transcript outputs to the console. Second, instead of the default log formatter provided by Python, we specify the custom :any:`transcript.Formatter` provided by Cicada, which is designed to work with the rich set of log records and custom fields generated during transcript.\n",
"\n",
".. warning::\n",
"\n",
" Transcript logging generates a rich set of log records and custom fields that require :any:`transcript.Formatter` to be output correctly ... your program will likely throw exceptions if you try to display transcript events with other formatters. For this reason, the transcript logger has propagation turned-off by default, so transcript outputs are managed separately from other, more general log messages.\n",
" Transcript logging generates many special fields that require :any:`transcript.Formatter` for correct output ... your program will likely throw exceptions if you try to display transcript events with other formatters. For this reason, the transcript logger has propagation turned-off by default, so that transcript outputs are managed separately from other, more general log messages.\n",
"\n",
"Finally, we call :any:`transcript.record` before running the rest of the program, which is necessary to begin generating the transcription.\n",
"Finally, we call :any:`transcript.record` before running the rest of the program to enable transcription.\n",
"\n",
"In the above example the transcript logger doesn't produce any output because of the :any:`transcript.HideAllFunctions` log filter, which we'll discuss shortly. In the meantime, let's produce some output by using :any:`transcript.log` to add application-specific messages to the transcript:"
"Despite all this, the above example doesn't produce any output because of the :any:`transcript.HideAllFunctions` log filter, which we'll be discussing in a moment. In the meantime, let's produce some output using :any:`transcript.log` to add application-specific messages to the transcript:"
]
},
{
Expand Down Expand Up @@ -236,7 +236,7 @@
"tags": []
},
"source": [
"Now, we see output that originates directly from our script. Messages logged by the application can provide valuable context about what the program is doing at a high level, making it much easier to understand the rest of the transcript output."
"Now, we see the output that originates directly from our script. Messages logged by the application can provide valuable context about what the program is doing at a high level, making it much easier to understand the rest of the transcript output."
]
},
{
Expand All @@ -254,7 +254,7 @@
"Message Transcripts\n",
"-------------------\n",
"\n",
"Let's continue adding events to our transcript. In some situations, you may want a detailed log of every message that Cicada sends over the network at runtime; this functionality is available using a pair of log filters, :any:`transcript.ShowSentMessages` and :any:`transcript.ShowReceivedMessages`:"
"Let's generate more output. In some situations, you may want a detailed log of every message that Cicada sends over the network at runtime; this functionality is available using a pair of log filters, :any:`transcript.ShowSentMessages` and :any:`transcript.ShowReceivedMessages`:"
]
},
{
Expand Down Expand Up @@ -349,15 +349,15 @@
"tags": []
},
"source": [
"Now, our transcript contains every message transmitted during execution. The logged events show the rank of the players sending and receiving the message, along with the message tag (message type) and payload.\n",
"Now, our transcript contains every single message transmitted by the program. The logged events show the rank of the players sending and receiving the message, along with the message type and payload.\n",
"\n",
".. admonition:: Cool trick\n",
".. admonition:: By the way ...\n",
"\n",
" If you examine the message transcript closely, you may be surprised to see that there aren't any messages sent when our program generates secret shares. How is this possible? It's because Cicada uses a cool trick - pseudorandom zero sharing - to generate additive secret shares without communication. Communication isn't necessary when adding additive secret shares either, which is why we only need to communicate when we reveal the results in this case.\n",
" If you examine the message transcript closely, you may be surprised to see that our program sends messages while setting-up secret sharing and revealing the final result, but not while generating secret shares. How can this be? It's because Cicada uses a cool trick - pseudorandom zero sharing - to generate additive secret shares without communication.\n",
"\n",
"If you want to customize the transcript, you can override the message format string for :any:`transcript.Formatter`, using a rich set of fields including `message.arrow` (message direction, relative to the local rank), `message.comm.name` (communicator name), `message.dir` (message direction, relative to the local rank), `message.dst` (message destination), `message.other` (the other player sending or receiving with the local rank), `message.payload` (message payload), `message.comm.rank` (local player), `message.src` (message source), `message.tag` (message type), and `message.verb` (\"send\" or \"receive\", depending on whether the local player is sending or receiving).\n",
"\n",
"For example, you could change the default message format to produce more compact output:"
"For example, you could override the default message format to produce more compact output:"
]
},
{
Expand Down Expand Up @@ -454,7 +454,7 @@
"tags": []
},
"source": [
"Note from the log outputs that an entry is generated both when a message is sent *and* when it's received, and that the rank of the player logging the event is always on the left, whether they are the sender or the receiver. With the arrows indicating which direction the message is travelling, this is intuitive for a person to understand, but it can make programmatically parsing the transcript needlessly difficult. As an alternative, you could adjust the format to always put the sender on the left and the recipient on the right, regardless of which player is logging the event:"
"Note from the log outputs that an entry is generated both when a message is sent *and* when it's received, and that the rank of the player logging the event is always on the left, whether they are the sender or the receiver. With the arrows indicating which direction the message is travelling, this is intuitive for a person to understand, but it can complicate programmatically parsing the transcript. As an alternative, you could use different fields to unconditionally put the sender on the left and the recipient on the right, regardless of which player is logging the event:"
]
},
{
Expand Down Expand Up @@ -552,7 +552,7 @@
"tags": []
},
"source": [
"Since this format produces two completely identical events for each message (once when the message is sent, and once when the message is received), you may wish to eliminate the duplication, e.g. by only logging messages when they're sent. As you might guess, this is simply a matter of removing the :any:`transcript.ShowReceivedMessages` filter:"
"Since this format produces two completely identical events for each message (once when the message is sent, and once when the message is received), you may wish to eliminate the duplication, e.g. by only logging messages when they're sent. As you might guess, this is a matter of simply removing the :any:`transcript.ShowReceivedMessages` filter:"
]
},
{
Expand Down Expand Up @@ -637,7 +637,7 @@
"tags": []
},
"source": [
"Of course, you could remove :any:`transcript.ShowSentMessages` instead, to show just the received messages if you prefer."
"Naturally, you could remove :any:`transcript.ShowSentMessages` instead, if you prefer to only see messages when they're received."
]
},
{
Expand All @@ -655,7 +655,7 @@
"Tracing Function Calls\n",
"----------------------\n",
"\n",
"In addition to logging application and network message events, Cicada's transcription framework can log function calls as they happen, which is why we've been using the :any:`transcript.HideAllFunctions` filter. However, we need to be cautious about removing :any:`HideAllFunctions` because unfiltered tracing will generate entries for literally *every* function call in the entire Cicada library, which is extremely noisy and could easily swamp our notebook with log output. Instead, we'll use the :any:`transcript.basic_config` function to replace :any:`HideAllFunctions` with a default set of filters tailored to achieve a reasonable balance between utility and verbosity:"
"In addition to logging application and network message events, Cicada's transcription framework can log function calls as they happen, which is why we've been using the :any:`transcript.HideAllFunctions` filter. We need to be cautious about removing :any:`HideAllFunctions` because unfiltered tracing will generate log entries for literally *every* function call in the entire Cicada library, which is extremely noisy and could easily swamp our notebook with output. Instead, we'll use the :any:`transcript.basic_config` function to replace :any:`HideAllFunctions` with a curated set of filters tailored to achieve a reasonable balance between utility and verbosity:"
]
},
{
Expand Down Expand Up @@ -818,9 +818,9 @@
"tags": []
},
"source": [
"Now, the transcript includes every notable function call made during execution of the script, along with every corresponding function return value, even for functions that don't actually return a value. The output for each call includes the arguments that were passed to the function (albeit with the `self` arguments of class methods omitted for clarity).\n",
"Now, the transcript includes notable function calls made during execution of the script, along with matching function returns. The output for each call includes the arguments that were passed to the function, but with the `self` arguments of class methods omitted for clarity.\n",
"\n",
"The log entries are indented based on stack depth, but this is difficult to follow because the output from all the players is interleaved on-screen. To address this, let's send the players' transcripts to separate files on disk instead:"
"The log entries are indented based on stack depth, but this is difficult to see because the output from all the players is interleaved on-screen. To fix this, let's send the players' transcripts to separate files on disk instead:"
]
},
{
Expand Down Expand Up @@ -1028,9 +1028,9 @@
"tags": []
},
"source": [
"With the logs separated we can follow each player's progress in detail. Notice that you can see values as they are generated and manipulated to perform calculations, and that you can see the results, even with functions like :any:`inplace_subtract` that operate inline on their arguments!\n",
"In addition to being more privacy preserving, no we can follow each player's progress in detail. Notice that you can see values as they are generated and manipulated, including function return values, even for functions like :any:`inplace_subtract` that operate on their arguments inline!\n",
"\n",
"Let's include message events alongside function calls in our transcripts. This is as simple as adding the :any:`ShowSentMessages` and :any:`ShowReceivedMessages` filters, but with one caveat - these filters *must* be added to the handler *before* any other filters, including the filters added by :any:`basic_config`:"
"Let's include message events alongside the function calls in our transcripts. This is as simple as adding the :any:`ShowSentMessages` and :any:`ShowReceivedMessages` filters, but with one caveat - these filters *must* be added to the handler *before* any other filters, which means adding them *before* the call to :any:`basic_config`:"
]
},
{
Expand Down Expand Up @@ -1239,7 +1239,7 @@
"source": [
"As expected, we now see a combination of application, message, and function call logging.\n",
"\n",
"So far, the default formatting for the transcript has been chosen for human readability, but we might want to generate a machinee-readable transcript for further analysis, such as zero knowledge proofs. Fortunately, :any:`basic_config` allows us to override the full set of format strings supported by :any:`transcript.Formatter`, so we can generate nearly any output we like. For example, let's try generating some comma-delimited output that's more easily machine-parsable:"
"So far, the default formatting for the transcript has been chosen for human readability, but we might want to generate a machine-readable transcript for further analysis, such as zero knowledge proofs. Fortunately, :any:`basic_config` allows us to override the full set of format strings supported by :any:`transcript.Formatter`, so we can generate nearly any output we like. For example, let's try generating some comma-delimited output that's more easily machine-parsable:"
]
},
{
Expand Down Expand Up @@ -1451,7 +1451,7 @@
"tags": []
},
"source": [
"This is pretty good, and should work with most delimited text parsers, including Python's :mod:`csv` module; however, the Python objects in the function call arguments and return values aren't very portable - it would be nice to convert them into something language agnostic. One option would be to use :any:`transcript.JSONArguments` to replace them with JSON representations:"
"This is pretty good, and should work with most delimited text parsers, including Python's :mod:`csv` module; however, the Python objects in the function traces aren't very portable - it might be nice to convert them into something language agnostic. One option would be to use :any:`transcript.JSONArguments` to replace them with JSON representations:"
]
},
{
Expand Down Expand Up @@ -1664,7 +1664,7 @@
"tags": []
},
"source": [
"... note that we added :any:`transcript.JSONArguments` *after* :any:`transcript.basic_config` so it only has to work with logged events that will eventually be visible.\n",
"... note that we added :any:`transcript.JSONArguments` *after* :any:`transcript.basic_config` so it doesn't waste time converting arguments for events that will be filtered-out later anyway.\n",
"\n",
"If you need to further customize the output, you have the full generality of the Python :mod:`logging` system at your fingertips. We encourage you to look at the many log filters defined in the :mod:`~cicada.transcript` module for code examples and inspiration."
]
Expand Down

0 comments on commit 371e85c

Please sign in to comment.