There are a number of cases where javascript code should be reporting issues to the system log, not presenting dialog boxes to the user. This seems like an easy win.

An example of the problem: #634628: AJAX "HTTP Error 0" when AJAX operation is interrupted.. We put a big ugly dialog box in front of the user (formerly) saying that they had an error, when in fact there was no error (or at least nothing they could do about an error). This is a place where stuff should be logged to watchdog.

Comments

mrconnerton’s picture

So I was a bit bored and played around with this for a short bit. The problem is figuring out WHERE to put the code for this.

My brain thinger sees it as a method on Drupal such as:

(function ($) {
  Drupal.watchdog = function (type, message, variables, severity, link) {
    $.post("system/watchdog", { type:type, message:message, variables:variables, severity:severity, link:link } );
  };
})(jQuery);

That hits a menu callback that passes the vars onto watchdog(); Having never done much with Drupal core before, I had problems figuring out where I should put this stuff so I did this just as a personal proof of concept:

  1. Created core/misc/watchdog.js and put the code above in it.
  2. Added that file to system_libraries_info() in system.module
  3. Added drupal_add_library('system', 'drupal.watchdog'); at the bottom of system_init cause I didn't know where else to do it.
  4. Added the callback "system/watchdog" to system_menu
  5. In my system/watchdog callback I just pass the $_POST vars to watchdog.

Then I gave the Drupal.watchdog() method a test and it works just as expected. Of course this is all proof of concept, just wondering if I'm barking up the right tree and/or where I should put this stuff.

nod_’s picture

On the issue itself I'm not sure that's a good idea, what happens if I run :

while (true) {
  Drupal.watchdog('spamscript', "I'll end your server");
}

Anybody could run that, it's just JS, leave that on for a while and you can say goodbye to your DB. If you add a permission that's a bit better but you won't be able to log events for everyone, which defeats a big part of the issue and you'd still have to do user permission check on the server side. Might not kill the DB but sure won't help the webserver.

All in all i think that's not something that should be in core. You can't protect anything in javascript, there is no security whatsoever in the language and this will only open a big ugly can of worms.

Just a comment on the function signature, usually that's done more like this in jQuery :

(function ($) {
  Drupal.watchdog = function (type, message, options) {
    $.post("system/watchdog", $.extend({ type:type, message:message }, options));
  };
})(jQuery);
mrconnerton’s picture

I went to bed knowing someone would comment on the security of it :-)

Of course there needs to be some sort of security and I assumed it would be on the server side menu callback. I don't know what that security looks like, maybe some sort of threshold trigger to prevent overflow. I'm just tossing out ideas since it's an old issue :-)

I don't think the fact that the menu callback anyone can run is an issue. Assuming someone can help with the security of the callback, then it doesn't matter who calls Drupal.watchdog() or how many time they call it.

Again, my primary question is WHERE this code would go at the moment. I'm sure there is a solution to the security.

nod_’s picture

Fair enough :) you're assuming that'll make it in core. I'm questioning just that.

I'd be much more interested in hearing about a solution to fixing the threshold/abuse issue first. At this point I don't think it really matters where abuse-prone code lives.

rfay’s picture

Thanks for the work on this.

There are, of course, ways of limiting the the number of posts (as contact module does) and we can use a hash or just use FAPI for the submission as well. I do think it's worth thinking about the DoS implications, so good thinking there. However, this is do-able and the security/DoS implications can be handled.

nod_’s picture

Thanks for the clarification. I'll let you get back to the code placement issue :)

BJ___’s picture

(Sorry if this is the wrong place to post this)
What is the recommended way (secure) to solve this problem "now" with D7 ?
The patch in http://drupal.org/node/1232416 ?

effulgentsia’s picture

What is the recommended way (secure) to solve this problem "now" with D7 ?

If the problem you're trying to solve is an unwanted alert to your website users, then you can apply the patch in #1232416-17: Drupal alerts "An AJAX HTTP request terminated abnormally" during normal site operation, confusing site visitors/editors. Note that this will also remove the alert from places where a real error occurred, and this won't be logged anywhere, but there's no solution for that at this time that I'm aware of. If someone is aware of such a solution, please add links here to those issues / resources.

Regarding #1, in addition to dealing with security and flood control, there's also the thorniness that what we're trying to respond to is an error occurring in the prior ajax request, so does it make sense to respond to it by initiating another ajax request? Especially if we look at the specific use-case of #1232416: Drupal alerts "An AJAX HTTP request terminated abnormally" during normal site operation, confusing site visitors/editors, what we have there is an "error" occurring because the browser aborted the prior ajax request in order to submit a full-page form request. Surely in that case we wouldn't want to begin a new ajax request. And the current problem we're facing in that issue is not yet knowing what the code can use to distinguish a real error from a browser-initiated abort.

effulgentsia’s picture

There's some sandbox code, jDog, that might be of interest for people wanting to experiment with ajax approaches.

nod_’s picture

Forgot to link to that on related issues #1419652: JavaScript logging and error reporting there is a few things that needs coordinating about the whole logging thing.

attiks’s picture

my 2c: i'm not in favor of javascript posting to drupal (and writing to the database) without access control, looks to me it will be better in devel(ish) module.

apotek’s picture

The errors could be logged to the browser console with Drupal.log(). This will take them out of the user's screen, while still allowing a developer to see them.

Then, on a production system, you'd want to turn off error reporting so nothing too intimate about your server shows up in the console.

