Jump to content

Updating the LabVIEW Error Handling Core


crelf

Recommended Posts

I'm a slightly overweight bearded man in his mid thirties.

It could be worse... you could be a balding game-show host from the 50's with a billboard forehead, a nose that would make Pinocchio jealous, and a grin that just reeks of, "Hey kid... want a piece of candy?"

I'm not short - I'm vertically challenged.

My daughter says she's "fun sized."

Link to comment

OK - I've uploaded the presentation video in the first post in this thread here. I didn't screencapture the examples, but you should be able to see what I was talking about from the video and the code that's included.

Mediafire, for instance, seems to allow 200 MB files without even registering.

Thanks Yair - I'll try out Mediafire and see how it goes...

Link to comment
  • 1 month later...

So there's an off-list thrust in breathing some life back into this thread. If you haven't watched the presentation, and are interested in making error handling in LabVIEW better, please do so and post your thoughts. I'd like to come up with a feature list and add a timeline to it.

  • Like 1
Link to comment
  • 4 months later...
  • 3 years later...
  • 1 year later...
  • 1 year later...

So if there is any interest, I'd like to either get this thread started again or get some links to other threads or discussions. 

I have been programming in LV for about 6 years (I've been programming for over 30 years now in several languages).  I have never been really happy with LV native error handling.

I'm architecting a new, large project, leading 5 programmers, and I want to make sure we start off with a robust error system.  The project will include hardware abstraction using plug-ins, clonable modules that run independently and communicate through Request and Broadcast events (one of the broadcasts being an error event).

So I need an error handling system that encompasses the concepts of severity and priority and allows for multiple errors to be carried.  I'm intrigued by the idea of NEC-in-OO-in-NEC that was mentioned earlier in this thread and would like to explore that further.

The best thing would be some example code, but barring that, a discussion here or links to other discussions would be helpful, thanks.

I'll post next week about some of my ideas for the specifications for an error system...

Cordially,

Allen Goldstein, NIST

Link to comment

Thanks Shaun:

I'll have a look at it and get back to this thread. 

From the log image you posted it looks like it has a type, which I guess could be a priority or severity or possibly treated as, for example, a 2-nybble uint-8 with 16 priorities and 16 severities...

Link to comment

Thanks again Shaun:

I had a look and see what you are doing in the source string by formatting the codes into it.

This is not really what I'm looking for however.  Since there are multiple clones with plug-ins in my project, we may not know all the error codes at design-time.  Plug-in child classes can be made by the user and new error codes may be created after code release. I'm hoping to find something following the NI week lecture from 2009.  I'm looking for both multiple concurrent errors and priority/severity.  As I said earlier, the idea of NEC-in-OO-in-NEC is very interesting and I'm looking to see if anyone has followed up on the work started in '09.

Link to comment

Another more recent thread on the same topic you may not have seen:

To me, when I see needs like "multiple concurrent errors and priority/severity" it sounds like the real interest is in better way to report errors, not handle them. I mean, I can count on 1 hand the number of times I actually check the specific error code programmatically (TCP errors come to mind, sometimes file I/O). More often I either handle any error coming from a function or sequence of functions, or just spit it up to a log or to the user.

From that perspective, it recently occurred to me that syslog (the newer one, RFC5424) really has most everything you want in a reporting packet: source machine, source process, severity, time, general string, and a set of key-value pairs which can hold anything. Similarly you could use the existing error cluster (or the old syslog packet, RFC3164) where the message/source string is just a dynamic json object so you can add any info you want.

At one point I made a prototype of this using the variant repository and probe (using the variant as just a key-value store for things like severity, call chain, etc, and using the probe to display it)...but the conclusion I came to is the same conclusion I think everyone else came to: its just way too hard to move from the old error cluster to the new.

Link to comment
12 minutes ago, smithd said:

To me, when I see needs like "multiple concurrent errors and priority/severity" it sounds like the real interest is in better way to report errors, not handle them

Yes, that was the actual point of this thread and the 2009 NI week lecture that it was based on.  I don't think "handling" really belonged in the title of this thread...  I'm working through the example code right now and it looks kind of promising, once I wrap my head around it all, (possibly needing to do a UML diagram of both the OO-in-NEC and NEC-in-OO examples), I might take a crack at implementing the NEC-in-OO-in-NEC idea.

That other thread does look interesting, I'll look through it.

Because of the nature of my project, an application which has launched clones of stand-alone, pluggable modules, needs to know:

1) When a clone has a fatal error, so the clone can be unloaded as gracefully as possible and the launching app can decide what to do.
2) When the user needs to perform some action (for example, point to the correct file when a file is not found, or tell the program to cleanly abort the operation) in progress.
3) When some kind of parameter is input beyond it's operating range, so the system can either limit the parameter and try again, reset the operation and inform the user that the parameter must be changed before trying again.
4) When something needs to be logged but the user does not need to know (though my system also has status message broadcasts).
5) When there is an issue in a state machine such that it needs to be reset and/or the user informed of the issue.

