Skip to content

Commit

Permalink
Merge pull request #845 from sjinks/logger-firephp
Browse files Browse the repository at this point in the history
[NFR] FirePHP Log Adapter and Formatter
  • Loading branch information
Phalcon committed Jul 15, 2013
2 parents e29a21a + c997e98 commit 2705089
Show file tree
Hide file tree
Showing 10 changed files with 575 additions and 63 deletions.
2 changes: 2 additions & 0 deletions ext/config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,13 @@ config/adapter/json.c \
config/exception.c \
filterinterface.c \
logger/multiple.c \
logger/formatter/firephp.c \
logger/formatter/json.c \
logger/formatter/line.c \
logger/formatter/syslog.c \
logger/formatter.c \
logger/adapter/file.c \
logger/adapter/firephp.c \
logger/adapter/stream.c \
logger/adapter/syslog.c \
logger/exception.c \
Expand Down
4 changes: 2 additions & 2 deletions ext/config.w32
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ if (PHP_PHALCON != "no") {
ADD_SOURCES("ext/phalcon/config/adapter", "ini.c json.c", "phalcon")
ADD_SOURCES("ext/phalcon/config", "exception.c", "phalcon")
ADD_SOURCES("ext/phalcon/logger", "multiple.c formatter.c exception.c adapterinterface.c formatterinterface.c adapter.c item.c", "phalcon")
ADD_SOURCES("ext/phalcon/logger/formatter", "json.c line.c syslog.c", "phalcon")
ADD_SOURCES("ext/phalcon/logger/adapter", "file.c stream.c syslog.c", "phalcon")
ADD_SOURCES("ext/phalcon/logger/formatter", "json.c line.c syslog.c firephp.c", "phalcon")
ADD_SOURCES("ext/phalcon/logger/adapter", "file.c stream.c syslog.c firephp.c", "phalcon")
ADD_SOURCES("ext/phalcon/filter", "exception.c userfilterinterface.c", "phalcon")
ADD_SOURCES("ext/phalcon/queue", "beanstalk.c", "phalcon")
ADD_SOURCES("ext/phalcon/queue/beanstalk", "job.c", "phalcon")
Expand Down
1 change: 1 addition & 0 deletions ext/kernel/string.c
Original file line number Diff line number Diff line change
Expand Up @@ -1232,6 +1232,7 @@ void phalcon_json_encode(zval *return_value, zval *v, int opts TSRMLS_DC)
smart_str buf = { NULL, 0, 0 };

php_json_encode(&buf, v, opts TSRMLS_CC);
smart_str_0(&buf);
ZVAL_STRINGL(return_value, buf.c, buf.len, 0);
}

Expand Down
221 changes: 221 additions & 0 deletions ext/logger/adapter/firephp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@

/*
+------------------------------------------------------------------------+
| Phalcon Framework |
+------------------------------------------------------------------------+
| Copyright (c) 2011-2013 Phalcon Team (http://www.phalconphp.com) |
+------------------------------------------------------------------------+
| This source file is subject to the New BSD License that is bundled |
| with this package in the file docs/LICENSE.txt. |
| |
| If you did not receive a copy of the license and are unable to |
| obtain it through the world-wide-web, please send an email |
| to license@phalconphp.com so we can send you a copy immediately. |
+------------------------------------------------------------------------+
| Authors: Andres Gutierrez <andres@phalconphp.com> |
| Eduar Carvajal <eduar@phalconphp.com> |
| Vladimir Kolesnikov <vladimir@extrememember.com> |
+------------------------------------------------------------------------+
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_phalcon.h"
#include "phalcon.h"

#include "main/SAPI.h"
#include "ext/standard/php_smart_str.h"

#include "Zend/zend_operators.h"
#include "Zend/zend_exceptions.h"
#include "Zend/zend_interfaces.h"

#include "kernel/main.h"
#include "kernel/memory.h"
#include "kernel/fcall.h"
#include "kernel/object.h"

#include "logger/adapter/firephp.h"

/**
* Phalcon\Logger\Adapter\Firephp
*
* Sends logs to FirePHP
*
*<code>
* $logger = new \Phalcon\Logger\Adapter\Firephp("");
* $logger->log("This is a message");
* $logger->log("This is an error", \Phalcon\Logger::ERROR);
* $logger->error("This is another error");
*</code>
*/


/**
* Phalcon\Logger\Adapter\Firephp initializer
*/
PHALCON_INIT_CLASS(Phalcon_Logger_Adapter_Firephp){

PHALCON_REGISTER_CLASS_EX(Phalcon\\Logger\\Adapter, Firephp, logger_adapter_firephp, "phalcon\\logger\\adapter", phalcon_logger_adapter_firephp_method_entry, 0);

zend_declare_property_bool(phalcon_logger_adapter_firephp_ce, SL("_initialized"), 0, ZEND_ACC_PRIVATE | ZEND_ACC_STATIC TSRMLS_CC);
zend_declare_property_long(phalcon_logger_adapter_firephp_ce, SL("_index"), 1, ZEND_ACC_PRIVATE | ZEND_ACC_STATIC TSRMLS_CC);

zend_class_implements(phalcon_logger_adapter_firephp_ce TSRMLS_CC, 1, phalcon_logger_adapterinterface_ce);

return SUCCESS;
}

