Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Warning handling in Actor Core

I apologize if someone has already brought this up on the AF community page. I'm new to this Community interface and I had trouble using the search.

In the existing applications that I maintain along with a few other developers, we make fairly frequent use of warnings. One case is DAQmx calibration notifications. We try to keep up to date on all of our hardware calibrations, which we get notifed about from the DAQmx driver by warnings. I don't have an application in mind for AF right now that would require me to handle warnings in Do.vi, but I'm the first one really diving in to AF in my group, and I know everyone else would be much more comfortable starting to use it if they knew warning handling was already in place for them. Some of the warnings we have seen came about unexpectedly and notified us of something that would have eventually become a major problem.

I don't think it's possible to override Actor Core so that warnings are always handled by Handle Error.vi. To handle warnings in Actor Core, I would have to edit my vi.lib copy to remove/modify the case structure around Handle Error.vi, which I don't want to do. The best alternative suggestion I've heard is to put something in all of your Do.vi's so that warnings get converted to errors, then have Handle Error turn them back to warnings. The problem I have with this option is that it seems to suggest creating a Message child that all of your messages inherit from, to preserve this functionality. Can Message Maker be modified to use this class instead of the Message parent?

Even if so, i'd prefer a simpler solution. Has anyone else developed a solution to handle warnings within Actor Core.vi? Is there a particular reason why Actor Core was set up to always ignore warnings?

Thanks!

Max

0 Kudos
Message 1 of 5
(4,731 Views)

Short Summary: In any method that can generate warnings, you are able to send messages to parents about the warning, store into the actor's private data the fact that the warning happened or change the warning to an error. AF doesn't care if a method produces a warning, but AF also doesn't maintain warnings iteration over iteration by design because there is no general way of accumulating warnings over time that is meaningful to all actors. In LV2012 you had to put code regarding warnings into each method that could produce those warnings, and I'm still of the opinion that is the best decision -- create a reusable subVI if you have common operations, but let each method decide what is a meaningful warning or not. In LV2013 there is a new dynamic dispatch method on Actor called "Receive Message.vi" that you could override to provide common warning handling. This method was added to support other use cases, but you could safely and correctly use it to add this kind of handling. Personally, I would advise against that approach for the reasons I lay out below.

Details: Let's first clarify what you mean by "handle warnings".

When a function generates an error, there is functionality in place to react to that error because the actor cannot do whatever it was that it was supposed to do -- it's very existence is at stake and so we can define behavior common to all Actors (or an Actor can define behavior common to all errors regardless of code). A warning indicates that the actor can continue operating normally. For Actors generally then, warnings are irrelevant. Unless a particular Actor says, "This is relevant to me," it is correct to simply ignore warnings -- which the AF generally does. So when you say "handle warnings", you can mean one of three things that I can think of:

  1. A mechanism to signal up to your caller that "something is a bit funny, just thought you should know."
  2. A mechanism to upgrade a warning to an error because whatever just happened is a bit *too* funny to keep working.
  3. You may also be seeking record that the funniness happened because if it happens repeatedly, that might become an error.
    (Note: This is different than logging to a file somewhere, which is a separate discussion entirely. I'm talking about recording the warning in the Actor's private data.)

Let's call these "alert", "escalate" and "record" respectively, just to keep the conversation clear.

For the alert case, you can obviously create a message that you send to your caller that includes the warning. But rather than sending the actor-specific warning, you more likely want to create some sort of status message that is more meaningful to the caller. For example, suppose I have a sensor actor that uses a timed loop to regularly poll a voltage and keep a running average. Now suppose that every once in a while, that actor generates a warnings about timing misses in the timed loop. The actor could tell its caller "I have timing misses". But better design would probably be to send a message that says "Data has this margin of error", without necessarily saying why that margin of error has opened up. The caller cares about the margin of error and can respond to that. The caller has no idea what to do about a timed loop miss. Notice that this is something that would be specific to one part of the sensor actor -- there probably isn't a general "warning handler" subVI that converts timing misses into estimates of error margin.

For the upgrade case, whether or not to upgrade a warning to an error almost always in my observation depends upon the particular method that generated the warning. A warning about mathematical overflow of an integer in one computation may be a critical fault, but in another is expected behavior. A central handler subVI that upgrades all such warnings to errors generally isn't useful. So, again, putting that logic inside the particular method that generates the warning seems appropriate to me.