Just a few handling examples off the top of my head.

The above discusses severity, priority is important when sorting the order in which the errors are handled.  For example, if 5 errors occurred and one of them is fatal, then that should probably be handled first,  However severity and priority do not always go hand-in-hand.

These are all handler issues, but as you say, first what is needed is a better core system.

Link to comment
7 hours ago, Argold said:

Thanks again Shaun:

I had a look and see what you are doing in the source string by formatting the codes into it.

This is not really what I'm looking for however.  Since there are multiple clones with plug-ins in my project, we may not know all the error codes at design-time.  Plug-in child classes can be made by the user and new error codes may be created after code release. I'm hoping to find something following the NI week lecture from 2009.  I'm looking for both multiple concurrent errors and priority/severity.  As I said earlier, the idea of NEC-in-OO-in-NEC is very interesting and I'm looking to see if anyone has followed up on the work started in '09.

Umm. No.

The numbers in the user source string is just so you can see which message belongs to which error otherwise you'd just have a load of starts and finishes and unable to check which write generated it.

The "priority", or "level" as it is called is the Typedef (Error, Warning, User etc). I've used 4 because that was always enough for me, although I think I will change it from a U8 field to a U64 to give 61 User level/priorities in total rather than 5. That should be enough, right?

Edited by ShaunR
Link to comment

One other concern I have with priority/severity is...well how do you decide? If you're writing application-specific code, sure its reasonable. But developing a library? Something that may be critical to you may be minor or expected from the application, so anything reporting that would have to do conversion of some kind. How do you guys handle that sort of thing?

Link to comment
45 minutes ago, smithd said:

One other concern I have with priority/severity is...well how do you decide? If you're writing application-specific code, sure its reasonable. But developing a library? Something that may be critical to you may be minor or expected from the application, so anything reporting that would have to do conversion of some kind. How do you guys handle that sort of thing?

I think you misunderstand. An API doesn't decide the meaning of a priority as such. It's just another field that you can use to group errors. The developer still decides if it's fatal, recoverable or just nice to know but he can decide to limit the granularity of written data or filter and sort it (e.g.fatal only). Think of it as categories of errors. Most APIs have a few built-in "categories" for the developer to use.

Edited by ShaunR
Link to comment

Hi Shaun,

I also see that you use Error code 0 for warnings. However most places in LabVIEW consider 0 as "No error and no warning". Warnings still have an error code, and what differentiates them from errors is the error? Boolean.

Am I mistaken?

Link to comment
1 hour ago, Manudelavega said:

Hi Shaun,

I also see that you use Error code 0 for warnings. However most places in LabVIEW consider 0 as "No error and no warning". Warnings still have an error code, and what differentiates them from errors is the error? Boolean.

Am I mistaken?