/**
* Returns the internal formatter
*
* @return Phalcon\Logger\FormatterInterface
*/
PHP_METHOD(Phalcon_Logger_Adapter_Firephp, getFormatter){

zval *formatter = NULL;

PHALCON_MM_GROW();

PHALCON_OBS_VAR(formatter);
phalcon_read_property_this(&formatter, this_ptr, SL("_formatter"), PH_NOISY_CC);
if (Z_TYPE_P(formatter) != IS_OBJECT) {
/* This will update $this->_formatter, no need to call phalcon_update_property_this() explicitly */
object_init_ex(formatter, phalcon_logger_formatter_firephp_ce);
}

RETURN_CCTOR(formatter);
}

/**
* Writes the log to the stream itself
*
* @param string $message
* @param int $type
* @param int $time
* @see http://www.firephp.org/Wiki/Reference/Protocol
*/
PHP_METHOD(Phalcon_Logger_Adapter_Firephp, logInternal){

zval *message, *type, *time, *formatter, *applied_format;
zval *initialized, *index;
sapi_header_line h = { NULL, 0, 0 };
smart_str str = { NULL, 0, 0 };
int size, offset, num_bytes;
const int chunk = 4960;

/* If headers has already been sent, we can do nothing. Exit early. */
if (SG(headers_sent)) {
RETURN_FALSE;
}

PHALCON_MM_GROW();

phalcon_fetch_params(1, 3, 0, &message, &type, &time);

PHALCON_INIT_VAR(formatter);
phalcon_call_method(formatter, this_ptr, "getformatter");

PHALCON_OBS_VAR(initialized);
phalcon_read_static_property(&initialized, SL("phalcon\\logger\\adapter\\firephp"), SL("_initialized") TSRMLS_CC);
if (!zend_is_true(initialized)) {
/**
* Send the required initialization headers.
* Use Zend API here so that the user can see the progress and because
* if we delegate this to Phalcon and there will be a fatal errors,
* chances are that the headers will never ne sent.
*/
h.line = "X-Wf-Protocol-1: http://meta.wildfirehq.org/Protocol/JsonStream/0.2";
h.line_len = sizeof("X-Wf-Protocol-1: http://meta.wildfirehq.org/Protocol/JsonStream/0.2")-1;
sapi_header_op(SAPI_HEADER_REPLACE, &h TSRMLS_CC);

h.line = "X-Wf-1-Plugin-1: http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3";
h.line_len = sizeof("X-Wf-1-Plugin-1: http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3")-1;
sapi_header_op(SAPI_HEADER_REPLACE, &h TSRMLS_CC);

h.line = "X-Wf-1-Structure-1: http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1";
h.line_len = sizeof("X-Wf-1-Structure-1: http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1")-1;
sapi_header_op(SAPI_HEADER_REPLACE, &h TSRMLS_CC);

ZVAL_TRUE(initialized); /* This will also update the property because "initialized" was not separated */
}

PHALCON_INIT_VAR(applied_format);
phalcon_call_method_p3(applied_format, formatter, "format", message, type, time);
if (Z_TYPE_P(applied_format) != IS_STRING) {
PHALCON_THROW_EXCEPTION_STR(phalcon_logger_exception_ce, "The formatted message is not valid");
return;
}

PHALCON_OBS_VAR(index);
phalcon_read_static_property(&index, SL("phalcon\\logger\\adapter\\firephp"), SL("_index") TSRMLS_CC);

size = Z_STRLEN_P(applied_format);
offset = 0;

/**
* We need to send the data in chunks not exceeding 5,000 bytes.
* Allocate the smart string once to avoid performance penalties.
*/
smart_str_alloc4(&str, (size > chunk ? chunk : size), 0, num_bytes);

while (size > 0) {
smart_str_appends(&str, "X-Wf-1-1-1-");
smart_str_append_long(&str, Z_LVAL_P(index));
smart_str_appends(&str, ": ");
num_bytes = size > chunk ? chunk : size;

if (offset) {
/* This is not the first chunk, prepend the payload with "|" */
smart_str_appendc(&str, '|');
}

/* Grab the chunk from the encoded string */
smart_str_appendl(&str, Z_STRVAL_P(applied_format) + offset, num_bytes);

size -= num_bytes;
offset += num_bytes;

if (size) {
/* If we have more data to send, append "|/" */
smart_str_appendl(&str, "|\\", 2);
}

smart_str_0(&str); /* Not strictly necessary but just to be safe */

/* Send the result */
h.line = str.c;
h.line_len = str.len;
sapi_header_op(SAPI_HEADER_REPLACE, &h TSRMLS_CC);

/* Update header index; this will update Phalcon\Logger\Adapter\Firephp as well */
ZVAL_LONG(index, Z_LVAL_P(index)+1);

/**
* Do not free and then reallocate memory. Just pretend the string
* is empty. We will take care of deallocation later.
*/
str.len = 0;
}

/* Deallocate the smnart string if it is not empty */
if (str.c) {
smart_str_free(&str);
}

PHALCON_MM_RESTORE();
}

