1

this is an atomic example of my current issue:

For the moment I have a project containing several R scripts (all in the same directory named DIR). I have a main script in DIR sourcing all the R files and, containing a basicconfig:

basicConfig()

I take two scripts in DIR, dog.r and cat.r. I have currently only one function in these scripts. In dog.r :

feedDog <- function(){
    loginfo("The dog is happy to eat!", logger="dog.r")

}

And in cat.r :

feedCat <- function(){
     loginfo("The cat is voracious", logger="cat.r")
}

It's fine with this example. But in real I have something like 20 scripts and 20 possible error messages in each. So that instead of writting:

loginfo("some message", logger="name of script")

I would like to write:

loginfo("some message", logger=logger)

And configure different loggers. The issue is that if I declare a logger in each R scripts, only one will be taken into account when I source all files with my main ... I dunno how to bypass this issue.

PS: in Python it is possible to define a logger in each file taking automatically the name of the script like this:

logger = logging.getLogger(__name__)

But I am afraid it is not possible in R ?

Colonel Beauvel
  • 30,423
  • 11
  • 47
  • 87

1 Answers1

4

If your source() a file, the functions created in that file will have an attribute called srcref that stored the location from the sourced file that the function came from. If you have a name that points to that function, you can use getSrcFilename to get the filename the function came from. For example, create a file that we can source

# -- testthis.R --

testthis <- function() {
    loginfo("Hello")
}

Now if we enter R, we can run

loginfo <-function(msg) {
    fnname <- sys.call(-1)[[1]]
    fnfile <- getSrcFilename(eval(fnname))
    paste(msg, "from", deparse(fnname), "in", fnfile)
}

source("testthis.R")

testthis()
# [1] "Hello from testthis in testthis.R"

The function loginfo uses sys.call(-1) to see what function it was called from. Then it extracts the name from that call (with [[1]]) and then we use eval() to turn that "name" object into the actual function. Once we have the function, we can get the source file name. This is the same as running

getSrcFilename(testthis)

if you already knew the name of the function. So it is possible, it's just a bit tricky. I believe this special attribute is only added to functions. Other than that, each source file doesn't get it's own namespace or anything so they can't each have their own logger.

MrFlick
  • 195,160
  • 17
  • 277
  • 295