Logging for fun and profit

Update 28-May-2022: The Toolbox provided in this original post has been updated significantly. The newer version can be downloaded from the more recent post on this topic titled “Logging tool (LogRec) suitable for tracing Action Code.”


Original post:
I have developed a moderately simple tool that allows Tinderbox users to record log entries in log books. I’m sharing this tool with the Tinderbox community via this posting, and would very much appreciate feedback and any suggestions for improvements.

In a nutshell, this document provides a function that can be called as:

LogRec(logbook,entry);

The function will append a new record containing the text provided as the “entry” argument to a Tinderbox note specified by the “logbook” argument. If the referenced logbook does not exist, it will be created and initialized on the fly.

Logging is a powerful capability that can be used for a variety of purposes. It is often used to maintain a record of events as they happen over time, or for debugging purposes. I suspect that other Tinderbox users will find the debugging aspects of logging to be especially useful since code can have calls to the LogRec() function inserted that will record the current state of variables or other data used by their code, or indications of what path has been taken within their code.

While the concept of logging is simple, it turns out that there are a lot of practical considerations that can complicate real world logging. I have tried to provide some useful enhancements that improve the utility of logging operations, yet keep things fairly simple.

In the attached Tinderbox document named “Toolbox v1a” I have included a note labeled “Logging Tools” under the “Main Document” container. This provides a comprehensive description of the complete logging package included, along with instructions on how to use this tool and associated notes, containers, and stamps. Again, I welcome feedback and suggestions for this documentation.

My aspirational objectives for sharing this logging tool are to establish a foundation for developing and sharing other tools that could be broadly useful to the Tinderbox community. In this regard, I am soliciting the following:

  • Your experiences with actually incorporating these logging tools into your documents, should you try this. I anticipate that there will be a few rough spots, and so this exercise represents an opportunity to collectively learn how best to facilitate sharing of tools and other reusable code while documenting the practices that work best.
  • Ideas/suggestions for other tools that people would find useful. Some of the community members have considerable experience with Tinderbox coding, and perhaps have tools that can be packaged up and shared. At the same time, suggestions for tools that you might have wished you had would be helpful feedback.
  • Thoughts, suggestions, practical experiences that relate to the ways that tools can be moved between documents. In many cases, this will involve more than just copying code, but will require setting up attributes, containers, prototypes, templates, stamps, etc. that will be part of the tool package.
  • Insights into what would be required to set up a repository that enables sharing of tools with each other. What guidance can offered for how to add to a repository, and also to utilize a repository in building out our Tinderbox projects.

This is an ambitious agenda, but I hope to get us started by putting forward a tool that some of you may find useful. I am willing to serve as a coordinator for efforts to build and distribute a toolbox repository.

…Chuck Wade

Toolbox v1a.tbx (214.0 KB)

7 Likes

Hi Chuck,
great and perfect logging solution - great documentation too. I’m impressed.
I would have created custom attributes instead of using $MyNumber and this line:
$MyNumber("/Core/LogBooks")=1+$MyNumber("/Core/LogBooks");
should go to the end of the function inside the if (log_stamp.size>0) condition.

If someone would like to copy the solution into an existing file - you could use the CopyAttributes solution with this function call:

createUserAttributes_db(“DatestampLogs:boolean;IndexLogs:boolean;LoggingEnabled:boolean;TimestampLogs:boolean”);

Then it is just a copy and paste of the notes from Chucks solution.

Again - thanks a lot!

Thanks for the feedback, and for the reference to your post on copying user attributes to another Tinderbox document. I had realized that passing attributes between documents was an issue that needed to be addressed for any sort of toolbox or other code sharing, and now you’ve provided an approach that addresses this problem.

There is a manual approach to activating the user attributes that come with a note/container/prototype that is copied from the Toolbox to another document, and I should have at least documented that method (an oversight). However, you’ve provided another approach that also copies default values, so I’ll be digging into your approach.

