Anvil Community Forum

Way to find out which function implementation (server, uplink(s)) is called?

Often my apps have uplink code, server code (and of course client code). Maybe scheduled and background tasks. Then I have a dev and prod version. And three PCs where I develop on.
I might move code from the uplink to the sever or vice versa.

So what happens more often than I like is that I’m not 100% sure which code handles a specific anvil.server.call.
Sometimes I’m puzzled that a code change doesn’t do anything. Turns out there is some orphan process (from a debug session), maybe on my other dev system, that is still serving the uplink.

It would be convenient to have a way to find out where a called function is served from. Any ideas to find this out?

1 Like

Python functions can return multiple values. So you might have the function return location information, such as %COMPUTERNAME%, %CD%, or proxies for those values.

Of course one could instrument the app in that way. But that does not help my use case, which is more debugging of weird situations while developing.

As I understand it, once a function returns, that’s it. Returning from a function destroys any record of the circumstances it was running in. The time to capture that information is when it is still known and available – i.e., during the function-call’s lifetime.

The other way to do it is with logging. If the function doesn’t return the information directly, have it record that information somewhere else, where it can be found on demand.

2 Likes

Maybe you know what the function does and maybe you know what input to pass to cause it to crash and maybe the crashing function shows a traceback and maybe that traceback gives you a hint of where that function is running?

That’s a lot of maybes, but it maybe worth trying :slight_smile:

I think I expressed myself poorly.
Code can be called in multiple ways. Uplink code from the server or the client. Uplink code can run on multiple machines. I can develop on multiple machines.
I’d like, while developing/debugging, to know a way to check which code is actually handling the call. On more that one occasion I’ve had that some uplink code was still running somewhere (eg because of an unclean exit from the IDE). Should not happen, but still…

If I understand you are calling a function and you expect it to run on an uplink machine and instead it runs on the server or on another uplink machine.

Calling the function with argument values that cause the function to crash, you may see a traceback that gives you a hint of where that function is running. It’s a long shot, because the function is running in another interpreter, and the traceback you see may only talk about your interpreter. But if you can pass argument values that you know will cause the function to crash, it shouldn’t be too difficult to try.

Indeed, there are heavy handed ways of finding out where some code runs.
I was hoping for a more elegant way of finding out what runs where. Something like a call graph. Anvil must have this information somewhere…

1 Like

I agree, it would be nice to have a monitor for your account that shows this type of info.

I don’t think Anvil has an easy way to show what has been called by what or what is being called by what, but it should be easy to know what could be called.

I mean there should be somewhere a list of all the registered server, uplink, background, whatever functions for each app in your account.

Having a way to look at this table would be very useful. Now that Anvil is open source… I could try to dig and see if I can figure out where that list is :wink:

Why? It makes sense to build and retain such a data structure while running in a debugger, and some debuggers do just that. But to be in debug mode all day, every day, on every machine, adds a great deal of run-time overhead.

Anvil must already register what code to call where. The data structures are no doubt build up when using @anvil.server.callable and the like, and when the uplink connects.

True. Now, when multiple programs make the same function available, Anvil can choose any location to call, at random. (Load balancing.) Once a value is returned, Anvil doesn’t have to remember which location it actually did call.

Didn’t know about the load balancing.
Still to load balance Anvil must maintain a list of available callable functions (possibly the same function on different uplinks). That is exactly the info I’m after.

1 Like

I’d love to have that information available, as well. If it’s critical, you might want to make an official Feature Request.

Note that this will tell you which location responded to a call only if there was exactly one location for that function name, at the time the call was initiated.

I would love to have a table that lists what’s registered, even without knowing what is executing right now.

Something like a table with the following columns would allow to figure out if and where there is an old / obsolete function out there: function name, type (uplink, background, etc.), machine name, app name, module name, time of registration, time of last execution.

By having access to the time of last execution, you have an indirect answer to the question in this original post.

2 Likes

Agreed. Even if Anvil kept logs for us – I hope they don’t, for performance reasons – they wouldn’t have that level of detail. But with Anvil, building that infrastructure is pretty easy: a database table for each kind of object to track, with an appropriately complete primary key; and making sure that each Uplink program adds/updates an entry when needed.

I’ve planned an update to my app for doing exactly those things. Then it’s relatively easy to throw a dashboard on top of it.

I think something like this came up before a few months ago but for something else.

There was an answer where we decided that one possible configuration could be to put a unique ID into the @anvil.server.callable like @anvil.server.callable("origional_func_name" + machine_id) when the script is run from a specific place, registering the name of the function apended with a unique machine identifiable ID once the script is run and connects to anvil, registering the name.

The unique ID’s do not have to be hard coded, they could be gathered at run-time from the system that runs the script (like a salted, hashed UUID or something), and stored in an anvil data-table and retrieved to a variable that would be passed to anvil.server.call().

In this way you could know exactly what machine was running what function, using identifiable information.

1 Like

@p.colbert and @ianbuywise :
I agree that your suggestions would help a little, but they rely on following good practices during debugging, which sometimes is an oxymoron. I am doing a quick test, I forget to follow the guidelines, the phone rings and tomorrow my uplink doesn’t work as expected because I left some debugging stuff in some computer.

I think that the best answer for this post is a feature request.

2 Likes