3

I am writing an overlay UI for one application using Greasemonkey, injecting JS to a page.

Now I have issue to hook on some ajax calls that runs on the webpage. However, the page is generating console logs, informing that content is fully loaded. My question is:

In plain javascript, is there a possibility of reading console output generated by completely different script?

function blackBox(){
   //this is generating come console output.
   //this runs on code layer I have no access to.
}

function readConsole(){
   //read console record by record
   if(console.msg == "something I want"){
      doSomething();
   }

}

Thanks in advance :)

5
  • 2
    Could you not redefine console.log to record prints as well as print? I've never tried that, but it should work. Commented Sep 15, 2018 at 18:40
  • The console object is not read-only, you could overwrite it early on and the blackbox would hit your code. Commented Sep 15, 2018 at 18:43
  • It does appear to work, at least in my Android app. Example: var print = console.log; console.log = function(msg) { print("Altered!: " + msg); } console.log("Some message"); Commented Sep 15, 2018 at 18:44
  • The page's javascript environment doesn't have access to the console window's environment, so no you cannot directly access the output. You would, as Carcigenicate suggests, have to override the log method. Commented Sep 15, 2018 at 18:45
  • Can you run a script before the function from which you want the console msg? If yes, run a script which stores console.log in a variable cl and define a global array ar. Then redefine console.log to first push the message to ar and then use cv to output normally. This should happen before the function from which you want to capture output. After the function ends, execute your code to search the message from the array ar. Commented Sep 15, 2018 at 18:48

4 Answers 4

2

As others have stated, you can override the console.log() function with your own, and implement your own implementation:

var oldLog = unsafeWindow.console.log;
var messages = [];

unsafeWindow.console.log = function(msg) {
    messages.push(msg);
    oldLog.apply(null, arguments);
}

// Access the entire console.log history in messages
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, this obviously works in general, but sadly, it works only inside the scope of my script and not globally. all console.logs from my script are being hooked, but console logs, which comes from the original scripts or even from console itself (write console.log directly into dev console) are not captured... anyway, marking this as solved, because for most other people seeking this, it will work... thanks again :)
@Zorak, have you been able to also capture log statements stemming from other scripts? I'm developing a support tool for an application portal, where users can raise tickets. Getting console output from 3rd party applications would be quite useful....
2

Even if it were possible, that would be bad practice. The console is for human eyes to see, when debugging. It usually takes several milliseconds to execute console.log, so executing it in production code is not a good idea.

I would say programming in booleans (like ifDidX and ifDidY) would be better. But if you really had to do this message-history thing, a better alternative would be to store messages in some other array. Here is an example:

var messagesLog = [];
//Since console.log takes several milliseconds to execute, you should tick this to false in production code.
const logToConsole = true;

function logMessage( message ){

  //adds message to JS log.
  messagesLog.push(message);
  
  //performs console.log if not production code
  if(logToConsole){
    console.log(message);
  }
}

logMessage("pizza");
logMessage("second to last message");
logMessage("last message");

//checks last message and this will be true
if( messagesLog[messagesLog.length - 1] == "last message" ){
  logMessage("The last message in the log was 'last message'");
}
//checks last message and this will be false
if( messagesLog[messagesLog.length - 1] == "pizza" ){
  logMessage("This will not occur because the last message was 'last message'");
}
//searches through log to find certain message
for(let i = 0; i < messagesLog.length; i++){
  if(messagesLog[i] == "pizza"){
    logMessage("one of the messages in the log was pizza");
  }
}

Comments

1

Redefine console.log and storage messages on a array:

var consoleStorage = [];

console.log = function(msg){
   consoleStorage.push(msg);
   console.warn(msg); // if you need to print the output
}

Now you can read all logs:

function readConsole(){
   //read console record by record
   consoleStorage.forEach(msg => {
      doSomething(msg);
   });
}

Comments

1

Directly there's no way to access console outputs, but what you can do is that you can override console.log in a way where it checks for you condition first and then outputs the content, below is a sample code for that

console.stdlog = console.log.bind(console);
console.log = function(msg){
    if(msg == "something I want"){
    ...
    }
    console.stdlog.apply(console, arguments);
}

Although you'll need to be very careful with this since if you add any console.log in that condition, it will create an infinite loop.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.