Regarding the Index number my logging tool uses as a global shared value, I made the conscious decision to not create a new attribute. By design, there is only one master log record index, and I didn’t see the need to add clutter to the list of user attributes. Since the LogRec() function depends on the existence of the “/Core/LogBooks” container, this seemed to be the logical place to keep this index, and $MyNumber is adequate for this purpose. Furthermore, this avoids any potential for conflicting with another user’s attributes.

Also, the approach I took with the log index was to make sure that the index gets incremented every time the LogRec() function is called, unless logging has been globally disabled. Gaps in displayed index sequences are not the concern, since the purpose of the index is to confirm the time order of log records. I used a single global index so that log entries could be time sequenced across multiple log books. If a user chooses to not include the index number in their log records, then I made the design decision that the index should still be incremented so that there would at least be an indication as to how many log entries were recorded.

As someone who investigates log records just about every day (and I don’t want to even think about how much of my life has been spent digging through massive volumes of log records searching for a clue to some obscure fault condition), I have a few strongly held perspectives on what is important. To me, a reliable log index that will always tell you the time order of log entries is near the top of my list of desirable features. Sadly, in the real world, this is seldom available.

Hi Chuck,

but you increment the number even if no log entry was sent - the number records only the calls of the function but not the logging itself (whatever we define as “logging” - calling the function or writing to the log). This would confuse me. Seeing gaps in the log without any idea why they are there?!

Using $MyNumber: for me the name of a variable (or attribute in TBX) is important. If I look into the “LogBooks” note I get no idea what MyNumber is representing.

But the namespace is a problem if we share our code - that the reason why I add “_db” to all my functions.

Just cross-linking to may post here about demo docs offered for general use noting their version at submission. I’ve got docs going back to v2.3.4 and the app’s changed a lot.

So, might I suggest add function to ‘log’ (add) a root note indicating current version of the doc as at saving. This can aid a later user figure if a seeming error is due to their re-use or to interim changes in Tinderbox features. Should the author update their doc, they’d then replace cor annotate//update this colophon note.

Now we have both action code functions and the notion of transferrable (code) library notes, annotation such as above might prove useful. Another useful library feature might stamp code to add to library note text a function shell with boilerplate comments indicating where to annotate input argument and return type/purpose, etc.

1 Like

You make a valid observation. I addressed this in the first sentence of the documentation included in this Toolbox “package” (see “/Main Document/Logging Tools”). However, we do need to come up with a standardized and predictable way of declaring the base (minimum?) version of Tinderbox that supports the features in the packaged application.

