Skip to content

Commit

Permalink
Merge branch 'master' into github-166-capture-error-stacktraces
Browse files Browse the repository at this point in the history
  • Loading branch information
rokob authored May 31, 2017
2 parents 9462611 + c73b83d commit c522357
Show file tree
Hide file tree
Showing 10 changed files with 692 additions and 4 deletions.
6 changes: 5 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
language: php
dist: trusty

php:
- 7.0
- 5.6
- 5.5
- 5.4
- 5.3
- hhvm
matrix:
include:
- php: 5.3
dist: precise

sudo: false

Expand Down
42 changes: 41 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,39 @@ Rollbar::init(array(
?>
```

## Integration with Rollbar.js

In case you want to report your JavaScript errors using [Rollbar.js](https://github.com/rollbar/rollbar.js), you can configure the SDK to enable Rollbar.js on your site. Example:

```php
$rollbarJs = Rollbar\RollbarJsHelper::buildJs(
array(
"accessToken" => "POST_CLIENT_ITEM_ACCESS_TOKEN",
"captureUncaught" => true,
"payload" => array(
"environment" => "production"
),
/* other configuration you want to pass to RollbarJS */
)
);
```

Or if you are using Content-Security-Policy: script-src 'unsafe-inline'
```php
$rollbarJs = Rollbar\RollbarJsHelper::buildJs(
array(
"accessToken" => "POST_CLIENT_ITEM_ACCESS_TOKEN",
"captureUncaught" => true,
"payload" => array(
"environment" => "production"
),
/* other configuration you want to pass to RollbarJS */
),
headers_list(),
$yourNonceString
);
```

## Basic Usage

That's it! Uncaught errors and exceptions will now be reported to Rollbar.
Expand Down Expand Up @@ -242,9 +275,16 @@ All of the following options can be passed as keys in the `$config` array.
Default: `/var/www`
</dd>

<dt>endpoint
</dt>
<dd>The API URL to post to. Note: the URL has to end with a trailing slash.

Default: `https://api.rollbar.com/api/1/`
</dd>

<dt>base_api_url
</dt>
<dd>The base api url to post to.
<dd><strong>Deprecated (use <i>endpoint</i> instead).</strong> The base api url to post to.

Default: `https://api.rollbar.com/api/1/`
</dd>
Expand Down
1 change: 1 addition & 0 deletions data/rollbar.snippet.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 20 additions & 1 deletion src/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class Config
private $mt_randmax;

private $included_errno = ROLLBAR_INCLUDED_ERRNO_BITMASK;
private $use_error_reporting = false;

/**
* @var boolean Should debug_backtrace() data be sent with string messages
Expand Down Expand Up @@ -108,6 +109,10 @@ protected function updateConfig($c)
if (isset($c['included_errno'])) {
$this->included_errno = $c['included_errno'];
}

if (isset($c['use_error_reporting'])) {
$this->use_error_reporting = $c['use_error_reporting'];
}
}

private function setAccessToken($c)
Expand Down Expand Up @@ -169,7 +174,11 @@ private function setSender($c)
$default = "Rollbar\Senders\CurlSender";

if (array_key_exists('base_api_url', $c)) {
$c['senderOptions']['endpoint'] = $c['base_api_url'];
$c['senderOptions']['endpoint'] = $c['base_api_url'] . 'item/';
}

if (array_key_exists('endpoint', $c)) {
$c['senderOptions']['endpoint'] = $c['endpoint'] . 'item/';
}

if (array_key_exists('timeout', $c)) {
Expand Down Expand Up @@ -298,6 +307,11 @@ public function getDataBuilder()
{
return $this->dataBuilder;
}

public function getSender()
{
return $this->sender;
}

/**
* @param Payload $payload
Expand Down Expand Up @@ -354,6 +368,11 @@ public function checkIgnored($payload, $accessToken, $toLog, $isUncaught)
return true;
}

if ($this->use_error_reporting && ($errno & error_reporting()) != $errno) {
// ignore due to error_reporting level
return true;
}

if (isset($this->error_sample_rates[$errno])) {
// get a float in the range [0, 1)
// mt_rand() is inclusive, so add 1 to mt_randmax
Expand Down
6 changes: 5 additions & 1 deletion src/DataBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,9 @@ public function getExceptionTrace($exc)
$baseException = $this->getBaseException();
while ($previous instanceof $baseException) {
$chain[] = $this->makeTrace($previous, $this->includeExcCodeContext);
if ($previous->getPrevious() === $previous) {
break;
}
$previous = $previous->getPrevious();
}

Expand Down Expand Up @@ -624,7 +627,8 @@ public function getUrlProto()

if (empty($proto)) {
if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
$proto = strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']);
$proto = explode(',', strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']));
$proto = $proto[0];
} elseif (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
$proto = 'https';
} else {
Expand Down
170 changes: 170 additions & 0 deletions src/RollbarJsHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
<?php namespace Rollbar;

class RollbarJsHelper
{

protected $config;

/**
* @param array $config The array passed to he should have the same
* available options that you can find in Rollbar.js, using symbols or
* strings for the keys.
*/
public function __construct($config)
{
$this->config = $config;
}

/**
* Shortcut method for building the RollbarJS Javascript
*
* @param array $config @see addJs()
* @param string $nonce @see addJs()
*
* @return string
*/
public static function buildJs($config, $headers = null, $nonce = null)
{
$helper = new self($config);
return $helper->addJs($headers, $nonce);
}

/**
* Build Javascript required to include RollbarJS on
* an HTML page
*
* @param array $headers Response headers usually retrieved through
* headers_list() used to verify if nonce should be added to script
* tags based on Content-Security-Policy
* @param string $nonce Content-Security-Policy nonce string if exists
*
* @return string
*/
public function addJs($headers = null, $nonce = null)
{
return $this->scriptTag(
$this->configJsTag() .$this->jsSnippet(),
$headers,
$nonce
);
}

/**
* Build RollbarJS config script
*
* @return string
*/
public function configJsTag()
{
$config = isset($this->config['options']) ? $this->config['options'] : new \stdClass();
return "var _rollbarConfig = " . json_encode($config) . ";";
}

/**
* Build rollbar.snippet.js string
*
* @return string
*/
public function jsSnippet()
{
return file_get_contents(
$this->snippetPath()
);
}

/**
* @return string Path to the rollbar.snippet.js
*/
public function snippetPath()
{
return realpath(__DIR__ . "/../data/rollbar.snippet.js");
}

/**
* Should JS snippet be added to the HTTP response
*
* @param int $status
* @param array $headers
*
* @return boolean
*/
public function shouldAddJs($status, $headers)
{
return
$status == 200 &&
$this->isHtml($headers) &&
!$this->hasAttachment($headers);

/**
* @todo not sure if below two conditions will be applicable
*/
/* !env[JS_IS_INJECTED_KEY] */
/* && !streaming?(env) */
}

/**
* Is the HTTP response a valid HTML response
*
* @param array $headers
*
* @return boolean
*/
public function isHtml($headers)
{
return in_array('Content-Type: text/html', $headers);
}

/**
* Does the HTTP response include an attachment
*
* @param array $headers
*
* @return boolean
*/
public function hasAttachment($headers)
{
return in_array('Content-Disposition: attachment', $headers);
}

/**
* Is `nonce` attribute on the script tag needed?
*
* @param array $headers
*
* @return boolean
*/
public function shouldAppendNonce($headers)
{
foreach ($headers as $header) {
if (strpos($header, 'Content-Security-Policy') !== false &&
strpos($header, "'unsafe-inline'") !== false) {
return true;
}
}

return false;
}

/**
* Build safe HTML script tag
*
* @param string $content
* @param array $headers
* @param
*
* @return string
*/
public function scriptTag($content, $headers = null, $nonce = null)
{
if ($headers !== null && $this->shouldAppendNonce($headers)) {
if (!$nonce) {
throw new \Exception('Content-Security-Policy is script-src '.
'inline-unsafe but nonce value not provided.');
}

return "\n<script type=\"text/javascript\" nonce=\"$nonce\">$content</script>";
} else {
return "\n<script type=\"text/javascript\">$content</script>";
}
}
}
5 changes: 5 additions & 0 deletions src/Senders/CurlSender.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ public function __construct($opts)
$this->verifyPeer = $opts['verifyPeer'];
}
}

public function getEndpoint()
{
return $this->endpoint;
}

public function send($scrubbedPayload, $accessToken)
{
Expand Down
Loading

0 comments on commit c522357

Please sign in to comment.