├── .gitattributes ├── .gitignore ├── Applications ├── HttpServer │ ├── HttpServer.php │ ├── config │ │ ├── autoload.php │ │ ├── config.php │ │ ├── database.php │ │ ├── mimes.php │ │ └── redis.php │ ├── controllers │ │ └── Test.php │ ├── core │ │ └── Base_Controller.php │ ├── libraries │ │ └── Doer │ │ │ └── DoerError.php │ ├── start_http_server.php │ └── system │ │ ├── core │ │ ├── Common.php │ │ ├── Config.php │ │ ├── Controller.php │ │ ├── Input.php │ │ ├── Loader.php │ │ ├── Log.php │ │ ├── Model.php │ │ ├── Output.php │ │ └── Security.php │ │ └── database │ │ ├── DB.php │ │ ├── DB_active_rec.php │ │ ├── DB_cache.php │ │ ├── DB_driver.php │ │ ├── DB_forge.php │ │ ├── DB_query_builder.php │ │ ├── DB_result.php │ │ ├── DB_utility.php │ │ ├── drivers │ │ ├── cubrid │ │ │ ├── cubrid_driver.php │ │ │ ├── cubrid_forge.php │ │ │ ├── cubrid_result.php │ │ │ ├── cubrid_utility.php │ │ │ └── index.html │ │ ├── ibase │ │ │ ├── ibase_driver.php │ │ │ ├── ibase_forge.php │ │ │ ├── ibase_result.php │ │ │ ├── ibase_utility.php │ │ │ └── index.html │ │ ├── index.html │ │ ├── mssql │ │ │ ├── index.html │ │ │ ├── mssql_driver.php │ │ │ ├── mssql_forge.php │ │ │ ├── mssql_result.php │ │ │ └── mssql_utility.php │ │ ├── mysql │ │ │ ├── index.html │ │ │ ├── mysql_driver.php │ │ │ ├── mysql_forge.php │ │ │ ├── mysql_result.php │ │ │ └── mysql_utility.php │ │ ├── mysqli │ │ │ ├── index.html │ │ │ ├── mysqli_driver.php │ │ │ ├── mysqli_forge.php │ │ │ ├── mysqli_result.php │ │ │ └── mysqli_utility.php │ │ ├── oci8 │ │ │ ├── index.html │ │ │ ├── oci8_driver.php │ │ │ ├── oci8_forge.php │ │ │ ├── oci8_result.php │ │ │ └── oci8_utility.php │ │ ├── odbc │ │ │ ├── index.html │ │ │ ├── odbc_driver.php │ │ │ ├── odbc_forge.php │ │ │ ├── odbc_result.php │ │ │ └── odbc_utility.php │ │ ├── pdo │ │ │ ├── index.html │ │ │ ├── pdo_driver.php │ │ │ ├── pdo_forge.php │ │ │ ├── pdo_result.php │ │ │ ├── pdo_utility.php │ │ │ └── subdrivers │ │ │ │ ├── index.html │ │ │ │ ├── pdo_4d_driver.php │ │ │ │ ├── pdo_4d_forge.php │ │ │ │ ├── pdo_cubrid_driver.php │ │ │ │ ├── pdo_cubrid_forge.php │ │ │ │ ├── pdo_dblib_driver.php │ │ │ │ ├── pdo_dblib_forge.php │ │ │ │ ├── pdo_firebird_driver.php │ │ │ │ ├── pdo_firebird_forge.php │ │ │ │ ├── pdo_ibm_driver.php │ │ │ │ ├── pdo_ibm_forge.php │ │ │ │ ├── pdo_informix_driver.php │ │ │ │ ├── pdo_informix_forge.php │ │ │ │ ├── pdo_mysql_driver.php │ │ │ │ ├── pdo_mysql_forge.php │ │ │ │ ├── pdo_oci_driver.php │ │ │ │ ├── pdo_oci_forge.php │ │ │ │ ├── pdo_odbc_driver.php │ │ │ │ ├── pdo_odbc_forge.php │ │ │ │ ├── pdo_pgsql_driver.php │ │ │ │ ├── pdo_pgsql_forge.php │ │ │ │ ├── pdo_sqlite_driver.php │ │ │ │ ├── pdo_sqlite_forge.php │ │ │ │ ├── pdo_sqlsrv_driver.php │ │ │ │ └── pdo_sqlsrv_forge.php │ │ ├── postgre │ │ │ ├── index.html │ │ │ ├── postgre_driver.php │ │ │ ├── postgre_forge.php │ │ │ ├── postgre_result.php │ │ │ └── postgre_utility.php │ │ ├── sqlite │ │ │ ├── index.html │ │ │ ├── sqlite_driver.php │ │ │ ├── sqlite_forge.php │ │ │ ├── sqlite_result.php │ │ │ └── sqlite_utility.php │ │ ├── sqlite3 │ │ │ ├── index.html │ │ │ ├── sqlite3_driver.php │ │ │ ├── sqlite3_forge.php │ │ │ ├── sqlite3_result.php │ │ │ └── sqlite3_utility.php │ │ └── sqlsrv │ │ │ ├── index.html │ │ │ ├── sqlsrv_driver.php │ │ │ ├── sqlsrv_forge.php │ │ │ ├── sqlsrv_result.php │ │ │ └── sqlsrv_utility.php │ │ └── index.html └── Logger │ └── start_logger.php ├── GatewayWorker ├── BusinessWorker.php ├── Gateway.php ├── Lib │ ├── Context.php │ ├── Db.php │ ├── DbConnection.php │ └── Gateway.php ├── Protocols │ └── GatewayProtocol.php └── Register.php ├── Logger ├── Autoloader.php ├── Client.php ├── Monolog │ ├── ErrorHandler.php │ ├── Formatter │ │ ├── ChromePHPFormatter.php │ │ ├── ElasticaFormatter.php │ │ ├── FlowdockFormatter.php │ │ ├── FluentdFormatter.php │ │ ├── FormatterInterface.php │ │ ├── GelfMessageFormatter.php │ │ ├── HtmlFormatter.php │ │ ├── JsonFormatter.php │ │ ├── LineFormatter.php │ │ ├── LogglyFormatter.php │ │ ├── LogstashFormatter.php │ │ ├── MongoDBFormatter.php │ │ ├── NormalizerFormatter.php │ │ ├── ScalarFormatter.php │ │ └── WildfireFormatter.php │ ├── Handler │ │ ├── AbstractHandler.php │ │ ├── AbstractProcessingHandler.php │ │ ├── AbstractSyslogHandler.php │ │ ├── AmqpHandler.php │ │ ├── BrowserConsoleHandler.php │ │ ├── BufferHandler.php │ │ ├── ChromePHPHandler.php │ │ ├── CouchDBHandler.php │ │ ├── CubeHandler.php │ │ ├── Curl │ │ │ └── Util.php │ │ ├── DeduplicationHandler.php │ │ ├── DoctrineCouchDBHandler.php │ │ ├── DynamoDbHandler.php │ │ ├── ElasticSearchHandler.php │ │ ├── ErrorLogHandler.php │ │ ├── FilterHandler.php │ │ ├── FingersCrossed │ │ │ ├── ActivationStrategyInterface.php │ │ │ ├── ChannelLevelActivationStrategy.php │ │ │ └── ErrorLevelActivationStrategy.php │ │ ├── FingersCrossedHandler.php │ │ ├── FirePHPHandler.php │ │ ├── FleepHookHandler.php │ │ ├── FlowdockHandler.php │ │ ├── FormattableHandlerInterface.php │ │ ├── FormattableHandlerTrait.php │ │ ├── GelfHandler.php │ │ ├── GroupHandler.php │ │ ├── Handler.php │ │ ├── HandlerInterface.php │ │ ├── HandlerWrapper.php │ │ ├── HipChatHandler.php │ │ ├── IFTTTHandler.php │ │ ├── LogEntriesHandler.php │ │ ├── LogglyHandler.php │ │ ├── MailHandler.php │ │ ├── MandrillHandler.php │ │ ├── MissingExtensionException.php │ │ ├── MongoDBHandler.php │ │ ├── NativeMailerHandler.php │ │ ├── NewRelicHandler.php │ │ ├── NullHandler.php │ │ ├── PHPConsoleHandler.php │ │ ├── ProcessableHandlerInterface.php │ │ ├── ProcessableHandlerTrait.php │ │ ├── PsrHandler.php │ │ ├── PushoverHandler.php │ │ ├── RavenHandler.php │ │ ├── RedisHandler.php │ │ ├── RollbarHandler.php │ │ ├── RotatingFileHandler.php │ │ ├── SamplingHandler.php │ │ ├── SlackHandler.php │ │ ├── SocketHandler.php │ │ ├── StreamHandler.php │ │ ├── SwiftMailerHandler.php │ │ ├── SyslogHandler.php │ │ ├── SyslogUdp │ │ │ └── UdpSocket.php │ │ ├── SyslogUdpHandler.php │ │ ├── TestHandler.php │ │ ├── WhatFailureGroupHandler.php │ │ └── ZendMonitorHandler.php │ ├── Logger.php │ ├── Processor │ │ ├── GitProcessor.php │ │ ├── IntrospectionProcessor.php │ │ ├── MemoryPeakUsageProcessor.php │ │ ├── MemoryProcessor.php │ │ ├── MemoryUsageProcessor.php │ │ ├── ProcessIdProcessor.php │ │ ├── PsrLogMessageProcessor.php │ │ ├── TagProcessor.php │ │ ├── UidProcessor.php │ │ └── WebProcessor.php │ └── Registry.php ├── Psr │ └── Log │ │ ├── LogLevel.php │ │ ├── LoggerAwareInterface.php │ │ └── LoggerInterface.php └── Server.php ├── README.md ├── Workerman ├── .gitignore ├── Autoloader.php ├── Connection │ ├── AsyncTcpConnection.php │ ├── ConnectionInterface.php │ ├── TcpConnection.php │ └── UdpConnection.php ├── Events │ ├── Ev.php │ ├── Event.php │ ├── EventInterface.php │ ├── Libevent.php │ └── Select.php ├── Lib │ ├── Constants.php │ └── Timer.php ├── MIT-LICENSE.txt ├── Protocols │ ├── Frame.php │ ├── Http.php │ ├── Http │ │ └── mime.types │ ├── ProtocolInterface.php │ ├── Text.php │ ├── Websocket.php │ └── Ws.php ├── README.md ├── WebServer.php ├── Worker.php └── composer.json └── start.php /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /Applications/HttpServer/config/autoload.php: -------------------------------------------------------------------------------- 1 | '112.124.234.121', 9 | 'username' => 'test', 10 | 'password' => 'test', 11 | 'database' => 'test', 12 | 'dbdriver' => 'mysqli', 13 | 'dbprefix' => '', 14 | 'pconnect' => TRUE, 15 | 'db_debug' => TRUE, 16 | 'cache_on' => FALSE, 17 | 'cachedir' => '', 18 | 'char_set' => 'utf8mb4', 19 | 'dbcollat' => 'utf8_general_ci', 20 | 'swap_pre' => '', 21 | 'autoinit' => TRUE, 22 | 'stricton' => FALSE, 23 | 'compress' => TRUE 24 | ); 25 | 26 | 27 | /* Location: ./application/config/database.php */ -------------------------------------------------------------------------------- /Applications/HttpServer/config/redis.php: -------------------------------------------------------------------------------- 1 | output_json(1,1); 25 | } 26 | } -------------------------------------------------------------------------------- /Applications/HttpServer/libraries/Doer/DoerError.php: -------------------------------------------------------------------------------- 1 | others = $others; 144 | } 145 | } 146 | 147 | -------------------------------------------------------------------------------- /Applications/HttpServer/start_http_server.php: -------------------------------------------------------------------------------- 1 | input = get_instance()->input; 27 | $this->output = get_instance()->output; 28 | $this->load = get_instance()->load; 29 | } 30 | 31 | /** 32 | * 每次访问方法都会执行这里 33 | */ 34 | public function __CI_construct(){ 35 | 36 | } 37 | public function __get($name) 38 | { 39 | return get_instance()->$name; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/core/Model.php: -------------------------------------------------------------------------------- 1 | $key; 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/cubrid/cubrid_utility.php: -------------------------------------------------------------------------------- 1 | db->data_cache['db_names'])) 57 | { 58 | return $this->db->data_cache['db_names']; 59 | } 60 | 61 | return $this->db->data_cache['db_names'] = cubrid_list_dbs($this->db->conn_id); 62 | } 63 | 64 | // -------------------------------------------------------------------- 65 | 66 | /** 67 | * CUBRID Export 68 | * 69 | * @param array Preferences 70 | * @return mixed 71 | */ 72 | protected function _backup($params = array()) 73 | { 74 | // No SQL based support in CUBRID as of version 8.4.0. Database or 75 | // table backup can be performed using CUBRID Manager 76 | // database administration tool. 77 | return $this->db->display_error('db_unsupported_feature'); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/cubrid/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 | 8 |

Directory access is forbidden.

