Ravenbrook / Projects / Memory Pool System / Version 1.111 Product Sources / Design Documents
This document contains a guide to MPS diagnostic feedback, followed by the historical initial design. References, History, Copyright and License are at the end.
Readership: any MPS developer. Not confidential.
Diagnostic feedback is information created by the MPS diagnostic system for the purpose of helping MPS programmers and client-code programmers.
Such a piece of information is called "a diagnostic". (See also Parts of the MPS diagnostic system, below).
A diagnostic is not intended to be end-user readable (or visible), or machine-parseable. A diagnostic is not intended to be stable from one release to the next: it may be modified or removed at any time.
MPS diagnostic feedback code must do these things:
Note: the knowledge/code/logic for constructing the human-useful message is kept inside normal MPS source code. This means it is always in-sync with changes to the MPS. This also means that any external utilities used to display the messages do not need to understand, or keep in sync with, the details of what's going inside the MPS.
To run the MPS and get diagnostic output from it:
A diagnostic has three parts:
A diagnostic is emitted by the MPS at a certain point in time when a certain event happens.
Diagnostics are not nested. Every diagnostic must have a tag. Each diagnostic should have a unique tag (uniqueness is just to help the humans; the diagnostic system does not care).
The paragraph of text can be many lines long. It usually explains what event caused the diagnostic to be emitted, and commonly also includes the output of some <object>Describe() methods for various relevant objects. (For example, the TraceStart diagnostic might call, and include the output generated by, the TraceDescribe() method).
All diagnostics are emitted and then filtered according to the "diagnostic filter rules".
The first level of control is filtering by tag. (For example, only show TraceStart diagnostics).
The second level of control is filtering by paragraph content. (For example, only show TraceStart diagnostics where the trace is started because a nursery generation is full).
The third level of control is filtering by line content. (For example, only show lines containing the word "whiteSet").
See diag.c for details.
Note: the entire filtering mechanism can be turned off, so that diagnostics go immediately to mps_lib_stdout, with no buffering or filtering See diag.c#.filter-disable.
Where possible, don't put clever code into an event-triggered diagnostic: put it into a stateless <object>Describe() method instead, and then call that method when emitting your diagnostic.
For example:
FooDescribe(Foo foo, mps_lib_FILE *stream) { /* show value of new "quux" field */ WriteF(stream, "Foo: $P { quux: $U }\n", foo, foo->quux); } FooWibble(Foo foo) { ... DIAG_FIRSTF(( "FooWibble", "Wibbling foo $P", foo, NULL)); DIAG( FooDescribe(foo, DIAG_STREAM); ); DIAG_END("FooWibble"); ... }
This is much better, because other people can use your human-useful output in their diagnostics, or 'live' in a debugger.
For a simple diagnostic, use DIAG_SINGLEF. This begins the tag, puts text into the paragraph, and ends the tag immediately.
For a more complex diagnostic, the first call must be DIAG_FIRSTF, which begins a diag tag.
While a tag is current, you can add text to the diagnostic's paragraph using DIAG_MOREF, and WriteF( DIAG_STREAM, ... ).
(Note: DIAG_STREAM is not a real standard C library stream. If you want stream-level access, you may use Stream_fputc() and Stream_fputs().)
End the tag by calling DIAG_END.
Wrap non-output code with the DIAG() and DIAG_DECL() macros, to make sure that non-diag varieties do not execute diagnostic-generating code.
For complex diagnostic-generating code, it may be cleaner to move it into a separate local function. Put "_diag" on the end of the function name (eg. "TraceStart_diag()").
Obviously, diagnostic-generating code must have no side effects.
Tags should be valid C identifiers. Unless you know of a good reason why not. (Not currently checked).
There's no formal scheme for tag naming, but make it helpful and — informally — hierarchical, eg. TraceBegin, TraceStart, TraceEnd, etc. (not BeginTrace, EndTrace, ...).
IMPORTANT: Make your diagnostics easy to understand! Other people will read your diagnostics! Make them clear and helpful. Do not make them terse and cryptic. If you use symbols, print a key in the diagnostic. (If you don't want to see this the screen clutter, then you can always add a filter rule to your personal rule set to filter it out).
If you add a 'noisy' diagnostic, add a rule to the default ruleset to turn it off.
The recommended channel is WriteF to stdout.
Other possible of future channels might be:
Currently, only printf and WriteF are supported. See the DIAG_WITH_ macros in mpm.h.
You can also use a debugger to call <type>Describe() methods directly, from within the debugger.
Note: it is unfortunate that choice of channel may (for some channels) also dictate the form of the code that synthesises the message. (For example, WriteF-style parameter-expansion is not possible when using the printf channel, because there is no way to get WriteF to produce its output into a string). This is just a technical hitch; logically, the code that synthesises a diagnostic message should not care which channel will be used to transmit it out of the MPS.
The following facilities are considered part of the MPS diagnostic system:
The MPS diagnostic system is separate from the following other MPS systems:
See http://info.ravenbrook.com/mail/2007/04/13/13-07-45/0.txt: "diagnostic feedback from the MPS" by RHSK.
Diverse types of diagnostic feedback: http://info.ravenbrook.com/mail/2007/04/18/10-58-49/0.txt.
RHSK 2007-06-28
It must be possible to add, modify, or remove diagnostics to affect diagnostic varieties, without a substantial secondary effect on non-diagnostic varieties. It is not a requirement that there be zero effect.
This means:
Note: the MPS diagnostic feedback system was initially developed in mps/branch/2007-04-18/diag, mps/branch/2007-07-19/gcdiag, and mps/branch/2007-08-07/diagtag.
2007-06-28 | RHSK | Create. |
2007-06-28 | RHSK | Telemetry-log-events system is a possible channel. |
2007-06-29 | RHSK | Feedback (not output), each "a diagnostic". Parts of the system; related systems. Link to initial design email. |
2007-08-14 | RHSK | (Diag Filtering). Expand section: How to see some MPS diagnostic output, with what a diagnostic is, and how to filter it. New section: How to write a diagnostic. Various minor updates and corrections. |
This document is copyright © 2007 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.
$Id: //info.ravenbrook.com/project/mps/version/1.111/design/diag/index.html#2 $
Ravenbrook / Projects / Memory Pool System / Version 1.111 Product Sources / Design Documents