Creating an Event Log in Xano (@nocodebackend)

Ray Deck builds a lightweight event-logging system in Xano by creating an eventlog table and a reusable addeventtolog function. This captures fine-grained steps inside functions and background tasks that Xano's built-in debugger can't show, especially useful for long function stacks or loops that exceed the debugger's ~1,000 statement limit.
Chapters
So something that comes up a lot in the state change community is the issue of trying to figure out what your events recently have been, knowing about what function calls there might have been or what endpoints might have been called specifically, but really like what turns in the logic have happened. And this can happen for a couple different reasons. One reason is that you might be inside a function stack, function stack that is just way too long., right, to have, and you lose things when you're looking at them through the debugger. And the other, and it can be trying to understand how the software actually gets used and when certain things inside the endpoints are actually occurring. Put a different way, we wanna keep track of events. So Xano provides us with a couple ways of tracking the use of our system. One is the, you can just take a look at the recent requests to see what was going on with that. And we can take a look at the request, particularly in the course of the last 24 hours by clicking on the request history when we're sitting here in the, in the, the at the top level of the workspace. And that can be really useful to get a flavor for a particular, very, very early on. There's also the metadata API, which lets you download those kinds of requests to a, to wherever you want them to go. You know, so you can be keeping track of that over a longer period. And of course, put that into a database or, you know, Airtable sheet or whatever for slicing and dicing as is going to be most helpful to you. Now, the, what I have found is that The, the most interesting questions are going to be about like specific turns of logic. What are we doing and when are we doing some of those things? This is important for like performance tuning to find out when certain activities have occurred. And this could also be important for, you know, the, the, the, you know, certain expensive services that we might be calling on a frequent basis. Things might be tied to functions as opposed to being directly tied to API requests, things that might be triggered out of our background tasks. These are all examples of things that are useful for us to know about. It can be very important for us to tune our applications, but the XAML doesn't really support out of the box. So how do we make it that we can get access to this information and do it in a way that's relatively easy? We could do it with an event log. And this is something we talk about kind of frequently over on StateChange Office Hours. So I'm giving you some inside dope here as to a technique that we've used more than once. So we can say we want to have a log and we'll just do it as a table for a second and we'll call it event_log. We don't want any endpoints for it because this is going to be a private log that's going to be useful inside the appliance. We can add additional, we can later have, you know, our endpoints or functions or whatever for doing analysis on it. But the important thing here is this is a safe place to be dumping the information. We'll just say add table here. Once this table exists, I find there are a few fields you want to put in. You don't want too many fields. It makes it too complicated. So I'm going to put in a text field, which is going to be source, usually indicating what function is adding information to the event log or endpoint or whatever it is. I'm going to have another one. I'm going to call it message, which is, you know, plain text way of describing what's, what's happening, why are we putting something into log. And then just to keep things simple, I like to use the JSON data type to have freeform data. So that, you know, whatever information you wanna put in. So one useful way of doing this is to have an event log that's going to become when you get data coming back from, I don't know, like OpenAI or something, right? Something that's a relatively expensive call. You wanna make sure that you can go back to find out, well, what were we working with and why didn't this thing work properly? Well, you can just take all that data from that request and dump it into the data field because data being a type of JSON, It's really Xano's equivalent of any, anything can go in there, which is super convenient. So now I've got my event log nice and flexible, not that much to it. And the next thing we want to do is, you know, you could apply it directly by putting in add record calls, but I like to have a little bit more control over that and abstract it. And so I use library and I create a function and I'll say function. And you know, thing in Xano is that the function names aren't actually the names that are used in the code. So we can name them something useful. Add event to log. Cool. And then I'll just set up the inputs to be kind of like what we talked about before. Source and message and data. And then I can just say, okay, we're going to make a database request that will add a record to my events table, event log. There it is. And it's actually sort of filtered in now, so it's kind of smart about that. And now I'm going to know when things happened. And then I can publish. Actually, before I publish that, I actually find these events are, these kinds of functions are most useful when they have no response that came out. So I just say, No response, please. Right, that way it just NA itself and it'll never have data coming out. That way you can drop it into any of your endpoints and it just works. So let's publish that for a second. Cool. And now let's make another function to test it and we're going to call it, you know, test_log. And we're going to do something where we're going to use it for a little bit of performance, right? And we're going to create a you know, we're gonna do a custom function and say add event to log and we're going to call it, you know, the source will be test log and the message will be starting, right? No particular data to it. Save. And then, you know, I could do something like, you know, utility and just tell it to, let's just try sleeping for 5 seconds, right? 5 seconds, save. And then I want to add the event to the log again. And I will say database requests and add, no, add record. No, I don't want to do that. The whole point was to do a custom function, right? So do add event to log. And I will say, and I will say this is going to be, you know, object. And I'm just going to set, you know, call this duration. 5, based on 5,000 milliseconds that we think went along with that. And really you can put whatever information you want to in here. And I'm going to say save that. And I will say, let's just run it. And run it. 5 seconds. Good. See, nothing goes back. It's interesting. And if I wanted to, I could go back over to database. Take a look at my event log, and I'll see that I have both my starting and the fact that I woke up from the nap. And if I take a look at the data when I woke up from the nap by double-clicking on it, I can see it has a duration of 5,000. The other thing you can do by having abstracted it into an object, into a function like this, is you can decide maybe later on that you don't think there's enough performance in putting it into a local database. Maybe you want it to go offsite. Maybe you want to use Datadog or one of these other logging systems. Totally fine. See, now you don't have to change the way the rest of your code works 'cause you've abstracted that concern through the function. And now I can go back down here to say add event to log, and maybe instead of doing the add record, you're going to be doing, you know, an external API request over to Datadog or whoever it is you're gonna have as your logging service, you know, CloudWatch, whatever it might be. The, this gives you more options because you've abstracted the concern and it also just allows you very easily to start at no marginal cost to you 'cause this works even on the free plan of Xano. To start having these kinds of events get tracked. And when you do, you're gonna be able to start walking through that, stepping one at a time, and you'll be able to see things that you couldn't see before. Like, you know, when Xano had, when you have a function stack that, you know, goes through more than 10,000 steps. So let's run up a score for a second. So we're just going to say we're not going to worry about the Datadog thing. Let's talk about one of the places where this becomes really useful. And that's going to be if I have a good event to log. And I'm going to, well, actually make sure it's not in draft mode. Publish, publish. Cool. And now let's talk how to test the event log. Test event log, here it is. And we will say event log, how about I'm going to, you know, right now, if I were to run this with a debugger, it should be kind of trivial, right? It would go 1, 2, 3, 4, 5. And the debugger is totally fine with it, right? It's just going to show me all the results. But what if I instead had something like, you know, data manipulation loops for, and we'll just say, you know, 10,000 steps, save, and I'm just going to, you know, establish a new variable, data manipulation, create variable, var1 with value 0, save. And then I'm just gonna say for each of those, we're going to do data manipulation, math, add to var1. We're just gonna add 1, right? That way each time it just gets kicked up by 1. We're not gonna sleep and we're gonna just have return var1. That way it'll return 10,000 at the end. Great. I can run that. You'll see it comes back with 10,000. You see it has 1,000+ statements? It doesn't tell us how it worked, right? So it'll tell us about the first N of those, probably the first 1,000 of those times it was adding the number. It won't tell us about any of the things that happen after those first 10,000. One of the cool things about the add_event_to_log is it makes sure that we're able to put them in. So what if I just said here, let's just say add, and I'm going to do a, you know, custom function. I'm going to do add_event_to_log. And custom function, add event log, and the source is going to be test event log adding. And here I'm just going to say this is, you know, once again, going to be total, and the value is just going to be whatever the current value is. All right, that way it'll keep on going up and up and up. So we'll say save, save, save. Great, let's rerun this. Now this will take a little bit longer because whenever you're writing things to the database, Xano waits for the journaling to occur, and that means you're, you're going to be slowed down by each of these queries that are going on in. Great, here we go. So now I have the 10,000 here, right? If I were to go back over to the database, I would see in my event log, sure, I started woke up, started woke up, started woke up. Oh wait, and now it's adding. You see, each time it adds, it, you know, knows how much that total was. It actually keeps all 10,000 of those are now in the event log in a way they couldn't have been in the debugger. So this becomes a way that you can be using the event log for both tracking things in production to see how people are actually using your system. And also be even tracking things where you're just doing development and you're in something that's complicated enough that the Xano built-in debugger isn't giving you enough of a view of what's going on. And this can also be really helpful when you sort of have multi-part systems. You're trying to figure out, okay, what's happening when? And the combination of using created out of the log as well as the messages of what's thinking about as it goes can become super, super helpful. And of course then you can use functions or use endpoints or whatever to do more slicing of this information as you see fit. And this is all of course before you ever bring it over to one of those actual data retrieval services. So that's the skinny on how to use a nice simple event log to be able to get better understanding of your system in very, very short amount of time. I hope you find it helpful. And if you have enjoyed this, please, I guess, like and subscribe, but more importantly, tell me what other topics you'd find helpful because we're always trying to focus on the hardest 5% over at StateChange.










