Learn best practices for debugging Q-SYS plugin development with practical SDK examples and expert tips.
Key Takeaways
- Debugging is essential for quality code and supportability, though not mandatory for code to run.
- Use SDK examples as a reliable foundation for debugging implementation.
- Implement debug filters to focus on specific areas like logic flow or communication tracing.
- Always print errors openly to quickly identify issues.
- Keep debug statements clear, concise, and avoid excessive console output.
What the video covers
- Introduction to the last unused property: debugging in Q-SYS plugin development.
- Importance and challenges of debugging code for quality and verified code.
- Using SDK working code examples as a base for debugging implementation.
- Setting up debug variables and decision trees to filter debug output.
- Creating a system of filters to selectively trace logic, transmission, and reception.
- Applying debug principles systematically throughout the plugin script.
- Emphasizing printing errors without hiding them behind flags for better visibility.
- Using concise, readable debug statements to track function calls and states.
- Avoiding console spamming by skipping debug prints in frequently called helper functions.
- Final tips on debugging practices and the value of clear, filtered debug outputs.
Chapters
- 00:00Introduction to Debugging Property
- 01:44Using SDK Code Examples for Debugging
- 03:17Setting Debug Variables and Decision Trees
- 04:24Creating Debug Filters for Effective Troubleshooting
- 06:04Debug Principles and Applying Debug Statements
- 07:12Handling Errors and Debug Output Best Practices
- 11:45Avoiding Console Spam and Final Debug Tips
- 23:08Summary and Closing Remarks
Full Transcript — Download SRT & Markdown
Speaker A
All right, we're so very close to the end. If you've been keeping score at home, there is one last property that we have not yet used. Which one is that, Nate?
Speaker A
Uh, there's a hint right there. Was it debugging? This is surprisingly difficult to do.
Speaker A
Um, anyway. Yeah, debugging. We haven't used the debugging yet. One of the most tedious aspects of writing good code and in fact writing code that's going to put you on the path towards writing verified code is debugging. On the other hand, if
Speaker A
you've spent any amount of time actually working with code, you understand the inherent value of debugging. Where we're going to go is we're going to talk through a number of debugging principles and debugging actual mechanisms that we like to use from a perspective of best
Speaker A
practices coming from years of experience with CUCAs support but also from years of experience of actually administering plugins from the plugins team and in fact the SDK lays out many of the principles that we are going to be discussing here today. Now, as Nate
Speaker A
likes to say, is this necessary? Does this actually make code work? No. This really is both a quality of life thing for you, but also a quality of life sort of improvement to your code from the standpoint of support. So, with that,
Speaker A
let's dig in. Where I want to first go is I want to go back to the SDK for a couple of reasons. One, I want to recommend to you that the SDK has working code examples and anytime you
Speaker A
can see working code, you should use that as a base. So, let's do that. Let's go to the SDK. There we are. And let's go to code examples.
Speaker A
And I'm going to TCP socket because we have written a TCP socket. And I'm coming down to where we recognized right here, lines 231 to 243.
Speaker A
So I'm just going to copy all that right there straight out of the SDK. Let's go back to our code here. And up here at the top where we had our properties, we brought them in. I'm going to paste
Speaker A
those in. So let's talk about what did we just copy. We brought in from our example code three variables: debug tx, debug rx, debug function, and we set them all to be false. Right? So false because it was variable variable variable. Again,
Speaker A
that's a luism for how to do those things. Don't sweat that. Technically line 137 is what we said was line 34.
Speaker A
So, we could delete 34 or leave 34, whatever. Don't sweat it. For the sake of time, we're just going to keep rolling here. And then it opens a decision tree. If debug print is TXRX, because remember that was one of the
Speaker A
choices from the enumerated list of the properties, Nate, then set debug tx and debug rx to be true. Uh, else if debug print is TX then set debug TX to be true. If debug print is RX etc. You can
Speaker A
see how this works. No. Now why, why do this, Nate? So that when you experience issues like what I had in the previous video and you don't know what's wrong, you get a little debug window that tells you where
Speaker A
the error is because we fixed my problem. I was missing, I didn't end one of my loops [laughter] specifically. He didn't comment his ins.
Speaker A
thing that he was busting me over. He [clears throat] didn't. And it took like 10 minutes.
Speaker A
Yeah. I think more accurately I commented them too generically. I [laughter] was like, "This ends a loop." Yeah. Which loop? Nate didn't finish the other one, did you?
Speaker A
What this enables, and again, this might feel a little bit extra, but again, this is coming from having best practices bubble up to us from support and from the plugins team. It's really handy to create a system of filters. This is effectively
Speaker A
what we're doing. We already put console prints all throughout our control code. So, it was already talking to us very thoroughly because that's the way I like to write code. What this is enabling us to do is really give us filtering for
Speaker A
many of our debug prints because sometimes we're wanting to tackle an issue of, well, the logic, what functions are being called. Sometimes we want to be able to trace issues of, hey, we need to trace communications for what we are
Speaker A
transmitting or we need to trace communications for what we're receiving. This enables us to filter a little bit to see what we want to do. So from here we are systematically going to be espousing and applying a number of debug
Speaker A
principles and we have to march through the entirety of the script. No, it's tedious but it's really, really needful. So, we're going to do this and uh we're just going to plow our way through it and it's going to be okay.
Speaker A
So, you ready, Nate? No, but I'm going to do it regardless. That's generally how life works.
Speaker A
Although, you're going to find the most Nate way to follow along. All of my debugs are something happened.
Speaker A
What's the problem with that? It's very accurate. All right. First thing we're going to do is we're going to come to line 52 and our very first debug principle, right? We're going to call this principle here is that debug
Speaker A
function is for tracking logic. So far so good. So we're actually going to write a little construct like this. If debug function then we're going to print that funk set state was called.
Speaker A
And because I opened it, I'm going to close it. Now, at this point, Nate's going to look at my code and is going to probably say something snippy. Well, your debug function has a lowercase D and mine has
Speaker A
a capital D. Or do we have things that are different? Uh, I didn't spell it correctly.
Speaker A
[laughter] You are right. Then spell correctly. But that's not the snippy comment I was expecting.
Speaker A
Oh, mine worked because I did the autocomplete. You just typed it out. Yeah. I don't know what what's up with my autocomplete. It's not one.
Speaker A
It has faith that you're going to just type it properly the first time. Uh, we better hope so.
Speaker A
The snippiness you're anticipating is that you have broken style code by completing a total if statement with a then and an end in one line rather than doing it in three lines like we demand, like America demands or the world if
Speaker A
you're watching this outside of America. Yeah. One word, don't care. Tough. [laughter] Agreed. One line for debug is all we need. Let's be real. We're basically just setting a flag and printing, um, setting depending on how the flag is
Speaker A
set. This is very readable. It's very straightforward and it is a forgivable violation of the style guide. In fact, we would encourage you to just do it like this, uh, because it's just one thing and
Speaker A
again it's very readable. So, we're going to do this for every function call. So, that's going to happen a bunch. All right, but let's keep marching through looking at what else we got here. Line 56. We encountered an
Speaker A
unknown state, Nate. We sure did. What do you think we should do here? It's already being printed. What's the problem?
Speaker A
Principle. One of the principles for printing is going to be that errors should always be printed.
Speaker A
Just let it print, man. Something weird happened, we should know. We shouldn't hide that behind a flag. Just let it out. Let it go. All right. Is there anything else in funk set state? No.
Speaker A
Thank goodness. All right. So, I'm going to take this little line from line 54.
Speaker A
I'm going to put it at line 68 and I'm going to update it to say funk established connection was called. So there's that. Let's keep moving. And when I get down here to line 74.
Speaker A
Okay. Attempted to connect to. Yeah. Okay. So that's good. Uh, you know what we'll do? We'll just wrap it also in a debug function. That's fine. So line 74, because we opened it, we're going to close it.
Speaker A
And what about line 76? We're going to let it ride. Something went wrong. Tell me about it. Just tell me as quickly as possible. That's fine.
Speaker A
Let's keep moving. All right. Copy all of that. Move down here to funk send to device. Put that in there and update it to tell me that it was called. So funk send to device was called.
Speaker A
Now line 84. What do you think we should do about line 84, Nate? Delete it.
Speaker A
Delete it for sure. New principle: debug tx is for tracing comms. Tracing comms. So, we're gonna take a very similar approach.
Speaker A
Sync comms. I have no i
Speaker A
You've got a C instead of a G in tracing comms. And there are very few things I have left to be able to one up you on in the depths of this code. So, I'm going to be on top of every spelling error.
Speaker A
It's been a long day for y'all. And y'all are watching this probably at 2x speed. It's been a long day for us.
Speaker A
We're do we're operating it at 01 speed. Okay. [snorts] Line 84. Yeah. Debug tx. We're going to say that debugtx is for when we are talking. We want to know about that. So if I am sending to the device, I want to know about it.
Speaker A
All right. I see. I see. Okay. We're going to keep moving as quickly as possible. Otherwise, everyone will indeed fall asleep in this video.
Speaker A
All right. Again, right off the bat, we have an if debug function. And then we keep moving along. We have a print on line 96. Oops, that looks like an error.
Speaker A
Let it Let it ride. Line 100. Invalid command type. That looks like an error.
Speaker A
Let it ride. Any more prints? No. Thank goodness. Okay, let's keep removing. All right. Funk parse, our friend. Funk parse. Let that do its thing. So, if debug function, then print that funk parse was found.
Speaker A
Um, line 116. You know what? We're going to wrap it up as well. And because we opened it, we're going to close it. But this one's a little bit different, isn't it, Nate? Uh, it found some it received a good string.
Speaker A
Well, line 116 is different because we are receiving something. Yeah, that's not and that's not a debug tx right?
Speaker A
This won't be a TX. It'll be an RX, which we establish is one of the possible things. Debbt TX, debug RX or debug function.
Speaker A
Yeah. So, we're going to make this one, we're going to make line 116 be if debug RX, then print, hey, we received this stuff.
Speaker A
Yeah. Uh, line 119, we're going to make it also if debug rx because this is about receiving things.
Speaker A
That's fine. And then what else down here? We got line 127, we're going to wrap it up in an RX. Line 129, we're going to wrap it up in an RX.
Speaker A
And then line 133 and 135, those both seem to be errors. We're going to let those ride. Okay? Because we're going to keep this moving along.
Speaker A
All right. Additionally, as we keep moving. Here we go. Funk initialize script. We're going to say that it was called.
Speaker A
That's a debug function. That's a debug function. That's fine. Yeah. And that's all of the functions.
Speaker A
Sweet. Thank goodness. After this is all event handlers. It's all event. Is there a debug event handler contingency plan that we have to print for?
Speaker A
Well, but the event handlers are all just calling functions. So, it's going to happen.
Speaker A
Well, the event handlers are themselves often functions of themselves. Um, one of the things that's also useful to know is when an event happens. So, we already have that many of these are already doing that.
Speaker A
But let's also debug function these things. We're going to make it instead of saying that a funk ran, we're going to say that there was an event handler called for the IP address and namely it was called.
Speaker A
This is really about tracing logic. So this is why we are bothering with all of this. So there's that one. Um, then when we get down here to our levels and our saves and our recalls, we already have
Speaker A
prints there, but we should also wrap them up as well. And what I want to say here, I'm going to wrap it up. Boom.
Speaker A
Boom. Okay, there's that one. And here's this one. Again, we're tracing logic every time we do that. So, we're going to tag it with debug function. And we get down here to the timer.
Speaker A
Let it do its thing. Okay. We are so close to the end, Nate. Mhm.
Speaker A
All right. All that's left is the TCP socket itself. That sounds like the easiest one in no ways. [laughter] But that's got to be all TX and RX stuff, right?
Speaker A
Well, uh that is a very reasonable expectation. But again, our principles that we are providing you is coming from our friends both over uh in the plugins department, but also our friends in service. And one of the things that they
Speaker A
tell us is, hey, [laughter] if if you have a TCP socket, just make sure that it just always prints because that's probably what's wrong anyway.
Speaker A
So, we should we're just going to let it always print. And in fact, if you were with us for advanced, and you should have been if you're watching this class because it it's currently on the scope and sequence for all of these courses,
Speaker A
you may recall that the way that we actually wrote this event handler in the advanced class was we put in little uh debug prints for everyone of the little events that could happen. We're going to do the same thing here and just let it
Speaker A
go. So, here we are. If we have connected, we're going to print. We're going to have a socket event. And we're going to say connected.
Speaker A
There's that. And I'm going to copy. And I'm going to paste. And I'm going to paste. And I'm going to paste. And I'm going to paste. And I'm going to paste.
Speaker A
And then I'm going to update all of these to say exactly what the event is. So there's that, there's that, and there's that.
Speaker A
So now every one of the horns of the event handler for the TCP socket is going to say, "Hey, the socket had this event." Namely, it was connected, it was reconnected, it was data, it was closed, it was error, it was timeout. Should
Speaker A
those verbs be properly conjugated? Yes. Are we going to do that right now? No.
Speaker A
Has this been quite a bit? Yes. But you get the idea. Okay. So, uh, there's that. Let's do this. Control shiftB.
Speaker A
Building. Build it because we made it to the end. We did the end of our debug.
Speaker A
We made it to the end of the debugs. All right. So, remember, we're going to build. We're going to test. So, let's go test.
Speaker A
Okay. I got a version that's here. Got to make sure we turn on debug in the properties right?
Speaker A
Yep. That's going to be handy. So, I have to go offline. So I can drag in during this part of the process would it normally make sense to set the default state for that property to yes uh what
Speaker A
of the show debug since we're using it a lot you do you man I'm doing me you know you know how I know that I'm doing me cuz you done done it that my debug print starts off when it
Speaker A
opens up with just three identical lines that says something happened something happened something happened because as you were doing your thing I just copied and pasted the phrase debug print something happened into every single event handler. So, I'm in pretty good
Speaker A
shape. You are a mess. Let's see if I save something. Yep, something happened. Recall it. Something happened. This looks pretty good shape.
Speaker A
Lots Everything says something happened about 10 times. I don't see a problem with my code.
Speaker A
So, I need to connect. All right, I'm connected and my code is going to update after 10 seconds because that's what we configured.
Speaker A
socket event connected. Okay. And now there's my socket data event and all of that's working.
Speaker A
Okay, fun. So that was me having which of the filters applied? Uh none. None of the filters applied. So let's apply uh let's make all of them.
Speaker A
Let's let's do all of them. So there we go. Now it connects. Oh, and it's giving me lots of information.
Speaker A
Wow. Initialize script. We did the uh connection. It attempted. It actually connected. The state was updated. And now um all of the uh the timer poll went off and everything updated. And I have working code. I'm I'm TXing. I'm Rxing.
Speaker A
I have all the data. Everything is working. Super duper. Yours working, Nate? I mean, mine does what I told it to in that it just says something happened.
Speaker A
Something happened. something happened because that's in every single function, every single event handler and every timer right now. So what I have provided is an opportunity for my next engineers to really dive into their own troubleshooting skills and their
Speaker A
detective work that they've wanted to do for a long time to unravel this puzzle I've created for them. It's a gift that I honestly don't get enough praise for.
Speaker A
Nate, you know what's going to happen? They're going to figure out that your code is terrible.
Speaker A
Oh, I'll move out of the country, buddy. They're going to look in info.la and they're going to see that Nate from Nate Corp did it.
Speaker A
No, I got to change all those to Perkins. I got to change the author of this. Where do I They're going to murder you.
Speaker A
It's everywhere. Oh goodness. Why do we name it so many places with my name?
Speaker A
This is a bad choice. Don't spam the console. Just don't do it. Additionally, if you have little tiny helper functions that get called a bazillion times, because sometimes that's a thing, skip them. We don't need to know everything. Also, we
Speaker A
definitely realize that some of you are going to be writing plugins that have well information that's under NDA, and that means you might not be able to print all the things you want to print.
Speaker A
We get it. Also, don't spam the course log. Don't don't do that. Okay. Now, for my little rule followers, I love you guys and gals. My wife's one of them.
Speaker A
Here's the big idea. Here's the things we're trying to get through to you. Your debug needs to say enough that support and remember Nate, remember you're the support for Nate's plugin.
Speaker A
They're going to come to you. The good news is I can always borrow your plugin instead.
Speaker A
The big idea is that your plugin needs to put enough information in the console that you can figure out what's wrong.
Speaker A
And so actually there's one last thing I want to do when it comes to debugging.
Speaker A
Let's change back over. Go to the top of runtime.la. And in this first little bit, you can get rid of all of that stuff because that was from the text controller. And we're going to enter this print at the
Speaker A
very top, the very first thing. Plug in name. And let that be plugin info.name.
Speaker A
And then print I have there it goes. And then also print plugin version. And that's going to be plugin info.
Speaker A
Is it plug-in info or pluginfo? It's plugin info, which is why it tripped me up.
Speaker A
We're going to do plugin info.name and plugin info.ver version at the very top of runtime.la.
Speaker A
Here's why. You got any ideas? Well, I'm also writing plug-in author Jeff Perkins and I'm giving them your personal phone number. I'm going to get that out right now. One of the most handy pieces of information when you are
Speaker A
deep deep deep in debugging is putting this information at the top of the plug-in so that when it runs regardless of whatever it actually says in the canvas of designer because maybe they clicked on it and typed and they changed what it
Speaker A
said. This will tell the truth about what plugin are you looking at and what version is it? Because it might be that you know about a particular bug in one of the versions and they might be Josh and you. Okay. This is handy
Speaker A
information. You good, Nate? Yeah. All right. So, Nate, our process, right, is we build, we test, and we commit, right?
Speaker A
We Yeah. Did we build it? We built it. Did we test it? We tested it and it was fine. Yeah.
Speaker A
And we're ready to commit it. Seems like it. It seems like it. Except Except for You got a hesitation there.
Speaker A
I do. I do have a hesitation. There's always a fourth step between steps two and three with you.
Speaker A
Nate's not wrong. Especially when I call them out like this. There's one last thing we're going to do here. Our plugin is feature complete.
Speaker A
Nate, you know what that means? Means we don't have to control shiftB with a dev anymore.
Speaker A
Correct. We are going to celebrate with control shiftB and we're going to build it as a major.
Speaker A
A major. We made it to 1.0. We did. We did make it to 1.0. And because all we changed was we added these prints. I'm going to say it tested out fine. So we built it. Uh we tested
Speaker A
it. It's time to commit it. So let's come over here to changes. 1.0. Let's commit it. 1.0 O release. And with that, I'm going to hit commit and let it save.
Speaker A
And if Nate puts my contact information in his, I am going to not just commit code. I'm probably going to commit [music] manslaughter.
Speaker A
Committing. This is Jeff's first Nate's plugin. [laughter] Commit. Committing code's not the only thing I'm going to do. With that, I'll be back in a minute. We'll see where Nate is.
Speaker A
I'm gonna eat the last of the Mima cookies. See you.
Topics:Q-SYSplugin developmentdebuggingSDKcode examplesdebug principlesdebug filterssoftware supportcontrol scriptingbest practices











