Any way to write to log stream from a Server Script?

Apparently the usual Python print() command is prohibited in a Server Script.

As a work around I am using …

msg = []
msg.append(f"some{thing}, ")
msg.append("something {else}, ")
frappe.msgprint( msg = ''.join(msg), title = 'Debug Log' )

… so as to build up usefully large snapshots of what’s going on in my code.

It’s pretty horrible.

Is there a better alternative?

Alternatively, how can I call into my whitelisted functionality?

1 Like

Did you try frappe.logger()

used like this:

It would have been nice, but I get :

AttributeError: module has no attribute 'logger'

I was hoping this list of RestrictedPython commands was out of date. Seems not.

I really don’t get it. I seem to able to effect some fairly drastic changes to the database through a Server Script, but writing to a log file, “Oh, NO! Much too insecure!”

Weird!

2 Likes

Discovered this challenge myself, yesterday.

These 2 lines of syntax are accepted. They don’t violate RestrictedPython.

log("This is my message")
frappe.log_error("This is my message")

I have no idea where 'log()' is trying to write to. I haven’t been able to find it. I’ve scanned every file in the ./logs subdirectory. :man_shrugging:

The 'log_error()' does successfully write to the “Error Log” DocType.

1 Like

hey @brian_pond did you find a solution

@imbra

TL;DR: Yes, but it required altering Frappe Framework code.

Available Functions:

  1. log("This is my message using log()")
    • All this does is output the results to an HTTP Response, if you call Server Script using an API.

So it’s not really “logging” (imo). At least in the way I use that term.

  1. frappe.log_error("This is my message using frappe.log_error()")

Doesn’t Work

  1. frappe.logger()
    • This function is not available to Server Scripts.

My Workaround

  1. I wrote a new Python function to perform my logging. For example:
def brian_print(message):
	print(message)

This example above is very simple. You could definitely do more, such as writing the ‘message’ to a file or database.

  1. Next, you must teach Frappe Framework that your function is safe to use with Server Scripts.
    The related code is found in apps/frappe/frappe/utils/safe_exec.py, a function named get_safe_globals()

See screenshot below. I altered the out dictionary, adding a reference to my new “brian_print” function.

  1. Restart the web server.

  2. Call your function in a Server Script.

Now when you run the Server Script, the string is sent to stdout, just like you would expect.

Note

The above is just a tutorial/exercise. In real life, I don’t ever actually write Server Scripts. I write all my Python code in Apps.

So please use caution with the above; I have not fully tested this, or any possible side effects.