From 6adaf7a91aa4f242e1c8695b5b5f142e01874479 Mon Sep 17 00:00:00 2001 From: drigato Date: Fri, 23 Jan 2015 17:33:57 -0500 Subject: [PATCH 01/17] Disabling cue point analyzer --- .../airtime_analyzer/airtime_analyzer/analyzer_pipeline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python_apps/airtime_analyzer/airtime_analyzer/analyzer_pipeline.py b/python_apps/airtime_analyzer/airtime_analyzer/analyzer_pipeline.py index bf467c190..8f1abc499 100644 --- a/python_apps/airtime_analyzer/airtime_analyzer/analyzer_pipeline.py +++ b/python_apps/airtime_analyzer/airtime_analyzer/analyzer_pipeline.py @@ -54,7 +54,7 @@ class AnalyzerPipeline: # First, we extract the ID3 tags and other metadata: metadata = dict() metadata = MetadataAnalyzer.analyze(audio_file_path, metadata) - metadata = CuePointAnalyzer.analyze(audio_file_path, metadata) + #metadata = CuePointAnalyzer.analyze(audio_file_path, metadata) metadata = ReplayGainAnalyzer.analyze(audio_file_path, metadata) metadata = PlayabilityAnalyzer.analyze(audio_file_path, metadata) metadata = FileMoverAnalyzer.move(audio_file_path, import_directory, original_filename, metadata) From ea868607b4e4997a3fdf3d1fe88c8eee87909dfa Mon Sep 17 00:00:00 2001 From: drigato Date: Tue, 27 Jan 2015 13:21:44 -0500 Subject: [PATCH 02/17] Enabling cuepoint analyzer because the silan bug has been fixed --- .../airtime_analyzer/airtime_analyzer/analyzer_pipeline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python_apps/airtime_analyzer/airtime_analyzer/analyzer_pipeline.py b/python_apps/airtime_analyzer/airtime_analyzer/analyzer_pipeline.py index 8f1abc499..bf467c190 100644 --- a/python_apps/airtime_analyzer/airtime_analyzer/analyzer_pipeline.py +++ b/python_apps/airtime_analyzer/airtime_analyzer/analyzer_pipeline.py @@ -54,7 +54,7 @@ class AnalyzerPipeline: # First, we extract the ID3 tags and other metadata: metadata = dict() metadata = MetadataAnalyzer.analyze(audio_file_path, metadata) - #metadata = CuePointAnalyzer.analyze(audio_file_path, metadata) + metadata = CuePointAnalyzer.analyze(audio_file_path, metadata) metadata = ReplayGainAnalyzer.analyze(audio_file_path, metadata) metadata = PlayabilityAnalyzer.analyze(audio_file_path, metadata) metadata = FileMoverAnalyzer.move(audio_file_path, import_directory, original_filename, metadata) From c9231e9136c44f5f32e8024988e73093f4f54424 Mon Sep 17 00:00:00 2001 From: Albert Santoni Date: Tue, 27 Jan 2015 19:54:42 -0500 Subject: [PATCH 03/17] Sentry logging for Airtime Pro --- airtime_mvc/application/logging/Logging.php | 2 + .../application/logging/SentryLogging.php | 111 +++++ composer.json | 3 +- composer.lock | 386 ------------------ 4 files changed, 115 insertions(+), 387 deletions(-) create mode 100644 airtime_mvc/application/logging/SentryLogging.php delete mode 100644 composer.lock diff --git a/airtime_mvc/application/logging/Logging.php b/airtime_mvc/application/logging/Logging.php index d49c94238..06a30398f 100644 --- a/airtime_mvc/application/logging/Logging.php +++ b/airtime_mvc/application/logging/Logging.php @@ -1,4 +1,5 @@ err(self::getLinePrefix(true) . self::toString($p_msg)); + SentryLogger::getInstance()->captureError(self::toString($p_msg)); } public static function debug($p_msg) diff --git a/airtime_mvc/application/logging/SentryLogging.php b/airtime_mvc/application/logging/SentryLogging.php new file mode 100644 index 000000000..1f15bca11 --- /dev/null +++ b/airtime_mvc/application/logging/SentryLogging.php @@ -0,0 +1,111 @@ +sentryClient = new Raven_Client($dsn, + array( + //FIXME: This doesn't seem to be working... + 'processorOptions' => array( + 'Raven_SanitizeDataProcessor' => array( + 'fields_re' => '/(user_password|user_token|user_secret)/i', + 'values_re' => '/^(?:\d[ -]*?){15,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) + { + $client = $this->sentryClient; + + // 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) + { + $client = $this->sentryClient; + self::addUserData($client); + + $event_id = $client->getIdent($client->captureException($exception, array( + 'extra' => $this->getExtraData(), + 'tags' => $this->getTags(), + ))); + $client->context->clear(); + } + + public function captureError($errorMessage) + { + $client = $this->sentryClient; + + // Provide some additional data with an exception + self::addUserData($client); + $event_id = $client->getIdent($client->captureMessage($errorMessage, array( + 'extra' => $this->getExtraData(), + 'tags' => $this->getTags(), + ))); + $client->context->clear(); + } + + private static function getTags() + { + $tags = array(); + $tags['dev_env'] = Config::getConfig()["dev_env"]; + return $tags; + } + + 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; + } + +} \ No newline at end of file diff --git a/composer.json b/composer.json index f389308e4..39a2a6093 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,7 @@ { "require": { "propel/propel1": "1.7.0-stable", - "aws/aws-sdk-php": "2.7.9" + "aws/aws-sdk-php": "2.7.9", + "raven/raven": "0.10.0" } } diff --git a/composer.lock b/composer.lock deleted file mode 100644 index 17879613a..000000000 --- a/composer.lock +++ /dev/null @@ -1,386 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", - "This file is @generated automatically" - ], - "hash": "311983cf9bb84cfacbfcc6c5dfc9e841", - "packages": [ - { - "name": "aws/aws-sdk-php", - "version": "2.7.9", - "source": { - "type": "git", - "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "f39354df58eec97f0ef22ccf3caf753607a47dca" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/f39354df58eec97f0ef22ccf3caf753607a47dca", - "reference": "f39354df58eec97f0ef22ccf3caf753607a47dca", - "shasum": "" - }, - "require": { - "guzzle/guzzle": "~3.7", - "php": ">=5.3.3" - }, - "require-dev": { - "doctrine/cache": "~1.0", - "ext-openssl": "*", - "monolog/monolog": "~1.4", - "phpunit/phpunit": "~4.0", - "symfony/yaml": "~2.1" - }, - "suggest": { - "doctrine/cache": "Adds support for caching of credentials and responses", - "ext-apc": "Allows service description opcode caching, request and response caching, and credentials caching", - "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages", - "monolog/monolog": "Adds support for logging HTTP requests and responses", - "symfony/yaml": "Eases the ability to write manifests for creating jobs in AWS Import/Export" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.7-dev" - } - }, - "autoload": { - "psr-0": { - "Aws": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Amazon Web Services", - "homepage": "http://aws.amazon.com" - } - ], - "description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project", - "homepage": "http://aws.amazon.com/sdkforphp", - "keywords": [ - "amazon", - "aws", - "cloud", - "dynamodb", - "ec2", - "glacier", - "s3", - "sdk" - ], - "time": "2014-12-08 21:56:46" - }, - { - "name": "guzzle/guzzle", - "version": "v3.9.2", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle3.git", - "reference": "54991459675c1a2924122afbb0e5609ade581155" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/54991459675c1a2924122afbb0e5609ade581155", - "reference": "54991459675c1a2924122afbb0e5609ade581155", - "shasum": "" - }, - "require": { - "ext-curl": "*", - "php": ">=5.3.3", - "symfony/event-dispatcher": "~2.1" - }, - "replace": { - "guzzle/batch": "self.version", - "guzzle/cache": "self.version", - "guzzle/common": "self.version", - "guzzle/http": "self.version", - "guzzle/inflection": "self.version", - "guzzle/iterator": "self.version", - "guzzle/log": "self.version", - "guzzle/parser": "self.version", - "guzzle/plugin": "self.version", - "guzzle/plugin-async": "self.version", - "guzzle/plugin-backoff": "self.version", - "guzzle/plugin-cache": "self.version", - "guzzle/plugin-cookie": "self.version", - "guzzle/plugin-curlauth": "self.version", - "guzzle/plugin-error-response": "self.version", - "guzzle/plugin-history": "self.version", - "guzzle/plugin-log": "self.version", - "guzzle/plugin-md5": "self.version", - "guzzle/plugin-mock": "self.version", - "guzzle/plugin-oauth": "self.version", - "guzzle/service": "self.version", - "guzzle/stream": "self.version" - }, - "require-dev": { - "doctrine/cache": "~1.3", - "monolog/monolog": "~1.0", - "phpunit/phpunit": "3.7.*", - "psr/log": "~1.0", - "symfony/class-loader": "~2.1", - "zendframework/zend-cache": "2.*,<2.3", - "zendframework/zend-log": "2.*,<2.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.9-dev" - } - }, - "autoload": { - "psr-0": { - "Guzzle": "src/", - "Guzzle\\Tests": "tests/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Guzzle Community", - "homepage": "https://github.com/guzzle/guzzle/contributors" - } - ], - "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ], - "time": "2014-08-11 04:32:36" - }, - { - "name": "phing/phing", - "version": "2.9.1", - "source": { - "type": "git", - "url": "https://github.com/phingofficial/phing.git", - "reference": "393edeffa8a85d43636ce0c9b4deb1ff9ac60a5c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phingofficial/phing/zipball/393edeffa8a85d43636ce0c9b4deb1ff9ac60a5c", - "reference": "393edeffa8a85d43636ce0c9b4deb1ff9ac60a5c", - "shasum": "" - }, - "require": { - "php": ">=5.2.0" - }, - "require-dev": { - "ext-pdo_sqlite": "*", - "lastcraft/simpletest": "@dev", - "pdepend/pdepend": "1.x", - "pear-pear.php.net/http_request2": "2.2.x", - "pear-pear.php.net/net_growl": "2.7.x", - "pear-pear.php.net/pear_packagefilemanager": "1.7.x", - "pear-pear.php.net/pear_packagefilemanager2": "1.0.x", - "pear-pear.php.net/xml_serializer": "0.20.x", - "pear/pear_exception": "@dev", - "pear/versioncontrol_git": "@dev", - "pear/versioncontrol_svn": "@dev", - "phpdocumentor/phpdocumentor": "2.x", - "phploc/phploc": "2.x", - "phpunit/phpunit": ">=3.7", - "sebastian/phpcpd": "2.x", - "squizlabs/php_codesniffer": "1.5.x" - }, - "suggest": { - "pdepend/pdepend": "PHP version of JDepend", - "pear/archive_tar": "Tar file management class", - "pear/versioncontrol_git": "A library that provides OO interface to handle Git repository", - "pear/versioncontrol_svn": "A simple OO-style interface for Subversion, the free/open-source version control system", - "phpdocumentor/phpdocumentor": "Documentation Generator for PHP", - "phploc/phploc": "A tool for quickly measuring the size of a PHP project", - "phpmd/phpmd": "PHP version of PMD tool", - "phpunit/php-code-coverage": "Library that provides collection, processing, and rendering functionality for PHP code coverage information", - "phpunit/phpunit": "The PHP Unit Testing Framework", - "sebastian/phpcpd": "Copy/Paste Detector (CPD) for PHP code", - "tedivm/jshrink": "Javascript Minifier built in PHP" - }, - "bin": [ - "bin/phing" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.9.x-dev" - } - }, - "autoload": { - "classmap": [ - "classes/phing/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "classes" - ], - "license": [ - "LGPL-3.0" - ], - "authors": [ - { - "name": "Phing Community", - "homepage": "http://www.phing.info/trac/wiki/Development/Contributors" - }, - { - "name": "Michiel Rook", - "email": "mrook@php.net" - } - ], - "description": "PHing Is Not GNU make; it's a PHP project build system or build tool based on Apache Ant.", - "homepage": "http://www.phing.info/", - "keywords": [ - "build", - "phing", - "task", - "tool" - ], - "time": "2014-12-03 09:18:46" - }, - { - "name": "propel/propel1", - "version": "1.7.0", - "source": { - "type": "git", - "url": "https://github.com/propelorm/Propel.git", - "reference": "09058f1443bc287e550b9342a4379aac2e0a0b8f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/propelorm/Propel/zipball/09058f1443bc287e550b9342a4379aac2e0a0b8f", - "reference": "09058f1443bc287e550b9342a4379aac2e0a0b8f", - "shasum": "" - }, - "require": { - "phing/phing": "~2.4", - "php": ">=5.2.4" - }, - "require-dev": { - "pear-pear.php.net/pear_packagefilemanager2": "@stable" - }, - "bin": [ - "generator/bin/propel-gen", - "generator/bin/propel-gen.bat" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.7-dev" - } - }, - "autoload": { - "classmap": [ - "runtime/lib", - "generator/lib" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "runtime/lib", - "generator/lib" - ], - "license": [ - "MIT" - ], - "authors": [ - { - "name": "William Durand", - "email": "william.durand1@gmail.com", - "homepage": "http://www.willdurand.fr" - } - ], - "description": "Propel is an open-source Object-Relational Mapping (ORM) for PHP5.", - "homepage": "http://www.propelorm.org/", - "keywords": [ - "Active Record", - "database", - "mapping", - "orm", - "persistence" - ], - "time": "2013-10-21 12:52:56" - }, - { - "name": "symfony/event-dispatcher", - "version": "v2.6.1", - "target-dir": "Symfony/Component/EventDispatcher", - "source": { - "type": "git", - "url": "https://github.com/symfony/EventDispatcher.git", - "reference": "720fe9bca893df7ad1b4546649473b5afddf0216" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/720fe9bca893df7ad1b4546649473b5afddf0216", - "reference": "720fe9bca893df7ad1b4546649473b5afddf0216", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~2.0", - "symfony/dependency-injection": "~2.6", - "symfony/expression-language": "~2.6", - "symfony/stopwatch": "~2.2" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.6-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\EventDispatcher\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "Symfony EventDispatcher Component", - "homepage": "http://symfony.com", - "time": "2014-12-02 20:19:20" - } - ], - "packages-dev": [], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "platform": [], - "platform-dev": [] -} From 8e4aa298d04d4954777a14c30de1c9355b9b1c03 Mon Sep 17 00:00:00 2001 From: Albert Santoni Date: Tue, 27 Jan 2015 19:55:30 -0500 Subject: [PATCH 04/17] Scrub Sentry API KEY (old one is revoked) --- airtime_mvc/application/logging/SentryLogging.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airtime_mvc/application/logging/SentryLogging.php b/airtime_mvc/application/logging/SentryLogging.php index 1f15bca11..9b1055b6c 100644 --- a/airtime_mvc/application/logging/SentryLogging.php +++ b/airtime_mvc/application/logging/SentryLogging.php @@ -24,7 +24,7 @@ class SentryLogger private function __construct() { // Instantiate a new client with a compatible DSN - $dsn = 'http://6a495f2d42b345f3a995b0c2219c3b9f:383164e96bb741998d8c2af468edf503@sentry.sourcefabric.org/12'; + $dsn = 'TODO: FILL ME IN'; $this->sentryClient = new Raven_Client($dsn, array( //FIXME: This doesn't seem to be working... From 3f6983aa3e6808c4feb6219e869d250c5061cc9b Mon Sep 17 00:00:00 2001 From: Albert Santoni Date: Mon, 2 Feb 2015 12:18:33 -0500 Subject: [PATCH 05/17] Renabling CuePointAnalyzer --- .../airtime_analyzer/airtime_analyzer/analyzer_pipeline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python_apps/airtime_analyzer/airtime_analyzer/analyzer_pipeline.py b/python_apps/airtime_analyzer/airtime_analyzer/analyzer_pipeline.py index 8f1abc499..bf467c190 100644 --- a/python_apps/airtime_analyzer/airtime_analyzer/analyzer_pipeline.py +++ b/python_apps/airtime_analyzer/airtime_analyzer/analyzer_pipeline.py @@ -54,7 +54,7 @@ class AnalyzerPipeline: # First, we extract the ID3 tags and other metadata: metadata = dict() metadata = MetadataAnalyzer.analyze(audio_file_path, metadata) - #metadata = CuePointAnalyzer.analyze(audio_file_path, metadata) + metadata = CuePointAnalyzer.analyze(audio_file_path, metadata) metadata = ReplayGainAnalyzer.analyze(audio_file_path, metadata) metadata = PlayabilityAnalyzer.analyze(audio_file_path, metadata) metadata = FileMoverAnalyzer.move(audio_file_path, import_directory, original_filename, metadata) From ee6862e7311acb7d91335499385f1e5913486787 Mon Sep 17 00:00:00 2001 From: Albert Santoni Date: Mon, 2 Feb 2015 12:26:22 -0500 Subject: [PATCH 06/17] Fixed quotation issue with playability analyzer --- .../airtime_analyzer/airtime_analyzer/playability_analyzer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python_apps/airtime_analyzer/airtime_analyzer/playability_analyzer.py b/python_apps/airtime_analyzer/airtime_analyzer/playability_analyzer.py index ec102eeb2..0ca8a84c1 100644 --- a/python_apps/airtime_analyzer/airtime_analyzer/playability_analyzer.py +++ b/python_apps/airtime_analyzer/airtime_analyzer/playability_analyzer.py @@ -19,7 +19,7 @@ class PlayabilityAnalyzer(Analyzer): :param metadata: A metadata dictionary where the results will be put :return: The metadata dictionary ''' - command = [PlayabilityAnalyzer.LIQUIDSOAP_EXECUTABLE, '-v', '-c', "output.dummy(audio_to_stereo(single('%s')))" % filename] + command = [PlayabilityAnalyzer.LIQUIDSOAP_EXECUTABLE, '-v', '-c', "output.dummy(audio_to_stereo(single(argv(1))))", '--', filename] try: subprocess.check_output(command, stderr=subprocess.STDOUT, close_fds=True) From 9baed1b3288a0466616c699c3534c76d01581ca0 Mon Sep 17 00:00:00 2001 From: Albert Santoni Date: Mon, 2 Feb 2015 13:14:14 -0500 Subject: [PATCH 07/17] Make the unit tests pass again --- .../airtime_analyzer/analyzer_pipeline.py | 11 ++++++----- .../airtime_analyzer/message_listener.py | 6 +++++- .../airtime_analyzer/tests/analyzer_pipeline_tests.py | 3 ++- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/python_apps/airtime_analyzer/airtime_analyzer/analyzer_pipeline.py b/python_apps/airtime_analyzer/airtime_analyzer/analyzer_pipeline.py index 514c1db38..f3cf04180 100644 --- a/python_apps/airtime_analyzer/airtime_analyzer/analyzer_pipeline.py +++ b/python_apps/airtime_analyzer/airtime_analyzer/analyzer_pipeline.py @@ -21,7 +21,7 @@ class AnalyzerPipeline: """ @staticmethod - def run_analysis(queue, audio_file_path, import_directory, original_filename): + def run_analysis(queue, audio_file_path, import_directory, original_filename, cloud_storage_enabled): """Analyze and import an audio file, and put all extracted metadata into queue. Keyword arguments: @@ -34,7 +34,7 @@ class AnalyzerPipeline: preserve. The file at audio_file_path typically has a temporary randomly generated name, which is why we want to know what the original name was. - station_domain: The Airtime Pro account's domain name. i.e. bananas + cloud_storage_enabled: Whether to store the file in the cloud or on the local disk. """ # It is super critical to initialize a separate log file here so that we # don't inherit logging/locks from the parent process. Supposedly @@ -50,6 +50,8 @@ class AnalyzerPipeline: raise TypeError("import_directory must be unicode. Was of type " + type(import_directory).__name__ + " instead.") if not isinstance(original_filename, unicode): raise TypeError("original_filename must be unicode. Was of type " + type(original_filename).__name__ + " instead.") + if not isinstance(cloud_storage_enabled, bool): + raise TypeError("cloud_storage_enabled must be a boolean. Was of type " + type(cloud_storage_enabled).__name__ + " instead.") # Analyze the audio file we were told to analyze: @@ -60,9 +62,8 @@ class AnalyzerPipeline: metadata = ReplayGainAnalyzer.analyze(audio_file_path, metadata) metadata = PlayabilityAnalyzer.analyze(audio_file_path, metadata) - - csu = CloudStorageUploader() - if csu.enabled(): + if cloud_storage_enabled: + csu = CloudStorageUploader() metadata = csu.upload_obj(audio_file_path, metadata) else: metadata = FileMoverAnalyzer.move(audio_file_path, import_directory, original_filename, metadata) diff --git a/python_apps/airtime_analyzer/airtime_analyzer/message_listener.py b/python_apps/airtime_analyzer/airtime_analyzer/message_listener.py index f88fa6bc7..8ed5fa782 100644 --- a/python_apps/airtime_analyzer/airtime_analyzer/message_listener.py +++ b/python_apps/airtime_analyzer/airtime_analyzer/message_listener.py @@ -207,9 +207,13 @@ class MessageListener: @staticmethod def spawn_analyzer_process(audio_file_path, import_directory, original_filename): ''' Spawn a child process to analyze and import a new audio file. ''' + + csu = CloudStorageUploader() + cloud_storage_enabled = csu.enabled() + q = multiprocessing.Queue() p = multiprocessing.Process(target=AnalyzerPipeline.run_analysis, - args=(q, audio_file_path, import_directory, original_filename)) + args=(q, audio_file_path, import_directory, original_filename, cloud_storage_enabled)) p.start() p.join() if p.exitcode == 0: diff --git a/python_apps/airtime_analyzer/tests/analyzer_pipeline_tests.py b/python_apps/airtime_analyzer/tests/analyzer_pipeline_tests.py index 54458e33f..23d7d046b 100644 --- a/python_apps/airtime_analyzer/tests/analyzer_pipeline_tests.py +++ b/python_apps/airtime_analyzer/tests/analyzer_pipeline_tests.py @@ -20,8 +20,9 @@ def teardown(): def test_basic(): filename = os.path.basename(DEFAULT_AUDIO_FILE) q = multiprocessing.Queue() + cloud_storage_enabled = False #This actually imports the file into the "./Test Artist" directory. - AnalyzerPipeline.run_analysis(q, DEFAULT_AUDIO_FILE, u'.', filename) + AnalyzerPipeline.run_analysis(q, DEFAULT_AUDIO_FILE, u'.', filename, cloud_storage_enabled) metadata = q.get() assert metadata['track_title'] == u'Test Title' assert metadata['artist_name'] == u'Test Artist' From e32a26956b4f0797d7144f97d05a796c547f13e5 Mon Sep 17 00:00:00 2001 From: Albert Santoni Date: Mon, 2 Feb 2015 13:31:52 -0500 Subject: [PATCH 08/17] Fixed the unit tests again --- .../cloud_storage_uploader.py | 27 +++++++++++++------ .../cloud_storage_uploader_libcloud.py | 26 ++++++++++++------ 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader.py b/python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader.py index bea905b71..b8fc2261f 100644 --- a/python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader.py +++ b/python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader.py @@ -1,7 +1,7 @@ import os import logging import uuid -import config_file +import ConfigParser from boto.s3.connection import S3Connection from boto.s3.key import Key @@ -25,20 +25,31 @@ class CloudStorageUploader: def __init__(self): - config = config_file.read_config_file(CLOUD_CONFIG_PATH) + try: + config = ConfigParser.SafeConfigParser() + config.readfp(open(CLOUD_CONFIG_PATH)) + cloud_storage_config_section = config.get("current_backend", "storage_backend") + self._storage_backend = cloud_storage_config_section + except IOError as e: + print "Failed to open config file at " + CLOUD_CONFIG_PATH + ": " + e.strerror + print "Defaulting to file storage" + self._storage_backend = STORAGE_BACKEND_FILE + except Exception as e: + print e + print "Defaulting to file storage" + self._storage_backend = STORAGE_BACKEND_FILE - CLOUD_STORAGE_CONFIG_SECTION = config.get("current_backend", "storage_backend") - self._storage_backend = CLOUD_STORAGE_CONFIG_SECTION if self._storage_backend == STORAGE_BACKEND_FILE: self._host = "" self._bucket = "" self._api_key = "" self._api_key_secret = "" else: - self._host = config.get(CLOUD_STORAGE_CONFIG_SECTION, 'host') - self._bucket = config.get(CLOUD_STORAGE_CONFIG_SECTION, 'bucket') - self._api_key = config.get(CLOUD_STORAGE_CONFIG_SECTION, 'api_key') - self._api_key_secret = config.get(CLOUD_STORAGE_CONFIG_SECTION, 'api_key_secret') + self._host = config.get(cloud_storage_config_section, 'host') + self._bucket = config.get(cloud_storage_config_section, 'bucket') + self._api_key = config.get(cloud_storage_config_section, 'api_key') + self._api_key_secret = config.get(cloud_storage_config_section, 'api_key_secret') + def enabled(self): if self._storage_backend == "file": diff --git a/python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader_libcloud.py b/python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader_libcloud.py index 045c719f1..c0950dc15 100644 --- a/python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader_libcloud.py +++ b/python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader_libcloud.py @@ -1,7 +1,7 @@ import os import logging import uuid -import config_file +import ConfigParser from libcloud.storage.providers import get_driver from libcloud.storage.types import Provider, ContainerDoesNotExistError, ObjectDoesNotExistError @@ -27,20 +27,30 @@ class CloudStorageUploader: def __init__(self): - config = config_file.read_config_file(CLOUD_CONFIG_PATH) + config = ConfigParser.SafeConfigParser() + try: + config.readfp(open(CLOUD_CONFIG_PATH)) + cloud_storage_config_section = config.get("current_backend", "storage_backend") + self._storage_backend = cloud_storage_config_section + except IOError as e: + print "Failed to open config file at " + CLOUD_CONFIG_PATH + ": " + e.strerror + print "Defaulting to file storage" + self._storage_backend = STORAGE_BACKEND_FILE + except Exception as e: + print e + print "Defaulting to file storage" + self._storage_backend = STORAGE_BACKEND_FILE - CLOUD_STORAGE_CONFIG_SECTION = config.get("current_backend", "storage_backend") - self._storage_backend = CLOUD_STORAGE_CONFIG_SECTION if self._storage_backend == STORAGE_BACKEND_FILE: self._provider = "" self._bucket = "" self._api_key = "" self._api_key_secret = "" else: - self._provider = config.get(CLOUD_STORAGE_CONFIG_SECTION, 'provider') - self._bucket = config.get(CLOUD_STORAGE_CONFIG_SECTION, 'bucket') - self._api_key = config.get(CLOUD_STORAGE_CONFIG_SECTION, 'api_key') - self._api_key_secret = config.get(CLOUD_STORAGE_CONFIG_SECTION, 'api_key_secret') + self._provider = config.get(cloud_storage_config_section, 'provider') + self._bucket = config.get(cloud_storage_config_section, 'bucket') + self._api_key = config.get(cloud_storage_config_section, 'api_key') + self._api_key_secret = config.get(cloud_storage_config_section, 'api_key_secret') def enabled(self): if self._storage_backend == "file": From f69e5afbff74ca6d15aae4218eca1058e638986c Mon Sep 17 00:00:00 2001 From: Albert Santoni Date: Mon, 2 Feb 2015 14:42:20 -0500 Subject: [PATCH 09/17] SAAS-576: Fixed the Sentry data sanitizer and moved DSN into a config file --- airtime_mvc/application/configs/constants.php | 2 + .../application/logging/SentryLogging.php | 41 +- composer.json | 2 +- composer.lock | 441 ++++++++++++++++++ 4 files changed, 474 insertions(+), 12 deletions(-) create mode 100644 composer.lock diff --git a/airtime_mvc/application/configs/constants.php b/airtime_mvc/application/configs/constants.php index 818e868b5..273b8a0b7 100644 --- a/airtime_mvc/application/configs/constants.php +++ b/airtime_mvc/application/configs/constants.php @@ -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'); \ No newline at end of file diff --git a/airtime_mvc/application/logging/SentryLogging.php b/airtime_mvc/application/logging/SentryLogging.php index 9b1055b6c..e3c87b700 100644 --- a/airtime_mvc/application/logging/SentryLogging.php +++ b/airtime_mvc/application/logging/SentryLogging.php @@ -1,9 +1,4 @@ sentryClient = null; + return; + } // Instantiate a new client with a compatible DSN - $dsn = 'TODO: FILL ME IN'; + $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' => '/(user_password|user_token|user_secret)/i', - 'values_re' => '/^(?:\d[ -]*?){15,16}$/' + 'fields_re' => '/(authorization|password|passwd|user_token|secret|WHMCS_|SESSION)/i', + 'values_re' => '/^(?:\d[ -]*?){13,16}$/' ) ) )); @@ -50,7 +50,12 @@ class SentryLogger 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)); @@ -61,8 +66,13 @@ class SentryLogger 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(), @@ -73,13 +83,17 @@ class SentryLogger 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(), - 'tags' => $this->getTags(), + 'extra' => $this->getExtraData() ))); $client->context->clear(); } @@ -87,10 +101,15 @@ class SentryLogger private static function getTags() { $tags = array(); - $tags['dev_env'] = Config::getConfig()["dev_env"]; + $tags['Development Environment'] = Config::getConfig()["dev_env"]; return $tags; } + private static function addTags($client) + { + $client->tags_context(self::getTags()); + } + private static function addUserData($client) { $userData = array(); diff --git a/composer.json b/composer.json index 39a2a6093..6d92538de 100644 --- a/composer.json +++ b/composer.json @@ -2,6 +2,6 @@ "require": { "propel/propel1": "1.7.0-stable", "aws/aws-sdk-php": "2.7.9", - "raven/raven": "0.10.0" + "raven/raven": "0.8.x-dev" } } diff --git a/composer.lock b/composer.lock new file mode 100644 index 000000000..17d9b1085 --- /dev/null +++ b/composer.lock @@ -0,0 +1,441 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "30ad5215f679ce0ab55c7210b21a3b32", + "packages": [ + { + "name": "aws/aws-sdk-php", + "version": "2.7.9", + "source": { + "type": "git", + "url": "https://github.com/aws/aws-sdk-php.git", + "reference": "f39354df58eec97f0ef22ccf3caf753607a47dca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/f39354df58eec97f0ef22ccf3caf753607a47dca", + "reference": "f39354df58eec97f0ef22ccf3caf753607a47dca", + "shasum": "" + }, + "require": { + "guzzle/guzzle": "~3.7", + "php": ">=5.3.3" + }, + "require-dev": { + "doctrine/cache": "~1.0", + "ext-openssl": "*", + "monolog/monolog": "~1.4", + "phpunit/phpunit": "~4.0", + "symfony/yaml": "~2.1" + }, + "suggest": { + "doctrine/cache": "Adds support for caching of credentials and responses", + "ext-apc": "Allows service description opcode caching, request and response caching, and credentials caching", + "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages", + "monolog/monolog": "Adds support for logging HTTP requests and responses", + "symfony/yaml": "Eases the ability to write manifests for creating jobs in AWS Import/Export" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-0": { + "Aws": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Amazon Web Services", + "homepage": "http://aws.amazon.com" + } + ], + "description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project", + "homepage": "http://aws.amazon.com/sdkforphp", + "keywords": [ + "amazon", + "aws", + "cloud", + "dynamodb", + "ec2", + "glacier", + "s3", + "sdk" + ], + "time": "2014-12-08 21:56:46" + }, + { + "name": "guzzle/guzzle", + "version": "v3.9.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle3.git", + "reference": "54991459675c1a2924122afbb0e5609ade581155" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/54991459675c1a2924122afbb0e5609ade581155", + "reference": "54991459675c1a2924122afbb0e5609ade581155", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "php": ">=5.3.3", + "symfony/event-dispatcher": "~2.1" + }, + "replace": { + "guzzle/batch": "self.version", + "guzzle/cache": "self.version", + "guzzle/common": "self.version", + "guzzle/http": "self.version", + "guzzle/inflection": "self.version", + "guzzle/iterator": "self.version", + "guzzle/log": "self.version", + "guzzle/parser": "self.version", + "guzzle/plugin": "self.version", + "guzzle/plugin-async": "self.version", + "guzzle/plugin-backoff": "self.version", + "guzzle/plugin-cache": "self.version", + "guzzle/plugin-cookie": "self.version", + "guzzle/plugin-curlauth": "self.version", + "guzzle/plugin-error-response": "self.version", + "guzzle/plugin-history": "self.version", + "guzzle/plugin-log": "self.version", + "guzzle/plugin-md5": "self.version", + "guzzle/plugin-mock": "self.version", + "guzzle/plugin-oauth": "self.version", + "guzzle/service": "self.version", + "guzzle/stream": "self.version" + }, + "require-dev": { + "doctrine/cache": "~1.3", + "monolog/monolog": "~1.0", + "phpunit/phpunit": "3.7.*", + "psr/log": "~1.0", + "symfony/class-loader": "~2.1", + "zendframework/zend-cache": "2.*,<2.3", + "zendframework/zend-log": "2.*,<2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.9-dev" + } + }, + "autoload": { + "psr-0": { + "Guzzle": "src/", + "Guzzle\\Tests": "tests/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Guzzle Community", + "homepage": "https://github.com/guzzle/guzzle/contributors" + } + ], + "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2014-08-11 04:32:36" + }, + { + "name": "phing/phing", + "version": "2.9.1", + "source": { + "type": "git", + "url": "https://github.com/phingofficial/phing.git", + "reference": "393edeffa8a85d43636ce0c9b4deb1ff9ac60a5c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phingofficial/phing/zipball/393edeffa8a85d43636ce0c9b4deb1ff9ac60a5c", + "reference": "393edeffa8a85d43636ce0c9b4deb1ff9ac60a5c", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "require-dev": { + "ext-pdo_sqlite": "*", + "lastcraft/simpletest": "@dev", + "pdepend/pdepend": "1.x", + "pear-pear.php.net/http_request2": "2.2.x", + "pear-pear.php.net/net_growl": "2.7.x", + "pear-pear.php.net/pear_packagefilemanager": "1.7.x", + "pear-pear.php.net/pear_packagefilemanager2": "1.0.x", + "pear-pear.php.net/xml_serializer": "0.20.x", + "pear/pear_exception": "@dev", + "pear/versioncontrol_git": "@dev", + "pear/versioncontrol_svn": "@dev", + "phpdocumentor/phpdocumentor": "2.x", + "phploc/phploc": "2.x", + "phpunit/phpunit": ">=3.7", + "sebastian/phpcpd": "2.x", + "squizlabs/php_codesniffer": "1.5.x" + }, + "suggest": { + "pdepend/pdepend": "PHP version of JDepend", + "pear/archive_tar": "Tar file management class", + "pear/versioncontrol_git": "A library that provides OO interface to handle Git repository", + "pear/versioncontrol_svn": "A simple OO-style interface for Subversion, the free/open-source version control system", + "phpdocumentor/phpdocumentor": "Documentation Generator for PHP", + "phploc/phploc": "A tool for quickly measuring the size of a PHP project", + "phpmd/phpmd": "PHP version of PMD tool", + "phpunit/php-code-coverage": "Library that provides collection, processing, and rendering functionality for PHP code coverage information", + "phpunit/phpunit": "The PHP Unit Testing Framework", + "sebastian/phpcpd": "Copy/Paste Detector (CPD) for PHP code", + "tedivm/jshrink": "Javascript Minifier built in PHP" + }, + "bin": [ + "bin/phing" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.9.x-dev" + } + }, + "autoload": { + "classmap": [ + "classes/phing/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "classes" + ], + "license": [ + "LGPL-3.0" + ], + "authors": [ + { + "name": "Phing Community", + "homepage": "http://www.phing.info/trac/wiki/Development/Contributors" + }, + { + "name": "Michiel Rook", + "email": "mrook@php.net" + } + ], + "description": "PHing Is Not GNU make; it's a PHP project build system or build tool based on Apache Ant.", + "homepage": "http://www.phing.info/", + "keywords": [ + "build", + "phing", + "task", + "tool" + ], + "time": "2014-12-03 09:18:46" + }, + { + "name": "propel/propel1", + "version": "1.7.0", + "source": { + "type": "git", + "url": "https://github.com/propelorm/Propel.git", + "reference": "09058f1443bc287e550b9342a4379aac2e0a0b8f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/propelorm/Propel/zipball/09058f1443bc287e550b9342a4379aac2e0a0b8f", + "reference": "09058f1443bc287e550b9342a4379aac2e0a0b8f", + "shasum": "" + }, + "require": { + "phing/phing": "~2.4", + "php": ">=5.2.4" + }, + "require-dev": { + "pear-pear.php.net/pear_packagefilemanager2": "@stable" + }, + "bin": [ + "generator/bin/propel-gen", + "generator/bin/propel-gen.bat" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.7-dev" + } + }, + "autoload": { + "classmap": [ + "runtime/lib", + "generator/lib" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "runtime/lib", + "generator/lib" + ], + "license": [ + "MIT" + ], + "authors": [ + { + "name": "William Durand", + "email": "william.durand1@gmail.com", + "homepage": "http://www.willdurand.fr" + } + ], + "description": "Propel is an open-source Object-Relational Mapping (ORM) for PHP5.", + "homepage": "http://www.propelorm.org/", + "keywords": [ + "Active Record", + "database", + "mapping", + "orm", + "persistence" + ], + "time": "2013-10-21 12:52:56" + }, + { + "name": "raven/raven", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/getsentry/raven-php.git", + "reference": "407d77059c004d4771e8bb1fa50d8b62c850c7e3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/getsentry/raven-php/zipball/407d77059c004d4771e8bb1fa50d8b62c850c7e3", + "reference": "407d77059c004d4771e8bb1fa50d8b62c850c7e3", + "shasum": "" + }, + "require": { + "php": ">=5.2.4" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*" + }, + "bin": [ + "bin/raven" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.8.x-dev" + } + }, + "autoload": { + "psr-0": { + "Raven_": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD" + ], + "authors": [ + { + "name": "David Cramer", + "email": "dcramer@gmail.com" + } + ], + "description": "A PHP client for Sentry (http://getsentry.com)", + "homepage": "http://getsentry.com", + "keywords": [ + "log", + "logging" + ], + "time": "2015-01-23 20:50:15" + }, + { + "name": "symfony/event-dispatcher", + "version": "v2.6.3", + "target-dir": "Symfony/Component/EventDispatcher", + "source": { + "type": "git", + "url": "https://github.com/symfony/EventDispatcher.git", + "reference": "40ff70cadea3785d83cac1c8309514b36113064e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/40ff70cadea3785d83cac1c8309514b36113064e", + "reference": "40ff70cadea3785d83cac1c8309514b36113064e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.0,>=2.0.5", + "symfony/dependency-injection": "~2.6", + "symfony/expression-language": "~2.6", + "symfony/stopwatch": "~2.3" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "http://symfony.com", + "time": "2015-01-05 14:28:40" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "raven/raven": 20 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} From 147ded498b6bbe224115b60ed656c10a5ddd4c2b Mon Sep 17 00:00:00 2001 From: Albert Santoni Date: Mon, 2 Feb 2015 16:56:03 -0500 Subject: [PATCH 10/17] PHP 5.3 compatibility fix for my Sentry code --- airtime_mvc/application/logging/SentryLogging.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/airtime_mvc/application/logging/SentryLogging.php b/airtime_mvc/application/logging/SentryLogging.php index e3c87b700..06ae7a9cc 100644 --- a/airtime_mvc/application/logging/SentryLogging.php +++ b/airtime_mvc/application/logging/SentryLogging.php @@ -101,7 +101,8 @@ class SentryLogger private static function getTags() { $tags = array(); - $tags['Development Environment'] = Config::getConfig()["dev_env"]; + $config = Config::getConfig(); + $tags['Development Environment'] = $config["dev_env"]; return $tags; } From df4bc01ff82c373f92f4a699862926cfdc324cb4 Mon Sep 17 00:00:00 2001 From: Albert Santoni Date: Mon, 2 Feb 2015 18:03:13 -0500 Subject: [PATCH 11/17] Log all PHP errors (including parse errors) to our zend log --- .../controllers/ShowbuilderController.php | 8 ++++ airtime_mvc/application/logging/Logging.php | 45 +++++++++++++++++++ airtime_mvc/public/index.php | 1 + 3 files changed, 54 insertions(+) diff --git a/airtime_mvc/application/controllers/ShowbuilderController.php b/airtime_mvc/application/controllers/ShowbuilderController.php index 9abbeb167..189ef2aa8 100644 --- a/airtime_mvc/application/controllers/ShowbuilderController.php +++ b/airtime_mvc/application/controllers/ShowbuilderController.php @@ -283,6 +283,14 @@ class ShowbuilderController extends Zend_Controller_Action $mediaItems = $request->getParam("mediaIds", array()); $scheduledItems = $request->getParam("schedIds", array()); + $log_vars = array(); + $log_vars["url"] = $_SERVER['HTTP_HOST']; + $log_vars["action"] = "showbuilder/schedule-add"; + $log_vars["params"] = array(); + $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); diff --git a/airtime_mvc/application/logging/Logging.php b/airtime_mvc/application/logging/Logging.php index d49c94238..a32aa9410 100644 --- a/airtime_mvc/application/logging/Logging.php +++ b/airtime_mvc/application/logging/Logging.php @@ -123,4 +123,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'); + } + } + diff --git a/airtime_mvc/public/index.php b/airtime_mvc/public/index.php index a82aceef8..e7a579ba3 100644 --- a/airtime_mvc/public/index.php +++ b/airtime_mvc/public/index.php @@ -63,6 +63,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 { From 75ce7325122ad286fa2d43e40f544fecdda03d83 Mon Sep 17 00:00:00 2001 From: Albert Santoni Date: Mon, 2 Feb 2015 18:04:08 -0500 Subject: [PATCH 12/17] Fixed bad merge --- .../application/controllers/ShowbuilderController.php | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/airtime_mvc/application/controllers/ShowbuilderController.php b/airtime_mvc/application/controllers/ShowbuilderController.php index 31728a3c0..5638cf719 100644 --- a/airtime_mvc/application/controllers/ShowbuilderController.php +++ b/airtime_mvc/application/controllers/ShowbuilderController.php @@ -299,15 +299,7 @@ class ShowbuilderController extends Zend_Controller_Action $log_vars["params"]["media_items"] = $mediaItems; $log_vars["params"]["scheduled_items"] = $scheduledItems; Logging::info($log_vars); - - $log_vars = array(); - $log_vars["url"] = $_SERVER['HTTP_HOST']; - $log_vars["action"] = "showbuilder/schedule-add"; - $log_vars["params"] = array(); - $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); From e0269e1e229a85421273e2e4f3c0b20829b53bf3 Mon Sep 17 00:00:00 2001 From: Duncan Sommerville Date: Tue, 3 Feb 2015 14:16:44 -0500 Subject: [PATCH 13/17] smartReadFile fix for saas show-logo --- .../application/controllers/ApiController.php | 46 +++++++++++++++---- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php index 089052e68..2f54a64ae 100644 --- a/airtime_mvc/application/controllers/ApiController.php +++ b/airtime_mvc/application/controllers/ApiController.php @@ -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,55 @@ 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, $size, $mimeType); + } + /** * 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"); + } + + $time= date('r', filemtime($location)); + + $fm = @fopen($location, 'rb'); if (!$fm) { header ("HTTP/1.1 505 Internal server error"); - return; } From 6601e016a6a1707619244f8f076e977f2c404fdc Mon Sep 17 00:00:00 2001 From: Duncan Sommerville Date: Tue, 3 Feb 2015 15:19:41 -0500 Subject: [PATCH 14/17] Removed unused variable --- airtime_mvc/application/controllers/ApiController.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php index 2f54a64ae..b7937de0d 100644 --- a/airtime_mvc/application/controllers/ApiController.php +++ b/airtime_mvc/application/controllers/ApiController.php @@ -168,8 +168,6 @@ class ApiController extends Zend_Controller_Action throw new Exception("Invalid file size returned for file at $location"); } - $time= date('r', filemtime($location)); - $fm = @fopen($location, 'rb'); if (!$fm) { header ("HTTP/1.1 505 Internal server error"); From b5f6077c046dc01ca0df67c10821846c9a472429 Mon Sep 17 00:00:00 2001 From: Duncan Sommerville Date: Tue, 3 Feb 2015 16:22:12 -0500 Subject: [PATCH 15/17] Quick fix for pro --- .../application/controllers/ApiController.php | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php index b7937de0d..a274f588a 100644 --- a/airtime_mvc/application/controllers/ApiController.php +++ b/airtime_mvc/application/controllers/ApiController.php @@ -157,17 +157,9 @@ class ApiController extends Zend_Controller_Action 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"); - } - + + $size= filesize($location); + $fm = @fopen($location, 'rb'); if (!$fm) { header ("HTTP/1.1 505 Internal server error"); From d5477dfb5b055f12a8c331bc0767870663ac30d7 Mon Sep 17 00:00:00 2001 From: Duncan Sommerville Date: Tue, 3 Feb 2015 16:23:26 -0500 Subject: [PATCH 16/17] Fix misordering of params in readfile function --- airtime_mvc/application/controllers/ApiController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php index a274f588a..07d075267 100644 --- a/airtime_mvc/application/controllers/ApiController.php +++ b/airtime_mvc/application/controllers/ApiController.php @@ -135,7 +135,7 @@ class ApiController extends Zend_Controller_Action $size = $storedFile->getFileSize(); $mimeType = $storedFile->getPropelOrm()->getDbMime(); - $this->smartReadFile($filepath, $size, $mimeType); + $this->smartReadFile($filepath, $mimeType, $size); } From 7eef9d941e69705ea05f9037bc0740f96f0ce0ba Mon Sep 17 00:00:00 2001 From: Duncan Sommerville Date: Tue, 3 Feb 2015 16:33:48 -0500 Subject: [PATCH 17/17] Recommitting filesize checks in smartReadFile --- .../application/controllers/ApiController.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php index 07d075267..124b4b4d0 100644 --- a/airtime_mvc/application/controllers/ApiController.php +++ b/airtime_mvc/application/controllers/ApiController.php @@ -157,9 +157,17 @@ class ApiController extends Zend_Controller_Action if (!$location || $location == "") { throw new FileDoesNotExistException("Requested file does not exist!"); } - - $size= filesize($location); - + + // 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");