/**
* Closes the logger
*
* @return boolean
*/
PHP_METHOD(Phalcon_Logger_Adapter_Firephp, close){

RETURN_TRUE;
}

39 changes: 39 additions & 0 deletions ext/logger/adapter/firephp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@

/*
+------------------------------------------------------------------------+
| Phalcon Framework |
+------------------------------------------------------------------------+
| Copyright (c) 2011-2013 Phalcon Team (http://www.phalconphp.com) |
+------------------------------------------------------------------------+
| This source file is subject to the New BSD License that is bundled |
| with this package in the file docs/LICENSE.txt. |
| |
| If you did not receive a copy of the license and are unable to |
| obtain it through the world-wide-web, please send an email |
| to license@phalconphp.com so we can send you a copy immediately. |
+------------------------------------------------------------------------+
| Authors: Andres Gutierrez <andres@phalconphp.com> |
| Eduar Carvajal <eduar@phalconphp.com> |
| Vladimir Kolesnikov <vladimir@extrememember.com> |
+------------------------------------------------------------------------+
*/

#ifndef PHALCON_LOGGER_ADAPTER_FIREPHP_H
#define PHALCON_LOGGER_ADAPTER_FIREPHP_H

extern zend_class_entry *phalcon_logger_adapter_firephp_ce;

PHALCON_INIT_CLASS(Phalcon_Logger_Adapter_Firephp);

PHP_METHOD(Phalcon_Logger_Adapter_Firephp, getFormatter);
PHP_METHOD(Phalcon_Logger_Adapter_Firephp, logInternal);
PHP_METHOD(Phalcon_Logger_Adapter_Firephp, close);

PHALCON_INIT_FUNCS(phalcon_logger_adapter_firephp_method_entry){
PHP_ME(Phalcon_Logger_Adapter_Firephp, getFormatter, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Phalcon_Logger_Adapter_Firephp, logInternal, arginfo_phalcon_logger_adapter_file_loginternal, ZEND_ACC_PUBLIC)
PHP_ME(Phalcon_Logger_Adapter_Firephp, close, NULL, ZEND_ACC_PUBLIC)
PHP_FE_END
};

#endif /* PHALCON_LOGGER_ADAPTER_FIREPHP_H */
73 changes: 12 additions & 61 deletions ext/logger/formatter.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,70 +59,21 @@ PHALCON_INIT_CLASS(Phalcon_Logger_Formatter){
*/
PHP_METHOD(Phalcon_Logger_Formatter, getTypeString){

zval *type, *type_str = NULL;
static const char *lut[10] = {
"EMERGENCY", "CRITICAL", "ALERT", "ERROR", "WARNING",
"NOTICE", "INFO", "DEBUG", "CUSTOM", "SPECIAL"
};

PHALCON_MM_GROW();
zval *type;
int itype;

phalcon_fetch_params(1, 1, 0, &type);


switch (phalcon_get_intval(type)) {

case 7:
PHALCON_INIT_VAR(type_str);
ZVAL_STRING(type_str, "DEBUG", 1);
break;

case 3:
PHALCON_INIT_NVAR(type_str);
ZVAL_STRING(type_str, "ERROR", 1);
break;

case 4:
PHALCON_INIT_NVAR(type_str);
ZVAL_STRING(type_str, "WARNING", 1);
break;

case 1:
PHALCON_INIT_NVAR(type_str);
ZVAL_STRING(type_str, "CRITICAL", 1);
break;

case 8:
PHALCON_INIT_NVAR(type_str);
ZVAL_STRING(type_str, "CUSTOM", 1);
break;

case 2:
PHALCON_INIT_NVAR(type_str);
ZVAL_STRING(type_str, "ALERT", 1);
break;

case 5:
PHALCON_INIT_NVAR(type_str);
ZVAL_STRING(type_str, "NOTICE", 1);
break;

case 6:
PHALCON_INIT_NVAR(type_str);
ZVAL_STRING(type_str, "INFO", 1);
break;

case 0:
PHALCON_INIT_NVAR(type_str);
ZVAL_STRING(type_str, "EMERGENCE", 1);
break;

case 9:
PHALCON_INIT_NVAR(type_str);
ZVAL_STRING(type_str, "SPECIAL", 1);
break;

default:
PHALCON_INIT_NVAR(type_str);
ZVAL_STRING(type_str, "CUSTOM", 1);
phalcon_fetch_params(0, 1, 0, &type);

itype = phalcon_get_intval(type);
if (itype > 0 && itype < 10) {
RETURN_STRING(lut[itype], 1);
}
RETURN_CTOR(type_str);

RETURN_STRING("CUSTOM", 1);
}

Loading

0 comments on commit 2705089

Please sign in to comment.