Merge branch 'saas' into saas-cloud-storage-config-per-dev-env
Conflicts: python_apps/airtime_analyzer/airtime_analyzer/analyzer_pipeline.py python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader.py python_apps/airtime_analyzer/airtime_analyzer/message_listener.py
This commit is contained in:
commit
c6fc184559
14 changed files with 322 additions and 39 deletions
|
@ -86,3 +86,5 @@ define('SOUNDCLOUD_ERROR' , -3);
|
|||
define("WHMCS_API_URL", "https://account.sourcefabric.com/includes/api.php");
|
||||
define("SUBDOMAIN_WHMCS_CUSTOM_FIELD_NAME", "Choose your domain");
|
||||
|
||||
//Sentry error logging
|
||||
define('SENTRY_CONFIG_PATH', '/etc/airtime-saas/sentry.airtime_web.ini');
|
|
@ -115,7 +115,7 @@ class ApiController extends Zend_Controller_Action
|
|||
header('Content-Disposition: inline; filename="'.$filename.'"');
|
||||
}
|
||||
|
||||
$this->smartReadFile($media);
|
||||
$this->readStoredFileObject($media);
|
||||
exit;
|
||||
} else {
|
||||
header ("HTTP/1.1 404 Not Found");
|
||||
|
@ -124,29 +124,53 @@ class ApiController extends Zend_Controller_Action
|
|||
|
||||
$this->_helper->json->sendJson(array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Read data from StoredFile object and send with XHR response
|
||||
*
|
||||
* @param Application_Model_StoredFile $storedFile - StoredFile object holding file information
|
||||
*/
|
||||
private function readStoredFileObject($storedFile) {
|
||||
$filepath = $storedFile->getFilePath();
|
||||
$size = $storedFile->getFileSize();
|
||||
$mimeType = $storedFile->getPropelOrm()->getDbMime();
|
||||
|
||||
$this->smartReadFile($filepath, $mimeType, $size);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads the requested portion of a file and sends its contents to the client with the appropriate headers.
|
||||
*
|
||||
* This HTTP_RANGE compatible read file function is necessary for allowing streaming media to be skipped around in.
|
||||
*
|
||||
* @param string $location
|
||||
* @param string $mimeType
|
||||
* @param string $location - the full filepath pointing to the location of the file
|
||||
* @param string $mimeType - the file's mime type. Defaults to 'audio/mp3'
|
||||
* @param integer $size - the file size, in bytes
|
||||
* @return void
|
||||
*
|
||||
* @link https://groups.google.com/d/msg/jplayer/nSM2UmnSKKA/Hu76jDZS4xcJ
|
||||
* @link http://php.net/manual/en/function.readfile.php#86244
|
||||
*/
|
||||
public function smartReadFile($media)
|
||||
private function smartReadFile($location, $mimeType = 'audio/mp3', $size = null)
|
||||
{
|
||||
$filepath = $media->getFilePath();
|
||||
$size= $media->getFileSize();
|
||||
$mimeType = $media->getPropelOrm()->getDbMime();
|
||||
|
||||
$fm = @fopen($filepath, 'rb');
|
||||
if (!$location || $location == "") {
|
||||
throw new FileDoesNotExistException("Requested file does not exist!");
|
||||
}
|
||||
|
||||
// If we're passing in a Stored File object, it's faster
|
||||
// to use getFileSize() and pass in the result
|
||||
if (!$size || $size <= 0) {
|
||||
$size= filesize($location);
|
||||
}
|
||||
|
||||
if ($size <= 0) {
|
||||
throw new Exception("Invalid file size returned for file at $location");
|
||||
}
|
||||
|
||||
$fm = @fopen($location, 'rb');
|
||||
if (!$fm) {
|
||||
header ("HTTP/1.1 505 Internal server error");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -299,7 +299,7 @@ class ShowbuilderController extends Zend_Controller_Action
|
|||
$log_vars["params"]["media_items"] = $mediaItems;
|
||||
$log_vars["params"]["scheduled_items"] = $scheduledItems;
|
||||
Logging::info($log_vars);
|
||||
|
||||
|
||||
try {
|
||||
$scheduler = new Application_Model_Scheduler();
|
||||
$scheduler->scheduleAfter($scheduledItems, $mediaItems);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
require_once('SentryLogging.php');
|
||||
|
||||
class Logging {
|
||||
|
||||
|
@ -82,6 +83,7 @@ class Logging {
|
|||
{
|
||||
$logger = self::getLogger();
|
||||
$logger->err(self::getLinePrefix(true) . self::toString($p_msg));
|
||||
SentryLogger::getInstance()->captureError(self::toString($p_msg));
|
||||
}
|
||||
|
||||
public static function debug($p_msg)
|
||||
|
@ -123,4 +125,49 @@ class Logging {
|
|||
Propel::setLogger(null);
|
||||
}
|
||||
|
||||
public static function loggingShutdownCallback()
|
||||
{
|
||||
//Catch the types of errors that PHP doesn't normally let us catch and
|
||||
//would otherwise log to the apache log. We route these to our Airtime log to improve the modularity
|
||||
//and reliability of our error logging. (All errors are in one spot!)
|
||||
$err = error_get_last();
|
||||
if (!is_array($err) || !array_key_exists('type', $err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch($err['type'])
|
||||
{
|
||||
case E_ERROR:
|
||||
case E_PARSE:
|
||||
case E_CORE_ERROR:
|
||||
case E_CORE_WARNING:
|
||||
case E_COMPILE_ERROR:
|
||||
case E_COMPILE_WARNING:
|
||||
//error_log("Oh noes, a fatal: " . var_export($err, true), 1, 'fatals@example.com');
|
||||
$errorStr = '';
|
||||
if (array_key_exists('message', $err)) {
|
||||
$errorStr .= $err['message'];
|
||||
}
|
||||
if (array_key_exists('file', $err))
|
||||
{
|
||||
$errorStr .= ' at ' .$err['file'];
|
||||
}
|
||||
if (array_key_exists('line', $err))
|
||||
{
|
||||
$errorStr .= ':' . $err['line'];
|
||||
}
|
||||
|
||||
$errorStr .= "\n" . var_export($err, true);
|
||||
Logging::error($errorStr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static function setupParseErrorLogging()
|
||||
{
|
||||
//Static callback:
|
||||
register_shutdown_function('Logging::loggingShutdownCallback');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
131
airtime_mvc/application/logging/SentryLogging.php
Normal file
131
airtime_mvc/application/logging/SentryLogging.php
Normal file
|
@ -0,0 +1,131 @@
|
|||
<?php
|
||||
|
||||
class SentryLogger
|
||||
{
|
||||
private static $instance = null;
|
||||
private $sentryClient;
|
||||
|
||||
/** Singleton getter */
|
||||
public static function getInstance()
|
||||
{
|
||||
if (!is_null(self::$instance)) {
|
||||
return self::$instance;
|
||||
} else {
|
||||
self::$instance = new SentryLogger();
|
||||
return self::$instance;
|
||||
}
|
||||
}
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
if (!file_exists(SENTRY_CONFIG_PATH)) {
|
||||
$this->sentryClient = null;
|
||||
return;
|
||||
}
|
||||
// Instantiate a new client with a compatible DSN
|
||||
$sentry_config = parse_ini_file(SENTRY_CONFIG_PATH, false);
|
||||
$dsn = $sentry_config['dsn'];
|
||||
$this->sentryClient = new Raven_Client($dsn,
|
||||
array(
|
||||
//FIXME: This doesn't seem to be working...
|
||||
'processorOptions' => array(
|
||||
'Raven_SanitizeDataProcessor' => array(
|
||||
'fields_re' => '/(authorization|password|passwd|user_token|secret|WHMCS_|SESSION)/i',
|
||||
'values_re' => '/^(?:\d[ -]*?){13,16}$/'
|
||||
)
|
||||
)
|
||||
));
|
||||
$client = $this->sentryClient;
|
||||
|
||||
/* The Raven docs suggest not enabling these because they're "too noisy".
|
||||
// Install error handlers and shutdown function to catch fatal errors
|
||||
$error_handler = new Raven_ErrorHandler($client);
|
||||
$error_handler->registerExceptionHandler(true);
|
||||
$error_handler->registerErrorHandler(true);
|
||||
$error_handler->registerShutdownFunction(true);
|
||||
*/
|
||||
$error_handler = new Raven_ErrorHandler($client);
|
||||
$error_handler->registerExceptionHandler();
|
||||
}
|
||||
|
||||
public function captureMessage($msg)
|
||||
{
|
||||
if (!$this->sentryClient) {
|
||||
return;
|
||||
}
|
||||
$client = $this->sentryClient;
|
||||
self::addUserData($client);
|
||||
self::addTags($client);
|
||||
|
||||
// Capture a message
|
||||
$event_id = $client->getIdent($client->captureMessage($msg));
|
||||
if ($client->getLastError() !== null) {
|
||||
//printf('There was an error sending the event to Sentry: %s', $client->getLastError());
|
||||
}
|
||||
}
|
||||
|
||||
public function captureException($exception)
|
||||
{
|
||||
if (!$this->sentryClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
$client = $this->sentryClient;
|
||||
self::addUserData($client);
|
||||
self::addTags($client);
|
||||
|
||||
$event_id = $client->getIdent($client->captureException($exception, array(
|
||||
'extra' => $this->getExtraData(),
|
||||
'tags' => $this->getTags(),
|
||||
)));
|
||||
$client->context->clear();
|
||||
}
|
||||
|
||||
public function captureError($errorMessage)
|
||||
{
|
||||
if (!$this->sentryClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
$client = $this->sentryClient;
|
||||
|
||||
// Provide some additional data with an exception
|
||||
self::addUserData($client);
|
||||
self::addTags($client);
|
||||
$event_id = $client->getIdent($client->captureMessage($errorMessage, array(
|
||||
'extra' => $this->getExtraData()
|
||||
)));
|
||||
$client->context->clear();
|
||||
}
|
||||
|
||||
private static function getTags()
|
||||
{
|
||||
$tags = array();
|
||||
$config = Config::getConfig();
|
||||
$tags['Development Environment'] = $config["dev_env"];
|
||||
return $tags;
|
||||
}
|
||||
|
||||
private static function addTags($client)
|
||||
{
|
||||
$client->tags_context(self::getTags());
|
||||
}
|
||||
|
||||
private static function addUserData($client)
|
||||
{
|
||||
$userData = array();
|
||||
$userData['client_id'] = Application_Model_Preference::GetClientId();
|
||||
$userData['station_url'] = array_key_exists('SERVER_NAME', $_SERVER) ? $_SERVER['SERVER_NAME'] : "";
|
||||
$client->user_context($userData);
|
||||
}
|
||||
|
||||
/** Extra data to log with Sentry */
|
||||
private function getExtraData()
|
||||
{
|
||||
$extraData = array();
|
||||
$extraData['php_version'] = phpversion();
|
||||
$extraData['client_id'] = Application_Model_Preference::GetClientId();
|
||||
return $extraData;
|
||||
}
|
||||
|
||||
}
|
|
@ -79,6 +79,7 @@ $application = new Zend_Application(
|
|||
|
||||
require_once (APPLICATION_PATH."/logging/Logging.php");
|
||||
Logging::setLogPath('/var/log/airtime/zendphp.log');
|
||||
Logging::setupParseErrorLogging();
|
||||
|
||||
// Create application, bootstrap, and run
|
||||
try {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue