Skip to content

Commit

Permalink
Merge pull request #13 from zumba/add-troubleshooting
Browse files Browse the repository at this point in the history
Add way to troubleshoot connection problems when tracking an event
  • Loading branch information
jrbasso committed May 3, 2016
2 parents 94f3364 + 437c137 commit bbca31d
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 10 deletions.
83 changes: 83 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,89 @@ $amplitude->init('APIKEY', '[email protected]')
// This is a simple example to get you started, see the rest of the readme for more examples
```

## Getting Started & Troubleshooting

When you are initially getting your application set up, if you do not see your event show up in Amplitude, you may need to do a little troubleshooting. Normally your indication that "it worked" is when you see your event show up in your Amplitude app for the first time.

If you never see that first event show up, you can see what Amplitude's response is when the event is logged. This may help find and fix the problem (such as an invalid API key, PHP environment errors, connection problems, etc.)

Amplitude uses `Psr\Logger` for logging the communication with the Amplitude HTTP API. You can take advantage of this by setting a logger (using `$amlitude->setLogger()`) to help catch any problems.

### Stand-alone Troubleshooting Script

Below is a stand-alone script, meant to be copied into a PHP file at the root of your application's document root. Just change the `APIKEY` and if needed, adjust the line that requires the `autoload.php` file for composer. Then visit the script's URL from a browser to see any messages logged.

```php
<?php
// Stand-alone Amplitude troubleshooting script - just change APIKEY in next line
$apikey = 'APIKEY';

// Composer Autoloader - If new to composer, see https://getcomposer.org
require __DIR__ . '/vendor/autoload.php';

// Make sure if there is some error, we will see it
ini_set('display_errors', true);
error_reporting(E_ALL);

// Quick logger to display log messages - NOT for production use, this displays log message to the browser
class ChattyLogger extends \Psr\Log\AbstractLogger
{
public function log($level, $message, array $context = [])
{
echo "<p><strong>".ucfirst($level).":</strong> $message<br>";
if (!empty($context)) {
echo '<strong>Context:</strong><br><span class="code">'.print_r($context,true).'</span>';
}
}
}

$chatty = new ChattyLogger();
// Test logging an event
?>
<style>
.code {
display: inline-block;
border: 1px solid #a7a7a7;
padding: 15px;
margin: 0 5px;
background-color: #eaeaea;
white-space: pre;
}
p {
padding-bottom: 5px;
border-bottom: thin dashed gray;
}
</style>
<h1>Testing Amplitude Log Event Response</h1>
<h2>API Key: '<?= $apikey ?>'</h2>
<?php
$amplitude = new \Zumba\Amplitude\Amplitude();

// Add the chatty logger so we can see log messages
$amplitude->setLogger($chatty);

// Initialize Amplitude with the API key and a dummy test user ID
$amplitude->init($apikey, 'TEST-USER-ID');

$chatty->info('Calling $amplitude->logEvent(\'TEST EVENT\')...');

// Log a test event
$amplitude->logEvent('TEST EVENT');

$chatty->info('Done logging event');
```

### Troubleshooting Tips

* The Amplitude library will throw a `LogicException` for any problems caused by errors in the code, for instance if you try to log an event without setting the API key first, or try to log an event without specifying the event type. Make sure your server's error logging is set up to display (or otherwise log) any exceptions that might be thrown so that you can see if there is a coding error causing a problem.
* Make sure PHP error logging is enabled (or display errors is enabled), so you can see any PHP errors that may point to the problem.
* Use the `setLogger(...)` method in amplitude to use your app's logging or your own custom logger like the standalone test script above. As long as it implements the `Psr\Log\LoggerInterface`.
* If no logs are generated: It did not attempt to send an event after the point your app's logger was set, or the event was logged using a different instance that does not have a logger set.
* If you see `Curl error:` logged: then something went wrong when it tried to send the request, the error message and context should help point to the problem.
* If there are no curl errors, it will log a message starting with `Amplitude HTTP API response:`:
* `success` with `httpCode = 200` : Amplitude got the request and the event should have been logged. If you are not seeing it in Amplitude, check again after a few minutes, sometimes Amplitude can lag a little behind.
* Anything Else: The event was not logged successfully, refer to the message and context to help troubleshoot the problem.

# Logging Anonymous Users

Since this is a PHP SDK, there are a lot of options for tracking Anonymous users. Since this could be run in CLI mode or as a cron job, this SDK does not handle sessions for you.
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
}
],
"require": {
"php": ">=5.4"
"php": ">=5.4",
"psr/log": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "4.8.*",
Expand Down
57 changes: 48 additions & 9 deletions src/Amplitude.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
<?php
namespace Zumba\Amplitude;

use Psr\Log;

class Amplitude
{
use Log\LoggerAwareTrait;

const AMPLITUDE_API_URL = 'https://api.amplitude.com/httpapi';

const EXCEPTION_MSG_NO_API_KEY = 'API Key is required to log an event';
Expand Down Expand Up @@ -58,6 +62,20 @@ class Amplitude
*/
protected $optOut = false;

/**
* Flag for if should save the last HTTP response for debugging purposes
*
* @var boolean True to enable saving the last response
*/
protected $debugResponse = false;

/**
* Last response from logging event
*
* @var array|null
*/
protected $lastHttpResponse;

/**
* Array of Amplitude instances
*
Expand All @@ -81,6 +99,7 @@ class Amplitude
* - User Properties
* - Event Queue (if events are queued before the amplitude instance is initialized)
* - Event object - for the next event that will be sent or queued
* - Logger
* - Opt out status
*
* @param string $instanceName Optional, can use to maintain multiple singleton instances of amplitude, each with
Expand All @@ -99,12 +118,15 @@ public static function getInstance($instanceName = 'default')
* Constructor, optionally sets the api key
*
* @param string $apiKey
* @param \Psr\Log $logger
*/
public function __construct($apiKey = null)
{
if (!empty($apiKey)) {
$this->apiKey = (string)$apiKey;
}
// Initialize logger to be null logger
$this->setLogger(new Log\NullLogger());
}

/**
Expand Down Expand Up @@ -456,27 +478,44 @@ public function getOptOut()
*
* Requres $this->event and $this->apiKey to be set, otherwise it throws an exception.
*
* @return integer|boolean HTTP Status code or boolean false if problem making connection
* @return void
* @throws \InternalErrorException If event or api key not set
*/
protected function sendEvent()
{
if (empty($this->event) || empty($this->apiKey)) {
throw new \InternalErrorException('Event or api key not set, cannot send event');
}
$ch = curl_init(static::AMPLITUDE_API_URL);
if (!$ch) {
// Could be a number of PHP environment problems, log a critical error
$this->logger->critical(
'Call to curl_init(' . static::AMPLITUDE_API_URL . ') failed, unable to send Amplitude event'
);
return;
}
$postFields = [
'api_key' => $this->apiKey,
'event' => json_encode($this->event),
];
$ch = curl_init(static::AMPLITUDE_API_URL);
if (!$ch) {
return false;
}
curl_setopt($ch, \CURLOPT_POSTFIELDS, $postFields);
curl_exec($ch);

$status = curl_getinfo($ch, \CURLINFO_HTTP_CODE);
// Always return instead of outputting response!
curl_setopt($ch, \CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$curlErrno = curl_errno($ch);
if ($curlErrno) {
$this->logger->critical(
'Curl error: ' . curl_error($ch),
compact('curlErrno', 'response', 'postFields')
);
} else {
$httpCode = curl_getinfo($ch, \CURLINFO_HTTP_CODE);
$this->logger->log(
$httpCode === 200 ? Log\LogLevel::INFO : Log\LogLevel::ERROR,
'Amplitude HTTP API response: ' . $response,
compact('httpCode', 'response', 'postFields')
);
}
curl_close($ch);
return (int)$status;
}
}

0 comments on commit bbca31d

Please sign in to comment.