Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Rather than covering every possible use-case in this module (of additional information), we should allow other modules to be able to add arbitrary data to the accesslog.
The API should allow modules to declare field definitions and views definitions in a single place and perform all of the necessary schema alterations at appropriate times. I'm envisioning something like the following:
hook_better_statistics_fields() {
$fields = array();
// Which would become {accesslog}.my_module_foo
$fields['my_module_foo'] = array(
// Schema definition for this field
'schema' => array(
'type' => 'int',
'size' => 'normal',
'default' => 0,
'description' => 'A description about foo.',
),
// Called with the field name as a single argument.
// E.g. my_module_get_stats_values('my_module_foo');
// In PHP 5.3, this could also be a closure.
'callback' => 'my_module_get_stats_values',
// Optionally define views handlers here.
'views_field' => array(
'title' => t('Foo', array(), $en),
'help' => t('Description of foo for site builders..', array(), $en),
),
);
return $fields;
}
Comment | File | Size | Author |
---|---|---|---|
#16 | ip_geoloc.statistics.zip | 1.74 KB | mondrake |
#8 | bs_browscap.zip | 2.79 KB | mondrake |
#2 | better_statistics-create_statistics_api-1779204-1.patch | 10.35 KB | iamEAP |
Comments
Comment #1
iamEAP CreditAttribution: iamEAP commentedPosting progress so far. This does the following:
Still to be done:
Comment #2
iamEAP CreditAttribution: iamEAP commentedWhoops. Here's the patch.
Comment #3
mondrakeVery promisiing...
I got your patch above and tested it OK.
I'd suggest a couple of points -
a) include in every field an identification of the module where it is originating from
b) include an 'enabled' flag for each field
The idea could be to have each module to present its own 'full menu' of fields (with enabled flag preset by module developer), and an admin form in better_statistics where admins will cherry pick the fields they really need to make statistics upon.
What do you think? I may propose some patch here (when I have some time)...
Comment #4
iamEAP CreditAttribution: iamEAP commentedRegarding a: this won't be necessary within the field array itself, since we can get that information by looping through the results of module_implements(). Definitely worth having, though.
Regarding b: I keep going back and forth on this. Ultimately, I think it's a good idea. When it's implemented, I also think it'd be a great way to get rid of those three extra hook implementations that call the single field alteration function. This way, instead of updating db schema on either flush caches/module enable/disable, it would just be on saving the admin form.
Some other problems that came up while I was thinking about it:
Thanks for the thoughts, mondrake.
Comment #5
iamEAP CreditAttribution: iamEAP commentedI've pushed a huge change into the 7.x-1.x dev branch that implements the API I suggested. Mondrake, please have a look and let me know of any bugs or anything I may have overlooked. Since this could be extremely handy elsewhere, a few more eyes would be great too. If you can, please refer others.
I put a significant amount of work into documentation; for that, please see better_statistics.api.php.
Otherwise, I'll also update the issue summary above to reflect the new information.
Comment #6
mondrakeHi and thanks for that. Brilliant.
Very first thoughts, will test more later in the week. Please take them as they are :)
a) if I understand right the callback ony takes the field name as the argument. However, we would need at least another argument to be taken. For instance, I was trying a micromodule for integrating Browscap with just the hook implementation + a data fetching function. In order to get the name of the browser I would need to pass the field name to be returned, plus the user-agent string which is used by browscap to fetch the info. In other words instead of
something like
Or maybe I am missing something...
b) how about introducing also a 'file' entry to the api to specifiy a file where the callback fucntion is coded? Like Forms API.
c)did not look in detail, but wouldn't it make sense to unify what _better_statistics_update_fields() and _better_statistics_settings_form_submit() do to the db and the schema, and call cache flush to trigger it from form submission? I was coming to it from the fact that after _better_statistics_settings_form_submit() there is no cache flush (and I have a module that caches the structure of the tables...)
d) for some reason I get a PDO exception when adding my hooked field -
In terms of spreading the news and getting reviews - I was thinking about preparing a couple of test modules for integrating Browscap (I started that, if you can give hints as to point sub (a) above it will get ready quickly) and IP Geolocation, and then posting in those modules' issue queues a proposal to integrate. What's your view?
Comment #7
mondrakeOops - just realised I can get around point a) in #6 above... at least for Browscap and IP Geolocation. The $_SERVER variable would provide user agent and remote address...
Maybe a) could stay just as an option.
... and on (d)...
I was specifying 'not null' = TRUE but without specifying a default value for the field ... sorry for that :(
Comment #8
mondrakeHi iamEAP,
I am leaving all the story above, just as a reference. Please let me know if this is too much and I will edit/remove anything unnecessary.
Here attached, an example of a micro-module to 'bridge' between Better Statistics and Browscap. It is already making me happy :)
Will test further, just two observations on top of above:
e) in the admin form, it may be worth having each module's exposed fields in a collapsible fieldset, as the list tends to grow
f) if you play around with adding/removing fields, then a cache flush is needed to have a proper list exposed in Views - if you don't, then the View keeps fields already removed in the list
Cheers
Comment #9
iamEAP CreditAttribution: iamEAP commentedWow, thanks for the very detailed review, mondrake!
a) In some of the older code I posted previously, I tried using a "callback_argument," but because of the way the API is engineered, it could only be a static value, even though the way it's declared makes it seem like it could be dynamic (i.e. setting
$fields['my_field']['callback_argument'] = my_function()
, which would work once and then permanently "cache" the value it returned). As a result, I just decided to get rid of the callback argument and force the declared callback function to take the field name as an argument. That way, in your callback function, you could set up a very simple switch/case; or, if that was still undesirable for whatever reason, you could specify different callback functions for each field and just ignore the field argument passed to them. Hopefully it's flexible enough how it is; it would require some non-trivial reengineering otherwise.b) I like this idea, especially having seen your mini browscap integration module. Sounds like what might be best is to take cues from Views, Rules, et al. and introduce the concept of a my_module.statistics.inc file that gets autoloaded when needed. That way, the stats API code and callback won't have to clutter up the main module and those who don't want it or don't have Better Statistics installed won't have to care. I created an issue for that here: #1786896: Allow Stats API code to live in a module.statistics.inc file
c) It might be a good addition to call _better_statistics_update_fields() in the form submit, but the cases where that would need to happen would be pretty small. I don't think it would be necessary to flush the entire cache each time that form was saved. My only apprehension is having multiple, separate variable saves, but that issue can be worked out. Issue created here: #1786900: Better Stats field update code might also need running on configuration save
d) I ran into this a couple of times myself. I thought it was appropriate to fail gracefully in the case of a schema updates (since this would be happening, at least currently, when an admin was performing seemingly unrelated actions), but I think the schema add should fail hard like you saw so that developers can catch them before general release.
e) Good idea! Issue here: #1786906: Make each module's checkboxes a collapsible fieldset
f) This probably goes hand in hand with c above, though again, I don't think a full cache flush on saving that form is necessarily a good idea. I think it's best to just clear whatever caching mechanism Views uses for the field list and call it good. Issue here: #1786910: Views can list invalid fields after adding/removing Better Stats fields
Thanks again!
Comment #10
mondrakePosted a request to review into Browscap issue queue
#1787488: Integration with Better Statistics [Discussion]
Comment #11
mondrakejust posted a comment to #1786906: Make each module's checkboxes a collapsible fieldset, I have an issue there
Comment #12
iamEAP CreditAttribution: iamEAP commentedJust saw, and taken care of with a recent commit.
I'm signing off for the evening now, but everything in dev should be a little more stable. I'd checkout the repo directly for the latest, or if you'd prefer, wait for the Sept 19th dev package.
All of your major points above should be addressed now, so consider what's up in the repo (or the Sept 19th dev package) to be a release candidate.
I used your browscap work above to test the new hook_statistics_api() functionality, so you might try that out. See the documentation at #1786896: Allow Stats API code to live in a module.statistics.inc file
Thanks again!
Comment #13
mondrakeThanks!
I suppose you developed a patch for Browscap then, with a browscap.statistics.inc file including more or less the contents of the mini-module, and a change to the browscap.module to implement browscap_statistics_api().
Can you please share if so? When we'll be happy and tested, and the new release of Better Statistics on air, we could then post it to Browscap's #1787488: Integration with Better Statistics [Discussion] issue I opened asking for it to be included there.
Comment #14
iamEAP CreditAttribution: iamEAP commentedAll I did was take your module, stick it in browscap.statistics.inc, and add the following code to browscap.module:
I'll let you do the honors (once Better Statistics 7.x-1.1 is released) since you put all of the effort into making the thing.
Comment #15
mondrakeGot it, thanks.
Just a question - ctools dependency is only for Better Statistcs, right?
In other words, I understand modules do not have to put a ctools dependency in their .info file; just add the hook in .module and add the MODULE.statistics.inc file, then if the module is installed in a non-ctools (and therefore non-Better Statistics) environment, simply the add'l code will stay there idle.
Comment #16
mondrakeHi,
I've made for IP Geoloc what I already did for Browscap. I am attaching ip_geoloc.statistics.inc here for you to review if you happen to use this module.
A couple of questions, although I believe these would be off topic. Maybe you can help anyway.
1) IP Geoloc runs the geolocation routine asychronously - that means that when a user hits a page, a ajax call is launched to get the geolocation; only when this is available, the lat/long and address are associated to the IP address and stored in a table. This requires some time, so most likely at the time when Better Statistics is getting the data for storing in the acceslog, this would not be available yet. For the time being I was thinking about trying to hook in the routines that update the info associated to the IP address when the ajax call is completed, and at that time fetch all the accesslog entries for that IP address that were created 'blank', and rewriting them back with the freshly received information. Definitely to be raised to the IP Geoloc maintainer when posting a request to integrate, but was wondering if you have any idea here.
2) Hopefully more trivial :) connected to my limited knowledge of Views - I can see now all the accesslog fields to be selected but for the user id and name... am I doing anything wrong? If I had those I could have a neat replacement to the core Recent hits report, inclusive of Browscap and IP Geoloc fields...
Thanks for your great work
Comment #17
iamEAP CreditAttribution: iamEAP commented0) Correct. You will only need ctools for the Better Statistics module. If a module (like Browscap or IP Geoloc) specifies a hook_statistics_api() and has a module.statistics.inc file, but they don't have Better Statistics (or ctools), the module.statistics.inc file will never be loaded.
1) Hmm. Very cool that they're pulling the data asynchronously that way, but definitely more difficult for integration. I think that what you described may be the only good option; I don't know the specifics of how the module works, but it might be worth running the data update on cron instead of what you described? Hard to say without diving in. I don't know how the module handles it now, but the most performant way to do the statistics side is to keep whatever geo data it returns in a cookie (once it's loaded) and in the statistics callback, just pull it from the cookie. Another, very useful integration point here would be a way for Views to take that data from accesslog and place points on a map. That level of Views API work is beyond me, though.
2)
This looks to be a bug.I could've sworn this field was available by default without Better Stats installed, but I guess not. It's not a bug, you just have to go to the "Advanced" fieldset in the right of the Views UI and add a user relationship.Comment #18
iamEAP CreditAttribution: iamEAP commentedEdit: wrong tab...
Comment #19
mondrakeHi
two days with Better Statistics + Browscap + IP Geoloc integrations running on my test env; quite smooth.
Thanks for your replies in #17. Here's my Views' based replacement of core's Recent hits report :)
Just an example for anyone reviewing these posts.
Comment #20
mondrake... and the bad news: I got
PDOException: SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'rendering_engine_description' at row 1: INSERT INTO {accesslog} (aid, sid, title, path, url, hostname, uid, timer, timestamp, user_agent, device_name, device_maker, is_mobile_device, ...
when the string returned from the callback is longer than what the db field can take. This is worse than @ #6.d because it happens at page hit time, not at config time. I fixed by changing the field definition in the statistics.inc file from varchar to text - but believe we cannot assume that the callbacks will always behave. How about wrapping the db_insert in the better_statistics_exit() function in a try/catch block?
Cheers
Comment #21
iamEAP CreditAttribution: iamEAP commentedProbably a good idea. Since the schema is available at that point anyway, it might be worth doing a runtime check for strlen of the callback return vs. length of the declared schema (if one exists). Opened #1790836: Fail gracefully if db insert in hook_exit() fails for some reason
Comment #22
iamEAP CreditAttribution: iamEAP commentedOne thing I haven't tested, but I think should be tested, is what happens in the event that someone has 7.x-1.0 installed, somehow doesn't have ctools installed, and then updates to 7.x-1.1. I'm going to guess Drupal will error out in a very bad way.
Comment #23
mondrakePosted a request to review into IP Geolocation issue queue
#1791526: Integration with Better Statistics
Comment #24
iamEAP CreditAttribution: iamEAP commentedBelieve most of the kinks have been ironed out at this point. If you don't have any objections, mondrake, I'd like to release 7.x-1.1 with the API. Then we can focus on those integrations; if there are any other issues, we can handle them in the usual way.
Comment #25
mondrakeThanks. Let's roll :)
Please have a look at #1791068: Provide an enhanced 'Recent hit details' page when you can.
Comment #26
iamEAP CreditAttribution: iamEAP commentedTag pushed up; release to come shortly. Thanks again for all your help, mondrake! Let's see about getting the browscap and IP Gelocation integrations underway.
http://drupal.org/node/1792876
Comment #27
mondrakeHi
I started to propose patches to Browscap and IP Geoloc. Issues
#1787488: Integration with Better Statistics [Discussion]
and
#1791526: Integration with Better Statistics
I really trust you'll be following and contributing :))
Thanks for the credits in your release notes!
Comment #28.0
(not verified) CreditAttribution: commentedUpdating how the API is used.