I thought about using the version() operator as the way to automatically retrieve the required Tinderbox version, but then realized that what is really needed is the base version, so this should probably be declared somewhere that can be easily accessed in a consistent manner. Perhaps just a note in whatever is the “Cover” top level container ("Main Document in my example) that is named something obvious like “Version Info.”

I would recommend capturing this version information:

  • Version of the provided Tinderbox document (application, utility, tool, whatever)
  • Release date for the provided Tinderbox document
  • Author name and contact info
  • Maintainer name and contact info
  • Tinderbox version used for the current release
  • Tinderbox minimum required version

I will include this in the next version of my Toolbox document so we can try it out for suitability.

There is the potential that a particular function or other type of Action code might depend on some specific Tinderbox feature that might be version specific, and thus might warrant a comment stating such. However, I think this would be more the exception than the rule if base level version info is provided for the complete document/package.

1 Like

@webline—Actually, I only increment the log Index if a log entry will be recorded. The increment comes after both the global and local log book tests for $LoggingEnabled, so if either is false, the Index will not be incremented and the call to LogRec is essential a noop (a.k.a., no operation).

My use of $MyNumber("/Core/LogBooks") as the place to store the logging Index counter is a judgement call. I took pains to document this usage in both the code and the documentation in the “/Main Document/Logging Tools” note.

The application I’m working on already has user attributes numbering in the hundreds as a necessary condition to facilitate the operation of this application. I am not terribly concerned about the overhead associated with more attributes, but I am sensitive to how cluttered this can become. Therefore, I think before adding a new user attribute to store one value in one place.

However, anyone who incorporates the logging applet/tool I have provided is welcome to fork their own version that introduces a new attribute for the logging Index, and to change where and how this index gets incremented.

sorry to disagree again - it’s no critic about your great work - just as a comment to bring in a different point of view.

You test for both the global and local log book tests for $LoggingEnabled - but at the end you have if (log_stamp.size>0) - so it is possible that you increment and log_stamp.size == 0 - no output but the number =+ 1 :wink:

@webline—Detlef, I do recognize your different perspective on this, and I will try to address this in a future update, even if all I do is document the issue.

To be clear, the conditional test for (log_stamp.size>0) is to handle the condition where the user has configured things so that neither the index nor a date-/time-stamp is being prepended to the log record with their supplied “entry.” The reason for this test is to add a visual “|” separator between any prepended text and the user-supplied log entry, but if there is no prepended text, the separator should not be inserted. However, in this case, there is still a log record being recorded with the entry provided by the calling Action code. My design decision was to continue to increment the index whenever any log entry is recorded.

So, if you turn off each of the $IndexLogs, $DatestampLogs, and $TimestampLogs switches (boolean user attributes), you can still record the user-supplied log entry, and I chose to increment the Index in such cases.

Here is a worked example using only the “Stamp Log Entry” and “Bookmark Entry” logging stamps. This illustrates that the Index increments with each log entry recorded, which is by design:

Log book <StampLog> created Tue, 18 Jan 2022 14:16:00 -0500
First log entry ($IndexLogs, $DatestampLogs, & $TimestampLogs all unchecked)
Second log entry…
***** Bookmark: Index=00003: 22-01-18 14:17 *****
Third log entry (note that bookmark shows current index of 00003)
Fourth log entry (next the $IndexLog will be checked in /Core/LogBooks)
00006 | Fifth log entry (the current index will be prepended)
00007 | Sixth log entry (Bookmark caused extra increment, so this is 00007)

I hope this clarifies my intent. This may not be what you want, but you’re free to adapt to your own use case.

1 Like

I think that bar those constrained by their current OS, I think most active users are on the current version (even if not the minor point version).

Figuring our the ‘base’ version might be hard. To avoid making aTbRef pages too dotted with “From vN.n.n, …blah…” texts, for each now major version baseline (certainly from v5 onwards) I purge all the minor release references ready for the new baseline. An unwitting error in v6-8 was to not annotate pages new to the .0.0 release. As on v9 baseline that’s now fixed. I don’t think app Help has ever captured this specific detail (no obvious need, to be fair), though if can be found indirectly by perusing release notes.

A further complication is the baseline is not as simple as action operator changes. There I are things like new data types (or changes to them) actions that act on new features, etc.

This a baseline version is perhaps a stretch but great if known). The version used to create (or version) the TBX is useful.

I am providing an updated version of this Toolbox document with some additional documentation notes. See Mark’s post below for the actual file.

Specifically, I have added:

  1. A “Logging tools Manifest” that provides version info and a complete listing of all objects and user attributes used to this package.
  2. A step-by-step guide titled “How to add logging tools to another Document” that describes in detail how to copy the logging tools into another document and the additional steps required to integrate the tools into the destination document.

I have also tweaked some comments in the code to reduce some potential ambiguity about what the code is doing.

The step-by-step guide has been thoroughly tested. However, there are other approaches to performing the integration that might be easier. I will try to test some of these other, user-provided, approaches, and will update the documentation as appropriate once I have evaluated how these work.

I welcome further comments on these changes.

2 Likes

@echuck, I think the link to the TBX got mashed somehow. No big deal :slight_smile:

Thanks for the update.

Edit: just saw your PM about the upload issue - I’ll look into it.

Here is Chuck’s revised document: Toolbox v1b.zip (1.8 MB)