diff --git a/composer.json b/composer.json new file mode 100755 index 0000000..749a8f6 --- /dev/null +++ b/composer.json @@ -0,0 +1,6 @@ +{ + "require": { + "rollbar/rollbar": "0.18.2", + "psr/log": "dev-master" + } +} \ No newline at end of file diff --git a/logs_http.admin.inc b/logs_http.admin.inc index 1f020c2..d3da685 100644 --- a/logs_http.admin.inc +++ b/logs_http.admin.inc @@ -18,11 +18,34 @@ function logs_http_admin_settings($form, &$form_state) { $form['logs_http_url'] = array( '#type' => 'textfield', + '#size' => 100, '#title' => t('Endpoint'), '#description' => t('The URL to POST the data to.'), '#default_value' => variable_get('logs_http_url', NULL), ); + $form['logs_http_use_rollbar'] = array( + '#type' => 'checkbox', + '#title' => t('Use rollbar API'), + '#description' => t('Enable Logs HTTP POST for rollbar'), + '#default_value' => variable_get('logs_http_use_rollbar', FALSE), + ); + + $form['logs_http_rollbar_access_token'] = array( + '#type' => 'textfield', + '#size' => 100, + '#title' => t('Rollbar Server Access Token'), + '#default_value' => variable_get('logs_http_rollbar_access_token', NULL), + ); + + $form['logs_http_rollbar_access_token_js'] = array( + '#type' => 'textfield', + '#size' => 100, + '#title' => t('Rollbar Client Access Token (javascript)'), + '#description' => t('Type 0 to disable'), + '#default_value' => variable_get('logs_http_rollbar_access_token_js', 0), + ); + $options = array( WATCHDOG_EMERGENCY => t('Emergency'), WATCHDOG_ALERT => t('Alert'), @@ -46,7 +69,7 @@ function logs_http_admin_settings($form, &$form_state) { '#type' => 'textfield', '#title' => t('Unique ID'), '#description' => t('An arbitrary ID that will identify the environment.'), - '#default_value' => variable_get('logs_http_uuid'), + '#default_value' => variable_get('development'), ); return system_settings_form($form); diff --git a/logs_http.module b/logs_http.module index 1f0cf79..59d5739 100644 --- a/logs_http.module +++ b/logs_http.module @@ -99,18 +99,114 @@ function logs_http_shutdown() { $url = logs_http_get_http_url(); + // Post to rollbar. + if (variable_get('logs_http_use_rollbar', FALSE)) { + logs_http_rollbar_post($events, $url); + } + // Regular logging. + else { + // Send events to logs. + foreach ($events as $event) { + $options = array( + 'method' => 'POST', + 'data' => drupal_json_encode($event), + ); + + // Send data to Logs. + $response = drupal_http_request($url, $options); + } + } +} + +/** + * Run rollbar API + */ +function logs_http_rollbar_post($events, $url) { + global $user; + $config = array( + // required + 'access_token' => variable_get('logs_http_rollbar_access_token', NULL), + 'local_username' => isset($user->name) ? $user->name : 'anonymous', + // optional - environment name. any string will do. + 'environment' => variable_get('logs_http_uuid', 'development'), + 'base_api_url' => $url, + ); + // Log with Rollbar + Rollbar::init($config); + // Send events to logs. foreach ($events as $event) { - $options = array( - 'method' => 'POST', - 'data' => drupal_json_encode($event), - ); - // Send data to Logs. - $response = drupal_http_request($url, $options); + switch ($event['severity']) { + case WATCHDOG_ALERT: + case WATCHDOG_CRITICAL: + case WATCHDOG_EMERGENCY: + case WATCHDOG_ERROR: + $level = 'error'; + break; + case WATCHDOG_WARNING: + $level = 'warning'; + break; + case WATCHDOG_INFO: + case WATCHDOG_DEBUG: + case WATCHDOG_NOTICE: + $level = 'info'; + break; + default: + $level = 'info'; + break; + } + Rollbar::report_message("{$event['type']} : {$event['message']}", $level, $event); } } +/** + * Implements hook_init(). + */ +function logs_http_init() { + + // If php support is turned off then return. + if (!variable_get('logs_http_rollbar_access_token_js', 0)) { + return; + } + // If not disabled. + if (!$url = logs_http_get_http_url()) { + return; + } + // Client settings. + $token = check_plain(variable_get('logs_http_rollbar_access_token_js', '')); + $env = check_plain(variable_get('logs_http_uuid', 'development')); + + // I had some issues appending this via jQuery and using Drupal.behaviors, + // so have opted to use javascript, in line with Rollbar.com + // documentation this is essentially an exact copy of the code + // located @ https://rollbar.com/docs/items_js/ + $js = " + var _rollbarConfig = { + accessToken:\"" . $token . "\", + captureUncaught: true, + captureUnhandledRejections: true, + endpoint: \"" . $url . "\", + payload: { + environment:\"" . $env . "\" + } + }; + // Rollbar Snippet + !function(r){function e(n){if(o[n])return o[n].exports;var t=o[n]={exports:{},id:n,loaded:!1};return r[n].call(t.exports,t,t.exports,e),t.loaded=!0,t.exports}var o={};return e.m=r,e.c=o,e.p=\"\",e(0)}([function(r,e,o){\"use strict\";var n=o(1).Rollbar,t=o(2);_rollbarConfig.rollbarJsUrl=_rollbarConfig.rollbarJsUrl||\"https://cdnjs.cloudflare.com/ajax/libs/rollbar.js/1.9.4/rollbar.min.js\";var a=n.init(window,_rollbarConfig),i=t(a,_rollbarConfig);a.loadFull(window,document,!_rollbarConfig.async,_rollbarConfig,i)},function(r,e){\"use strict\";function o(r){return function(){try{return r.apply(this,arguments)}catch(r){try{console.error(\"[Rollbar]: Internal error\",r)}catch(r){}}}}function n(r,e,o){window._rollbarWrappedError&&(o[4]||(o[4]=window._rollbarWrappedError),o[5]||(o[5]=window._rollbarWrappedError._rollbarContext),window._rollbarWrappedError=null),r.uncaughtError.apply(r,o),e&&e.apply(window,o)}function t(r){var e=function(){var e=Array.prototype.slice.call(arguments,0);n(r,r._rollbarOldOnError,e)};return e.belongsToShim=!0,e}function a(r){this.shimId=++c,this.notifier=null,this.parentShim=r,this._rollbarOldOnError=null}function i(r){var e=a;return o(function(){if(this.notifier)return this.notifier[r].apply(this.notifier,arguments);var o=this,n=\"scope\"===r;n&&(o=new e(this));var t=Array.prototype.slice.call(arguments,0),a={shim:o,method:r,args:t,ts:new Date};return window._rollbarShimQueue.push(a),n?o:void 0})}function l(r,e){if(e.hasOwnProperty&&e.hasOwnProperty(\"addEventListener\")){var o=e.addEventListener;e.addEventListener=function(e,n,t){o.call(this,e,r.wrap(n),t)};var n=e.removeEventListener;e.removeEventListener=function(r,e,o){n.call(this,r,e&&e._wrapped?e._wrapped:e,o)}}}var c=0;a.init=function(r,e){var n=e.globalAlias||\"Rollbar\";if(\"object\"==typeof r[n])return r[n];r._rollbarShimQueue=[],r._rollbarWrappedError=null,e=e||{};var i=new a;return o(function(){if(i.configure(e),e.captureUncaught){i._rollbarOldOnError=r.onerror,r.onerror=t(i);var o,a,c=\"EventTarget,Window,Node,ApplicationCache,AudioTrackList,ChannelMergerNode,CryptoOperation,EventSource,FileReader,HTMLUnknownElement,IDBDatabase,IDBRequest,IDBTransaction,KeyOperation,MediaController,MessagePort,ModalWindow,Notification,SVGElementInstance,Screen,TextTrack,TextTrackCue,TextTrackList,WebSocket,WebSocketWorker,Worker,XMLHttpRequest,XMLHttpRequestEventTarget,XMLHttpRequestUpload\".split(\",\");for(o=0;o 'inline', + 'scope' => 'header', + 'weight' => -99, + 'group' => JS_LIBRARY + )); +} + + /** * Register an event in a static cache. *