9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/ibase/ibase_utility.php: -------------------------------------------------------------------------------- 1 | db->hostname, $this->db->username, $this->db->password)) 58 | { 59 | $res = ibase_backup($service, $this->db->database, $filename.'.fbk'); 60 | 61 | // Close the service connection 62 | ibase_service_detach($service); 63 | return $res; 64 | } 65 | 66 | return FALSE; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/ibase/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 | 8 |

Directory access is forbidden.

9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 | 8 |

Directory access is forbidden.

9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/mssql/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 | 8 |

Directory access is forbidden.

9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/mssql/mssql_utility.php: -------------------------------------------------------------------------------- 1 | db->display_error('db_unsupported_feature'); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/mysql/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 | 8 |

Directory access is forbidden.

9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/mysqli/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 | 8 |

Directory access is forbidden.

9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/oci8/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 | 8 |

Directory access is forbidden.

9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/oci8/oci8_utility.php: -------------------------------------------------------------------------------- 1 | db->display_error('db_unsupported_feature'); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/odbc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 | 8 |

Directory access is forbidden.

9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/odbc/odbc_forge.php: -------------------------------------------------------------------------------- 1 | db->display_error('db_unsupported_feature'); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/pdo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 | 8 |

Directory access is forbidden.

9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/pdo/pdo_forge.php: -------------------------------------------------------------------------------- 1 | db->display_error('db_unsupported_feature'); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/pdo/subdrivers/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 | 8 |

Directory access is forbidden.

9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 | 8 |

Directory access is forbidden.

9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/postgre/postgre_utility.php: -------------------------------------------------------------------------------- 1 | db->display_error('db_unsupported_feature'); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/sqlite/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 | 8 |

Directory access is forbidden.

9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/sqlite/sqlite_utility.php: -------------------------------------------------------------------------------- 1 | db->display_error('db_unsupported_feature'); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/sqlite3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 | 8 |

Directory access is forbidden.

9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/sqlite3/sqlite3_utility.php: -------------------------------------------------------------------------------- 1 | db->display_error('db_unsupported_feature'); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/sqlsrv/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 | 8 |

Directory access is forbidden.

9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/drivers/sqlsrv/sqlsrv_utility.php: -------------------------------------------------------------------------------- 1 | db->display_error('db_unsupported_feature'); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /Applications/HttpServer/system/database/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 | 8 |

Directory access is forbidden.

9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Applications/Logger/start_logger.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace GatewayWorker\Lib; 15 | 16 | use Exception; 17 | 18 | /** 19 | * 上下文 包含当前用户 uid, 内部通信 local_ip local_port socket_id,以及客户端 client_ip client_port 20 | */ 21 | class Context 22 | { 23 | /** 24 | * 内部通讯 id 25 | * 26 | * @var string 27 | */ 28 | public static $local_ip; 29 | 30 | /** 31 | * 内部通讯端口 32 | * 33 | * @var int 34 | */ 35 | public static $local_port; 36 | 37 | /** 38 | * 客户端 ip 39 | * 40 | * @var string 41 | */ 42 | public static $client_ip; 43 | 44 | /** 45 | * 客户端端口 46 | * 47 | * @var int 48 | */ 49 | public static $client_port; 50 | 51 | /** 52 | * client_id 53 | * 54 | * @var string 55 | */ 56 | public static $client_id; 57 | 58 | /** 59 | * 连接 connection->id 60 | * 61 | * @var int 62 | */ 63 | public static $connection_id; 64 | 65 | /** 66 | * 旧的session 67 | * 68 | * @var string 69 | */ 70 | public static $old_session; 71 | 72 | /** 73 | * 编码 session 74 | * 75 | * @param mixed $session_data 76 | * @return string 77 | */ 78 | public static function sessionEncode($session_data = '') 79 | { 80 | if ($session_data !== '') { 81 | return serialize($session_data); 82 | } 83 | return ''; 84 | } 85 | 86 | /** 87 | * 解码 session 88 | * 89 | * @param string $session_buffer 90 | * @return mixed 91 | */ 92 | public static function sessionDecode($session_buffer) 93 | { 94 | return unserialize($session_buffer); 95 | } 96 | 97 | /** 98 | * 清除上下文 99 | * 100 | * @return void 101 | */ 102 | public static function clear() 103 | { 104 | self::$local_ip = self::$local_port = self::$client_ip = self::$client_port = 105 | self::$client_id = self::$connection_id = self::$old_session = null; 106 | } 107 | 108 | /** 109 | * 通讯地址到 client_id 的转换 110 | * 111 | * @param int $local_ip 112 | * @param int $local_port 113 | * @param int $connection_id 114 | * @return string 115 | */ 116 | public static function addressToClientId($local_ip, $local_port, $connection_id) 117 | { 118 | return bin2hex(pack('NnN', $local_ip, $local_port, $connection_id)); 119 | } 120 | 121 | /** 122 | * client_id 到通讯地址的转换 123 | * 124 | * @param string $client_id 125 | * @return array 126 | * @throws Exception 127 | */ 128 | public static function clientIdToAddress($client_id) 129 | { 130 | if (strlen($client_id) !== 20) { 131 | throw new Exception("client_id $client_id is invalid"); 132 | } 133 | return unpack('Nlocal_ip/nlocal_port/Nconnection_id', pack('H*', $client_id)); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /GatewayWorker/Lib/Db.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace GatewayWorker\Lib; 15 | 16 | use Config\Db as DbConfig; 17 | use Exception; 18 | 19 | /** 20 | * 数据库类 21 | */ 22 | class Db 23 | { 24 | /** 25 | * 实例数组 26 | * 27 | * @var array 28 | */ 29 | protected static $instance = array(); 30 | 31 | /** 32 | * 获取实例 33 | * 34 | * @param string $config_name 35 | * @return DbConnection 36 | * @throws Exception 37 | */ 38 | public static function instance($config_name) 39 | { 40 | if (!isset(DbConfig::$$config_name)) { 41 | echo "\\Config\\Db::$config_name not set\n"; 42 | throw new Exception("\\Config\\Db::$config_name not set\n"); 43 | } 44 | 45 | if (empty(self::$instance[$config_name])) { 46 | $config = DbConfig::$$config_name; 47 | self::$instance[$config_name] = new DbConnection($config['host'], $config['port'], 48 | $config['user'], $config['password'], $config['dbname']); 49 | } 50 | return self::$instance[$config_name]; 51 | } 52 | 53 | /** 54 | * 关闭数据库实例 55 | * 56 | * @param string $config_name 57 | */ 58 | public static function close($config_name) 59 | { 60 | if (isset(self::$instance[$config_name])) { 61 | self::$instance[$config_name]->closeConnection(); 62 | self::$instance[$config_name] = null; 63 | } 64 | } 65 | 66 | /** 67 | * 关闭所有数据库实例 68 | */ 69 | public static function closeAll() 70 | { 71 | foreach (self::$instance as $connection) { 72 | $connection->closeConnection(); 73 | } 74 | self::$instance = array(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Logger/Autoloader.php: -------------------------------------------------------------------------------- 1 | $logger_name, 88 | 'logger_level' => $logger_level, 89 | 'logger_message' => $logger_message 90 | ) )); 91 | return self::sendData(self::$address, $bin_data); 92 | } 93 | 94 | /** 95 | * 发送数据给logger系统 96 | * @param string $address 97 | * @param string $buffer 98 | * @return boolean 99 | */ 100 | public static function sendData($address, $buffer) 101 | { 102 | $socket = stream_socket_client($address); 103 | if(!$socket) 104 | { 105 | return false; 106 | } 107 | return stream_socket_sendto($socket, $buffer) == strlen($buffer); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /Logger/Monolog/Formatter/ChromePHPFormatter.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Formatter; 13 | 14 | use Monolog\Logger; 15 | 16 | /** 17 | * Formats a log message according to the ChromePHP array format 18 | * 19 | * @author Christophe Coevoet 20 | */ 21 | class ChromePHPFormatter implements FormatterInterface 22 | { 23 | /** 24 | * Translates Monolog log levels to Wildfire levels. 25 | */ 26 | private $logLevels = array( 27 | Logger::DEBUG => 'log', 28 | Logger::INFO => 'info', 29 | Logger::NOTICE => 'info', 30 | Logger::WARNING => 'warn', 31 | Logger::ERROR => 'error', 32 | Logger::CRITICAL => 'error', 33 | Logger::ALERT => 'error', 34 | Logger::EMERGENCY => 'error', 35 | ); 36 | 37 | /** 38 | * {@inheritdoc} 39 | */ 40 | public function format(array $record) 41 | { 42 | // Retrieve the line and file if set and remove them from the formatted extra 43 | $backtrace = 'unknown'; 44 | if (isset($record['extra']['file'], $record['extra']['line'])) { 45 | $backtrace = $record['extra']['file'].' : '.$record['extra']['line']; 46 | unset($record['extra']['file'], $record['extra']['line']); 47 | } 48 | 49 | $message = array('message' => $record['message']); 50 | if ($record['context']) { 51 | $message['context'] = $record['context']; 52 | } 53 | if ($record['extra']) { 54 | $message['extra'] = $record['extra']; 55 | } 56 | if (count($message) === 1) { 57 | $message = reset($message); 58 | } 59 | 60 | return array( 61 | $record['channel'], 62 | $message, 63 | $backtrace, 64 | $this->logLevels[$record['level']], 65 | ); 66 | } 67 | 68 | public function formatBatch(array $records) 69 | { 70 | $formatted = array(); 71 | 72 | foreach ($records as $record) { 73 | $formatted[] = $this->format($record); 74 | } 75 | 76 | return $formatted; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Logger/Monolog/Formatter/ElasticaFormatter.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Formatter; 13 | 14 | use Elastica\Document; 15 | 16 | /** 17 | * Format a log message into an Elastica Document 18 | * 19 | * @author Jelle Vink 20 | */ 21 | class ElasticaFormatter extends NormalizerFormatter 22 | { 23 | /** 24 | * @var string Elastic search index name 25 | */ 26 | protected $index; 27 | 28 | /** 29 | * @var string Elastic search document type 30 | */ 31 | protected $type; 32 | 33 | /** 34 | * @param string $index Elastic Search index name 35 | * @param string $type Elastic Search document type 36 | */ 37 | public function __construct($index, $type) 38 | { 39 | // elasticsearch requires a ISO 8601 format date with optional millisecond precision. 40 | parent::__construct('Y-m-d\TH:i:s.uP'); 41 | 42 | $this->index = $index; 43 | $this->type = $type; 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | public function format(array $record) 50 | { 51 | $record = parent::format($record); 52 | 53 | return $this->getDocument($record); 54 | } 55 | 56 | /** 57 | * Getter index 58 | * @return string 59 | */ 60 | public function getIndex() 61 | { 62 | return $this->index; 63 | } 64 | 65 | /** 66 | * Getter type 67 | * @return string 68 | */ 69 | public function getType() 70 | { 71 | return $this->type; 72 | } 73 | 74 | /** 75 | * Convert a log message into an Elastica Document 76 | * 77 | * @param array $record Log message 78 | * @return Document 79 | */ 80 | protected function getDocument($record) 81 | { 82 | $document = new Document(); 83 | $document->setData($record); 84 | $document->setType($this->type); 85 | $document->setIndex($this->index); 86 | 87 | return $document; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Logger/Monolog/Formatter/FlowdockFormatter.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Formatter; 13 | 14 | /** 15 | * formats the record to be used in the FlowdockHandler 16 | * 17 | * @author Dominik Liebler 18 | */ 19 | class FlowdockFormatter implements FormatterInterface 20 | { 21 | /** 22 | * @var string 23 | */ 24 | private $source; 25 | 26 | /** 27 | * @var string 28 | */ 29 | private $sourceEmail; 30 | 31 | /** 32 | * @param string $source 33 | * @param string $sourceEmail 34 | */ 35 | public function __construct($source, $sourceEmail) 36 | { 37 | $this->source = $source; 38 | $this->sourceEmail = $sourceEmail; 39 | } 40 | 41 | /** 42 | * {@inheritdoc} 43 | */ 44 | public function format(array $record) 45 | { 46 | $tags = array( 47 | '#logs', 48 | '#' . strtolower($record['level_name']), 49 | '#' . $record['channel'], 50 | ); 51 | 52 | foreach ($record['extra'] as $value) { 53 | $tags[] = '#' . $value; 54 | } 55 | 56 | $subject = sprintf( 57 | 'in %s: %s - %s', 58 | $this->source, 59 | $record['level_name'], 60 | $this->getShortMessage($record['message']) 61 | ); 62 | 63 | $record['flowdock'] = array( 64 | 'source' => $this->source, 65 | 'from_address' => $this->sourceEmail, 66 | 'subject' => $subject, 67 | 'content' => $record['message'], 68 | 'tags' => $tags, 69 | 'project' => $this->source, 70 | ); 71 | 72 | return $record; 73 | } 74 | 75 | /** 76 | * {@inheritdoc} 77 | */ 78 | public function formatBatch(array $records) 79 | { 80 | $formatted = array(); 81 | 82 | foreach ($records as $record) { 83 | $formatted[] = $this->format($record); 84 | } 85 | 86 | return $formatted; 87 | } 88 | 89 | /** 90 | * @param string $message 91 | * 92 | * @return string 93 | */ 94 | public function getShortMessage($message) 95 | { 96 | static $hasMbString; 97 | 98 | if (null === $hasMbString) { 99 | $hasMbString = function_exists('mb_strlen'); 100 | } 101 | 102 | $maxLength = 45; 103 | 104 | if ($hasMbString) { 105 | if (mb_strlen($message, 'UTF-8') > $maxLength) { 106 | $message = mb_substr($message, 0, $maxLength - 4, 'UTF-8') . ' ...'; 107 | } 108 | } else { 109 | if (strlen($message) > $maxLength) { 110 | $message = substr($message, 0, $maxLength - 4) . ' ...'; 111 | } 112 | } 113 | 114 | return $message; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /Logger/Monolog/Formatter/FluentdFormatter.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Formatter; 13 | 14 | /** 15 | * Class FluentdFormatter 16 | * 17 | * Serializes a log message to Fluentd unix socket protocol 18 | * 19 | * Fluentd config: 20 | * 21 | * 22 | * type unix 23 | * path /var/run/td-agent/td-agent.sock 24 | * 25 | * 26 | * Monolog setup: 27 | * 28 | * $logger = new Monolog\Logger('fluent.tag'); 29 | * $fluentHandler = new Monolog\Handler\SocketHandler('unix:///var/run/td-agent/td-agent.sock'); 30 | * $fluentHandler->setFormatter(new Monolog\Formatter\FluentdFormatter()); 31 | * $logger->pushHandler($fluentHandler); 32 | * 33 | * @author Andrius Putna 34 | */ 35 | class FluentdFormatter implements FormatterInterface 36 | { 37 | /** 38 | * @var bool $levelTag should message level be a part of the fluentd tag 39 | */ 40 | protected $levelTag = false; 41 | 42 | public function __construct($levelTag = false) 43 | { 44 | if (!function_exists('json_encode')) { 45 | throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s FluentdUnixFormatter'); 46 | } 47 | 48 | $this->levelTag = (bool) $levelTag; 49 | } 50 | 51 | public function isUsingLevelsInTag() 52 | { 53 | return $this->levelTag; 54 | } 55 | 56 | public function format(array $record) 57 | { 58 | $tag = $record['channel']; 59 | if ($this->levelTag) { 60 | $tag .= '.' . strtolower($record['level_name']); 61 | } 62 | 63 | $message = array( 64 | 'message' => $record['message'], 65 | 'extra' => $record['extra'], 66 | ); 67 | 68 | if (!$this->levelTag) { 69 | $message['level'] = $record['level']; 70 | $message['level_name'] = $record['level_name']; 71 | } 72 | 73 | return json_encode(array($tag, $record['datetime']->getTimestamp(), $message)); 74 | } 75 | 76 | public function formatBatch(array $records) 77 | { 78 | $message = ''; 79 | foreach ($records as $record) { 80 | $message .= $this->format($record); 81 | } 82 | 83 | return $message; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Logger/Monolog/Formatter/FormatterInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Formatter; 13 | 14 | /** 15 | * Interface for formatters 16 | * 17 | * @author Jordi Boggiano 18 | */ 19 | interface FormatterInterface 20 | { 21 | /** 22 | * Formats a log record. 23 | * 24 | * @param array $record A record to format 25 | * @return mixed The formatted record 26 | */ 27 | public function format(array $record); 28 | 29 | /** 30 | * Formats a set of log records. 31 | * 32 | * @param array $records A set of records to format 33 | * @return mixed The formatted set of records 34 | */ 35 | public function formatBatch(array $records); 36 | } 37 | -------------------------------------------------------------------------------- /Logger/Monolog/Formatter/LogglyFormatter.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Formatter; 13 | 14 | /** 15 | * Encodes message information into JSON in a format compatible with Loggly. 16 | * 17 | * @author Adam Pancutt 18 | */ 19 | class LogglyFormatter extends JsonFormatter 20 | { 21 | /** 22 | * Overrides the default batch mode to new lines for compatibility with the 23 | * Loggly bulk API. 24 | * 25 | * @param int $batchMode 26 | */ 27 | public function __construct($batchMode = self::BATCH_MODE_NEWLINES, $appendNewline = false) 28 | { 29 | parent::__construct($batchMode, $appendNewline); 30 | } 31 | 32 | /** 33 | * Appends the 'timestamp' parameter for indexing by Loggly. 34 | * 35 | * @see https://www.loggly.com/docs/automated-parsing/#json 36 | * @see \Monolog\Formatter\JsonFormatter::format() 37 | */ 38 | public function format(array $record) 39 | { 40 | if (isset($record["datetime"]) && ($record["datetime"] instanceof \DateTime)) { 41 | $record["timestamp"] = $record["datetime"]->format("Y-m-d\TH:i:s.uO"); 42 | unset($record["datetime"]); 43 | } 44 | 45 | return parent::format($record); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Logger/Monolog/Formatter/ScalarFormatter.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Formatter; 13 | 14 | /** 15 | * Formats data into an associative array of scalar values. 16 | * Objects and arrays will be JSON encoded. 17 | * 18 | * @author Andrew Lawson 19 | */ 20 | class ScalarFormatter extends NormalizerFormatter 21 | { 22 | /** 23 | * {@inheritdoc} 24 | */ 25 | public function format(array $record) 26 | { 27 | foreach ($record as $key => $value) { 28 | $record[$key] = $this->normalizeValue($value); 29 | } 30 | 31 | return $record; 32 | } 33 | 34 | /** 35 | * @param mixed $value 36 | * @return mixed 37 | */ 38 | protected function normalizeValue($value) 39 | { 40 | $normalized = $this->normalize($value); 41 | 42 | if (is_array($normalized) || is_object($normalized)) { 43 | return $this->toJson($normalized, true); 44 | } 45 | 46 | return $normalized; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Logger/Monolog/Formatter/WildfireFormatter.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Formatter; 13 | 14 | use Monolog\Logger; 15 | 16 | /** 17 | * Serializes a log message according to Wildfire's header requirements 18 | * 19 | * @author Eric Clemmons (@ericclemmons) 20 | * @author Christophe Coevoet 21 | * @author Kirill chEbba Chebunin 22 | */ 23 | class WildfireFormatter extends NormalizerFormatter 24 | { 25 | const TABLE = 'table'; 26 | 27 | /** 28 | * Translates Monolog log levels to Wildfire levels. 29 | */ 30 | private $logLevels = array( 31 | Logger::DEBUG => 'LOG', 32 | Logger::INFO => 'INFO', 33 | Logger::NOTICE => 'INFO', 34 | Logger::WARNING => 'WARN', 35 | Logger::ERROR => 'ERROR', 36 | Logger::CRITICAL => 'ERROR', 37 | Logger::ALERT => 'ERROR', 38 | Logger::EMERGENCY => 'ERROR', 39 | ); 40 | 41 | /** 42 | * {@inheritdoc} 43 | */ 44 | public function format(array $record) 45 | { 46 | // Retrieve the line and file if set and remove them from the formatted extra 47 | $file = $line = ''; 48 | if (isset($record['extra']['file'])) { 49 | $file = $record['extra']['file']; 50 | unset($record['extra']['file']); 51 | } 52 | if (isset($record['extra']['line'])) { 53 | $line = $record['extra']['line']; 54 | unset($record['extra']['line']); 55 | } 56 | 57 | $record = $this->normalize($record); 58 | $message = array('message' => $record['message']); 59 | $handleError = false; 60 | if ($record['context']) { 61 | $message['context'] = $record['context']; 62 | $handleError = true; 63 | } 64 | if ($record['extra']) { 65 | $message['extra'] = $record['extra']; 66 | $handleError = true; 67 | } 68 | if (count($message) === 1) { 69 | $message = reset($message); 70 | } 71 | 72 | if (isset($record['context'][self::TABLE])) { 73 | $type = 'TABLE'; 74 | $label = $record['channel'] .': '. $record['message']; 75 | $message = $record['context'][self::TABLE]; 76 | } else { 77 | $type = $this->logLevels[$record['level']]; 78 | $label = $record['channel']; 79 | } 80 | 81 | // Create JSON object describing the appearance of the message in the console 82 | $json = $this->toJson(array( 83 | array( 84 | 'Type' => $type, 85 | 'File' => $file, 86 | 'Line' => $line, 87 | 'Label' => $label, 88 | ), 89 | $message, 90 | ), $handleError); 91 | 92 | // The message itself is a serialization of the above JSON object + it's length 93 | return sprintf( 94 | '%s|%s|', 95 | strlen($json), 96 | $json 97 | ); 98 | } 99 | 100 | public function formatBatch(array $records) 101 | { 102 | throw new \BadMethodCallException('Batch formatting does not make sense for the WildfireFormatter'); 103 | } 104 | 105 | protected function normalize($data) 106 | { 107 | if (is_object($data) && !$data instanceof \DateTime) { 108 | return $data; 109 | } 110 | 111 | return parent::normalize($data); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/AbstractHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Monolog\Logger; 15 | 16 | /** 17 | * Base Handler class providing basic level/bubble support 18 | * 19 | * @author Jordi Boggiano 20 | */ 21 | abstract class AbstractHandler extends Handler 22 | { 23 | protected $level = Logger::DEBUG; 24 | protected $bubble = true; 25 | 26 | /** 27 | * @param int $level The minimum logging level at which this handler will be triggered 28 | * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not 29 | */ 30 | public function __construct($level = Logger::DEBUG, $bubble = true) 31 | { 32 | $this->setLevel($level); 33 | $this->bubble = $bubble; 34 | } 35 | 36 | /** 37 | * {@inheritdoc} 38 | */ 39 | public function isHandling(array $record): bool 40 | { 41 | return $record['level'] >= $this->level; 42 | } 43 | 44 | /** 45 | * Sets minimum logging level at which this handler will be triggered. 46 | * 47 | * @param int|string $level Level or level name 48 | * @return self 49 | */ 50 | public function setLevel($level): self 51 | { 52 | $this->level = Logger::toMonologLevel($level); 53 | 54 | return $this; 55 | } 56 | 57 | /** 58 | * Gets minimum logging level at which this handler will be triggered. 59 | * 60 | * @return int 61 | */ 62 | public function getLevel(): int 63 | { 64 | return $this->level; 65 | } 66 | 67 | /** 68 | * Sets the bubbling behavior. 69 | * 70 | * @param Boolean $bubble true means that this handler allows bubbling. 71 | * false means that bubbling is not permitted. 72 | * @return self 73 | */ 74 | public function setBubble(bool $bubble): self 75 | { 76 | $this->bubble = $bubble; 77 | 78 | return $this; 79 | } 80 | 81 | /** 82 | * Gets the bubbling behavior. 83 | * 84 | * @return Boolean true means that this handler allows bubbling. 85 | * false means that bubbling is not permitted. 86 | */ 87 | public function getBubble(): bool 88 | { 89 | return $this->bubble; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/AbstractProcessingHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | /** 15 | * Base Handler class providing the Handler structure 16 | * 17 | * Classes extending it should (in most cases) only implement write($record) 18 | * 19 | * @author Jordi Boggiano 20 | * @author Christophe Coevoet 21 | */ 22 | abstract class AbstractProcessingHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface 23 | { 24 | use ProcessableHandlerTrait; 25 | use FormattableHandlerTrait; 26 | 27 | /** 28 | * {@inheritdoc} 29 | */ 30 | public function handle(array $record): bool 31 | { 32 | if (!$this->isHandling($record)) { 33 | return false; 34 | } 35 | 36 | if ($this->processors) { 37 | $record = $this->processRecord($record); 38 | } 39 | 40 | $record['formatted'] = $this->getFormatter()->format($record); 41 | 42 | $this->write($record); 43 | 44 | return false === $this->bubble; 45 | } 46 | 47 | /** 48 | * Writes the record down to the log of the implementing handler 49 | * 50 | * @param array $record 51 | * @return void 52 | */ 53 | abstract protected function write(array $record); 54 | } 55 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/AbstractSyslogHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Monolog\Logger; 15 | use Monolog\Formatter\FormatterInterface; 16 | use Monolog\Formatter\LineFormatter; 17 | 18 | /** 19 | * Common syslog functionality 20 | */ 21 | abstract class AbstractSyslogHandler extends AbstractProcessingHandler 22 | { 23 | protected $facility; 24 | 25 | /** 26 | * Translates Monolog log levels to syslog log priorities. 27 | */ 28 | protected $logLevels = array( 29 | Logger::DEBUG => LOG_DEBUG, 30 | Logger::INFO => LOG_INFO, 31 | Logger::NOTICE => LOG_NOTICE, 32 | Logger::WARNING => LOG_WARNING, 33 | Logger::ERROR => LOG_ERR, 34 | Logger::CRITICAL => LOG_CRIT, 35 | Logger::ALERT => LOG_ALERT, 36 | Logger::EMERGENCY => LOG_EMERG, 37 | ); 38 | 39 | /** 40 | * List of valid log facility names. 41 | */ 42 | protected $facilities = array( 43 | 'auth' => LOG_AUTH, 44 | 'authpriv' => LOG_AUTHPRIV, 45 | 'cron' => LOG_CRON, 46 | 'daemon' => LOG_DAEMON, 47 | 'kern' => LOG_KERN, 48 | 'lpr' => LOG_LPR, 49 | 'mail' => LOG_MAIL, 50 | 'news' => LOG_NEWS, 51 | 'syslog' => LOG_SYSLOG, 52 | 'user' => LOG_USER, 53 | 'uucp' => LOG_UUCP, 54 | ); 55 | 56 | /** 57 | * @param mixed $facility 58 | * @param int $level The minimum logging level at which this handler will be triggered 59 | * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not 60 | */ 61 | public function __construct($facility = LOG_USER, $level = Logger::DEBUG, $bubble = true) 62 | { 63 | parent::__construct($level, $bubble); 64 | 65 | if (!defined('PHP_WINDOWS_VERSION_BUILD')) { 66 | $this->facilities['local0'] = LOG_LOCAL0; 67 | $this->facilities['local1'] = LOG_LOCAL1; 68 | $this->facilities['local2'] = LOG_LOCAL2; 69 | $this->facilities['local3'] = LOG_LOCAL3; 70 | $this->facilities['local4'] = LOG_LOCAL4; 71 | $this->facilities['local5'] = LOG_LOCAL5; 72 | $this->facilities['local6'] = LOG_LOCAL6; 73 | $this->facilities['local7'] = LOG_LOCAL7; 74 | } else { 75 | $this->facilities['local0'] = 128; // LOG_LOCAL0 76 | $this->facilities['local1'] = 136; // LOG_LOCAL1 77 | $this->facilities['local2'] = 144; // LOG_LOCAL2 78 | $this->facilities['local3'] = 152; // LOG_LOCAL3 79 | $this->facilities['local4'] = 160; // LOG_LOCAL4 80 | $this->facilities['local5'] = 168; // LOG_LOCAL5 81 | $this->facilities['local6'] = 176; // LOG_LOCAL6 82 | $this->facilities['local7'] = 184; // LOG_LOCAL7 83 | } 84 | 85 | // convert textual description of facility to syslog constant 86 | if (array_key_exists(strtolower($facility), $this->facilities)) { 87 | $facility = $this->facilities[strtolower($facility)]; 88 | } elseif (!in_array($facility, array_values($this->facilities), true)) { 89 | throw new \UnexpectedValueException('Unknown facility value "'.$facility.'" given'); 90 | } 91 | 92 | $this->facility = $facility; 93 | } 94 | 95 | /** 96 | * {@inheritdoc} 97 | */ 98 | protected function getDefaultFormatter(): FormatterInterface 99 | { 100 | return new LineFormatter('%channel%.%level_name%: %message% %context% %extra%'); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/BufferHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Monolog\Logger; 15 | 16 | /** 17 | * Buffers all records until closing the handler and then pass them as batch. 18 | * 19 | * This is useful for a MailHandler to send only one mail per request instead of 20 | * sending one per log message. 21 | * 22 | * @author Christophe Coevoet 23 | */ 24 | class BufferHandler extends AbstractHandler implements ProcessableHandlerInterface 25 | { 26 | use ProcessableHandlerTrait; 27 | 28 | protected $handler; 29 | protected $bufferSize = 0; 30 | protected $bufferLimit; 31 | protected $flushOnOverflow; 32 | protected $buffer = array(); 33 | protected $initialized = false; 34 | 35 | /** 36 | * @param HandlerInterface $handler Handler. 37 | * @param int $bufferLimit How many entries should be buffered at most, beyond that the oldest items are removed from the buffer. 38 | * @param int $level The minimum logging level at which this handler will be triggered 39 | * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not 40 | * @param Boolean $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded 41 | */ 42 | public function __construct(HandlerInterface $handler, $bufferLimit = 0, $level = Logger::DEBUG, $bubble = true, $flushOnOverflow = false) 43 | { 44 | parent::__construct($level, $bubble); 45 | $this->handler = $handler; 46 | $this->bufferLimit = (int) $bufferLimit; 47 | $this->flushOnOverflow = $flushOnOverflow; 48 | } 49 | 50 | /** 51 | * {@inheritdoc} 52 | */ 53 | public function handle(array $record): bool 54 | { 55 | if ($record['level'] < $this->level) { 56 | return false; 57 | } 58 | 59 | if (!$this->initialized) { 60 | // __destructor() doesn't get called on Fatal errors 61 | register_shutdown_function(array($this, 'close')); 62 | $this->initialized = true; 63 | } 64 | 65 | if ($this->bufferLimit > 0 && $this->bufferSize === $this->bufferLimit) { 66 | if ($this->flushOnOverflow) { 67 | $this->flush(); 68 | } else { 69 | array_shift($this->buffer); 70 | $this->bufferSize--; 71 | } 72 | } 73 | 74 | if ($this->processors) { 75 | $record = $this->processRecord($record); 76 | } 77 | 78 | $this->buffer[] = $record; 79 | $this->bufferSize++; 80 | 81 | return false === $this->bubble; 82 | } 83 | 84 | public function flush() 85 | { 86 | if ($this->bufferSize === 0) { 87 | return; 88 | } 89 | 90 | $this->handler->handleBatch($this->buffer); 91 | $this->clear(); 92 | } 93 | 94 | public function __destruct() 95 | { 96 | // suppress the parent behavior since we already have register_shutdown_function() 97 | // to call close(), and the reference contained there will prevent this from being 98 | // GC'd until the end of the request 99 | } 100 | 101 | /** 102 | * {@inheritdoc} 103 | */ 104 | public function close() 105 | { 106 | $this->flush(); 107 | } 108 | 109 | /** 110 | * Clears the buffer without flushing any messages down to the wrapped handler. 111 | */ 112 | public function clear() 113 | { 114 | $this->bufferSize = 0; 115 | $this->buffer = array(); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/CouchDBHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Monolog\Formatter\FormatterInterface; 15 | use Monolog\Formatter\JsonFormatter; 16 | use Monolog\Logger; 17 | 18 | /** 19 | * CouchDB handler 20 | * 21 | * @author Markus Bachmann 22 | */ 23 | class CouchDBHandler extends AbstractProcessingHandler 24 | { 25 | private $options; 26 | 27 | public function __construct(array $options = array(), $level = Logger::DEBUG, $bubble = true) 28 | { 29 | $this->options = array_merge(array( 30 | 'host' => 'localhost', 31 | 'port' => 5984, 32 | 'dbname' => 'logger', 33 | 'username' => null, 34 | 'password' => null, 35 | ), $options); 36 | 37 | parent::__construct($level, $bubble); 38 | } 39 | 40 | /** 41 | * {@inheritDoc} 42 | */ 43 | protected function write(array $record) 44 | { 45 | $basicAuth = null; 46 | if ($this->options['username']) { 47 | $basicAuth = sprintf('%s:%s@', $this->options['username'], $this->options['password']); 48 | } 49 | 50 | $url = 'http://'.$basicAuth.$this->options['host'].':'.$this->options['port'].'/'.$this->options['dbname']; 51 | $context = stream_context_create(array( 52 | 'http' => array( 53 | 'method' => 'POST', 54 | 'content' => $record['formatted'], 55 | 'ignore_errors' => true, 56 | 'max_redirects' => 0, 57 | 'header' => 'Content-type: application/json', 58 | ), 59 | )); 60 | 61 | if (false === @file_get_contents($url, null, $context)) { 62 | throw new \RuntimeException(sprintf('Could not connect to %s', $url)); 63 | } 64 | } 65 | 66 | /** 67 | * {@inheritDoc} 68 | */ 69 | protected function getDefaultFormatter(): FormatterInterface 70 | { 71 | return new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/Curl/Util.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler\Curl; 13 | 14 | class Util 15 | { 16 | private static $retriableErrorCodes = array( 17 | CURLE_COULDNT_RESOLVE_HOST, 18 | CURLE_COULDNT_CONNECT, 19 | CURLE_HTTP_NOT_FOUND, 20 | CURLE_READ_ERROR, 21 | CURLE_OPERATION_TIMEOUTED, 22 | CURLE_HTTP_POST_ERROR, 23 | CURLE_SSL_CONNECT_ERROR, 24 | ); 25 | 26 | /** 27 | * Executes a CURL request with optional retries and exception on failure 28 | * 29 | * @param resource $ch curl handler 30 | * @throws \RuntimeException 31 | */ 32 | public static function execute($ch, $retries = 5, $closeAfterDone = true) 33 | { 34 | while ($retries--) { 35 | if (curl_exec($ch) === false) { 36 | $curlErrno = curl_errno($ch); 37 | 38 | if (false === in_array($curlErrno, self::$retriableErrorCodes, true) || !$retries) { 39 | $curlError = curl_error($ch); 40 | 41 | if ($closeAfterDone) { 42 | curl_close($ch); 43 | } 44 | 45 | throw new \RuntimeException(sprintf('Curl error (code %s): %s', $curlErrno, $curlError)); 46 | } 47 | 48 | continue; 49 | } 50 | 51 | if ($closeAfterDone) { 52 | curl_close($ch); 53 | } 54 | break; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/DoctrineCouchDBHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Monolog\Logger; 15 | use Monolog\Formatter\NormalizerFormatter; 16 | use Monolog\Formatter\FormatterInterface; 17 | use Doctrine\CouchDB\CouchDBClient; 18 | 19 | /** 20 | * CouchDB handler for Doctrine CouchDB ODM 21 | * 22 | * @author Markus Bachmann 23 | */ 24 | class DoctrineCouchDBHandler extends AbstractProcessingHandler 25 | { 26 | private $client; 27 | 28 | public function __construct(CouchDBClient $client, $level = Logger::DEBUG, $bubble = true) 29 | { 30 | $this->client = $client; 31 | parent::__construct($level, $bubble); 32 | } 33 | 34 | /** 35 | * {@inheritDoc} 36 | */ 37 | protected function write(array $record) 38 | { 39 | $this->client->postDocument($record['formatted']); 40 | } 41 | 42 | protected function getDefaultFormatter(): FormatterInterface 43 | { 44 | return new NormalizerFormatter; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/DynamoDbHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Aws\Common\Aws; 15 | use Aws\DynamoDb\DynamoDbClient; 16 | use Monolog\Formatter\FormatterInterface; 17 | use Monolog\Formatter\ScalarFormatter; 18 | use Monolog\Logger; 19 | 20 | /** 21 | * Amazon DynamoDB handler (http://aws.amazon.com/dynamodb/) 22 | * 23 | * @link https://github.com/aws/aws-sdk-php/ 24 | * @author Andrew Lawson 25 | */ 26 | class DynamoDbHandler extends AbstractProcessingHandler 27 | { 28 | const DATE_FORMAT = 'Y-m-d\TH:i:s.uO'; 29 | 30 | /** 31 | * @var DynamoDbClient 32 | */ 33 | protected $client; 34 | 35 | /** 36 | * @var string 37 | */ 38 | protected $table; 39 | 40 | /** 41 | * @param DynamoDbClient $client 42 | * @param string $table 43 | * @param int $level 44 | * @param bool $bubble 45 | */ 46 | public function __construct(DynamoDbClient $client, $table, $level = Logger::DEBUG, $bubble = true) 47 | { 48 | if (!defined('Aws\Common\Aws::VERSION') || version_compare('3.0', Aws::VERSION, '<=')) { 49 | throw new \RuntimeException('The DynamoDbHandler is only known to work with the AWS SDK 2.x releases'); 50 | } 51 | 52 | $this->client = $client; 53 | $this->table = $table; 54 | 55 | parent::__construct($level, $bubble); 56 | } 57 | 58 | /** 59 | * {@inheritdoc} 60 | */ 61 | protected function write(array $record) 62 | { 63 | $filtered = $this->filterEmptyFields($record['formatted']); 64 | $formatted = $this->client->formatAttributes($filtered); 65 | 66 | $this->client->putItem(array( 67 | 'TableName' => $this->table, 68 | 'Item' => $formatted, 69 | )); 70 | } 71 | 72 | /** 73 | * @param array $record 74 | * @return array 75 | */ 76 | protected function filterEmptyFields(array $record) 77 | { 78 | return array_filter($record, function ($value) { 79 | return !empty($value) || false === $value || 0 === $value; 80 | }); 81 | } 82 | 83 | /** 84 | * {@inheritdoc} 85 | */ 86 | protected function getDefaultFormatter(): FormatterInterface 87 | { 88 | return new ScalarFormatter(self::DATE_FORMAT); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/ErrorLogHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Monolog\Formatter\LineFormatter; 15 | use Monolog\Formatter\FormatterInterface; 16 | use Monolog\Logger; 17 | 18 | /** 19 | * Stores to PHP error_log() handler. 20 | * 21 | * @author Elan Ruusamäe 22 | */ 23 | class ErrorLogHandler extends AbstractProcessingHandler 24 | { 25 | const OPERATING_SYSTEM = 0; 26 | const SAPI = 4; 27 | 28 | protected $messageType; 29 | protected $expandNewlines; 30 | 31 | /** 32 | * @param int $messageType Says where the error should go. 33 | * @param int $level The minimum logging level at which this handler will be triggered 34 | * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not 35 | * @param Boolean $expandNewlines If set to true, newlines in the message will be expanded to be take multiple log entries 36 | */ 37 | public function __construct($messageType = self::OPERATING_SYSTEM, $level = Logger::DEBUG, $bubble = true, $expandNewlines = false) 38 | { 39 | parent::__construct($level, $bubble); 40 | 41 | if (false === in_array($messageType, self::getAvailableTypes())) { 42 | $message = sprintf('The given message type "%s" is not supported', print_r($messageType, true)); 43 | throw new \InvalidArgumentException($message); 44 | } 45 | 46 | $this->messageType = $messageType; 47 | $this->expandNewlines = $expandNewlines; 48 | } 49 | 50 | /** 51 | * @return array With all available types 52 | */ 53 | public static function getAvailableTypes() 54 | { 55 | return array( 56 | self::OPERATING_SYSTEM, 57 | self::SAPI, 58 | ); 59 | } 60 | 61 | /** 62 | * {@inheritDoc} 63 | */ 64 | protected function getDefaultFormatter(): FormatterInterface 65 | { 66 | return new LineFormatter('[%datetime%] %channel%.%level_name%: %message% %context% %extra%'); 67 | } 68 | 69 | /** 70 | * {@inheritdoc} 71 | */ 72 | protected function write(array $record) 73 | { 74 | if ($this->expandNewlines) { 75 | $lines = preg_split('{[\r\n]+}', (string) $record['formatted']); 76 | foreach ($lines as $line) { 77 | error_log($line, $this->messageType); 78 | } 79 | } else { 80 | error_log((string) $record['formatted'], $this->messageType); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler\FingersCrossed; 13 | 14 | /** 15 | * Interface for activation strategies for the FingersCrossedHandler. 16 | * 17 | * @author Johannes M. Schmitt 18 | */ 19 | interface ActivationStrategyInterface 20 | { 21 | /** 22 | * Returns whether the given record activates the handler. 23 | * 24 | * @param array $record 25 | * @return Boolean 26 | */ 27 | public function isHandlerActivated(array $record); 28 | } 29 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler\FingersCrossed; 13 | 14 | use Monolog\Logger; 15 | 16 | /** 17 | * Channel and Error level based monolog activation strategy. Allows to trigger activation 18 | * based on level per channel. e.g. trigger activation on level 'ERROR' by default, except 19 | * for records of the 'sql' channel; those should trigger activation on level 'WARN'. 20 | * 21 | * Example: 22 | * 23 | * 24 | * $activationStrategy = new ChannelLevelActivationStrategy( 25 | * Logger::CRITICAL, 26 | * array( 27 | * 'request' => Logger::ALERT, 28 | * 'sensitive' => Logger::ERROR, 29 | * ) 30 | * ); 31 | * $handler = new FingersCrossedHandler(new StreamHandler('php://stderr'), $activationStrategy); 32 | * 33 | * 34 | * @author Mike Meessen 35 | */ 36 | class ChannelLevelActivationStrategy implements ActivationStrategyInterface 37 | { 38 | private $defaultActionLevel; 39 | private $channelToActionLevel; 40 | 41 | /** 42 | * @param int $defaultActionLevel The default action level to be used if the record's category doesn't match any 43 | * @param array $channelToActionLevel An array that maps channel names to action levels. 44 | */ 45 | public function __construct($defaultActionLevel, $channelToActionLevel = array()) 46 | { 47 | $this->defaultActionLevel = Logger::toMonologLevel($defaultActionLevel); 48 | $this->channelToActionLevel = array_map('Monolog\Logger::toMonologLevel', $channelToActionLevel); 49 | } 50 | 51 | public function isHandlerActivated(array $record) 52 | { 53 | if (isset($this->channelToActionLevel[$record['channel']])) { 54 | return $record['level'] >= $this->channelToActionLevel[$record['channel']]; 55 | } 56 | 57 | return $record['level'] >= $this->defaultActionLevel; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler\FingersCrossed; 13 | 14 | use Monolog\Logger; 15 | 16 | /** 17 | * Error level based activation strategy. 18 | * 19 | * @author Johannes M. Schmitt 20 | */ 21 | class ErrorLevelActivationStrategy implements ActivationStrategyInterface 22 | { 23 | private $actionLevel; 24 | 25 | public function __construct($actionLevel) 26 | { 27 | $this->actionLevel = Logger::toMonologLevel($actionLevel); 28 | } 29 | 30 | public function isHandlerActivated(array $record) 31 | { 32 | return $record['level'] >= $this->actionLevel; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/FlowdockHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Monolog\Logger; 15 | use Monolog\Formatter\FlowdockFormatter; 16 | use Monolog\Formatter\FormatterInterface; 17 | 18 | /** 19 | * Sends notifications through the Flowdock push API 20 | * 21 | * This must be configured with a FlowdockFormatter instance via setFormatter() 22 | * 23 | * Notes: 24 | * API token - Flowdock API token 25 | * 26 | * @author Dominik Liebler 27 | * @see https://www.flowdock.com/api/push 28 | */ 29 | class FlowdockHandler extends SocketHandler 30 | { 31 | /** 32 | * @var string 33 | */ 34 | protected $apiToken; 35 | 36 | /** 37 | * @param string $apiToken 38 | * @param bool|int $level The minimum logging level at which this handler will be triggered 39 | * @param bool $bubble Whether the messages that are handled can bubble up the stack or not 40 | * 41 | * @throws MissingExtensionException if OpenSSL is missing 42 | */ 43 | public function __construct($apiToken, $level = Logger::DEBUG, $bubble = true) 44 | { 45 | if (!extension_loaded('openssl')) { 46 | throw new MissingExtensionException('The OpenSSL PHP extension is required to use the FlowdockHandler'); 47 | } 48 | 49 | parent::__construct('ssl://api.flowdock.com:443', $level, $bubble); 50 | $this->apiToken = $apiToken; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | */ 56 | public function setFormatter(FormatterInterface $formatter): HandlerInterface 57 | { 58 | if (!$formatter instanceof FlowdockFormatter) { 59 | throw new \InvalidArgumentException('The FlowdockHandler requires an instance of Monolog\Formatter\FlowdockFormatter to function correctly'); 60 | } 61 | 62 | return parent::setFormatter($formatter); 63 | } 64 | 65 | /** 66 | * Gets the default formatter. 67 | * 68 | * @return FormatterInterface 69 | */ 70 | protected function getDefaultFormatter(): FormatterInterface 71 | { 72 | throw new \InvalidArgumentException('The FlowdockHandler must be configured (via setFormatter) with an instance of Monolog\Formatter\FlowdockFormatter to function correctly'); 73 | } 74 | 75 | /** 76 | * {@inheritdoc} 77 | * 78 | * @param array $record 79 | */ 80 | protected function write(array $record) 81 | { 82 | parent::write($record); 83 | 84 | $this->closeSocket(); 85 | } 86 | 87 | /** 88 | * {@inheritdoc} 89 | * 90 | * @param array $record 91 | * @return string 92 | */ 93 | protected function generateDataStream($record) 94 | { 95 | $content = $this->buildContent($record); 96 | 97 | return $this->buildHeader($content) . $content; 98 | } 99 | 100 | /** 101 | * Builds the body of API call 102 | * 103 | * @param array $record 104 | * @return string 105 | */ 106 | private function buildContent($record) 107 | { 108 | return json_encode($record['formatted']['flowdock']); 109 | } 110 | 111 | /** 112 | * Builds the header of the API Call 113 | * 114 | * @param string $content 115 | * @return string 116 | */ 117 | private function buildHeader($content) 118 | { 119 | $header = "POST /v1/messages/team_inbox/" . $this->apiToken . " HTTP/1.1\r\n"; 120 | $header .= "Host: api.flowdock.com\r\n"; 121 | $header .= "Content-Type: application/json\r\n"; 122 | $header .= "Content-Length: " . strlen($content) . "\r\n"; 123 | $header .= "\r\n"; 124 | 125 | return $header; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/FormattableHandlerInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Monolog\Formatter\FormatterInterface; 15 | 16 | /** 17 | * Interface to describe loggers that have a formatter 18 | * 19 | * @author Jordi Boggiano 20 | */ 21 | interface FormattableHandlerInterface 22 | { 23 | /** 24 | * Sets the formatter. 25 | * 26 | * @param FormatterInterface $formatter 27 | * @return HandlerInterface self 28 | */ 29 | public function setFormatter(FormatterInterface $formatter): HandlerInterface; 30 | 31 | /** 32 | * Gets the formatter. 33 | * 34 | * @return FormatterInterface 35 | */ 36 | public function getFormatter(): FormatterInterface; 37 | } 38 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/FormattableHandlerTrait.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Monolog\Formatter\FormatterInterface; 15 | use Monolog\Formatter\LineFormatter; 16 | 17 | /** 18 | * Helper trait for implementing FormattableInterface 19 | * 20 | * @author Jordi Boggiano 21 | */ 22 | trait FormattableHandlerTrait 23 | { 24 | /** 25 | * @var FormatterInterface 26 | */ 27 | protected $formatter; 28 | 29 | /** 30 | * {@inheritdoc} 31 | */ 32 | public function setFormatter(FormatterInterface $formatter): HandlerInterface 33 | { 34 | $this->formatter = $formatter; 35 | 36 | return $this; 37 | } 38 | 39 | /** 40 | * {@inheritdoc} 41 | */ 42 | public function getFormatter(): FormatterInterface 43 | { 44 | if (!$this->formatter) { 45 | $this->formatter = $this->getDefaultFormatter(); 46 | } 47 | 48 | return $this->formatter; 49 | } 50 | 51 | /** 52 | * Gets the default formatter. 53 | * 54 | * @return FormatterInterface 55 | */ 56 | protected function getDefaultFormatter(): FormatterInterface 57 | { 58 | return new LineFormatter(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/GelfHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Gelf\IMessagePublisher; 15 | use Gelf\PublisherInterface; 16 | use Gelf\Publisher; 17 | use InvalidArgumentException; 18 | use Monolog\Logger; 19 | use Monolog\Formatter\GelfMessageFormatter; 20 | use Monolog\Formatter\FormatterInterface; 21 | 22 | /** 23 | * Handler to send messages to a Graylog2 (http://www.graylog2.org) server 24 | * 25 | * @author Matt Lehner 26 | * @author Benjamin Zikarsky 27 | */ 28 | class GelfHandler extends AbstractProcessingHandler 29 | { 30 | /** 31 | * @var Publisher the publisher object that sends the message to the server 32 | */ 33 | protected $publisher; 34 | 35 | /** 36 | * @param PublisherInterface|IMessagePublisher|Publisher $publisher a publisher object 37 | * @param int $level The minimum logging level at which this handler will be triggered 38 | * @param bool $bubble Whether the messages that are handled can bubble up the stack or not 39 | */ 40 | public function __construct($publisher, $level = Logger::DEBUG, $bubble = true) 41 | { 42 | parent::__construct($level, $bubble); 43 | 44 | if (!$publisher instanceof Publisher && !$publisher instanceof IMessagePublisher && !$publisher instanceof PublisherInterface) { 45 | throw new InvalidArgumentException('Invalid publisher, expected a Gelf\Publisher, Gelf\IMessagePublisher or Gelf\PublisherInterface instance'); 46 | } 47 | 48 | $this->publisher = $publisher; 49 | } 50 | 51 | /** 52 | * {@inheritdoc} 53 | */ 54 | public function close() 55 | { 56 | $this->publisher = null; 57 | } 58 | 59 | /** 60 | * {@inheritdoc} 61 | */ 62 | protected function write(array $record) 63 | { 64 | $this->publisher->publish($record['formatted']); 65 | } 66 | 67 | /** 68 | * {@inheritDoc} 69 | */ 70 | protected function getDefaultFormatter(): FormatterInterface 71 | { 72 | return new GelfMessageFormatter(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/GroupHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Monolog\Formatter\FormatterInterface; 15 | 16 | /** 17 | * Forwards records to multiple handlers 18 | * 19 | * @author Lenar Lõhmus 20 | */ 21 | class GroupHandler extends Handler implements ProcessableHandlerInterface 22 | { 23 | use ProcessableHandlerTrait; 24 | 25 | protected $handlers; 26 | 27 | /** 28 | * @param array $handlers Array of Handlers. 29 | * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not 30 | */ 31 | public function __construct(array $handlers, $bubble = true) 32 | { 33 | foreach ($handlers as $handler) { 34 | if (!$handler instanceof HandlerInterface) { 35 | throw new \InvalidArgumentException('The first argument of the GroupHandler must be an array of HandlerInterface instances.'); 36 | } 37 | } 38 | 39 | $this->handlers = $handlers; 40 | $this->bubble = $bubble; 41 | } 42 | 43 | /** 44 | * {@inheritdoc} 45 | */ 46 | public function isHandling(array $record): bool 47 | { 48 | foreach ($this->handlers as $handler) { 49 | if ($handler->isHandling($record)) { 50 | return true; 51 | } 52 | } 53 | 54 | return false; 55 | } 56 | 57 | /** 58 | * {@inheritdoc} 59 | */ 60 | public function handle(array $record): bool 61 | { 62 | if ($this->processors) { 63 | $record = $this->processRecord($record); 64 | } 65 | 66 | foreach ($this->handlers as $handler) { 67 | $handler->handle($record); 68 | } 69 | 70 | return false === $this->bubble; 71 | } 72 | 73 | /** 74 | * {@inheritdoc} 75 | */ 76 | public function handleBatch(array $records) 77 | { 78 | foreach ($this->handlers as $handler) { 79 | $handler->handleBatch($records); 80 | } 81 | } 82 | 83 | /** 84 | * {@inheritdoc} 85 | */ 86 | public function setFormatter(FormatterInterface $formatter) 87 | { 88 | foreach ($this->handlers as $handler) { 89 | $handler->setFormatter($formatter); 90 | } 91 | 92 | return $this; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/Handler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | /** 15 | * Base Handler class providing basic close() support as well as handleBatch 16 | * 17 | * @author Jordi Boggiano 18 | */ 19 | abstract class Handler implements HandlerInterface 20 | { 21 | /** 22 | * {@inheritdoc} 23 | */ 24 | public function handleBatch(array $records) 25 | { 26 | foreach ($records as $record) { 27 | $this->handle($record); 28 | } 29 | } 30 | 31 | /** 32 | * {@inheritdoc} 33 | */ 34 | public function close() 35 | { 36 | } 37 | 38 | public function __destruct() 39 | { 40 | try { 41 | $this->close(); 42 | } catch (\Exception $e) { 43 | // do nothing 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/HandlerInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | /** 15 | * Interface that all Monolog Handlers must implement 16 | * 17 | * @author Jordi Boggiano 18 | */ 19 | interface HandlerInterface 20 | { 21 | /** 22 | * Checks whether the given record will be handled by this handler. 23 | * 24 | * This is mostly done for performance reasons, to avoid calling processors for nothing. 25 | * 26 | * Handlers should still check the record levels within handle(), returning false in isHandling() 27 | * is no guarantee that handle() will not be called, and isHandling() might not be called 28 | * for a given record. 29 | * 30 | * @param array $record Partial log record containing only a level key 31 | * 32 | * @return Boolean 33 | */ 34 | public function isHandling(array $record): bool; 35 | 36 | /** 37 | * Handles a record. 38 | * 39 | * All records may be passed to this method, and the handler should discard 40 | * those that it does not want to handle. 41 | * 42 | * The return value of this function controls the bubbling process of the handler stack. 43 | * Unless the bubbling is interrupted (by returning true), the Logger class will keep on 44 | * calling further handlers in the stack with a given log record. 45 | * 46 | * @param array $record The record to handle 47 | * @return Boolean true means that this handler handled the record, and that bubbling is not permitted. 48 | * false means the record was either not processed or that this handler allows bubbling. 49 | */ 50 | public function handle(array $record): bool; 51 | 52 | /** 53 | * Handles a set of records at once. 54 | * 55 | * @param array $records The records to handle (an array of record arrays) 56 | */ 57 | public function handleBatch(array $records); 58 | 59 | /** 60 | * Closes the handler. 61 | * 62 | * This will be called automatically when the object is destroyed if you extend Monolog\Handler\Handler 63 | * 64 | * Implementations have to be indempotent (i.e. it should be possible to call close several times without breakage) 65 | * and ideally handlers should be able to reopen themselves on handle() after they have been closed. 66 | */ 67 | public function close(); 68 | } 69 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/HandlerWrapper.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Monolog\Formatter\FormatterInterface; 15 | 16 | /** 17 | * This simple wrapper class can be used to extend handlers functionality. 18 | * 19 | * Example: A filtering handle. Inherit from this class, override isHandling() like this 20 | * 21 | * public function isHandling(array $record) 22 | * { 23 | * if ($record meets certain conditions) { 24 | * return false; 25 | * } 26 | * return $this->handler->isHandling($record); 27 | * } 28 | * 29 | * @author Alexey Karapetov 30 | */ 31 | class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, FormattableHandlerInterface 32 | { 33 | /** 34 | * @var HandlerInterface 35 | */ 36 | private $handler; 37 | 38 | /** 39 | * HandlerWrapper constructor. 40 | * @param HandlerInterface $handler 41 | */ 42 | public function __construct(HandlerInterface $handler) 43 | { 44 | $this->handler = $handler; 45 | } 46 | 47 | /** 48 | * {@inheritdoc} 49 | */ 50 | public function isHandling(array $record): bool 51 | { 52 | return $this->handler->isHandling($record); 53 | } 54 | 55 | /** 56 | * {@inheritdoc} 57 | */ 58 | public function handle(array $record): bool 59 | { 60 | return $this->handler->handle($record); 61 | } 62 | 63 | /** 64 | * {@inheritdoc} 65 | */ 66 | public function handleBatch(array $records) 67 | { 68 | return $this->handler->handleBatch($records); 69 | } 70 | 71 | /** 72 | * {@inheritdoc} 73 | */ 74 | public function close() 75 | { 76 | return $this->handler->close(); 77 | } 78 | 79 | /** 80 | * {@inheritdoc} 81 | */ 82 | public function pushProcessor(callable $callback): HandlerInterface 83 | { 84 | if ($this->handler instanceof ProcessableHandlerInterface) { 85 | $this->handler->pushProcessor($callback); 86 | 87 | return $this; 88 | } 89 | 90 | throw new \LogicException('The wrapped handler does not implement ' . ProcessableHandlerInterface::class); 91 | } 92 | 93 | /** 94 | * {@inheritdoc} 95 | */ 96 | public function popProcessor(): callable 97 | { 98 | if ($this->handler instanceof ProcessableHandlerInterface) { 99 | return $this->handler->popProcessor(); 100 | } 101 | 102 | throw new \LogicException('The wrapped handler does not implement ' . ProcessableHandlerInterface::class); 103 | } 104 | 105 | /** 106 | * {@inheritdoc} 107 | */ 108 | public function setFormatter(FormatterInterface $formatter): HandlerInterface 109 | { 110 | if ($this->handler instanceof FormattableHandlerInterface) { 111 | $this->handler->setFormatter($formatter); 112 | } 113 | 114 | throw new \LogicException('The wrapped handler does not implement ' . FormattableHandlerInterface::class); 115 | } 116 | 117 | /** 118 | * {@inheritdoc} 119 | */ 120 | public function getFormatter(): FormatterInterface 121 | { 122 | if ($this->handler instanceof FormattableHandlerInterface) { 123 | return $this->handler->getFormatter($formatter); 124 | } 125 | 126 | throw new \LogicException('The wrapped handler does not implement ' . FormattableHandlerInterface::class); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/IFTTTHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Monolog\Logger; 15 | 16 | /** 17 | * IFTTTHandler uses cURL to trigger IFTTT Maker actions 18 | * 19 | * Register a secret key and trigger/event name at https://ifttt.com/maker 20 | * 21 | * value1 will be the channel from monolog's Logger constructor, 22 | * value2 will be the level name (ERROR, WARNING, ..) 23 | * value3 will be the log record's message 24 | * 25 | * @author Nehal Patel 26 | */ 27 | class IFTTTHandler extends AbstractProcessingHandler 28 | { 29 | private $eventName; 30 | private $secretKey; 31 | 32 | /** 33 | * @param string $eventName The name of the IFTTT Maker event that should be triggered 34 | * @param string $secretKey A valid IFTTT secret key 35 | * @param int $level The minimum logging level at which this handler will be triggered 36 | * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not 37 | */ 38 | public function __construct($eventName, $secretKey, $level = Logger::ERROR, $bubble = true) 39 | { 40 | $this->eventName = $eventName; 41 | $this->secretKey = $secretKey; 42 | 43 | parent::__construct($level, $bubble); 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | public function write(array $record) 50 | { 51 | $postData = array( 52 | "value1" => $record["channel"], 53 | "value2" => $record["level_name"], 54 | "value3" => $record["message"], 55 | ); 56 | $postString = json_encode($postData); 57 | 58 | $ch = curl_init(); 59 | curl_setopt($ch, CURLOPT_URL, "https://maker.ifttt.com/trigger/" . $this->eventName . "/with/key/" . $this->secretKey); 60 | curl_setopt($ch, CURLOPT_POST, true); 61 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 62 | curl_setopt($ch, CURLOPT_POSTFIELDS, $postString); 63 | curl_setopt($ch, CURLOPT_HTTPHEADER, array( 64 | "Content-Type: application/json", 65 | )); 66 | 67 | Curl\Util::execute($ch); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/LogEntriesHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Monolog\Logger; 15 | 16 | /** 17 | * @author Robert Kaufmann III 18 | */ 19 | class LogEntriesHandler extends SocketHandler 20 | { 21 | /** 22 | * @var string 23 | */ 24 | protected $logToken; 25 | 26 | /** 27 | * @param string $token Log token supplied by LogEntries 28 | * @param bool $useSSL Whether or not SSL encryption should be used. 29 | * @param int $level The minimum logging level to trigger this handler 30 | * @param bool $bubble Whether or not messages that are handled should bubble up the stack. 31 | * 32 | * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing 33 | */ 34 | public function __construct($token, $useSSL = true, $level = Logger::DEBUG, $bubble = true) 35 | { 36 | if ($useSSL && !extension_loaded('openssl')) { 37 | throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for LogEntriesHandler'); 38 | } 39 | 40 | $endpoint = $useSSL ? 'ssl://data.logentries.com:443' : 'data.logentries.com:80'; 41 | parent::__construct($endpoint, $level, $bubble); 42 | $this->logToken = $token; 43 | } 44 | 45 | /** 46 | * {@inheritdoc} 47 | * 48 | * @param array $record 49 | * @return string 50 | */ 51 | protected function generateDataStream($record) 52 | { 53 | return $this->logToken . ' ' . $record['formatted']; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/LogglyHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Monolog\Logger; 15 | use Monolog\Formatter\FormatterInterface; 16 | use Monolog\Formatter\LogglyFormatter; 17 | 18 | /** 19 | * Sends errors to Loggly. 20 | * 21 | * @author Przemek Sobstel 22 | * @author Adam Pancutt 23 | * @author Gregory Barchard 24 | */ 25 | class LogglyHandler extends AbstractProcessingHandler 26 | { 27 | const HOST = 'logs-01.loggly.com'; 28 | const ENDPOINT_SINGLE = 'inputs'; 29 | const ENDPOINT_BATCH = 'bulk'; 30 | 31 | protected $token; 32 | 33 | protected $tag = array(); 34 | 35 | public function __construct($token, $level = Logger::DEBUG, $bubble = true) 36 | { 37 | if (!extension_loaded('curl')) { 38 | throw new \LogicException('The curl extension is needed to use the LogglyHandler'); 39 | } 40 | 41 | $this->token = $token; 42 | 43 | parent::__construct($level, $bubble); 44 | } 45 | 46 | public function setTag($tag) 47 | { 48 | $tag = !empty($tag) ? $tag : array(); 49 | $this->tag = is_array($tag) ? $tag : array($tag); 50 | } 51 | 52 | public function addTag($tag) 53 | { 54 | if (!empty($tag)) { 55 | $tag = is_array($tag) ? $tag : array($tag); 56 | $this->tag = array_unique(array_merge($this->tag, $tag)); 57 | } 58 | } 59 | 60 | protected function write(array $record) 61 | { 62 | $this->send($record["formatted"], self::ENDPOINT_SINGLE); 63 | } 64 | 65 | public function handleBatch(array $records) 66 | { 67 | $level = $this->level; 68 | 69 | $records = array_filter($records, function ($record) use ($level) { 70 | return ($record['level'] >= $level); 71 | }); 72 | 73 | if ($records) { 74 | $this->send($this->getFormatter()->formatBatch($records), self::ENDPOINT_BATCH); 75 | } 76 | } 77 | 78 | protected function send($data, $endpoint) 79 | { 80 | $url = sprintf("https://%s/%s/%s/", self::HOST, $endpoint, $this->token); 81 | 82 | $headers = array('Content-Type: application/json'); 83 | 84 | if (!empty($this->tag)) { 85 | $headers[] = 'X-LOGGLY-TAG: '.implode(',', $this->tag); 86 | } 87 | 88 | $ch = curl_init(); 89 | 90 | curl_setopt($ch, CURLOPT_URL, $url); 91 | curl_setopt($ch, CURLOPT_POST, true); 92 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 93 | curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 94 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 95 | 96 | Curl\Util::execute($ch); 97 | } 98 | 99 | protected function getDefaultFormatter(): FormatterInterface 100 | { 101 | return new LogglyFormatter(); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/MailHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | /** 15 | * Base class for all mail handlers 16 | * 17 | * @author Gyula Sallai 18 | */ 19 | abstract class MailHandler extends AbstractProcessingHandler 20 | { 21 | /** 22 | * {@inheritdoc} 23 | */ 24 | public function handleBatch(array $records) 25 | { 26 | $messages = array(); 27 | 28 | foreach ($records as $record) { 29 | if ($record['level'] < $this->level) { 30 | continue; 31 | } 32 | $messages[] = $this->processRecord($record); 33 | } 34 | 35 | if (!empty($messages)) { 36 | $this->send((string) $this->getFormatter()->formatBatch($messages), $messages); 37 | } 38 | } 39 | 40 | /** 41 | * Send a mail with the given content 42 | * 43 | * @param string $content formatted email body to be sent 44 | * @param array $records the array of log records that formed this content 45 | */ 46 | abstract protected function send($content, array $records); 47 | 48 | /** 49 | * {@inheritdoc} 50 | */ 51 | protected function write(array $record) 52 | { 53 | $this->send((string) $record['formatted'], array($record)); 54 | } 55 | 56 | protected function getHighestRecord(array $records) 57 | { 58 | $highestRecord = null; 59 | foreach ($records as $record) { 60 | if ($highestRecord === null || $highestRecord['level'] < $record['level']) { 61 | $highestRecord = $record; 62 | } 63 | } 64 | 65 | return $highestRecord; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/MandrillHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Monolog\Logger; 15 | 16 | /** 17 | * MandrillHandler uses cURL to send the emails to the Mandrill API 18 | * 19 | * @author Adam Nicholson 20 | */ 21 | class MandrillHandler extends MailHandler 22 | { 23 | protected $message; 24 | protected $apiKey; 25 | 26 | /** 27 | * @param string $apiKey A valid Mandrill API key 28 | * @param callable|\Swift_Message $message An example message for real messages, only the body will be replaced 29 | * @param int $level The minimum logging level at which this handler will be triggered 30 | * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not 31 | */ 32 | public function __construct($apiKey, $message, $level = Logger::ERROR, $bubble = true) 33 | { 34 | parent::__construct($level, $bubble); 35 | 36 | if (!$message instanceof \Swift_Message && is_callable($message)) { 37 | $message = call_user_func($message); 38 | } 39 | if (!$message instanceof \Swift_Message) { 40 | throw new \InvalidArgumentException('You must provide either a Swift_Message instance or a callable returning it'); 41 | } 42 | $this->message = $message; 43 | $this->apiKey = $apiKey; 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | protected function send($content, array $records) 50 | { 51 | $message = clone $this->message; 52 | $message->setBody($content); 53 | $message->setDate(time()); 54 | 55 | $ch = curl_init(); 56 | 57 | curl_setopt($ch, CURLOPT_URL, 'https://mandrillapp.com/api/1.0/messages/send-raw.json'); 58 | curl_setopt($ch, CURLOPT_POST, 1); 59 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 60 | curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array( 61 | 'key' => $this->apiKey, 62 | 'raw_message' => (string) $message, 63 | 'async' => false, 64 | ))); 65 | 66 | Curl\Util::execute($ch); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/MissingExtensionException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | /** 15 | * Exception can be thrown if an extension for an handler is missing 16 | * 17 | * @author Christian Bergau 18 | */ 19 | class MissingExtensionException extends \Exception 20 | { 21 | } 22 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/MongoDBHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use MongoDB\Driver\BulkWrite; 15 | use MongoDB\Driver\Manager; 16 | use MongoDB\Client; 17 | use Monolog\Logger; 18 | use Monolog\Formatter\FormatterInterface; 19 | use Monolog\Formatter\NormalizerFormatter; 20 | 21 | /** 22 | * Logs to a MongoDB database. 23 | * 24 | * Usage example: 25 | * 26 | * $log = new \Monolog\Logger('application'); 27 | * $client = new \MongoDB\Client('mongodb://localhost:27017'); 28 | * $mongodb = new \Monolog\Handler\MongoDBHandler($client, 'logs', 'prod'); 29 | * $log->pushHandler($mongodb); 30 | * 31 | * The above examples uses the MongoDB PHP library's client class; however, the 32 | * MongoDB\Driver\Manager class from ext-mongodb is also supported. 33 | */ 34 | class MongoDBHandler extends AbstractProcessingHandler 35 | { 36 | private $collection; 37 | private $manager; 38 | private $namespace; 39 | 40 | /** 41 | * Constructor. 42 | * 43 | * @param Client|Manager $mongodb MongoDB library or driver client 44 | * @param string $database Database name 45 | * @param string $collection Collection name 46 | * @param int $level The minimum logging level at which this handler will be triggered 47 | * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not 48 | */ 49 | public function __construct($mongodb, $database, $collection, $level = Logger::DEBUG, $bubble = true) 50 | { 51 | if (!($mongodb instanceof Client || $mongodb instanceof Manager)) { 52 | throw new \InvalidArgumentException('MongoDB\Client or MongoDB\Driver\Manager instance required'); 53 | } 54 | 55 | if ($mongodb instanceof Client) { 56 | $this->collection = $mongodb->selectCollection($database, $collection); 57 | } else { 58 | $this->manager = $mongodb; 59 | $this->namespace = $database . '.' . $collection; 60 | } 61 | 62 | parent::__construct($level, $bubble); 63 | } 64 | 65 | protected function write(array $record) 66 | { 67 | if (isset($this->collection)) { 68 | $this->collection->insertOne($record['formatted']); 69 | } 70 | 71 | if (isset($this->manager, $this->namespace)) { 72 | $bulk = new BulkWrite; 73 | $bulk->insert($record["formatted"]); 74 | $this->manager->executeBulkWrite($this->namespace, $bulk); 75 | } 76 | } 77 | 78 | /** 79 | * {@inheritDoc} 80 | */ 81 | protected function getDefaultFormatter(): FormatterInterface 82 | { 83 | return new NormalizerFormatter; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/NullHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Monolog\Logger; 15 | 16 | /** 17 | * Blackhole 18 | * 19 | * Any record it can handle will be thrown away. This can be used 20 | * to put on top of an existing stack to override it temporarily. 21 | * 22 | * @author Jordi Boggiano 23 | */ 24 | class NullHandler extends Handler 25 | { 26 | private $level; 27 | 28 | /** 29 | * @param int $level The minimum logging level at which this handler will be triggered 30 | */ 31 | public function __construct(int $level = Logger::DEBUG) 32 | { 33 | $this->level = $level; 34 | } 35 | 36 | /** 37 | * {@inheritdoc} 38 | */ 39 | public function isHandling(array $record): bool 40 | { 41 | return $record['level'] >= $this->level; 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | public function handle(array $record): bool 48 | { 49 | if ($record['level'] < $this->level) { 50 | return false; 51 | } 52 | 53 | return true; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/ProcessableHandlerInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | /** 15 | * Interface to describe loggers that have processors 16 | * 17 | * @author Jordi Boggiano 18 | */ 19 | interface ProcessableHandlerInterface 20 | { 21 | /** 22 | * Adds a processor in the stack. 23 | * 24 | * @param callable $callback 25 | * @return HandlerInterface self 26 | */ 27 | public function pushProcessor(callable $callback): HandlerInterface; 28 | 29 | /** 30 | * Removes the processor on top of the stack and returns it. 31 | * 32 | * @throws LogicException In case the processor stack is empty 33 | * @return callable 34 | */ 35 | public function popProcessor(): callable; 36 | } 37 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/ProcessableHandlerTrait.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | /** 15 | * Helper trait for implementing ProcessableInterface 16 | * 17 | * @author Jordi Boggiano 18 | */ 19 | trait ProcessableHandlerTrait 20 | { 21 | /** 22 | * @var callable[] 23 | */ 24 | protected $processors = []; 25 | 26 | /** 27 | * {@inheritdoc} 28 | */ 29 | public function pushProcessor(callable $callback): HandlerInterface 30 | { 31 | if (!is_callable($callback)) { 32 | throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), '.var_export($callback, true).' given'); 33 | } 34 | array_unshift($this->processors, $callback); 35 | 36 | return $this; 37 | } 38 | 39 | /** 40 | * {@inheritdoc} 41 | */ 42 | public function popProcessor(): callable 43 | { 44 | if (!$this->processors) { 45 | throw new \LogicException('You tried to pop from an empty processor stack.'); 46 | } 47 | 48 | return array_shift($this->processors); 49 | } 50 | 51 | /** 52 | * Processes a record. 53 | * 54 | * @param array $record 55 | * @return array 56 | */ 57 | protected function processRecord(array $record) 58 | { 59 | foreach ($this->processors as $processor) { 60 | $record = $processor($record); 61 | } 62 | 63 | return $record; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/PsrHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Monolog\Logger; 15 | use Psr\Log\LoggerInterface; 16 | 17 | /** 18 | * Proxies log messages to an existing PSR-3 compliant logger. 19 | * 20 | * @author Michael Moussa 21 | */ 22 | class PsrHandler extends AbstractHandler 23 | { 24 | /** 25 | * PSR-3 compliant logger 26 | * 27 | * @var LoggerInterface 28 | */ 29 | protected $logger; 30 | 31 | /** 32 | * @param LoggerInterface $logger The underlying PSR-3 compliant logger to which messages will be proxied 33 | * @param int $level The minimum logging level at which this handler will be triggered 34 | * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not 35 | */ 36 | public function __construct(LoggerInterface $logger, $level = Logger::DEBUG, $bubble = true) 37 | { 38 | parent::__construct($level, $bubble); 39 | 40 | $this->logger = $logger; 41 | } 42 | 43 | /** 44 | * {@inheritDoc} 45 | */ 46 | public function handle(array $record): bool 47 | { 48 | if (!$this->isHandling($record)) { 49 | return false; 50 | } 51 | 52 | $this->logger->log(strtolower($record['level_name']), $record['message'], $record['context']); 53 | 54 | return false === $this->bubble; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/RedisHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Monolog\Formatter\LineFormatter; 15 | use Monolog\Formatter\FormatterInterface; 16 | use Monolog\Logger; 17 | 18 | /** 19 | * Logs to a Redis key using rpush 20 | * 21 | * usage example: 22 | * 23 | * $log = new Logger('application'); 24 | * $redis = new RedisHandler(new Predis\Client("tcp://localhost:6379"), "logs", "prod"); 25 | * $log->pushHandler($redis); 26 | * 27 | * @author Thomas Tourlourat 28 | */ 29 | class RedisHandler extends AbstractProcessingHandler 30 | { 31 | private $redisClient; 32 | private $redisKey; 33 | protected $capSize; 34 | 35 | /** 36 | * @param \Predis\Client|\Redis $redis The redis instance 37 | * @param string $key The key name to push records to 38 | * @param int $level The minimum logging level at which this handler will be triggered 39 | * @param bool $bubble Whether the messages that are handled can bubble up the stack or not 40 | * @param int $capSize Number of entries to limit list size to 41 | */ 42 | public function __construct($redis, $key, $level = Logger::DEBUG, $bubble = true, $capSize = false) 43 | { 44 | if (!(($redis instanceof \Predis\Client) || ($redis instanceof \Redis))) { 45 | throw new \InvalidArgumentException('Predis\Client or Redis instance required'); 46 | } 47 | 48 | $this->redisClient = $redis; 49 | $this->redisKey = $key; 50 | $this->capSize = $capSize; 51 | 52 | parent::__construct($level, $bubble); 53 | } 54 | 55 | /** 56 | * {@inheritDoc} 57 | */ 58 | protected function write(array $record) 59 | { 60 | if ($this->capSize) { 61 | $this->writeCapped($record); 62 | } else { 63 | $this->redisClient->rpush($this->redisKey, $record["formatted"]); 64 | } 65 | } 66 | 67 | /** 68 | * Write and cap the collection 69 | * Writes the record to the redis list and caps its 70 | * 71 | * @param array $record associative record array 72 | * @return void 73 | */ 74 | protected function writeCapped(array $record) 75 | { 76 | if ($this->redisClient instanceof \Redis) { 77 | $this->redisClient->multi() 78 | ->rpush($this->redisKey, $record["formatted"]) 79 | ->ltrim($this->redisKey, -$this->capSize, -1) 80 | ->exec(); 81 | } else { 82 | $redisKey = $this->redisKey; 83 | $capSize = $this->capSize; 84 | $this->redisClient->transaction(function ($tx) use ($record, $redisKey, $capSize) { 85 | $tx->rpush($redisKey, $record["formatted"]); 86 | $tx->ltrim($redisKey, -$capSize, -1); 87 | }); 88 | } 89 | } 90 | 91 | /** 92 | * {@inheritDoc} 93 | */ 94 | protected function getDefaultFormatter(): FormatterInterface 95 | { 96 | return new LineFormatter(); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/RollbarHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use RollbarNotifier; 15 | use Exception; 16 | use Monolog\Logger; 17 | 18 | /** 19 | * Sends errors to Rollbar 20 | * 21 | * If the context data contains a `payload` key, that is used as an array 22 | * of payload options to RollbarNotifier's report_message/report_exception methods. 23 | * 24 | * @author Paul Statezny 25 | */ 26 | class RollbarHandler extends AbstractProcessingHandler 27 | { 28 | /** 29 | * Rollbar notifier 30 | * 31 | * @var RollbarNotifier 32 | */ 33 | protected $rollbarNotifier; 34 | 35 | /** 36 | * Records whether any log records have been added since the last flush of the rollbar notifier 37 | * 38 | * @var bool 39 | */ 40 | private $hasRecords = false; 41 | 42 | /** 43 | * @param RollbarNotifier $rollbarNotifier RollbarNotifier object constructed with valid token 44 | * @param int $level The minimum logging level at which this handler will be triggered 45 | * @param bool $bubble Whether the messages that are handled can bubble up the stack or not 46 | */ 47 | public function __construct(RollbarNotifier $rollbarNotifier, $level = Logger::ERROR, $bubble = true) 48 | { 49 | $this->rollbarNotifier = $rollbarNotifier; 50 | 51 | parent::__construct($level, $bubble); 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | */ 57 | protected function write(array $record) 58 | { 59 | if (isset($record['context']['exception']) && $record['context']['exception'] instanceof Exception) { 60 | $context = $record['context']; 61 | $exception = $context['exception']; 62 | unset($context['exception']); 63 | 64 | $payload = array(); 65 | if (isset($context['payload'])) { 66 | $payload = $context['payload']; 67 | unset($context['payload']); 68 | } 69 | 70 | $this->rollbarNotifier->report_exception($exception, $context, $payload); 71 | } else { 72 | $extraData = array( 73 | 'level' => $record['level'], 74 | 'channel' => $record['channel'], 75 | 'datetime' => $record['datetime']->format('U'), 76 | ); 77 | 78 | $context = $record['context']; 79 | $payload = array(); 80 | if (isset($context['payload'])) { 81 | $payload = $context['payload']; 82 | unset($context['payload']); 83 | } 84 | 85 | $this->rollbarNotifier->report_message( 86 | $record['message'], 87 | $record['level_name'], 88 | array_merge($record['context'], $record['extra'], $extraData), 89 | $payload 90 | ); 91 | } 92 | 93 | $this->hasRecords = true; 94 | } 95 | 96 | /** 97 | * {@inheritdoc} 98 | */ 99 | public function close() 100 | { 101 | if ($this->hasRecords) { 102 | $this->rollbarNotifier->flush(); 103 | $this->hasRecords = false; 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/SamplingHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | /** 15 | * Sampling handler 16 | * 17 | * A sampled event stream can be useful for logging high frequency events in 18 | * a production environment where you only need an idea of what is happening 19 | * and are not concerned with capturing every occurrence. Since the decision to 20 | * handle or not handle a particular event is determined randomly, the 21 | * resulting sampled log is not guaranteed to contain 1/N of the events that 22 | * occurred in the application, but based on the Law of large numbers, it will 23 | * tend to be close to this ratio with a large number of attempts. 24 | * 25 | * @author Bryan Davis 26 | * @author Kunal Mehta 27 | */ 28 | class SamplingHandler extends AbstractHandler implements ProcessableHandlerInterface 29 | { 30 | use ProcessableHandlerTrait; 31 | 32 | /** 33 | * @var callable|HandlerInterface $handler 34 | */ 35 | protected $handler; 36 | 37 | /** 38 | * @var int $factor 39 | */ 40 | protected $factor; 41 | 42 | /** 43 | * @param callable|HandlerInterface $handler Handler or factory callable($record, $fingersCrossedHandler). 44 | * @param int $factor Sample factor 45 | */ 46 | public function __construct($handler, $factor) 47 | { 48 | parent::__construct(); 49 | $this->handler = $handler; 50 | $this->factor = $factor; 51 | 52 | if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) { 53 | throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object"); 54 | } 55 | } 56 | 57 | public function isHandling(array $record): bool 58 | { 59 | return $this->handler->isHandling($record); 60 | } 61 | 62 | public function handle(array $record): bool 63 | { 64 | if ($this->isHandling($record) && mt_rand(1, $this->factor) === 1) { 65 | // The same logic as in FingersCrossedHandler 66 | if (!$this->handler instanceof HandlerInterface) { 67 | $this->handler = call_user_func($this->handler, $record, $this); 68 | if (!$this->handler instanceof HandlerInterface) { 69 | throw new \RuntimeException("The factory callable should return a HandlerInterface"); 70 | } 71 | } 72 | 73 | if ($this->processors) { 74 | $record = $this->processRecord($record); 75 | } 76 | 77 | $this->handler->handle($record); 78 | } 79 | 80 | return false === $this->bubble; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/SwiftMailerHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Monolog\Logger; 15 | use Monolog\Formatter\LineFormatter; 16 | 17 | /** 18 | * SwiftMailerHandler uses Swift_Mailer to send the emails 19 | * 20 | * @author Gyula Sallai 21 | */ 22 | class SwiftMailerHandler extends MailHandler 23 | { 24 | protected $mailer; 25 | private $messageTemplate; 26 | 27 | /** 28 | * @param \Swift_Mailer $mailer The mailer to use 29 | * @param callable|\Swift_Message $message An example message for real messages, only the body will be replaced 30 | * @param int $level The minimum logging level at which this handler will be triggered 31 | * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not 32 | */ 33 | public function __construct(\Swift_Mailer $mailer, $message, $level = Logger::ERROR, $bubble = true) 34 | { 35 | parent::__construct($level, $bubble); 36 | 37 | $this->mailer = $mailer; 38 | $this->messageTemplate = $message; 39 | } 40 | 41 | /** 42 | * {@inheritdoc} 43 | */ 44 | protected function send($content, array $records) 45 | { 46 | $this->mailer->send($this->buildMessage($content, $records)); 47 | } 48 | 49 | /** 50 | * Creates instance of Swift_Message to be sent 51 | * 52 | * @param string $content formatted email body to be sent 53 | * @param array $records Log records that formed the content 54 | * @return \Swift_Message 55 | */ 56 | protected function buildMessage($content, array $records) 57 | { 58 | $message = null; 59 | if ($this->messageTemplate instanceof \Swift_Message) { 60 | $message = clone $this->messageTemplate; 61 | $message->generateId(); 62 | } elseif (is_callable($this->messageTemplate)) { 63 | $message = call_user_func($this->messageTemplate, $content, $records); 64 | } 65 | 66 | if (!$message instanceof \Swift_Message) { 67 | throw new \InvalidArgumentException('Could not resolve message as instance of Swift_Message or a callable returning it'); 68 | } 69 | 70 | if ($records) { 71 | $subjectFormatter = new LineFormatter($message->getSubject()); 72 | $message->setSubject($subjectFormatter->format($this->getHighestRecord($records))); 73 | } 74 | 75 | $message->setBody($content); 76 | $message->setDate(time()); 77 | 78 | return $message; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/SyslogHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Monolog\Logger; 15 | 16 | /** 17 | * Logs to syslog service. 18 | * 19 | * usage example: 20 | * 21 | * $log = new Logger('application'); 22 | * $syslog = new SyslogHandler('myfacility', 'local6'); 23 | * $formatter = new LineFormatter("%channel%.%level_name%: %message% %extra%"); 24 | * $syslog->setFormatter($formatter); 25 | * $log->pushHandler($syslog); 26 | * 27 | * @author Sven Paulus 28 | */ 29 | class SyslogHandler extends AbstractSyslogHandler 30 | { 31 | protected $ident; 32 | protected $logopts; 33 | 34 | /** 35 | * @param string $ident 36 | * @param mixed $facility 37 | * @param int $level The minimum logging level at which this handler will be triggered 38 | * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not 39 | * @param int $logopts Option flags for the openlog() call, defaults to LOG_PID 40 | */ 41 | public function __construct($ident, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true, $logopts = LOG_PID) 42 | { 43 | parent::__construct($facility, $level, $bubble); 44 | 45 | $this->ident = $ident; 46 | $this->logopts = $logopts; 47 | } 48 | 49 | /** 50 | * {@inheritdoc} 51 | */ 52 | public function close() 53 | { 54 | closelog(); 55 | } 56 | 57 | /** 58 | * {@inheritdoc} 59 | */ 60 | protected function write(array $record) 61 | { 62 | if (!openlog($this->ident, $this->logopts, $this->facility)) { 63 | throw new \LogicException('Can\'t open syslog for ident "'.$this->ident.'" and facility "'.$this->facility.'"'); 64 | } 65 | syslog($this->logLevels[$record['level']], (string) $record['formatted']); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/SyslogUdp/UdpSocket.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler\SyslogUdp; 13 | 14 | class UdpSocket 15 | { 16 | const DATAGRAM_MAX_LENGTH = 65023; 17 | 18 | protected $ip; 19 | protected $port; 20 | protected $socket; 21 | 22 | public function __construct($ip, $port = 514) 23 | { 24 | $this->ip = $ip; 25 | $this->port = $port; 26 | $this->socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); 27 | } 28 | 29 | public function write($line, $header = "") 30 | { 31 | $this->send($this->assembleMessage($line, $header)); 32 | } 33 | 34 | public function close() 35 | { 36 | if (is_resource($this->socket)) { 37 | socket_close($this->socket); 38 | $this->socket = null; 39 | } 40 | } 41 | 42 | protected function send($chunk) 43 | { 44 | if (!is_resource($this->socket)) { 45 | throw new \LogicException('The UdpSocket to '.$this->ip.':'.$this->port.' has been closed and can not be written to anymore'); 46 | } 47 | socket_sendto($this->socket, $chunk, strlen($chunk), $flags = 0, $this->ip, $this->port); 48 | } 49 | 50 | protected function assembleMessage($line, $header) 51 | { 52 | $chunkSize = self::DATAGRAM_MAX_LENGTH - strlen($header); 53 | 54 | return $header . substr($line, 0, $chunkSize); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/SyslogUdpHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | use Monolog\Logger; 15 | use Monolog\Handler\SyslogUdp\UdpSocket; 16 | 17 | /** 18 | * A Handler for logging to a remote syslogd server. 19 | * 20 | * @author Jesper Skovgaard Nielsen 21 | */ 22 | class SyslogUdpHandler extends AbstractSyslogHandler 23 | { 24 | protected $socket; 25 | 26 | /** 27 | * @param string $host 28 | * @param int $port 29 | * @param mixed $facility 30 | * @param int $level The minimum logging level at which this handler will be triggered 31 | * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not 32 | */ 33 | public function __construct($host, $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true) 34 | { 35 | parent::__construct($facility, $level, $bubble); 36 | 37 | $this->socket = new UdpSocket($host, $port ?: 514); 38 | } 39 | 40 | protected function write(array $record) 41 | { 42 | $lines = $this->splitMessageIntoLines($record['formatted']); 43 | 44 | $header = $this->makeCommonSyslogHeader($this->logLevels[$record['level']]); 45 | 46 | foreach ($lines as $line) { 47 | $this->socket->write($line, $header); 48 | } 49 | } 50 | 51 | public function close() 52 | { 53 | $this->socket->close(); 54 | } 55 | 56 | private function splitMessageIntoLines($message) 57 | { 58 | if (is_array($message)) { 59 | $message = implode("\n", $message); 60 | } 61 | 62 | return preg_split('/$\R?^/m', $message); 63 | } 64 | 65 | /** 66 | * Make common syslog header (see rfc5424) 67 | */ 68 | protected function makeCommonSyslogHeader($severity) 69 | { 70 | $priority = $severity + $this->facility; 71 | 72 | return "<$priority>1 "; 73 | } 74 | 75 | /** 76 | * Inject your own socket, mainly used for testing 77 | */ 78 | public function setSocket($socket) 79 | { 80 | $this->socket = $socket; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/WhatFailureGroupHandler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Handler; 13 | 14 | /** 15 | * Forwards records to multiple handlers suppressing failures of each handler 16 | * and continuing through to give every handler a chance to succeed. 17 | * 18 | * @author Craig D'Amelio 19 | */ 20 | class WhatFailureGroupHandler extends GroupHandler 21 | { 22 | /** 23 | * {@inheritdoc} 24 | */ 25 | public function handle(array $record): bool 26 | { 27 | if ($this->processors) { 28 | foreach ($this->processors as $processor) { 29 | $record = call_user_func($processor, $record); 30 | } 31 | } 32 | 33 | foreach ($this->handlers as $handler) { 34 | try { 35 | $handler->handle($record); 36 | } catch (\Exception $e) { 37 | // What failure? 38 | } 39 | } 40 | 41 | return false === $this->bubble; 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | public function handleBatch(array $records) 48 | { 49 | foreach ($this->handlers as $handler) { 50 | try { 51 | $handler->handleBatch($records); 52 | } catch (\Exception $e) { 53 | // What failure? 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Logger/Monolog/Handler/ZendMonitorHandler.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace Monolog\Handler; 12 | 13 | use Monolog\Formatter\FormatterInterface; 14 | use Monolog\Formatter\NormalizerFormatter; 15 | use Monolog\Logger; 16 | 17 | /** 18 | * Handler sending logs to Zend Monitor 19 | * 20 | * @author Christian Bergau 21 | */ 22 | class ZendMonitorHandler extends AbstractProcessingHandler 23 | { 24 | /** 25 | * Monolog level / ZendMonitor Custom Event priority map 26 | * 27 | * @var array 28 | */ 29 | protected $levelMap = array( 30 | Logger::DEBUG => 1, 31 | Logger::INFO => 2, 32 | Logger::NOTICE => 3, 33 | Logger::WARNING => 4, 34 | Logger::ERROR => 5, 35 | Logger::CRITICAL => 6, 36 | Logger::ALERT => 7, 37 | Logger::EMERGENCY => 0, 38 | ); 39 | 40 | /** 41 | * Construct 42 | * 43 | * @param int $level 44 | * @param bool $bubble 45 | * @throws MissingExtensionException 46 | */ 47 | public function __construct($level = Logger::DEBUG, $bubble = true) 48 | { 49 | if (!function_exists('zend_monitor_custom_event')) { 50 | throw new MissingExtensionException('You must have Zend Server installed in order to use this handler'); 51 | } 52 | parent::__construct($level, $bubble); 53 | } 54 | 55 | /** 56 | * {@inheritdoc} 57 | */ 58 | protected function write(array $record) 59 | { 60 | $this->writeZendMonitorCustomEvent( 61 | $this->levelMap[$record['level']], 62 | $record['message'], 63 | $record['formatted'] 64 | ); 65 | } 66 | 67 | /** 68 | * Write a record to Zend Monitor 69 | * 70 | * @param int $level 71 | * @param string $message 72 | * @param array $formatted 73 | */ 74 | protected function writeZendMonitorCustomEvent($level, $message, $formatted) 75 | { 76 | zend_monitor_custom_event($level, $message, $formatted); 77 | } 78 | 79 | /** 80 | * {@inheritdoc} 81 | */ 82 | public function getDefaultFormatter(): FormatterInterface 83 | { 84 | return new NormalizerFormatter(); 85 | } 86 | 87 | /** 88 | * Get the level map 89 | * 90 | * @return array 91 | */ 92 | public function getLevelMap() 93 | { 94 | return $this->levelMap; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Logger/Monolog/Processor/GitProcessor.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Processor; 13 | 14 | use Monolog\Logger; 15 | 16 | /** 17 | * Injects Git branch and Git commit SHA in all records 18 | * 19 | * @author Nick Otter 20 | * @author Jordi Boggiano 21 | */ 22 | class GitProcessor 23 | { 24 | private $level; 25 | private static $cache; 26 | 27 | public function __construct($level = Logger::DEBUG) 28 | { 29 | $this->level = Logger::toMonologLevel($level); 30 | } 31 | 32 | /** 33 | * @param array $record 34 | * @return array 35 | */ 36 | public function __invoke(array $record) 37 | { 38 | // return if the level is not high enough 39 | if ($record['level'] < $this->level) { 40 | return $record; 41 | } 42 | 43 | $record['extra']['git'] = self::getGitInfo(); 44 | 45 | return $record; 46 | } 47 | 48 | private static function getGitInfo() 49 | { 50 | if (self::$cache) { 51 | return self::$cache; 52 | } 53 | 54 | $branches = `git branch -v --no-abbrev`; 55 | if (preg_match('{^\* (.+?)\s+([a-f0-9]{40})(?:\s|$)}m', $branches, $matches)) { 56 | return self::$cache = array( 57 | 'branch' => $matches[1], 58 | 'commit' => $matches[2], 59 | ); 60 | } 61 | 62 | return self::$cache = array(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Logger/Monolog/Processor/IntrospectionProcessor.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Processor; 13 | 14 | use Monolog\Logger; 15 | 16 | /** 17 | * Injects line/file:class/function where the log message came from 18 | * 19 | * Warning: This only works if the handler processes the logs directly. 20 | * If you put the processor on a handler that is behind a FingersCrossedHandler 21 | * for example, the processor will only be called once the trigger level is reached, 22 | * and all the log records will have the same file/line/.. data from the call that 23 | * triggered the FingersCrossedHandler. 24 | * 25 | * @author Jordi Boggiano 26 | */ 27 | class IntrospectionProcessor 28 | { 29 | private $level; 30 | 31 | private $skipClassesPartials; 32 | 33 | private $skipStackFramesCount; 34 | 35 | private $skipFunctions = array( 36 | 'call_user_func', 37 | 'call_user_func_array', 38 | ); 39 | 40 | public function __construct($level = Logger::DEBUG, array $skipClassesPartials = array(), $skipStackFramesCount = 0) 41 | { 42 | $this->level = Logger::toMonologLevel($level); 43 | $this->skipClassesPartials = array_merge(array('Monolog\\'), $skipClassesPartials); 44 | $this->skipStackFramesCount = $skipStackFramesCount; 45 | } 46 | 47 | /** 48 | * @param array $record 49 | * @return array 50 | */ 51 | public function __invoke(array $record) 52 | { 53 | // return if the level is not high enough 54 | if ($record['level'] < $this->level) { 55 | return $record; 56 | } 57 | 58 | $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); 59 | 60 | // skip first since it's always the current method 61 | array_shift($trace); 62 | // the call_user_func call is also skipped 63 | array_shift($trace); 64 | 65 | $i = 0; 66 | 67 | while ($this->isTraceClassOrSkippedFunction($trace, $i)) { 68 | if (isset($trace[$i]['class'])) { 69 | foreach ($this->skipClassesPartials as $part) { 70 | if (strpos($trace[$i]['class'], $part) !== false) { 71 | $i++; 72 | continue 2; 73 | } 74 | } 75 | } elseif (in_array($trace[$i]['function'], $this->skipFunctions)) { 76 | $i++; 77 | continue; 78 | } 79 | 80 | break; 81 | } 82 | 83 | $i += $this->skipStackFramesCount; 84 | 85 | // we should have the call source now 86 | $record['extra'] = array_merge( 87 | $record['extra'], 88 | array( 89 | 'file' => isset($trace[$i - 1]['file']) ? $trace[$i - 1]['file'] : null, 90 | 'line' => isset($trace[$i - 1]['line']) ? $trace[$i - 1]['line'] : null, 91 | 'class' => isset($trace[$i]['class']) ? $trace[$i]['class'] : null, 92 | 'function' => isset($trace[$i]['function']) ? $trace[$i]['function'] : null, 93 | ) 94 | ); 95 | 96 | return $record; 97 | } 98 | 99 | private function isTraceClassOrSkippedFunction(array $trace, $index) 100 | { 101 | if (!isset($trace[$index])) { 102 | return false; 103 | } 104 | 105 | return isset($trace[$index]['class']) || in_array($trace[$index]['function'], $this->skipFunctions); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Logger/Monolog/Processor/MemoryPeakUsageProcessor.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Processor; 13 | 14 | /** 15 | * Injects memory_get_peak_usage in all records 16 | * 17 | * @see Monolog\Processor\MemoryProcessor::__construct() for options 18 | * @author Rob Jensen 19 | */ 20 | class MemoryPeakUsageProcessor extends MemoryProcessor 21 | { 22 | /** 23 | * @param array $record 24 | * @return array 25 | */ 26 | public function __invoke(array $record) 27 | { 28 | $bytes = memory_get_peak_usage($this->realUsage); 29 | $formatted = $this->formatBytes($bytes); 30 | 31 | $record['extra']['memory_peak_usage'] = $formatted; 32 | 33 | return $record; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Logger/Monolog/Processor/MemoryProcessor.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Processor; 13 | 14 | /** 15 | * Some methods that are common for all memory processors 16 | * 17 | * @author Rob Jensen 18 | */ 19 | abstract class MemoryProcessor 20 | { 21 | /** 22 | * @var bool If true, get the real size of memory allocated from system. Else, only the memory used by emalloc() is reported. 23 | */ 24 | protected $realUsage; 25 | 26 | /** 27 | * @var bool If true, then format memory size to human readable string (MB, KB, B depending on size) 28 | */ 29 | protected $useFormatting; 30 | 31 | /** 32 | * @param bool $realUsage Set this to true to get the real size of memory allocated from system. 33 | * @param bool $useFormatting If true, then format memory size to human readable string (MB, KB, B depending on size) 34 | */ 35 | public function __construct($realUsage = true, $useFormatting = true) 36 | { 37 | $this->realUsage = (boolean) $realUsage; 38 | $this->useFormatting = (boolean) $useFormatting; 39 | } 40 | 41 | /** 42 | * Formats bytes into a human readable string if $this->useFormatting is true, otherwise return $bytes as is 43 | * 44 | * @param int $bytes 45 | * @return string|int Formatted string if $this->useFormatting is true, otherwise return $bytes as is 46 | */ 47 | protected function formatBytes($bytes) 48 | { 49 | $bytes = (int) $bytes; 50 | 51 | if (!$this->useFormatting) { 52 | return $bytes; 53 | } 54 | 55 | if ($bytes > 1024 * 1024) { 56 | return round($bytes / 1024 / 1024, 2).' MB'; 57 | } elseif ($bytes > 1024) { 58 | return round($bytes / 1024, 2).' KB'; 59 | } 60 | 61 | return $bytes . ' B'; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Logger/Monolog/Processor/MemoryUsageProcessor.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Processor; 13 | 14 | /** 15 | * Injects memory_get_usage in all records 16 | * 17 | * @see Monolog\Processor\MemoryProcessor::__construct() for options 18 | * @author Rob Jensen 19 | */ 20 | class MemoryUsageProcessor extends MemoryProcessor 21 | { 22 | /** 23 | * @param array $record 24 | * @return array 25 | */ 26 | public function __invoke(array $record) 27 | { 28 | $bytes = memory_get_usage($this->realUsage); 29 | $formatted = $this->formatBytes($bytes); 30 | 31 | $record['extra']['memory_usage'] = $formatted; 32 | 33 | return $record; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Logger/Monolog/Processor/ProcessIdProcessor.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Processor; 13 | 14 | /** 15 | * Adds value of getmypid into records 16 | * 17 | * @author Andreas Hörnicke 18 | */ 19 | class ProcessIdProcessor 20 | { 21 | /** 22 | * @param array $record 23 | * @return array 24 | */ 25 | public function __invoke(array $record) 26 | { 27 | $record['extra']['process_id'] = getmypid(); 28 | 29 | return $record; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Logger/Monolog/Processor/PsrLogMessageProcessor.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Processor; 13 | 14 | /** 15 | * Processes a record's message according to PSR-3 rules 16 | * 17 | * It replaces {foo} with the value from $context['foo'] 18 | * 19 | * @author Jordi Boggiano 20 | */ 21 | class PsrLogMessageProcessor 22 | { 23 | /** 24 | * @param array $record 25 | * @return array 26 | */ 27 | public function __invoke(array $record) 28 | { 29 | if (false === strpos($record['message'], '{')) { 30 | return $record; 31 | } 32 | 33 | $replacements = array(); 34 | foreach ($record['context'] as $key => $val) { 35 | if (is_null($val) || is_scalar($val) || (is_object($val) && method_exists($val, "__toString"))) { 36 | $replacements['{'.$key.'}'] = $val; 37 | } elseif (is_object($val)) { 38 | $replacements['{'.$key.'}'] = '[object '.get_class($val).']'; 39 | } else { 40 | $replacements['{'.$key.'}'] = '['.gettype($val).']'; 41 | } 42 | } 43 | 44 | $record['message'] = strtr($record['message'], $replacements); 45 | 46 | return $record; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Logger/Monolog/Processor/TagProcessor.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Processor; 13 | 14 | /** 15 | * Adds a tags array into record 16 | * 17 | * @author Martijn Riemers 18 | */ 19 | class TagProcessor 20 | { 21 | private $tags; 22 | 23 | public function __construct(array $tags = array()) 24 | { 25 | $this->setTags($tags); 26 | } 27 | 28 | public function addTags(array $tags = array()) 29 | { 30 | $this->tags = array_merge($this->tags, $tags); 31 | } 32 | 33 | public function setTags(array $tags = array()) 34 | { 35 | $this->tags = $tags; 36 | } 37 | 38 | public function __invoke(array $record) 39 | { 40 | $record['extra']['tags'] = $this->tags; 41 | 42 | return $record; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Logger/Monolog/Processor/UidProcessor.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Processor; 13 | 14 | /** 15 | * Adds a unique identifier into records 16 | * 17 | * @author Simon Mönch 18 | */ 19 | class UidProcessor 20 | { 21 | private $uid; 22 | 23 | public function __construct($length = 7) 24 | { 25 | if (!is_int($length) || $length > 32 || $length < 1) { 26 | throw new \InvalidArgumentException('The uid length must be an integer between 1 and 32'); 27 | } 28 | 29 | $this->uid = substr(hash('md5', uniqid('', true)), 0, $length); 30 | } 31 | 32 | public function __invoke(array $record) 33 | { 34 | $record['extra']['uid'] = $this->uid; 35 | 36 | return $record; 37 | } 38 | 39 | /** 40 | * @return string 41 | */ 42 | public function getUid() 43 | { 44 | return $this->uid; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Logger/Monolog/Processor/WebProcessor.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Monolog\Processor; 13 | 14 | /** 15 | * Injects url/method and remote IP of the current web request in all records 16 | * 17 | * @author Jordi Boggiano 18 | */ 19 | class WebProcessor 20 | { 21 | /** 22 | * @var array|\ArrayAccess 23 | */ 24 | protected $serverData; 25 | 26 | /** 27 | * Default fields 28 | * 29 | * Array is structured as [key in record.extra => key in $serverData] 30 | * 31 | * @var array 32 | */ 33 | protected $extraFields = array( 34 | 'url' => 'REQUEST_URI', 35 | 'ip' => 'REMOTE_ADDR', 36 | 'http_method' => 'REQUEST_METHOD', 37 | 'server' => 'SERVER_NAME', 38 | 'referrer' => 'HTTP_REFERER', 39 | ); 40 | 41 | /** 42 | * @param array|\ArrayAccess $serverData Array or object w/ ArrayAccess that provides access to the $_SERVER data 43 | * @param array|null $extraFields Field names and the related key inside $serverData to be added. If not provided it defaults to: url, ip, http_method, server, referrer 44 | */ 45 | public function __construct($serverData = null, array $extraFields = null) 46 | { 47 | if (null === $serverData) { 48 | $this->serverData = &$_SERVER; 49 | } elseif (is_array($serverData) || $serverData instanceof \ArrayAccess) { 50 | $this->serverData = $serverData; 51 | } else { 52 | throw new \UnexpectedValueException('$serverData must be an array or object implementing ArrayAccess.'); 53 | } 54 | 55 | if (null !== $extraFields) { 56 | if (isset($extraFields[0])) { 57 | foreach (array_keys($this->extraFields) as $fieldName) { 58 | if (!in_array($fieldName, $extraFields)) { 59 | unset($this->extraFields[$fieldName]); 60 | } 61 | } 62 | } else { 63 | $this->extraFields = $extraFields; 64 | } 65 | } 66 | } 67 | 68 | /** 69 | * @param array $record 70 | * @return array 71 | */ 72 | public function __invoke(array $record) 73 | { 74 | // skip processing if for some reason request data 75 | // is not present (CLI or wonky SAPIs) 76 | if (!isset($this->serverData['REQUEST_URI'])) { 77 | return $record; 78 | } 79 | 80 | $record['extra'] = $this->appendExtraFields($record['extra']); 81 | 82 | return $record; 83 | } 84 | 85 | /** 86 | * @param string $extraName 87 | * @param string $serverName 88 | * @return $this 89 | */ 90 | public function addExtraField($extraName, $serverName) 91 | { 92 | $this->extraFields[$extraName] = $serverName; 93 | 94 | return $this; 95 | } 96 | 97 | /** 98 | * @param array $extra 99 | * @return array 100 | */ 101 | private function appendExtraFields(array $extra) 102 | { 103 | foreach ($this->extraFields as $extraName => $serverName) { 104 | $extra[$extraName] = isset($this->serverData[$serverName]) ? $this->serverData[$serverName] : null; 105 | } 106 | 107 | if (isset($this->serverData['UNIQUE_ID'])) { 108 | $extra['unique_id'] = $this->serverData['UNIQUE_ID']; 109 | } 110 | 111 | return $extra; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /Logger/Psr/Log/LogLevel.php: -------------------------------------------------------------------------------- 1 | transport = 'udp'; 38 | $worker->count = 2; 39 | $worker->name = 'LoggerServer'; 40 | $worker->onMessage = array ( 41 | $this, 42 | 'onMessage' 43 | ); 44 | $time = date ( $this->logger_name_dataFormat ); 45 | $this->stream = new StreamHandler ( $this->dir . "/$time.log", $this->logger_level ); 46 | $this->stream->setFormatter ( new LineFormatter () ); 47 | } 48 | 49 | /** 50 | * onMessage. 51 | * 52 | * @param TcpConnection $connection 53 | * @param string $data 54 | */ 55 | public function onMessage($connection, $data) { 56 | if (! $data) { 57 | return; 58 | } 59 | $data = unserialize ( $data ); 60 | $time = date ( 'Y-m-d H:i:s' ); 61 | $logger_name = $data ['logger_name']; 62 | $logger_level = $data ['logger_level']; 63 | $logger_message = $data ['logger_message']; 64 | $logger = $this->getLoger ( $logger_name ); 65 | $logger->addRecord ( $logger_level, $logger_message ); 66 | echo "[$time][$logger_name]" . $logger_message . "\n"; 67 | } 68 | 69 | private function getLoger($loger_name) { 70 | if (! array_key_exists ( $loger_name, $this->logerlist )) { 71 | $logger = new Logger ( $loger_name ); 72 | $logger->pushHandler ( $this->stream ); 73 | $this->logerlist [$loger_name] = $logger; 74 | } 75 | return $this->logerlist [$loger_name]; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CI-worker 2 | 基于workerman翻作的CI框架,与CI框架的函数保持兼容,结构保持一致。目前仅支持CI的model和controll,view并没有做支持。 3 | #如何使用 4 | 参考CI框架使用 5 | route由于效率问题被固定为‘test/test’这种类型。并没有引入Route和URL类, 6 | 理论上将原来的CI框架中的model,controll,config,help,lib等复制到对应的文件夹即可使用。 7 | 部分CI的类库没有默认加入到框架中,可自行放入,但切记涉及到core中未包含的类对象是无法访问的。 8 | Log,Input,Output进行了深度优化和CI原本的不一致 9 | workeman进行了少量的修改,主要为Http这个文件的一些修改 10 | #优化 11 | 不要在你的控制器方法中使用load,load应该被移到__construct中,__CI_construct为了保留CI的习惯这个方法在每次调用控制器方法前都会执行,同样这里只能做验证获取数据等操作不要使用load 12 | CI原版代码中大量使用了魔术方法,尽量不要使用魔术方法非常影响效率,在__construct中尽量缓存数据。 13 | #性能 14 | i3 4核 8G php7 event.so 环境下,裸跑workeman http协议请求能达到11W/s 15 | CI-worker简易逻辑,仅route获取get,post,header等数据测试结果在8.5W/s。 16 | 秒杀CI框架。 17 | 另外为了测试workerman http解析时效率问题,用swoole框架进行的对比发现swoole的http服务器性能为10W/s还略不如workerman。 18 | 19 | 20 | -------------------------------------------------------------------------------- /Workerman/.gitignore: -------------------------------------------------------------------------------- 1 | logs 2 | .buildpath 3 | .project 4 | .settings 5 | .idea -------------------------------------------------------------------------------- /Workerman/Autoloader.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman; 15 | 16 | /** 17 | * Autoload. 18 | */ 19 | class Autoloader 20 | { 21 | /** 22 | * Autoload root path. 23 | * 24 | * @var string 25 | */ 26 | protected static $_autoloadRootPath = ''; 27 | 28 | /** 29 | * Set autoload root path. 30 | * 31 | * @param string $root_path 32 | * @return void 33 | */ 34 | public static function setRootPath($root_path) 35 | { 36 | self::$_autoloadRootPath = $root_path; 37 | } 38 | 39 | /** 40 | * Load files by namespace. 41 | * 42 | * @param string $name 43 | * @return boolean 44 | */ 45 | public static function loadByNamespace($name) 46 | { 47 | $class_path = str_replace('\\', DIRECTORY_SEPARATOR, $name); 48 | if (strpos($name, 'Workerman\\') === 0) { 49 | $class_file = __DIR__ . substr($class_path, strlen('Workerman')) . '.php'; 50 | } else { 51 | if (self::$_autoloadRootPath) { 52 | $class_file = self::$_autoloadRootPath . DIRECTORY_SEPARATOR . $class_path . '.php'; 53 | } 54 | if (empty($class_file) || !is_file($class_file)) { 55 | $class_file = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . "$class_path.php"; 56 | } 57 | } 58 | 59 | if (is_file($class_file)) { 60 | require_once($class_file); 61 | if (class_exists($name, false)) { 62 | return true; 63 | } 64 | } 65 | return false; 66 | } 67 | } 68 | 69 | spl_autoload_register('\Workerman\Autoloader::loadByNamespace'); -------------------------------------------------------------------------------- /Workerman/Connection/ConnectionInterface.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Connection; 15 | 16 | /** 17 | * ConnectionInterface. 18 | */ 19 | abstract class ConnectionInterface 20 | { 21 | /** 22 | * Statistics for status command. 23 | * 24 | * @var array 25 | */ 26 | public static $statistics = array( 27 | 'connection_count' => 0, 28 | 'total_request' => 0, 29 | 'throw_exception' => 0, 30 | 'send_fail' => 0, 31 | ); 32 | 33 | /** 34 | * Emitted when data is received. 35 | * 36 | * @var callback 37 | */ 38 | public $onMessage = null; 39 | 40 | /** 41 | * Emitted when the other end of the socket sends a FIN packet. 42 | * 43 | * @var callback 44 | */ 45 | public $onClose = null; 46 | 47 | /** 48 | * Emitted when an error occurs with connection. 49 | * 50 | * @var callback 51 | */ 52 | public $onError = null; 53 | 54 | /** 55 | * Sends data on the connection. 56 | * 57 | * @param string $send_buffer 58 | * @return void|boolean 59 | */ 60 | abstract public function send($send_buffer); 61 | 62 | /** 63 | * Get remote IP. 64 | * 65 | * @return string 66 | */ 67 | abstract public function getRemoteIp(); 68 | 69 | /** 70 | * Get remote port. 71 | * 72 | * @return int 73 | */ 74 | abstract public function getRemotePort(); 75 | 76 | /** 77 | * Close connection. 78 | * 79 | * @param $data 80 | * @return void 81 | */ 82 | abstract public function close($data = null); 83 | } 84 | -------------------------------------------------------------------------------- /Workerman/Connection/UdpConnection.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Connection; 15 | 16 | /** 17 | * UdpConnection. 18 | */ 19 | class UdpConnection extends ConnectionInterface 20 | { 21 | /** 22 | * Application layer protocol. 23 | * The format is like this Workerman\\Protocols\\Http. 24 | * 25 | * @var \Workerman\Protocols\ProtocolInterface 26 | */ 27 | public $protocol = null; 28 | 29 | /** 30 | * Udp socket. 31 | * 32 | * @var resource 33 | */ 34 | protected $_socket = null; 35 | 36 | /** 37 | * Remote ip. 38 | * 39 | * @var string 40 | */ 41 | protected $_remoteIp = ''; 42 | 43 | /** 44 | * Remote port. 45 | * 46 | * @var int 47 | */ 48 | protected $_remotePort = 0; 49 | 50 | /** 51 | * Remote address. 52 | * 53 | * @var string 54 | */ 55 | protected $_remoteAddress = ''; 56 | 57 | /** 58 | * Construct. 59 | * 60 | * @param resource $socket 61 | * @param string $remote_address 62 | */ 63 | public function __construct($socket, $remote_address) 64 | { 65 | $this->_socket = $socket; 66 | $this->_remoteAddress = $remote_address; 67 | } 68 | 69 | /** 70 | * Sends data on the connection. 71 | * 72 | * @param string $send_buffer 73 | * @param bool $raw 74 | * @return void|boolean 75 | */ 76 | public function send($send_buffer, $raw = false) 77 | { 78 | if (false === $raw && $this->protocol) { 79 | $parser = $this->protocol; 80 | $send_buffer = $parser::encode($send_buffer, $this); 81 | if ($send_buffer === '') { 82 | return null; 83 | } 84 | } 85 | return strlen($send_buffer) === stream_socket_sendto($this->_socket, $send_buffer, 0, $this->_remoteAddress); 86 | } 87 | 88 | /** 89 | * Get remote IP. 90 | * 91 | * @return string 92 | */ 93 | public function getRemoteIp() 94 | { 95 | if (!$this->_remoteIp) { 96 | list($this->_remoteIp, $this->_remotePort) = explode(':', $this->_remoteAddress, 2); 97 | } 98 | return $this->_remoteIp; 99 | } 100 | 101 | /** 102 | * Get remote port. 103 | * 104 | * @return int 105 | */ 106 | public function getRemotePort() 107 | { 108 | if (!$this->_remotePort) { 109 | list($this->_remoteIp, $this->_remotePort) = explode(':', $this->_remoteAddress, 2); 110 | } 111 | return $this->_remotePort; 112 | } 113 | 114 | /** 115 | * Close connection. 116 | * 117 | * @param mixed $data 118 | * @return bool 119 | */ 120 | public function close($data = null) 121 | { 122 | if ($data !== null) { 123 | $this->send($data); 124 | } 125 | return true; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /Workerman/Events/EventInterface.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Events; 15 | 16 | interface EventInterface 17 | { 18 | /** 19 | * Read event. 20 | * 21 | * @var int 22 | */ 23 | const EV_READ = 1; 24 | 25 | /** 26 | * Write event. 27 | * 28 | * @var int 29 | */ 30 | const EV_WRITE = 2; 31 | 32 | /** 33 | * Signal event. 34 | * 35 | * @var int 36 | */ 37 | const EV_SIGNAL = 4; 38 | 39 | /** 40 | * Timer event. 41 | * 42 | * @var int 43 | */ 44 | const EV_TIMER = 8; 45 | 46 | /** 47 | * Timer once event. 48 | * 49 | * @var int 50 | */ 51 | const EV_TIMER_ONCE = 16; 52 | 53 | /** 54 | * Add event listener to event loop. 55 | * 56 | * @param mixed $fd 57 | * @param int $flag 58 | * @param callable $func 59 | * @param mixed $args 60 | * @return bool 61 | */ 62 | public function add($fd, $flag, $func, $args = null); 63 | 64 | /** 65 | * Remove event listener from event loop. 66 | * 67 | * @param mixed $fd 68 | * @param int $flag 69 | * @return bool 70 | */ 71 | public function del($fd, $flag); 72 | 73 | /** 74 | * Remove all timers. 75 | * 76 | * @return void 77 | */ 78 | public function clearAllTimer(); 79 | 80 | /** 81 | * Main loop. 82 | * 83 | * @return void 84 | */ 85 | public function loop(); 86 | } 87 | -------------------------------------------------------------------------------- /Workerman/Lib/Constants.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | 15 | // Date.timezone 16 | if (!ini_get('date.timezone')) { 17 | date_default_timezone_set('Asia/Shanghai'); 18 | } 19 | // Display errors. 20 | ini_set('display_errors', 'on'); 21 | // Reporting all. 22 | error_reporting(E_ALL); 23 | 24 | // For onError callback. 25 | define('WORKERMAN_CONNECT_FAIL', 1); 26 | // For onError callback. 27 | define('WORKERMAN_SEND_FAIL', 2); 28 | 29 | // Compatible with php7 30 | if(!class_exists('Error')) 31 | { 32 | class Error extends Exception 33 | { 34 | } 35 | } -------------------------------------------------------------------------------- /Workerman/MIT-LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2009-2015 walkor and contributors (see https://github.com/walkor/workerman/contributors) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Workerman/Protocols/Frame.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Protocols; 15 | 16 | use Workerman\Connection\TcpConnection; 17 | 18 | /** 19 | * Frame Protocol. 20 | */ 21 | class Frame 22 | { 23 | /** 24 | * Check the integrity of the package. 25 | * 26 | * @param string $buffer 27 | * @param TcpConnection $connection 28 | * @return int 29 | */ 30 | public static function input($buffer, TcpConnection $connection) 31 | { 32 | if (strlen($buffer) < 4) { 33 | return 0; 34 | } 35 | $unpack_data = unpack('Ntotal_length', $buffer); 36 | return $unpack_data['total_length']; 37 | } 38 | 39 | /** 40 | * Encode. 41 | * 42 | * @param string $buffer 43 | * @return string 44 | */ 45 | public static function decode($buffer) 46 | { 47 | return substr($buffer, 4); 48 | } 49 | 50 | /** 51 | * Decode. 52 | * 53 | * @param string $buffer 54 | * @return string 55 | */ 56 | public static function encode($buffer) 57 | { 58 | $total_length = 4 + strlen($buffer); 59 | return pack('N', $total_length) . $buffer; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Workerman/Protocols/Http/mime.types: -------------------------------------------------------------------------------- 1 | 2 | types { 3 | text/html html htm shtml; 4 | text/css css; 5 | text/xml xml; 6 | image/gif gif; 7 | image/jpeg jpeg jpg; 8 | application/x-javascript js; 9 | application/atom+xml atom; 10 | application/rss+xml rss; 11 | 12 | text/mathml mml; 13 | text/plain txt; 14 | text/vnd.sun.j2me.app-descriptor jad; 15 | text/vnd.wap.wml wml; 16 | text/x-component htc; 17 | 18 | image/png png; 19 | image/tiff tif tiff; 20 | image/vnd.wap.wbmp wbmp; 21 | image/x-icon ico; 22 | image/x-jng jng; 23 | image/x-ms-bmp bmp; 24 | image/svg+xml svg svgz; 25 | image/webp webp; 26 | 27 | application/java-archive jar war ear; 28 | application/mac-binhex40 hqx; 29 | application/msword doc; 30 | application/pdf pdf; 31 | application/postscript ps eps ai; 32 | application/rtf rtf; 33 | application/vnd.ms-excel xls; 34 | application/vnd.ms-powerpoint ppt; 35 | application/vnd.wap.wmlc wmlc; 36 | application/vnd.google-earth.kml+xml kml; 37 | application/vnd.google-earth.kmz kmz; 38 | application/x-7z-compressed 7z; 39 | application/x-cocoa cco; 40 | application/x-java-archive-diff jardiff; 41 | application/x-java-jnlp-file jnlp; 42 | application/x-makeself run; 43 | application/x-perl pl pm; 44 | application/x-pilot prc pdb; 45 | application/x-rar-compressed rar; 46 | application/x-redhat-package-manager rpm; 47 | application/x-sea sea; 48 | application/x-shockwave-flash swf; 49 | application/x-stuffit sit; 50 | application/x-tcl tcl tk; 51 | application/x-x509-ca-cert der pem crt; 52 | application/x-xpinstall xpi; 53 | application/xhtml+xml xhtml; 54 | application/zip zip; 55 | 56 | application/octet-stream bin exe dll; 57 | application/octet-stream deb; 58 | application/octet-stream dmg; 59 | application/octet-stream eot; 60 | application/octet-stream iso img; 61 | application/octet-stream msi msp msm; 62 | 63 | audio/midi mid midi kar; 64 | audio/mpeg mp3; 65 | audio/ogg ogg; 66 | audio/x-m4a m4a; 67 | audio/x-realaudio ra; 68 | 69 | video/3gpp 3gpp 3gp; 70 | video/mp4 mp4; 71 | video/mpeg mpeg mpg; 72 | video/quicktime mov; 73 | video/webm webm; 74 | video/x-flv flv; 75 | video/x-m4v m4v; 76 | video/x-mng mng; 77 | video/x-ms-asf asx asf; 78 | video/x-ms-wmv wmv; 79 | video/x-msvideo avi; 80 | } 81 | -------------------------------------------------------------------------------- /Workerman/Protocols/ProtocolInterface.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Protocols; 15 | 16 | use Workerman\Connection\ConnectionInterface; 17 | 18 | /** 19 | * Protocol interface 20 | */ 21 | interface ProtocolInterface 22 | { 23 | /** 24 | * Check the integrity of the package. 25 | * Please return the length of package. 26 | * If length is unknow please return 0 that mean wating more data. 27 | * If the package has something wrong please return false the connection will be closed. 28 | * 29 | * @param ConnectionInterface $connection 30 | * @param string $recv_buffer 31 | * @return int|false 32 | */ 33 | public static function input($recv_buffer, ConnectionInterface $connection); 34 | 35 | /** 36 | * Decode package and emit onMessage($message) callback, $message is the result that decode returned. 37 | * 38 | * @param ConnectionInterface $connection 39 | * @param string $recv_buffer 40 | * @return mixed 41 | */ 42 | public static function decode($recv_buffer, ConnectionInterface $connection); 43 | 44 | /** 45 | * Encode package brefore sending to client. 46 | * 47 | * @param ConnectionInterface $connection 48 | * @param mixed $data 49 | * @return string 50 | */ 51 | public static function encode($data, ConnectionInterface $connection); 52 | } 53 | -------------------------------------------------------------------------------- /Workerman/Protocols/Text.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Protocols; 15 | 16 | use Workerman\Connection\TcpConnection; 17 | 18 | /** 19 | * Text Protocol. 20 | */ 21 | class Text 22 | { 23 | /** 24 | * Check the integrity of the package. 25 | * 26 | * @param string $buffer 27 | * @param TcpConnection $connection 28 | * @return int 29 | */ 30 | public static function input($buffer, TcpConnection $connection) 31 | { 32 | // Judge whether the package length exceeds the limit. 33 | if (strlen($buffer) >= TcpConnection::$maxPackageSize) { 34 | $connection->close(); 35 | return 0; 36 | } 37 | // Find the position of "\n". 38 | $pos = strpos($buffer, "\n"); 39 | // No "\n", packet length is unknown, continue to wait for the data so return 0. 40 | if ($pos === false) { 41 | return 0; 42 | } 43 | // Return the current package length. 44 | return $pos + 1; 45 | } 46 | 47 | /** 48 | * Encode. 49 | * 50 | * @param string $buffer 51 | * @return string 52 | */ 53 | public static function encode($buffer) 54 | { 55 | // Add "\n" 56 | return $buffer . "\n"; 57 | } 58 | 59 | /** 60 | * Decode. 61 | * 62 | * @param string $buffer 63 | * @return string 64 | */ 65 | public static function decode($buffer) 66 | { 67 | // Remove "\n" 68 | return trim($buffer); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Workerman/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "workerman/workerman", 3 | "type" : "project", 4 | "keywords": ["event-loop", "asynchronous"], 5 | "homepage": "http://www.workerman.net", 6 | "license" : "MIT", 7 | "description": "An asynchronous event driven PHP framework for easily building fast, scalable network applications.", 8 | "authors" : [ 9 | { 10 | "name" : "walkor", 11 | "email" : "walkor@workerman.net", 12 | "homepage" : "http://www.workerman.net", 13 | "role": "Developer" 14 | } 15 | ], 16 | "support" : { 17 | "email" : "walkor@workerman.net", 18 | "issues": "https://github.com/walkor/workerman/issues", 19 | "forum" : "http://wenda.workerman.net/", 20 | "wiki" : "http://doc3.workerman.net/index.html", 21 | "source": "https://github.com/walkor/workerman" 22 | }, 23 | "require": { 24 | "php": ">=5.3" 25 | }, 26 | "suggest": { 27 | "ext-libevent": "For better performance." 28 | }, 29 | "autoload": { 30 | "psr-4": {"Workerman\\": "./"} 31 | }, 32 | "minimum-stability":"dev" 33 | } 34 | -------------------------------------------------------------------------------- /start.php: -------------------------------------------------------------------------------- 1 |