For the record case, you can add a private data field for an array of error clusters to any actor that cares. Or just add an integer if all you care about is the number of times that a warning occurred. But it is unlikely that any particular warning accumulation is common to many actors (other than child classes of that actor). Also, unless you expect many methods to generate that warning and need to increment the count, it is more efficient to just put the warning check in the method that can generate that warning, rather than making every message handle check the error cluster. You are just wasting processor cycles most of the time.

All of these can, as I said, be done in the particular method where the warning is generated. You suggested creating a common Message ancestor to centralize this into the Do.vi. That would work. There's also the 2013 method that I mentioned in the short summary. These will give you a centralized location for this code. But I encourage you not to use either of these solutions.

Overall, I'm pretty down on centralized error handling that cares about a particular error code. Not strictly opposed to it, just that I see it as something that is easily abused and creates a bottleneck in code, particularly code edited by multiple team members. It makes it very hard to handle special case methods. I am even more opposed to centralized warning handling. For errors, it is meaningful to say, "Regardless of the error code, this is my behavior if I still have an error at this point". For any error where you care about the particular code in a general way, that needs to be something that can come out of virtually any method. For warnings, if you ignore the code, the only meaningful action is to ignore the warning. And there are no warnings I know of that are so ubiquitous as to warrant centralized code checking.

So, there you have it... information on how you can do what you want to do and advice from me personally on why not to do it. I figure that's about the best balance that an architect can offer. 🙂 Good luck.

Message 2 of 5
(3,600 Views)

thanks for the great response!

I guess we're not really concerned about "warning handling", but more about "warning logging". We plan on creating actors to talk to hardware (DAQmx/VISA), and when hardware behaves oddly it typically generates a very helpful warning alerting you of a possible problem. We've ignored warnings in the past and we've been rewarded with debugging hell and lost schedule. Our current approach is to ignore and/or handle the errors/warnings we understand and let the rest pass through to the error logger/dialog so we know about them and then adjust accordingly.

do you know of any good resource listing all of the errors/warnings each primitive can produce? it would be nice if we could address the items in that list and not discover them using trial by error...

0 Kudos
Message 3 of 5
(3,600 Views)

Are you familiar with the Error Ring (added back in around LV 2012, on the Dialog & User Interface palette)? This categorizes errors by the software that is responsible for those errors (for example, VISA errors are contained under the VISA category).  I've found this to be very useful as a starting point.  It doesn't help as much for errors that can be caused by numerous sources (such as error 7, which is used in several contexts, or such as a file I/O error that occurs inside a Sound & Vibration function), but gives you 90+% of what you're looking for.

Cheers,

Matt Pollock
National Instruments
Message 4 of 5
(3,600 Views)

soupy wrote:

do you know of any good resource listing all of the errors/warnings each primitive can produce? it would be nice if we could address the items in that list and not discover them using trial by error...

No, there is no such resource. Identifying all the errors and warnings that can be produced by a particular function turns out to be a very difficult problem for software, one LabVIEW does not have a good solution for. (If you introduce a new error in a low level primitive, how do you track every VI that calls that primitive to update the documentation?) There have been proposals for how such could be tracked, but nothing exists and tracking it by hand was so infeasible that we have essentially stopped trying. We document errors that we think are commonly hit for each individual function, but nothing systemic. Warnings are pretty much in the same boat.

Matt has already told you how to get a list of all the possible errors/warnings, but because any code may be served as either an error or a warning, it is impossible to know from that list which is which (somethings are warnings at low level functions but are upgraded to errors in higher level APIs and vice versa).

Centralized error or warning logging can be implemented in LV 2013 by overriding the Receive Message.vi. Centralized logging is less of a problem than centralized processing, but it still makes it hard to completely not log errors that your software expects and compensates for (i.e. reading the config file and getting "file not found" is not a real error, just a signal that you should use the default values for your config, but a centralized error logger may dutifully log that error on every run of your app, which over time leads to a lot of useless noise in your log file). But the centralized logging doesn't break your application's functionality the way centralized processing can, so I have less concern when people want to add it.

0 Kudos
Message 5 of 5
(3,600 Views)