Logging users' error messages to any kind of system log or watchdog table is extremely dangerous. Not only will you be adding a second bootstrap to an ajax call that already did a bootstrap (and failed), if the problem is in the app (Drupal), your error might not be able to be logged back to that same app. Let's say, for example, that your db is having connection issues, and that's the cause of the ajax errors. Logging those errors back to Drupal, which is running on a flaky db, is not necessarily going to capture data. What you'd want to do is have a completely separate application for logging UI errors, say, a node.js service running against mongodb or a log text file, that just takes input and writes it. The separate app/service could then be rate limited by referring IP address so you don't get flooded.

peterx’s picture

@attiks and @apotek, the solution is to ban Ajax. :-)

The typical user case for Drupal 7 is someone responding to a page delivered from Drupal which means the system is working further than is required for an Ajax call. Based on using jDog at several sites, the errors associated with a broken database are going to time out the browser before Javascript activates.

Drupal 8 might be a little different if you have a user tapping many links on the page at the same time. In that case you have to allow for multiple simultaneous requests from every page and the resource overhead of handling a request in a working system is higher than the overhead for a simple watchdog log. Anything that can handle a regular request is overkill for a log request.

Drupal 8 should also offer a lower overhead process for simple requests. That is one of the targets for Drupal 8. That means the overhead for logging from the user interface is less again.

If the message goes to watchdog, the user cannot see the watchdog report so there is no security problem there. The Javascript cannot see anything "intimate" in the server and, again, is not a security problem. If you are sending sensitive information to the Web browser for use in Javascript, then the information is already public.

There is also a module to limit access to watchdog by role, should you need to have multiple levels of response to error logs.

Someone could write a script to flood the jDog style logging. They can write a script to flood every one of your Ajax links. The simplest solution is to ban Ajax. The only thing that you might want to add to Ajax is a use once code similar to forms to stop repeated processing of the same request. Instead of adding the code to form pages, add the code to every page. Accept only the first request from the page because that is the one signalling the error or other process. You can then drop any other requests from the same page. All Ajax calls need something similar to prevent multiple submissions from robots. It is not just a Javascript logging problem.

For the typical use cases I see in the sites using jDog, we need only the first report of a given error and that alerts someone to fix the problem. If subsequent errors pile up, it does not matter because someone is already working on the problem.

Another use case. One site was reporting several errors per day because Chrome supplied incorrect information to jQuery. For that site there is now some Javascript code to correct the data from Chrome. To test all the variations out in userland without jDog, we would have to test with more than ten variations of Chrome and over a hundred different devices.

Javascript logging to the server is important and, for most of the use cases I see, the watchdog log is more useful than a separate log because I can see the client side error listed with the server logging of the request.

attiks’s picture

@peterx I think we're on the same line, but we need a permission to control access to it, like we (can) do now for ajax callbacks. The only thing I'm not sure off is if we need this in core or in a separate module.

I'll try to have a closer look a jdog

Bevan’s picture

JS Watchdog module may serve as a discussion point or prototype for this issue.

peterx’s picture

Comparing the different approaches:

jDog does watchdog and email alerts.

JS Watchdog does only the watchdog part. If JS Watchdog was combined with the email part of Logging and alerts, http://drupal.org/project/logging_alerts, JS Watchdog would be a complete replacement for jDog and I could stop working on jDog. :-)

Has anyone used the email part of Logging and alerts? Is it reliable when things start acting strange? Will it work in D8? If yes to all questions, then D7 and D8 ports of JS Watchdog might be the best approach.

nod_’s picture

Issue summary: View changes
Status: Active » Closed (won't fix)
Issue tags: +JavaScript

3 years later it doesn't seems like there is a real case made for it. Let's not put that in core.

There is always 8.1.x if opinions changes.

rymcveigh’s picture

We have run into a use case were a POST to dblog would be useful. In our case, we would like to record the value of an autocomplete field using Drupal's logging API, but to do that we would need to perform a POST to Drupal via JS. Another use case were a dblog POST would be useful is to record JS console errors to the same log we use for tracking PHP errors on the site. That way we have a single source to visit where we can review both kinds of errors.

I created a sandbox module that does this but I think a REST resource in the dblog module makes more sense being that there is already a DBLogResource GET resource there.

What do you all think?

rymcveigh’s picture

Status: Closed (won't fix) » Active

I'm marking this issue as active because I feel it is worth revisiting the use-cases where this feature would be useful.

nod_’s picture

Issue tags: -JavaScript +JavaScript

8 years is a long time, we'll need to look at what's the state of the art around frontend logging, error or otherwise. And define the scope of what we'd want to do in core.

We've been using sentry in my team to log that kind of things, it's pretty effective :).

apaderno’s picture

Version: 8.0.x-dev » 8.9.x-dev
Issue tags: -JavaScript
rymcveigh’s picture

Sentry looks like a solid option for logging being that it supports JS and PHP systems. My thoughts are that it would be nice to utilize Drupal's logging system for both backend and frontend logging, whether that logging system is dblog or some other solution, especially as core moves more towards supporting a decoupled architecture.

It seems like adding support for a POST in the dblog module would be a quick win and would give users a central location to track errors in both their PHP and their JavaScript.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

andypost’s picture

peterx’s picture

One aspect, security, is raised against similar issues predating this issue. Security could be handled by something like issuing a UUID for a page and requiring the UUID from Javascript requests. You get a problem when long running pages update frequently with different Javascript. Do you reissue the id for every request?

The documentation for "modern" alternatives does not provide the detail needed to understand their security model. They might have a short term security idea in place. How do they handle a single page that is updated all day by Javascript?

From my reading of the Sentry doc, you need a YAS (Yet Another Server) and it is in a language I could not verify for security. Is there a page on their security model? On how it fits in along side a PHP based Web site under Nginx?

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.