0:03 Nice. So, let's get cracking. Um, thank 0:06 you so much for joining and and taking 0:07 your time to um participate in this 0:10 webinar. Uh, this is going to be on 0:12 debugging in RTO. Um, talking through AI 0:15 powered troubleshooting for your apps 0:17 and workflows. As an introduction from 0:19 me, I'm Ollie Clyde. Uh, I'm a support 0:21 engineer here at RETL. I have a 0:23 background in software development and 0:25 tech consulting. And unsurprisingly, in 0:27 my day-to-day work with customers, I do 0:30 loads of debugging, helping solve lots 0:32 of their more technical um challenges 0:34 and problems across retail. 0:37 So, let's start with a brief agenda of 0:40 what we're going to use this uh our 0:42 session for. Uh I'm first going to give 0:45 a little introduction around, you know, 0:46 what is debug debugging, why is it 0:48 important, etc., etc., you know, why are 0:50 we here? Um and then we're going to 0:52 spend the bulk of the session going 0:53 through uh the scenario that we're going 0:55 to use and then um spending around 354 0:59 minutes um talking through the scenario 1:01 and we'll give more details around 1:03 instructions um and how you can take 1:05 part or just watch along um for this 1:07 example. And then finally, um, at the 1:10 end, we'll run a little recap talking 1:12 through what were the main points I was 1:14 trying to get across, um, as well as 1:16 hopefully some time, um, depending on 1:18 how fast we go for some questions and 1:20 answers at the end. Um, again, yeah, 1:22 feel free to kind of chuck any questions 1:24 as we go, um, in the chat. Um, but with 1:27 that said, let's get let's get started. 1:29 So, uh, the art of debugging. Um, 1:32 sometimes it feels like an art, 1:34 sometimes like a science. Um I first of 1:36 all wanted to start with kind of why is 1:38 it important you know you know why are 1:39 we here why is it worth um discussing um 1:42 and I think essentially software 1:44 development is just as much about 1:46 debugging as it is about building uh and 1:49 it's kind of such a crucial skill and 1:51 although retool as maybe you already 1:53 know it's makes it far easier to build 1:55 software um and reduces that barrier to 1:57 entry it still requires um some of those 2:00 fundamental software development skills 2:02 and debugging skills um and as quoted by 2:05 Brian Kernahan um who is a famous 2:08 computer scientist. Um he says that 2:10 debugging is twice as hard as writing 2:12 the code in the first place. Um I 2:14 imagine maybe there's been times in your 2:15 life there's been very few in mine but 2:17 I've written a piece of code or built 2:19 some piece of software and it's worked 2:21 first time and I think I'm a incredible 2:23 genius. Um but 99.9% of the times uh I 2:27 get something wrong or I haven't thought 2:29 of an edge case or whatever it may be 2:31 and I need to iterate and um improve 2:34 what I've already built. Um and so it's 2:36 it's really kind of a part and parcel of 2:38 building things um is debugging. Uh 2:42 following that I think it's also worth 2:44 framing this in the importance of 2:47 defining the problem uh before the 2:50 solution. Although we'll mainly talk 2:52 around specific techniques within rout 2:54 retool and some kind of common errors 2:56 that I come across, it is a real real 2:59 common pitfall to get hung up on solving 3:01 a specific problem rather than 3:03 understanding the broader picture. Um, 3:05 and a quote that I I like to keep in 3:06 mind particularly when working with 3:07 customers is if I had one hour to save 3:10 the world, I'd spend 55 minutes defining 3:12 the problem and only five minutes 3:13 finding the solution. Um, from Albert 3:15 Einstein. I think it's a really nice way 3:17 to ensure that we're we're not getting 3:21 stuck in the weeds and obsessed around a 3:23 technical solution, but actually 3:24 understanding kind of what are we 3:25 solving for. I also thought it's worth 3:29 kind of framing this in the in the 3:30 context of of AI um and kind of both 3:33 where retail's going with this um but 3:35 also the wider industry. Um and I think 3:37 you know has this changed this you know 3:39 is debugging as important? Um and I 3:42 think on that first point um I think 3:45 it's you could argue that it's now less 3:47 about understanding specific technical 3:49 concepts or techniques um and more about 3:51 working through problems logically. Um 3:54 and so if anything um obviously I'd be 3:57 biased from from my position and role 3:59 but I would argue that debugging if 4:00 anything is more important um than it 4:03 kind of ever used to be. So you're more 4:04 likely to encounter code bases or 4:06 software or retool apps where maybe you 4:09 don't actually understand how it was 4:10 built um or you know who wrote the code 4:12 or how why it was written in that way. 4:14 Um and actually so you're more likely to 4:16 need to quite quickly understand the 4:19 problem you're trying to solve the 4:20 context around it etc etc. Um and so if 4:22 anything some of those core skills 4:24 around logical thinking and problem 4:26 solving I think are just as important if 4:28 not more so now with AI taking away 4:30 maybe you know some of the technical 4:31 knowledge you may need. And then 4:34 finally, I think an easier point to make 4:36 on on the second around defining the 4:37 problem. Um, I think it's probably going 4:39 to be easier than ever to create 4:41 solutions and build software. You know, 4:43 as I mentioned before, the barrier to 4:45 entry in software development is is 4:47 lowering and and that's particularly as 4:49 we'll talk about with assist, which is 4:51 retools um solution to use natural 4:54 language to build applications. There's 4:56 a greater chance that you're going to 4:57 build solutions that potentially don't 4:58 pro solve real problems. Um, and so I 5:02 think again that that makes this quote 5:04 an area even more important to think 5:05 about. Um, and so we'll touch on this 5:07 again kind of throughout this um, 5:09 webinar, but I think it's an important 5:10 thing to kind of anchor um, as we as we 5:13 go through um, this scenario. And so 5:16 moving on to that, um the scenario for 5:19 today is going to be about our colleague 5:22 Jerry who has built an MVP for a 5:24 software access request portal to help 5:27 demo where the retail can be used to 5:28 manage our company's various software 5:30 providers. Um but he's left for holiday 5:32 in Hawaii before finishing it, leaving 5:34 us to pick up the pieces. Um I think 5:36 it's fair to say we're not a fan of 5:38 Jerry anymore. He's really left us in 5:39 the lurch here. But unsurprisingly, it's 5:42 given us some good sections to run 5:44 through around debugging um and retool. 5:48 So, we're going to have these five main 5:49 sections that we're going to touch on. 5:51 We're going to start with app context 5:52 and the debugging tools. Then, we're 5:54 going to go into root cause analysis. 5:56 So, trying to understand the source of 5:59 of bugs and issues uh within RTO. We're 6:02 then going to get into resource query 6:03 debugging, JavaScript debugging, and 6:05 finish on workflow um debugging. Um to 6:11 um set some context around u kind of 6:13 knowledge for this. Um if you've never 6:16 touched retool, that's perfect. We'll go 6:17 really slowly and you can pick up um 6:20 lots of the basic things around 6:21 debugging within retool. If you have 6:23 used retail before and you're still 6:24 looking to try and find some new 6:26 techniques or new areas you come across, 6:27 I do hope that I will also um provide 6:30 some additional tools or or things you 6:32 haven't learned before. Um so hopefully 6:35 we can we can cover kind of both um kind 6:37 of both scenarios there. So onto some 6:41 logistics. You should have received an 6:43 invite email from our webinar instance. 6:46 It's AMIA um gosh actually what is it 6:50 called? It is called air amir 6:52 agents.retool.com. 6:54 Um, and using that invite email, you 6:56 should be able to log in and create an 6:58 account. Um, if you've joined us before 7:01 also, I could see some had logged in 7:03 earlier. You may need to kind of log in 7:04 again. And that should then take you to 7:06 this instance. Um, and this is if you 7:08 want to follow along um, manually, you 7:11 know, practically with us, you can uh 7:14 set up a copy of an app to then run 7:16 through the scenario with me. or if 7:18 you're not so interested, you can just 7:19 watch along and um watch me do it. Um as 7:23 also that's posted in the chat by Amar, 7:25 we should also have some instructions 7:26 for you to run through as well um if you 7:29 kind of get lost or um want to catch up 7:32 with where we are, but also have a 7:33 written summary of kind of what we 7:34 discussed today. So the main thing to 7:38 set your own app up is to ensure that 7:40 you copy um the main app. So it should 7:44 be once you log in you should be taken 7:46 to recents potent. Hopefully you should 7:48 see it there but if not you may need to 7:49 move to published and search for it. Um 7:52 and you can search for debugging or 7:54 main. 7:56 Um and in doing so you should then be 7:59 able to this ellipses at the side of the 8:02 app. Um you should then be able to 8:04 create a duplicate. 8:06 you'd want to include your email within 8:09 the duplicate just to ensure that um uh 8:11 there's you know there's no copies. If 8:13 you use the same name as someone else, 8:14 it will cause an error. Um and you want 8:16 to hopefully when you create it, you 8:18 should be able to set it um it in by 8:21 default it will set it within your own 8:22 drafts. Um so for example here if I do 8:25 olide at retool.com 8:29 and create the app 8:31 and it should be within my drafts here. 8:33 Um, and so then within those drafts 8:36 folder again at the top, you can then 8:37 click onto the app to then start this 8:39 web webinar scenario with me. Um, I'm 8:43 going to give a little pause there as I 8:44 imagine there may be some questions or 8:46 you're still logging in etc etc and 8:48 maybe I can give another run through um 8:50 if needed. 9:07 Nice. So, hopefully you're sat there 9:08 with your with your drafts tab open and 9:11 a nice copy of the main app. Um, and 9:14 then you can then click through onto the 9:16 app, which will then initially take you 9:17 to the preview. Um, I'm also taking the 9:20 fact that Omar hasn't um shouted at me 9:23 that there aren't any kind of core 9:25 questions or problems so far. So, I'm 9:27 going to take that as a sign to get 9:28 stuck into the scenario. 9:32 So the preview of the app. Um let's just 9:34 take a moment to have a little view of 9:36 what we think is going on here. So I can 9:38 see we have unsurprisingly this software 9:41 access request portal. Um at the top 9:44 there seems to be some KPIs around total 9:47 requests, pending approvals um and 9:49 approved requests. Then seems to have a 9:52 main table which I assume are just my 9:54 software access requests. Um that now 9:58 seems to be empty. And at the bottom 10:00 there seems to be a table for appro 10:02 admins to approve 10:05 um any access requests. It seems to be 10:07 at the top I can refresh but we seem to 10:10 be getting an error. And if I go to open 10:12 a request, okay, I can't seem to find 10:15 select any software. And so clearly 10:16 there's lots of issues here. Um so 10:18 chances are this is kind of some type of 10:21 portal where end users can come on uh 10:23 potentially request um software and 10:25 admins can then um either kind of reject 10:28 or approve that. So now let's go into 10:31 the bulk of uh the webinar which is 10:33 going to be editing and seeing what's 10:35 going under the hood. So at the top 10:37 right you should have the option to 10:38 click edit app and in doing so that will 10:42 then open up the app into this visual 10:44 editor. Um, and this is where we can now 10:47 look under the hood of what is going on 10:49 here. 10:53 So, where where do we start? Where's a 10:55 good place to get going here? Uh, and 10:57 with this newer feature in assist, which 11:00 can be found at the left sidebar at the 11:02 bottom, there should be a little icon 11:04 that you can click on to with assist. 11:06 This is a great place to start to ask 11:10 what does this app do and how is it 11:11 structured. Um, so with assist at the 11:14 bottom, we can select different modes. 11:15 So whether we want to build, create an 11:16 edit or just to ask. So for now, let's 11:20 just ask how does this app work and what 11:24 does it do? 11:26 And hopefully that should give us a nice 11:28 rundown uh of what's going on here, but 11:30 also while this is loading, I'm also 11:33 going to point to some core areas that I 11:36 would always go to when first coming 11:37 across a new app. Um on the sidebar we 11:40 have a load load of useful tools that um 11:42 you're going to come across or when 11:43 building and retool use frequently. The 11:45 first one at the top is pages. So this 11:47 gives a nice overview of if it's a 11:49 multi-page app, what are the page 11:50 structure here? At the moment it's just 11:52 one page. So it's nice and simple. We 11:54 also have the component tree. So this 11:55 gives a nice breakdown of how the 11:58 component structured. Are there any 11:59 hidden components? Um how do they fit 12:01 together? Not so important for today's 12:03 webinar but something to um keep in mind 12:05 and be aware of. And then importantly 12:08 the main section you should have is um 12:10 the code area. So this should give a 12:12 breakdown of quite simply all of the 12:14 logic um that's uh your app is 12:16 functioning on. So such things such you 12:19 know all of your queries, some variables 12:21 um some transformers etc etc. We're 12:24 going to go into this area in a lot more 12:26 detail and some of the kind of core bits 12:28 of this app within it. Hopefully if we 12:30 go back to exist we should now have a 12:32 nice overview of what's going on here. 12:35 So it seemed to have a clear purpose. So 12:37 the app allows employees to request 12:38 access to different software 12:39 applications and enables administrators 12:42 to review and approve and reject those. 12:43 So pretty much exactly what we thought 12:45 when we first had a little overview. Um 12:48 that seems to have that request button 12:49 at the top right where they can have a a 12:51 modal to then submit a request. Um we 12:55 using a retail database to be able to 12:57 store those requests. We have some 12:59 metrics at the top. We have the requests 13:02 table etc etc. and then the approval 13:05 model at the bottom. So when an admin 13:06 clicks to review a request, they can 13:08 approve it and reject it. Now some 13:10 technical architecture which is a really 13:12 useful bit of information to understand 13:14 kind of what's some of the logic that's 13:15 going on here. So we seem to have retal 13:18 database with a mock access requests 13:20 table as well as a postman mock server. 13:23 Um, and so 13:25 they seem to be giving our main uh 13:27 sources of data for this application as 13:29 well as a whole selection of different 13:31 queries um that's pulling or inserting 13:33 data um as well as some transformers um 13:36 that we're going to get into in more 13:37 detail. 13:39 Brilliant. So that's now given us a nice 13:41 overview of what's going on here. I'm 13:43 going to close that for now. And now the 13:45 other area I want to mention is the 13:47 debugging tools. So, at the bottom right 13:50 here, you should have the option to be 13:51 able to open up the debug tools. Um, and 13:54 if you haven't come across these before, 13:56 unsurprisingly, we're going to use these 13:57 very heavily during this session. 14:00 And I'm going to give a little just 14:01 overview of of how they're structured 14:03 and and uh how you can use them. 14:08 So, pardon me. So, it may look familiar 14:10 to some of you um because they mirror 14:13 the dev tools or similar debugging tools 14:16 um on your browser. Um just for those 14:18 that are curious um I always think it's 14:20 kind of um quite interesting to see um 14:22 if you double click on a page um kind of 14:25 outside of the retail visual editor um 14:27 you can see your own browsers dev tools 14:29 and unsurprisingly here you can see both 14:32 the kind of structure of this page lots 14:33 of the code as well as also uh the 14:36 console as well and network requests etc 14:38 etc um and so we've created our own 14:41 retool specific debugging tools that can 14:43 give you lots of information around um 14:45 what's going on in your retool runtime 14:47 time. And so the first page is the 14:49 console. So this will give you an 14:51 overview of all of the successful 14:53 queries, any errors, and also any info 14:55 messages. So for now, we're going to 14:57 filter it. So we just see the errors and 14:59 we just see the info messages. And this 15:02 is the the the main intel that we can 15:04 use to um start debugging. The other 15:07 area I wanted to highlight is the 15:08 timeline. So this gives a visual 15:11 representation of the query execution 15:13 order. So typically all of the queries 15:14 that are fetching or updating data um 15:18 and you can see um information around 15:21 timing of these etc etc. We're not going 15:23 to go into much detail on this now. This 15:25 is mostly mostly useful but for 15:27 performance issues um and the like. 15:31 Uh and the other area is state. So this 15:34 gives you a view of all of the current 15:35 components, queries, variables um etc 15:38 etc that are available um within retool. 15:41 Um what is state? state is effectively 15:44 the the snapshot at this given moment in 15:47 time um of you know all of the 15:49 information um within retool. We're 15:51 going to come into more detail around, 15:54 you know, why is state important, how 15:56 does it work, um, and how you can use it 15:58 to debug a little later on. Um, so it's 16:00 good to be able to flag this now. 16:03 Brilliant. So, I'm going to go back to 16:04 the console and have that nice kind of 16:07 open on the page here. Um, and now that 16:09 we've understood what's going on here 16:10 with the context of the application, as 16:12 well as had a little um, mooch around on 16:15 the console logs, we're now going to get 16:16 into the first kind of main section, 16:19 which is how do you find the root cause 16:20 of bugs? You've come across an 16:22 application and there's a load of errors 16:23 showing, oh no, you know, where do I 16:25 start with all of this? Um, and so we're 16:28 going to talk through kind of two main 16:29 ways to go about this. Um, and 16:32 effectively a great place to start 16:33 unsurprisingly is just to pick one of 16:35 these and use this to work your way 16:37 backwards to find the root cause of the 16:39 issue. Lots of times errors like this 16:42 are showing as symptoms of a issue 16:44 further upstream. And so we're going to 16:46 um we're going to work through a 16:48 scenario together. So to be able to open 16:50 up um and investigate this error in more 16:53 detail, you should be able to click um 16:56 on these on the side here to open up the 16:58 associated query with this error. The 17:01 one that I want to open up um is the one 17:03 that is named all requests with software 17:06 name. So you can see that on the right 17:07 here. For me, it may be different for 17:09 you. It's the fourth one down. And if I 17:11 click onto that, that should then open 17:13 up this transformer for me. And so then 17:16 I can use both the error in conjunction 17:18 here and also uh the transformer open to 17:21 now start debugging um um and finding 17:24 the root cause here. So for those that 17:25 aren't aware, transformers, you know, 17:27 what are they? um effectively they're 17:29 ways that um they're code within retool 17:32 that you can use to write larger re 17:34 reusable blocks of JavaScript. Um and 17:36 unsurprisingly it's typically used to 17:39 transform data. So whether you're 17:41 combining data sets, filtering or or 17:43 kind of whatever it may be so if we have 17:46 a quick run through together of what we 17:47 think is going on here at the top we 17:49 seem to be pulling in uh lots of kind of 17:52 all of the access requests. Then we seem 17:54 to be also getting the software 17:56 providers. Um, and then we seem to have 17:58 a function that is simply combining the 18:00 two. So we've got all of the quest 18:02 requests and we're going to find for 18:03 each request find the associated soft 18:05 piece of software and then we're going 18:07 to match on that and then we're going to 18:09 try and find the uh name of the 18:11 software. Um, and then we're returning 18:13 that so that they're kind of combined 18:15 together. So with that in mind, let's 18:17 get started into kind of analyzing this 18:19 error in more detail. So, as I mentioned 18:22 before, great place to start is actually 18:24 on the error itself. Unsurprisingly, um, 18:26 one thing to note, something that I do 18:28 all the time is I skim read an error and 18:30 then I think, oh, I know what's causing 18:32 this. This is simple. What am I, you 18:33 know, obvious don't take the time to 18:35 actually properly read it and analyze it 18:37 and then, you know, I'm down a rabbit 18:39 hole um when actually if I'd taken the 18:40 time initially, I could have saved 18:42 myself um lots of effort. So, let's take 18:45 a moment to read through this error. 18:47 We've got one error. Software.find is 18:49 not a function. And by clicking onto the 18:51 error, typically in JavaScript, you'll 18:53 always find a bit more information 18:54 around which line it's on. And so we can 18:56 see here it's highlighting line five. So 18:58 if we go to line five in the 19:00 transformer, we can see that 19:02 software.find function. 19:07 Now software defined is not a function 19:10 typically means that the property of 19:14 fine on software um doesn't exist. And 19:17 so in a slightly obscure JavaScript way, 19:19 simply that this is saying software is 19:21 most likely undefined 19:23 um or or kind of not appropriate an 19:25 array to be able to call.find on. Um so 19:28 let's now work our way backwards from 19:30 this using um the first method that is a 19:33 really powerful tool within a retool. Um 19:35 which is being able to hover over any 19:37 piece any variable um within a piece of 19:40 JavaScript within retool to understand 19:42 its current state. So if we were to 19:44 hover over software here we can quickly 19:45 analyze okay well you know it is 19:48 software indefined is it an error and in 19:50 quickly doing so here I can analyze the 19:53 data and I can see yeah there's there's 19:55 a clear error going on here and an error 19:57 message bad request etc etc so that is 20:00 undoubtedly must be causing this 20:02 software.find defined error in the 20:04 console. Um, and if we take a moment to 20:06 work our way back from there, we can see 20:07 software is defined at the top and then 20:10 it's actually defined from this query 20:11 get software providers. Um, as you may 20:14 know in RETL, a kind of real trademark 20:16 retool thing. Double curly braces allows 20:18 you to access any of these components 20:20 queries um state within RET um and and 20:23 kind of yeah access and then use that 20:25 data. Um, and so we can see here again 20:27 hovering over it, it's coming from this 20:30 get software providers query. Um and so 20:33 if we were to hover over the select icon 20:35 at the top, we can then open up the uh 20:37 culprit here. So that's one method which 20:40 is using uh basically the inbuilt um 20:44 function to hover over a v variable and 20:46 view the state instantly. Um it's really 20:48 powerful, really easy way to quickly 20:50 understand what's going on within a 20:52 within a transformer. 20:54 But the other method that I wanted to 20:55 also talk through is um how you can use 20:58 state and understand understand state to 21:00 debug more complex issues. Um so if I 21:04 now go back to opening the transformer 21:07 and I now open up the state tab um I'm 21:10 going to give a little uh little 21:12 overview story time of why state is 21:15 important and how you can use it to 21:16 debug within retool. So for more complex 21:20 issues typically where maybe unlike here 21:24 where we've got a clear error where 21:25 maybe data isn't showing where you think 21:27 it should be or a component is not 21:30 getting the correct column or or 21:31 whatever it can be a lot harder to 21:33 actually understand particularly more 21:35 complex applications where the data is 21:37 coming from and what links into what. Um 21:40 and so this state tab is a great place 21:42 to be and so why is it important and and 21:44 and kind of why is it a concept that we 21:46 need to understand? Um, and so to give a 21:48 brief overview, essentially front-end 21:50 frameworks like React or Angular, maybe 21:52 you've heard them heard of them or 21:54 worked with them before. Um, 21:55 essentially, 21:57 you know, why do they use state and why 21:58 is dependency so important? And it's 22:00 because if we didn't track states and 22:02 the dependencies between them, um then 22:05 essentially anytime a piece of software 22:07 updated in your in your app, you clicked 22:09 button um or sent a request or whatever 22:13 it may be, we would need to rerender the 22:15 whole page in order to ensure you know 22:17 all the all the right bits of 22:18 information updated in in your um user 22:21 interface. Um and so that unsurprisingly 22:23 that's deeply inefficient. Um and so 22:25 like those frameworks here, that's 22:27 exactly what we're doing in retool. 22:28 We're analyzing you know for each uh 22:30 piece of state you know what is it 22:32 dependent on and if you see here at the 22:34 bottom uh if we search for all requests 22:39 with software name so if we're searching 22:41 for this transformer we can actually see 22:43 you know what it's updating and what it 22:45 depends on that's really powerful and 22:47 really useful um I imagine if you have 22:49 ever played around with any of these 22:51 front-end frameworks like React um there 22:53 will be a time where dependency loops 22:55 happen um or um 22:59 um or yeah you haven't quite configured 23:01 state correctly um using ustate and it 23:03 causes all sorts of issues whereas here 23:04 we have a visual representation to 23:06 actually understand okay so you know 23:07 what is it updating and what what does 23:09 it depend on and then this is then 23:11 really powerful to then move up and down 23:13 that chain to be able to find the root 23:14 cause of different bugs. So if we were 23:17 to go down the chain in this example, so 23:19 clicking through on the component, the 23:21 table that should be displaying this 23:22 data, unsurprisingly, it's not showing 23:24 any data because it's relying on this 23:26 transformer. So if we go back up the 23:28 chain, we can see the transformer here 23:30 and it's null. Unsurprisingly, we just 23:33 discussed that, you know, has currently 23:35 has an issue returning any any data. So 23:37 nothing here. But now if we go back up 23:39 the chain, just like we figured out 23:40 before, we can see get all requests 23:42 query. And unsurprisingly, we do have a 23:44 request here. This is the one that is 23:45 working. Uh again, if we go back back, 23:48 we can now go check get stuff with 23:50 providers. I know we've already figured 23:51 this one out, but unsurprisingly, yes, 23:53 this is showing as having the error. 23:56 So, I'm going to give a little um pause 23:58 there. So, just give a recap. So far, 24:00 we've discussed how to understand um app 24:02 context with assist um and the debugging 24:05 tools. And then we've discussed two of 24:07 the main methods to um find the root 24:09 cause of issues. um one by 24:12 uh using the kind of inbuilt ability to 24:15 hover over variables um within retool to 24:18 understand its state but also the 24:20 concept of the state tab in and retool 24:22 and the ability to move up and down the 24:24 dependency chain. 24:27 So with that said we want to now open 24:29 get software providers uh as we have um 24:31 quite extensively covered that this is 24:33 most likely the root cause of the issue 24:35 and we're now going to get into resource 24:37 query debugging. So with any um uh kind 24:41 of query in the code editor um you can 24:43 both either test or run the query. Uh 24:46 main difference being test you're just 24:47 running it within the context of this 24:49 output you know output pane within this 24:51 query whereas run you're running it in 24:53 the context of the app. So you're 24:54 updating this the state um in the 24:56 context of of the application. Um so for 24:58 now we're just going to run test um to 25:00 not change anything and we can get a 25:02 clearer breakdown of the error here. 25:04 Invalid credentials error unable to 25:06 authenticate. double check your API key 25:08 and try again. Now, this is a classic um 25:11 authentication error. Again, probably 25:13 one of the most common um kind of 25:16 resource errors you're going to come 25:17 across. So, we're going to walk through, 25:20 you know, what are the main scenarios 25:21 here and how how can you go about 25:22 debugging this. So, typically with 25:24 authentication errors, there's um only a 25:27 limited number of options that could be 25:28 causing this. So either we aren't 25:30 sending the API key, we're sending it, 25:32 but it has the wrong credentials, or 25:34 we're sending it in the wrong format for 25:35 this server uh to be able to um uh 25:39 interpret it. So let's work our way 25:41 through kind of understanding what which 25:43 of those three is it likely to be before 25:44 we go into depth of actually researching 25:47 um uh the solution in more detail. So in 25:51 the output pane, we can uh switch across 25:54 to API request. And this gives us a nice 25:56 little breakdown of both what we're 25:58 sending. So the request so what what 26:00 we're sending to the resource uh and the 26:02 response of what are we what are we 26:03 getting back? And if I go to the request 26:06 property here um I can view okay we are 26:09 sending an API key. Um and it's nicely 26:11 sanitized by retool. Um so we do seem to 26:14 be sending something here. So next I'm 26:16 now going to check okay you know it does 26:18 seem to be the correct API key. Uh and 26:20 like I was showing before the ability to 26:22 hover over variables. We can hover over 26:24 this one and we can view. Okay. Yeah, we 26:26 are sending an API key here. Just as a 26:29 disclaimer, it's generally not best 26:31 practice to store an API key um kind of 26:34 in the header within the resource query 26:36 in an app. It's better unsurprisingly to 26:38 have it within the resource itself, but 26:40 for demonstration purposes here um I've 26:42 I've set this up um kind of within the 26:45 query. So, we've ticked off those first 26:47 two. So, chances are it's actually 26:48 something in how we have configured the 26:50 header. So we're going to go about um 26:52 asking assist to see whether it can help 26:54 us with this. So with opening up the 26:57 assist panel on the side uh we have the 27:00 ability to reference things within 27:02 within the app. So if I uh type at I can 27:07 then search for get software 27:10 uh providers. So I am selecting this 27:14 specific query and let's ask and see if 27:16 assist can help me. 27:19 How should I be setting up the resource 27:24 uh API key here? 27:28 So great class great place to start is 27:31 um asking assist or AI in general you 27:34 know how should I be configuring these 27:36 resources um how do they work you know 27:38 you know I'm getting this error back 27:40 typically you know what does it mean and 27:42 while assist is working on a little 27:44 response there and it seems to actually 27:45 have 27:47 given it um and we'll see if it 27:57 So it seems to be struggling here to get 28:00 understand what's going on. So it's 28:01 saying how to set up the API key. You 28:02 have two options. Create and configure. 28:08 So I don't think it's quite getting to 28:10 the root cause here. So the other option 28:12 is if AI maybe isn't quite giving you 28:14 the solution. Um the other option is 28:16 actually to go the old school way which 28:18 is going finding some documentation. So 28:19 let's search for Postman mock server um 28:23 API key and let's try and research. 28:26 Okay, how should things be configured 28:27 here? Uh I'm not going to read through 28:29 the docs with you um on this call but 28:31 let's have a quick uh run through and we 28:34 can see when creating a mock server from 28:36 an API call and if we give a quick skim 28:39 down here we can see okay to the request 28:42 X API key header. So actually it seems 28:44 to be we we're probably sending the 28:46 header in the wrong format. So if we go 28:48 back. Yeah, we're sending API key, not X 28:51 API key. Let's change it to X API key. 28:55 Hopefully give that a test. Amazing. 28:58 That's now returning a list of software. 29:00 So let's now click save and run. 29:03 Wonderful. That is working and sending 29:05 the right request. One. Amazing. 29:08 So to give a brief recap, we've 29:10 understood the app context. we have gone 29:12 into root cause analysis and then we 29:14 have looked at using both assist and 29:16 also manually looking at the 29:18 documentation to try and understand um 29:21 how a resource should be configured and 29:23 we've changed the resource header here 29:24 to X API key uh which is the header that 29:28 this postman server is looking for and 29:30 so now we're getting the appropriate 29:31 list of software providers I assume here 29:34 that um for this demo for this MVP that 29:36 Jerry's made um we're just currently 29:38 using example list of of software 29:44 Nice. 29:47 I'm going to take a quick pause there, 29:48 have a have a little drink, 29:51 and then let's go on to the next 29:54 section. 29:57 So, now we've made this change, we've 30:00 made this fix, let's see if there's more 30:01 errors for us to um get stuck into. So, 30:05 you can either reset the app state from 30:07 the top right here. You can click on the 30:09 ellipses 30:11 uh on you know at the top right of the 30:13 editor and click reset app state. Um or 30:15 you can just refresh the page and this 30:17 will just reset the state to see okay um 30:20 let's let's see if there we're still 30:21 getting any issues. Uh and just like we 30:23 did before let's go straight to the 30:25 debug tools to see if we have any 30:26 problems. 30:28 And looks like we're still got some 30:30 errors that are going on here. So just 30:32 like we did before let's start with 30:33 these and work our way backwards of of 30:36 what could be causing this. Um so again 30:38 like I did before you can open up 30:41 uh this specific uh route of this bug um 30:45 by clicking onto the um item here and 30:48 that will then open the transformer and 30:49 it seems to be the same transformer we 30:51 were looking at before. So the one that 30:52 was taking the requests getting the 30:54 software um and adding the software name 30:57 to the to the requests. And now let's 31:00 get into the wonderful world of 31:01 debugging in JavaScript. 31:04 So 31:07 it's a lifelong journey understanding 31:09 JavaScript errors and getting better at 31:11 debugging with it. Um I wanted to 31:13 highlight one of the main tools that u 31:17 that you would use to debug in 31:18 JavaScript um and then kind of talk 31:20 through um kind of some more areas from 31:23 that. So like we did before let's do a 31:26 slow work through of looking at the 31:28 error in more detail. So error cannot 31:30 read properties of undefined reading to 31:33 uppercase 31:35 and like we did before let's open up 31:37 this error and we can view which line 31:40 it's happening on. So this is line 8. 31:43 Let's go to line 8 in the transformer 31:46 and we can see um again here that two 31:49 uppercase issue. Um so similar to that 31:52 find.software issue the same thing here 31:54 means we're trying to read to uppercase 31:57 on full name. Um but 32:00 full name probably most likely is 32:02 undefined or doesn't exist here. Um so 32:04 let's now try and work our way back from 32:06 there. So looking at the code here, we 32:07 can see that there's a match um made on 32:10 software. Um so chances are here it's an 32:13 issue with um whether full name exists 32:16 as a property on software. So what we're 32:19 going to use here is something called um 32:21 console logs. Um, so effectively, 32:24 unsurprisingly, they're ways to be able 32:26 to print information into the console 32:28 that you have on the side here in your 32:30 debug tools. Uh, and they're one of the 32:32 main ways to understand um the 32:35 information that's what's going on 32:36 within um your logic. So you can do that 32:39 by typing console.log 32:42 and then you just type the specific 32:44 variable that you're looking to print. 32:45 And typically I always like to also 32:47 include a string, you know, a comma and 32:49 then a string to then also print, you 32:52 know, what am I actually showing here. 32:53 It can sometimes be hard if you have 32:55 lots of console logs to understand 32:57 what's printing what. I'm going to do 32:59 this for software and also while I'm 33:00 here, it can also just be useful to get 33:02 as much information as we can. So I'm 33:04 going to also do requests so we can see 33:07 both of them. And then we have the 33:09 ability to run a test. And then as you 33:13 can see here, it should then print out 33:15 in your console the information. You'll 33:17 need to make sure that you have both the 33:19 errors, well importantly the info 33:21 messages enabled. So you can view 33:23 console logs. And you can see every time 33:25 this piece of code runs, it's going to 33:27 keep printing out this information for 33:29 me. And then I can use this to 33:32 understand, okay, let's first look at 33:34 requests. And I can see requests is 33:36 coming through and nothing unusual 33:38 there. But if I open up software and 33:41 let's say we see we've got an array of 33:43 objects here. Um and if I open up the 33:45 object I can see the structure of the 33:47 software and we seem to have an ID a 33:49 name and a notes. So actually having a 33:51 look here we are defining the name um as 33:55 a property um rather than full name 33:57 here. So actually I think this should be 33:59 name rather than full name. So, I'm 34:02 going to change that. And like we did 34:03 before, I'm going to run a test. Ah, we 34:05 now have a software request with the 34:07 software name here. Amazing. And if I 34:10 run save, let's double check that. 34:11 Perfect. So, that's now saved and 34:12 working. We've got an access request 34:14 with a software name. So, that's working 34:17 as expected. 34:20 So, you may be thinking, that's great, 34:21 Ollie. I've used console logs, but that 34:23 was quite a lot of effort. And you just 34:25 showed me earlier around how you can 34:27 hover over um any variable in retool and 34:30 understand straight away what's going 34:31 on. So I could have just gone there. 34:33 Let's have a look at what the match is 34:34 made up of. We've got ID, name, and 34:36 notes. Okay, come on. That's name 34:38 straight away. Very quick fix. Um why 34:41 have you showed us console log here? Um 34:43 and I think the the main reason is um 34:45 for more complex applications um and 34:48 more complex pieces of code um 34:50 console.logs logs is always the fallback 34:52 to go to to understand the makeup of 34:54 what's going on here. Um, typically when 34:56 you find 34:58 uh AI can is incredibly efficient at 35:00 writing good bits of code. So if I was 35:02 to give this to um an AI and say write 35:06 me a more efficient solution, it 35:07 probably will come up with a better way 35:09 of writing this this piece of code. But 35:10 will it always have the appropriate 35:12 context of the data structured and how 35:14 it's being passed around etc etc? No. 35:17 And so um console.logs logs is a really 35:20 um good solution or or or way something 35:23 to have in your toolbox to fall back on 35:25 um to kind of really understand what's 35:26 going on in the code here. But then 35:29 following that you may say okay that's 35:30 great Ollie um I can you know use 35:32 console logs but what about if the AI 35:34 does understand context you know 35:36 unsurprisingly here we could um go to 35:38 assist and just like we did with the 35:40 resource we could probably at this 35:43 specific transformer like we did with 35:44 the resource and say fix this piece of 35:46 code for me and it will most likely give 35:49 a good effort at providing a solution. 35:51 Um and I think again we run into that 35:53 same issue that potentially for for 35:54 simpler issues um that would work but 35:57 soon as you get to a point where there's 35:59 you know it's more specific context that 36:01 that you you haven't passed on or takes 36:03 sort of effort to pass on um suddenly 36:05 you can be uh lost at sea with what's 36:08 going on in your code. Um and so having 36:09 the idea of being able to use 36:11 console.logs um is a great place um and 36:13 a great skill to have. 36:16 So, let's just for aesthetic reasons get 36:19 rid of those console logs. Now, we know 36:20 it's working. So, I'm going to delete 36:22 those and save that again. So, that will 36:23 then stop printing out on the console. 36:26 Uh, and just like we did before, let's 36:28 um refresh the page um to double check 36:31 whether if there are any more issues. 36:33 And we now seem to have no more problems 36:35 in the console. So, maybe we're we're 36:37 nearly there. Just to give a brief pause 36:39 um and recap, we have now discussed app 36:42 context, debugging um finding the root 36:45 cause of issues, debugging resource 36:47 queries, and also debugging JavaScript. 36:51 Uh we're going to now finally get into 36:53 the last section, 36:57 which is let's see if we can actually 36:59 submit an access request. So, I'm going 37:02 to click request. I'm going to click 37:04 through on a piece of software. So I'm 37:07 going to select one randomly. I want to 37:09 be an admin test and I'm going to write 37:12 just a test justification. Let's see if 37:14 we can submit this workflow. 37:20 Okay, unfortunately we're still getting 37:23 a problem here. It does seem to be 37:25 creating the access request, but the 37:26 workflow that seems to be triggered um 37:28 to send an approval doesn't seem to be 37:30 working. So just like we did before, 37:32 let's start with the debug tools. Let's 37:34 start going to the error. Let's start by 37:36 clicking onto the um the resource query 37:39 that's triggering this. And like we did 37:41 before, let's run a test to double check 37:43 what the error is. Okay. Yeah, we're 37:45 getting that problem through. Um so with 37:48 this scenario here, um it's only I have 37:51 access to the workflow. We're not going 37:52 to run through the same process of 37:53 duplicating um um dup duplicating the 37:57 JSON and etc, etc. So you can just watch 37:59 along if you have been following up 38:00 until now. 38:02 Uh, and so reading through this error, 38:04 we've got this error true message, no 38:06 recipients defined. We also get the 38:08 workflow run ID. So clearly there's 38:11 something wrong potentially with how 38:12 we've set up this workflow. So we can 38:14 open this workflow from this app and get 38:16 started into debugging workflows. 38:20 So just like we did before, we're going 38:21 to take a moment to understand what's 38:23 going on here. We have a start trigger 38:26 that seems to take in a request ID and 38:29 an email. We then get that the details 38:32 of of that specific request. We then if 38:34 we do get the uh details of the request, 38:37 we then are looking to send an email to 38:39 notify the admin to say you've got an 38:41 approval that you need to make. 38:43 Um and so that seems to be kind of what 38:46 we're trying to achieve here. So just 38:47 like with the app with the debugging 38:49 tools there, we have the run history or 38:50 run logs. Um where we should then be 38:53 able to go into more detail around what 38:55 caused the problem here. Um, 38:57 and what we can do is we can filter the 38:59 runs. Um, and I just want to try and 39:02 find the specific run that I'm looking 39:04 at here. Um, and by clicking onto that 39:08 one I want to investigate, we'll get a 39:10 full history of the uh, what happened. 39:13 Um, so the global all the blocks. So the 39:15 blocks are the individual bits of um, 39:17 code here. Um, so the start trigger, the 39:19 get requests, um, the even the branch 39:21 etc. And you'll see here we get a full 39:24 breakdown of what was triggered, whether 39:25 it was successful, etc., etc. And 39:28 actually, we can see the email admin 39:31 block is the one that's highlighted in 39:33 red. So, this is the issue. And if we go 39:34 to data or JSON, we can see a clearer 39:36 breakdown of this problem. So, error 39:38 true, no recipients defined. If we go to 39:41 the block, we can see here, chances are 39:43 we're not appropriately configuring the 39:46 um email to send the email to send this 39:50 uh to. So a really really useful tool 39:52 within workflows is to go to um inputs 39:55 and within here you'll see basically all 39:56 the information that this block takes in 39:59 um and in opening that you get lots of 40:01 insight into what you're trying to use 40:03 to um get that data and then what it 40:06 evaluated as. Um so we can see here for 40:09 this um who we're sending the email to. 40:11 We've got start trigger.data email. So 40:13 we're pulling from the start trigger and 40:15 we're just getting my full name but not 40:17 my email uh which isn't great. And if we 40:20 double check that so we can see what's 40:22 happening here with the body. We can see 40:23 we've got the raw expression with the 40:25 get request details data um and my name 40:28 um but 40:30 so that seems to be kind of working as 40:31 expected. So let's double check where 40:34 we're pulling this from which is the 40:35 start trigger. So we can click onto the 40:36 start trigger and again for this 40:38 specific workflow run we can view what 40:40 did this start trigger output? What was 40:41 it d what was its data? Um and viewing 40:44 this here we can see next to email again 40:46 we're just sent seem to have sent my 40:48 name in this um trigger uh rather than 40:51 my email. So actually it looks like the 40:53 error lies with the app um not with the 40:57 workflow. So, if we go back to the app, 41:00 um, we can now have a look at this in 41:02 more detail. And we can see here it 41:04 seems to be that we're sending my full 41:06 name. And just like we were doing 41:07 before, you can hover over to see the 41:09 current state. And we can see, yeah, I'm 41:11 sending Ollie Clyde there as my full 41:12 name, not email. But I do have access to 41:14 send my email here. So, let's change 41:16 that. 41:18 Um, and let's run the test again. 41:22 True. Amazing. So, that's now working. 41:24 And hopefully if you have followed along 41:26 um you should have been able to add your 41:28 email to current user and should have 41:30 received an email. Um so just like we 41:33 did before let's refresh and and finally 41:35 let's see if Jerry has made any more 41:37 problems. Um so I can see here I've now 41:40 got my pending request at the bot. Let's 41:43 try and approve that. So if I click on 41:45 to that pending request um I can now 41:50 determine whether to reject it or 41:52 approve it. Let's give myself access. 41:54 Let's approve it. Brilliant. Amazing. 41:56 And let's now turn to approved. So, it 41:57 looks like everything's working um as 42:00 expected. 42:02 Amazing. Thanks so much for following 42:04 along. Um I hope you found that 42:07 uh kind of useful and covered some areas 42:10 that either you haven't seen before um 42:12 or some new tips or tricks that you can 42:15 now use when working um in retail 42:17 yourself. Uh to give a little recap of 42:19 some of the main points I I wanted to 42:21 get across. Um, one, the importance of 42:25 starting broad um, and then going deep. 42:28 Um, effectively using things like assist 42:31 to understand the bigger picture of how 42:33 the app works and then going from the 42:35 debugging tools to the error um, to then 42:37 kind of work your way back to um, the 42:39 specific issues or like we found with 42:40 the resource query, what are the the 42:42 most likely um, uh, issues here and then 42:46 work our way picking them off before 42:48 going into the deep depth of reading 42:50 documentation. um the importance of 42:52 testing incrementally. Everything we 42:54 went through today would make one change 42:55 and then test. Um and so uh not trying 42:58 to fix everything at once, but iterating 43:00 is is really useful and important when 43:03 debugging, understanding dependencies, 43:05 checking dependencies, using the state 43:07 tab, understanding state, I think is a 43:09 really important part of debugging. Um 43:11 and so something to be familiar with. Um 43:14 and finally, the importance of reading 43:16 the documentation. Uh, I don't know if I 43:18 mentioned this already, but when I was 43:20 first started to um um get into software 43:22 development, biggest piece of advice I'd 43:24 got was always read the docs. Um, 43:26 obviously that's changing now with how 43:27 good AI is at um summarizing things for 43:30 you. Um, but 43:32 um effectively the amount of times I've 43:34 gone to set up a resource, skim the 43:35 docs, think I thought I understood 43:37 what's going on and then ended up um 43:38 having a really common error that I 43:40 could have avoided um uh earlier on. 43:44 Lovely. So, thanks so much for following 43:46 along and listening. Um, looking at the 43:49 time, we do have some some um uh some 43:53 extra bit at the end to talk through any 43:55 questions um that you may have. Um, I 43:57 don't know if there any in particular 43:58 that cropped up that we can get into um 44:00 straight away. 44:11 I think Mike had one question about uh 44:13 the header um in the resource 44:17 configuration. So maybe you could show 44:18 that on the screen. 44:22 >> Yes. Um so if I go back to that resource 44:26 query in the header that I have set up 44:28 here. Um 44:31 let me see if I can get the specifics of 44:33 the question. 44:51 Um, so yeah. Yeah. Any questions around 44:53 the header? The solution was to add in 44:55 the X API key. Um, which 44:59 >> yeah, 45:01 >> if you could show the uh if you edit the 45:03 resource configuration, how you can 45:04 place it there as well. uh so where it 45:06 should be for best 45:07 >> practice. Yeah. Yeah. So um so for best 45:10 practice um by editing the resource it 45:13 just means that anytime this resource is 45:15 used without within um any app um it 45:18 will then by default have that API key. 45:20 And so we could do the same here XP API 45:22 key here and then set it um just like we 45:26 did before. The only difference being 45:27 actually it's defined as an environment 45:29 variable here. 45:31 Um so we can see that postman API key 45:33 rather than within the app itself which 45:35 is stored in the retool context. Um so 45:39 um just explain that in detail there's a 45:40 slight um difference there set as an 45:42 environment variable um rather than a 45:44 within the retool context. Um so 45:46 effectively what this means is you as an 45:48 admin can set it up of here are the 45:49 details of how you can connect to this 45:50 resource and then you know you can then 45:53 um they can use that without knowing the 45:54 API key or it being exposed on the 45:57 within the app itself. um but they can 45:59 then still access the data or maybe 46:00 create even create their own requests um 46:02 to this endpoint. 46:06 >> Uh we had one question from uh Ollie 46:08 which is how do you know which queries 46:10 run on page load? 46:13 >> Great question. Um 46:16 so 46:17 on timeline here the the um so that was 46:21 in in the debugging tools um the 46:23 timeline tab. 46:25 Um, effectively if you refresh the page 46:31 um, and go to the timeline tab, this 46:32 will show you basically all of the ones 46:34 that that run kind of on page load. Um, 46:37 and typically it's also ones, you know, 46:39 most likely. Um, if you go to any 46:42 resource query here, 46:44 um, you should be able to view if we 46:46 were to say get request query, um, you 46:51 can look at the run behavior as well. 46:53 and you'll you'll be able to see okay 46:54 this run behavior is that it's going to 46:56 um kind of run on page load and so it's 46:58 automatic rather than something that's 47:00 done manually. So you're manually 47:01 tricking triggering it you know through 47:02 an event handler um whether you know 47:04 whether within a button or whatever it 47:06 may be. Um but yeah technically speaking 47:08 these are all on that refresh on that 47:10 page load. Um and yeah out of curiosity 47:13 as well you can sort of see some 47:14 information around um the timeline of 47:18 that load. Um, and so, um, yeah, as I 47:20 mentioned, you can use this to go into 47:22 more detail around, um, what could be 47:24 causing, um, uh, 47:28 performance issues within your 47:29 application. 47:42 Nice. Um, within the instructions, I've 47:44 also included some, um, useful 47:46 resources. Um effectively they're just a 47:48 rundown of you know the debugging tools 47:50 in the app. Um the run history setup and 47:52 workflows as well as kind of common 47:54 resource connection um errors that we 47:56 see. Um so they're very useful to um 47:59 have a read yourself uh and kind of use 48:02 when debugging and retool. 48:09 >> I think that's it for questions. 48:11 >> Nice. Um brilliant. 48:17 So to finish for the next event that 48:20 we're that we're running um we have a uh 48:23 we're running a retail summit uh in the 48:25 shard um March 26th um don't know m if 48:28 there are any more specifics on this but 48:30 if you if anyone wants to scan the QR 48:32 code um they can get some more details 48:34 around how they can register um find out 48:37 what's going on 48:41 and it would be brilliant to see you 48:43 Yeah. 48:59 Can see a question on 49:22 Okay, brilliant. Well, to wrap up there, 49:24 um, thanks so much for joining. Um, and 49:26 yeah, hopefully see you at Retall 49:28 Summit. Thank you so much.