Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use PSR-3 log interface (http2) #131

Open
wants to merge 3 commits into
base: http2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ entrust_root_certification_authority.pem
server_certificates_bundle_sandbox.pem
*~
Doc/Reference/html
composer.lock
vendor/
47 changes: 24 additions & 23 deletions ApnsPHP/Abstract.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
* @defgroup ApplePushNotificationService ApnsPHP
*/

use Psr\Log\LoggerInterface;

/**
* Abstract class: this is the superclass for all Apple Push Notification Service
* classes.
Expand Down Expand Up @@ -68,7 +70,7 @@ abstract class ApnsPHP_Abstract
protected $_nConnectRetryInterval; /**< @type integer Connect retry interval in micro seconds. */
protected $_nSocketSelectTimeout; /**< @type integer Socket select timeout in micro seconds. */

protected $_logger; /**< @type ApnsPHP_Log_Interface Logger. */
protected $_logger; /**< @type Psr\Log\LoggerInterface Logger. */

protected $_hSocket; /**< @type resource SSL Socket. */

Expand Down Expand Up @@ -115,30 +117,30 @@ public function __construct($nEnvironment, $sProviderCertificateFile, $nProtocol
* Set the Logger instance to use for logging purpose.
*
* The default logger is ApnsPHP_Log_Embedded, an instance
* of ApnsPHP_Log_Interface that simply print to standard
* of LoggerInterface that simply print to standard
* output log messages.
*
* To set a custom logger you have to implement ApnsPHP_Log_Interface
* To set a custom logger you have to implement LoggerInterface
* and use setLogger, otherwise standard logger will be used.
*
* @see ApnsPHP_Log_Interface
* @see Psr\Log\LoggerInterface
* @see ApnsPHP_Log_Embedded
*
* @param $logger @type ApnsPHP_Log_Interface Logger instance.
* @param $logger @type LoggerInterface Logger instance.
* @throws ApnsPHP_Exception if Logger is not an instance
* of ApnsPHP_Log_Interface.
* of LoggerInterface.
*/
public function setLogger(ApnsPHP_Log_Interface $logger)
public function setLogger(LoggerInterface $logger)
{
if (!is_object($logger)) {
throw new ApnsPHP_Exception(
"The logger should be an instance of 'ApnsPHP_Log_Interface'"
"The logger should be an instance of 'Psr\Log\LoggerInterface'"
);
}
if (!($logger instanceof ApnsPHP_Log_Interface)) {
if (!($logger instanceof LoggerInterface)) {
throw new ApnsPHP_Exception(
"Unable to use an instance of '" . get_class($logger) . "' as logger: " .
"a logger must implements ApnsPHP_Log_Interface."
"a logger must implements 'Psr\Log\LoggerInterface'."
);
}
$this->_logger = $logger;
Expand All @@ -147,7 +149,7 @@ public function setLogger(ApnsPHP_Log_Interface $logger)
/**
* Get the Logger instance.
*
* @return @type ApnsPHP_Log_Interface Current Logger instance.
* @return @type Psr\Log\LoggerInterface Current Logger instance.
*/
public function getLogger()
{
Expand Down Expand Up @@ -203,7 +205,7 @@ public function getCertificateAuthority()
/**
* Set the write interval.
*
* After each socket write operation we are sleeping for this
* After each socket write operation we are sleeping for this
* time interval. To speed up the sending operations, use Zero
* as parameter but some messages may be lost.
*
Expand Down Expand Up @@ -346,12 +348,12 @@ public function connect()
try {
$bConnected = $this->_connect();
} catch (ApnsPHP_Exception $e) {
$this->_log('ERROR: ' . $e->getMessage());
$this->_logger()->error($e->getMessage());
if ($nRetry >= $this->_nConnectRetryTimes) {
throw $e;
} else {
$this->_log(
"INFO: Retry to connect (" . ($nRetry+1) .
$this->_logger()->info(
"Retry to connect (" . ($nRetry+1) .
"/{$this->_nConnectRetryTimes})..."
);
usleep($this->_nConnectRetryInterval);
Expand All @@ -369,7 +371,7 @@ public function connect()
public function disconnect()
{
if (is_resource($this->_hSocket)) {
$this->_log('INFO: Disconnected.');
$this->_logger()->info('Disconnected.');
if ($this->_nProtocol === self::PROTOCOL_HTTP) {
curl_close($this->_hSocket);
return true;
Expand Down Expand Up @@ -441,7 +443,7 @@ protected function _httpInit()
*/
protected function _binaryConnect($sURL)
{
$this->_log("INFO: Trying {$sURL}...");
$this->_logger()->info("Trying {$sURL}...");

/**
* @see http://php.net/manual/en/context.ssl.php
Expand Down Expand Up @@ -469,21 +471,20 @@ protected function _binaryConnect($sURL)
stream_set_blocking($this->_hSocket, 0);
stream_set_write_buffer($this->_hSocket, 0);

$this->_log("INFO: Connected to {$sURL}.");
$this->_logger()->info("Connected to {$sURL}.");

return true;
}

/**
* Logs a message through the Logger.
*
* @param $sMessage @type string The message.
* Return the Logger (with lazy loading)
*/
protected function _log($sMessage)
protected function _logger()
{
if (!isset($this->_logger)) {
$this->_logger = new ApnsPHP_Log_Embedded();
}
$this->_logger->log($sMessage);

return $this->_logger;
}
}
8 changes: 4 additions & 4 deletions ApnsPHP/Feedback.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,11 @@ public function receive()
$this->_aFeedback = array();
$sBuffer = '';
while (!feof($this->_hSocket)) {
$this->_log('INFO: Reading...');
$this->_logger()->info('Reading...');
$sBuffer .= $sCurrBuffer = fread($this->_hSocket, 8192);
$nCurrBufferLen = strlen($sCurrBuffer);
if ($nCurrBufferLen > 0) {
$this->_log("INFO: {$nCurrBufferLen} bytes read.");
$this->_logger()->info("{$nCurrBufferLen} bytes read.");
}
unset($sCurrBuffer, $nCurrBufferLen);

Expand All @@ -85,7 +85,7 @@ public function receive()
$sFeedbackTuple = substr($sBuffer, 0, $nFeedbackTupleLen);
$sBuffer = substr($sBuffer, $nFeedbackTupleLen);
$this->_aFeedback[] = $aFeedback = $this->_parseBinaryTuple($sFeedbackTuple);
$this->_log(sprintf("INFO: New feedback tuple: timestamp=%d (%s), tokenLength=%d, deviceToken=%s.",
$this->_logger()->info(sprintf("New feedback tuple: timestamp=%d (%s), tokenLength=%d, deviceToken=%s.",
$aFeedback['timestamp'], date('Y-m-d H:i:s', $aFeedback['timestamp']),
$aFeedback['tokenLength'], $aFeedback['deviceToken']
));
Expand All @@ -97,7 +97,7 @@ public function receive()
$null = NULL;
$nChangedStreams = stream_select($read, $null, $null, 0, $this->_nSocketSelectTimeout);
if ($nChangedStreams === false) {
$this->_log('WARNING: Unable to wait for a stream availability.');
$this->_logger()->warning('Unable to wait for a stream availability.');
break;
}
}
Expand Down
31 changes: 19 additions & 12 deletions ApnsPHP/Log/Embedded.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
* @version $Id$
*/

use Psr\Log\AbstractLogger;

/**
* A simple logger.
*
Expand All @@ -28,17 +30,22 @@
*
* @ingroup ApnsPHP_Log
*/
class ApnsPHP_Log_Embedded implements ApnsPHP_Log_Interface
class ApnsPHP_Log_Embedded extends AbstractLogger
{
/**
* Logs a message.
*
* @param $sMessage @type string The message.
*/
public function log($sMessage)
{
printf("%s ApnsPHP[%d]: %s\n",
date('r'), getmypid(), trim($sMessage)
);
}

/**
* Logs with an arbitrary level.
*
* @param mixed $level
* @param string $message
* @param array $context
* @return null
*/
public function log($level, $message, array $context = array())
{
printf("%s: %s ApnsPHP[%d]: %s\n",
date('r'), strtoupper($level), getmypid(), trim($message)
);
}

}
41 changes: 0 additions & 41 deletions ApnsPHP/Log/Interface.php

This file was deleted.

16 changes: 8 additions & 8 deletions ApnsPHP/Push.php
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ public function send()
$this->_aErrors = array();
$nRun = 1;
while (($nMessages = count($this->_aMessageQueue)) > 0) {
$this->_log("INFO: Sending messages queue, run #{$nRun}: $nMessages message(s) left in queue.");
$this->_logger()->info("Sending messages queue, run #{$nRun}: $nMessages message(s) left in queue.");

$bError = false;
foreach($this->_aMessageQueue as $k => &$aMessage) {
Expand All @@ -171,26 +171,26 @@ public function send()
if (!empty($aMessage['ERRORS'])) {
foreach($aMessage['ERRORS'] as $aError) {
if ($aError['statusCode'] == 0) {
$this->_log("INFO: Message ID {$k} {$sCustomIdentifier} has no error ({$aError['statusCode']}), removing from queue...");
$this->_logger()->info("Message ID {$k} {$sCustomIdentifier} has no error ({$aError['statusCode']}), removing from queue...");
$this->_removeMessageFromQueue($k);
continue 2;
} else if ($aError['statusCode'] > 1 && $aError['statusCode'] <= 8) {
$this->_log("WARNING: Message ID {$k} {$sCustomIdentifier} has an unrecoverable error ({$aError['statusCode']}), removing from queue without retrying...");
$this->_logger()->warning("Message ID {$k} {$sCustomIdentifier} has an unrecoverable error ({$aError['statusCode']}), removing from queue without retrying...");
$this->_removeMessageFromQueue($k, true);
continue 2;
}
}
if (($nErrors = count($aMessage['ERRORS'])) >= $this->_nSendRetryTimes) {
$this->_log(
"WARNING: Message ID {$k} {$sCustomIdentifier} has {$nErrors} errors, removing from queue..."
$this->_logger()->warning(
"Message ID {$k} {$sCustomIdentifier} has {$nErrors} errors, removing from queue..."
);
$this->_removeMessageFromQueue($k, true);
continue;
}
}

$nLen = strlen($this->_nProtocol === self::PROTOCOL_HTTP ? $message->getPayload() : $aMessage['BINARY_NOTIFICATION']);
$this->_log("STATUS: Sending message ID {$k} {$sCustomIdentifier} (" . ($nErrors + 1) . "/{$this->_nSendRetryTimes}): {$nLen} bytes.");
$this->_logger()->debug("Sending message ID {$k} {$sCustomIdentifier} (" . ($nErrors + 1) . "/{$this->_nSendRetryTimes}): {$nLen} bytes.");

$aErrorMessage = null;

Expand Down Expand Up @@ -228,7 +228,7 @@ public function send()
$null = NULL;
$nChangedStreams = @stream_select($read, $null, $null, 0, $this->_nSocketSelectTimeout);
if ($nChangedStreams === false) {
$this->_log('ERROR: Unable to wait for a stream availability.');
$this->_logger()->error('Unable to wait for a stream availability.');
break;
} else if ($nChangedStreams > 0) {
$bError = $this->_updateQueue();
Expand Down Expand Up @@ -403,7 +403,7 @@ protected function _updateQueue($aErrorMessage = null)
unset($aStreamErrorMessage);
}

$this->_log('ERROR: Unable to send message ID ' .
$this->_logger()->error('Unable to send message ID ' .
$aErrorMessage['identifier'] . ': ' .
$aErrorMessage['statusMessage'] . ' (' . $aErrorMessage['statusCode'] . ').');

Expand Down
18 changes: 9 additions & 9 deletions ApnsPHP/Push/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,13 @@ public function onSignal($nSignal)
case SIGQUIT:
case SIGINT:
if (($nPid = posix_getpid()) != $this->_nParentPid) {
$this->_log("INFO: Child $nPid received signal #{$nSignal}, shutdown...");
$this->_logger()->info("Child $nPid received signal #{$nSignal}, shutdown...");
$this->_nRunningProcesses--;
exit(0);
}
break;
default:
$this->_log("INFO: Ignored signal #{$nSignal}.");
$this->_logger()->info("Ignored signal #{$nSignal}.");
break;
}
}
Expand All @@ -146,7 +146,7 @@ public function onSignal($nSignal)
public function onShutdown()
{
if (posix_getpid() == $this->_nParentPid) {
$this->_log('INFO: Parent shutdown, cleaning memory...');
$this->_logger()->info('Parent shutdown, cleaning memory...');
@shm_remove($this->_hShm) && @shm_detach($this->_hShm);
@sem_remove($this->_hSem);
}
Expand Down Expand Up @@ -178,17 +178,17 @@ public function start()
$this->_nCurrentProcess = $i;
$this->_aPids[$i] = $nPid = pcntl_fork();
if ($nPid == -1) {
$this->_log('WARNING: Could not fork');
$this->_logger()->warning('Could not fork');
} else if ($nPid > 0) {
// Parent process
$this->_log("INFO: Forked process PID {$nPid}");
$this->_logger()->info("Forked process PID {$nPid}");
$this->_nRunningProcesses++;
} else {
// Child process
try {
parent::connect();
} catch (ApnsPHP_Exception $e) {
$this->_log('ERROR: ' . $e->getMessage() . ', exiting...');
$this->_logger()->error($e->getMessage() . ', exiting...');
exit(1);
}
$this->_mainLoop();
Expand Down Expand Up @@ -276,7 +276,7 @@ protected function _mainLoop()
pcntl_signal_dispatch();

if (posix_getppid() != $this->_nParentPid) {
$this->_log("INFO: Parent process {$this->_nParentPid} died unexpectedly, exiting...");
$this->_logger()->info("Parent process {$this->_nParentPid} died unexpectedly, exiting...");
break;
}

Expand All @@ -294,7 +294,7 @@ protected function _mainLoop()

$nMessages = count($aQueue);
if ($nMessages > 0) {
$this->_log('INFO: Process ' . ($this->_nCurrentProcess + 1) . " has {$nMessages} messages, sending...");
$this->_logger()->info('Process ' . ($this->_nCurrentProcess + 1) . " has {$nMessages} messages, sending...");
parent::send();
} else {
usleep(self::MAIN_LOOP_USLEEP);
Expand Down Expand Up @@ -335,4 +335,4 @@ protected function _setQueue($nQueueKey, $nProcess = 0, $aQueue = array())
}
return shm_put_var($this->_hShm, $nQueueKey + $nProcess, $aQueue);
}
}
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Architecture
- **Push class**, to push one or more messages to Apple Push Notification service.
- **Feedback class**, to query the Apple Feedback service to get the list of broken device tokens.
- **Push Server class**, to create a Push Server with one or more (forked) processes reading from a common message queue.
- **Log class/interface**, to log to standard output or for custom logging purpose.
- **Log class/interface**, to log to standard output or for custom logging purpose (supports loggers implementing the PSR-3 logger interface).
- **Objective-C Demo Project** with not-running, running in foreground and running in background application state support.

Classes hierarchy
Expand Down
Loading