The API distinguishes between user errors and native LabVIEW errors. Since the implementation does not allow you to input user error numbers, the code number for user errors or warnings is moot and defaults to zero.This way it does not interfere with native LabVIEW errors and warnings. If you want to force an error with a specific error number then there is already a primitive to do so (Error Cluster From Error Code.vi) and the API will log it when you pass it in.

But don't get hung up on specifics. It's a an example of using a SQLite database for error logging so it isn't meant to be the ultimate silver bullet to error logging (although I don't think it is far off-it's a case of it works for me in everything so far ;) ). If you have some good ideas (like your suggestion of more levels/priorities) then maybe we can improve the example. But at the very least it is a good starting point.

Lets see how it fails your use-case and what we can do about it, eh?

Link to comment

I have attached my first take on an Error library.  TestError.vi demonstrates its use.

 

The ideas behind this are:

 

  1. The Labview native error system can only carry one error at a time, this carries an array of errors.

  2. This uses a tag for severity <sev> and a tag for priority <pri>.

    1. I decided to make the severity tag a string rather than a enum so programmers can create their own severities on the fly.  They may or may not choose to modify the error handler to accommodate these.  An enum of severities might be better, I'd like to hear what folks think.

    2. The error handler dialog has native support to the following severities:

      1. Fatal:  some applications that can be stopped dead may want to do an immediate stop on Fatal (like the native system does when you press "Stop"), other apps that must cleanly shut down can try a minimum clean shutdown)

      2. Critical: must stop but the application should do its best to cleanly exit.  A difference between a non-immediate-stop Fatal and Critical might be Fatal will evoke a minimum required shutdown while Critical can evoke a full clean shutdown)

      3. Abort: processes or state machines can be aborted (for example a state queue can be flushed) but the application can continue to run)

      4. Warning: warn the user about something and continue

      5. Inform:  like a warning but it evokes an error, not a warning.

      6. Log:  No dialog is shown but gives the programmer a chance to log the error or warning.

  3. The priority tag is used to sort multiple errors.  The ParseErrors.vi will place the lowest number priority first in the array so they can be handled first.

 

The test application is only one way to use the library, there are many other ways.  For example, in the test program, when multiple errors occur, all of them are shown to the user before the program exists or continues.   Another application may want to stop on a fatal error without trying to show the lower priority errors to the user.

 

I'd be happy to hear some critique of this.

 

Allen

ErrorLib.zip

Link to comment

Quick off-topic comment: in AddError.vi you unbundle then rebundle the 'status' and 'source' elements of the error cluster. I strongly suggest using In-Place-Element structures when you have this kind of situation, it optimizes the performances and also makes the code more readable.

Back on topic:

- I think any error or warning should always be logged as it is a very valuable source of information during troubleshooting. So maybe the 6th type of severity rather be "log only"

- Your architecture combining priority and 6 types of severity looks nice and powerful, and you coded it well, but like any "fancy" error handling architecture I'm always afraid the over-complication could lead the developers not to use or to misuse them.

I'm also in the midst of re-working the error handling in our main application (2000+ VIs) so I sympathize. It's tough! :wacko:

Link to comment
1 minute ago, Manudelavega said:

Quick off-topic comment: in AddError.vi you unbundle then rebundle the 'status' and 'source' elements of the error cluster. I strongly suggest using In-Place-Element structures when you have this kind of situation, it optimizes the performances and also makes the code more readable

I haven't looked at his code, but I want to clarify this: for unbundle/bundle, the IPE structure just enforces the "magic pattern". It doesn't add any logic behind the scenes at all. As for diagram legibility, that's subject to preference. :)

(The magic pattern is when you use unbundle by name on the same items, in the exact same order, in a path of unconditional logic (i.e. bundle node not in a case structure). If you change the order, or fail to bundle an item, or bundle an extra item, or put the bundle in a case structure the compiler will duplicate the entire cluster in order to finish the operation. If you follow the pattern, it'll update the items in-place.)

  • Like 1
Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.