Commit c88c089a by 王召彬

add cls file

parent 9f312bb1
<?php
/**
* Auto generated from CLS.proto at 2018-09-07 06:03:23
*
* cls package
*/
namespace Hdll\Services\Common\ClsLogger\Cls {
/**
* Log message
*/
class Log extends \ProtobufMessage
{
/* Field index constants */
const TIME = 1;
const CONTENTS = 2;
/* @var array Field descriptors */
protected static $fields = array(
self::TIME => array(
'name' => 'time',
'required' => true,
'type' => \ProtobufMessage::PB_TYPE_INT,
),
self::CONTENTS => array(
'name' => 'contents',
'repeated' => true,
'type' => '\Hdll\Services\Common\ClsLogger\Cls\Log_Content'
),
);
/**
* Constructs new message container and clears its internal state
*/
public function __construct()
{
$this->reset();
}
/**
* Clears message values and sets default ones
*
* @return null
*/
public function reset()
{
$this->values[self::TIME] = null;
$this->values[self::CONTENTS] = array();
}
/**
* Returns field descriptors
*
* @return array
*/
public function fields()
{
return self::$fields;
}
/**
* Sets value of 'time' property
*
* @param integer $value Property value
*
* @return null
*/
public function setTime($value)
{
return $this->set(self::TIME, $value);
}
/**
* Returns value of 'time' property
*
* @return integer
*/
public function getTime()
{
$value = $this->get(self::TIME);
return $value === null ? (integer)$value : $value;
}
/**
* Appends value to 'contents' list
*
* @param \Hdll\Services\Common\ClsLogger\Cls\Log_Content $value Value to append
*
* @return null
*/
public function appendContents(\Hdll\Services\Common\ClsLogger\Cls\Log_Content $value)
{
return $this->append(self::CONTENTS, $value);
}
/**
* Clears 'contents' list
*
* @return null
*/
public function clearContents()
{
return $this->clear(self::CONTENTS);
}
/**
* Returns 'contents' list
*
* @return \Hdll\Services\Common\ClsLogger\Cls\Log_Content[]
*/
public function getContents()
{
return $this->get(self::CONTENTS);
}
/**
* Returns 'contents' iterator
*
* @return \ArrayIterator
*/
public function getContentsIterator()
{
return new \ArrayIterator($this->get(self::CONTENTS));
}
/**
* Returns element from 'contents' list at given offset
*
* @param int $offset Position in list
*
* @return \Hdll\Services\Common\ClsLogger\Cls\Log_Content
*/
public function getContentsAt($offset)
{
return $this->get(self::CONTENTS, $offset);
}
/**
* Returns count of 'contents' list
*
* @return int
*/
public function getContentsCount()
{
return $this->count(self::CONTENTS);
}
}
}
\ No newline at end of file
<?php
/**
* Auto generated from CLS.proto at 2018-09-07 06:03:23
*
* cls package
*/
namespace Hdll\Services\Common\ClsLogger\Cls {
/**
* LogGroup message
*/
class LogGroup extends \ProtobufMessage
{
/* Field index constants */
const LOGS = 1;
const CONTEXTFLOW = 2;
const FILENAME = 3;
const SOURCE = 4;
/* @var array Field descriptors */
protected static $fields = array(
self::LOGS => array(
'name' => 'logs',
'repeated' => true,
'type' => '\Hdll\Services\Common\ClsLogger\Cls\Log'
),
self::CONTEXTFLOW => array(
'name' => 'contextFlow',
'required' => false,
'type' => \ProtobufMessage::PB_TYPE_STRING,
),
self::FILENAME => array(
'name' => 'filename',
'required' => false,
'type' => \ProtobufMessage::PB_TYPE_STRING,
),
self::SOURCE => array(
'name' => 'source',
'required' => false,
'type' => \ProtobufMessage::PB_TYPE_STRING,
),
);
/**
* Constructs new message container and clears its internal state
*/
public function __construct()
{
$this->reset();
}
/**
* Clears message values and sets default ones
*
* @return null
*/
public function reset()
{
$this->values[self::LOGS] = array();
$this->values[self::CONTEXTFLOW] = null;
$this->values[self::FILENAME] = null;
$this->values[self::SOURCE] = null;
}
/**
* Returns field descriptors
*
* @return array
*/
public function fields()
{
return self::$fields;
}
/**
* Appends value to 'logs' list
*
* @param \Hdll\Services\Common\ClsLogger\Cls\Log $value Value to append
*
* @return null
*/
public function appendLogs(\Hdll\Services\Common\ClsLogger\Cls\Log $value)
{
return $this->append(self::LOGS, $value);
}
/**
* Clears 'logs' list
*
* @return null
*/
public function clearLogs()
{
return $this->clear(self::LOGS);
}
/**
* Returns 'logs' list
*
* @return \Hdll\Services\Common\ClsLogger\Cls\Log[]
*/
public function getLogs()
{
return $this->get(self::LOGS);
}
/**
* Returns 'logs' iterator
*
* @return \ArrayIterator
*/
public function getLogsIterator()
{
return new \ArrayIterator($this->get(self::LOGS));
}
/**
* Returns element from 'logs' list at given offset
*
* @param int $offset Position in list
*
* @return \Hdll\Services\Common\ClsLogger\Cls\Log
*/
public function getLogsAt($offset)
{
return $this->get(self::LOGS, $offset);
}
/**
* Returns count of 'logs' list
*
* @return int
*/
public function getLogsCount()
{
return $this->count(self::LOGS);
}
/**
* Sets value of 'contextFlow' property
*
* @param string $value Property value
*
* @return null
*/
public function setContextFlow($value)
{
return $this->set(self::CONTEXTFLOW, $value);
}
/**
* Returns value of 'contextFlow' property
*
* @return string
*/
public function getContextFlow()
{
$value = $this->get(self::CONTEXTFLOW);
return $value === null ? (string)$value : $value;
}
/**
* Sets value of 'filename' property
*
* @param string $value Property value
*
* @return null
*/
public function setFilename($value)
{
return $this->set(self::FILENAME, $value);
}
/**
* Returns value of 'filename' property
*
* @return string
*/
public function getFilename()
{
$value = $this->get(self::FILENAME);
return $value === null ? (string)$value : $value;
}
/**
* Sets value of 'source' property
*
* @param string $value Property value
*
* @return null
*/
public function setSource($value)
{
return $this->set(self::SOURCE, $value);
}
/**
* Returns value of 'source' property
*
* @return string
*/
public function getSource()
{
$value = $this->get(self::SOURCE);
return $value === null ? (string)$value : $value;
}
}
}
\ No newline at end of file
<?php
/**
* Auto generated from CLS.proto at 2018-09-07 06:03:23
*
* cls package
*/
namespace Hdll\Services\Common\ClsLogger\Cls {
/**
* LogGroupList message
*/
class LogGroupList extends \ProtobufMessage
{
/* Field index constants */
const LOGGROUPLIST = 1;
/* @var array Field descriptors */
protected static $fields = array(
self::LOGGROUPLIST => array(
'name' => 'logGroupList',
'repeated' => true,
'type' => '\Hdll\Services\Common\ClsLogger\Cls\LogGroup'
),
);
/**
* Constructs new message container and clears its internal state
*/
public function __construct()
{
$this->reset();
}
/**
* Clears message values and sets default ones
*
* @return null
*/
public function reset()
{
$this->values[self::LOGGROUPLIST] = array();
}
/**
* Returns field descriptors
*
* @return array
*/
public function fields()
{
return self::$fields;
}
/**
* Appends value to 'logGroupList' list
*
* @param \Hdll\Services\Common\ClsLogger\Cls\LogGroup $value Value to append
*
* @return null
*/
public function appendLogGroupList(\Hdll\Services\Common\ClsLogger\Cls\LogGroup $value)
{
return $this->append(self::LOGGROUPLIST, $value);
}
/**
* Clears 'logGroupList' list
*
* @return null
*/
public function clearLogGroupList()
{
return $this->clear(self::LOGGROUPLIST);
}
/**
* Returns 'logGroupList' list
*
* @return \Hdll\Services\Common\ClsLogger\Cls\LogGroup[]
*/
public function getLogGroupList()
{
return $this->get(self::LOGGROUPLIST);
}
/**
* Returns 'logGroupList' iterator
*
* @return \ArrayIterator
*/
public function getLogGroupListIterator()
{
return new \ArrayIterator($this->get(self::LOGGROUPLIST));
}
/**
* Returns element from 'logGroupList' list at given offset
*
* @param int $offset Position in list
*
* @return \Hdll\Services\Common\ClsLogger\Cls\LogGroup
*/
public function getLogGroupListAt($offset)
{
return $this->get(self::LOGGROUPLIST, $offset);
}
/**
* Returns count of 'logGroupList' list
*
* @return int
*/
public function getLogGroupListCount()
{
return $this->count(self::LOGGROUPLIST);
}
}
}
\ No newline at end of file
<?php
/**
* Auto generated from CLS.proto at 2018-09-07 06:03:23
*
* cls package
*/
namespace Hdll\Services\Common\ClsLogger\Cls {
/**
* Content message embedded in Log message
*/
class Log_Content extends \ProtobufMessage
{
/* Field index constants */
const KEY = 1;
const VALUE = 2;
/* @var array Field descriptors */
protected static $fields = array(
self::KEY => array(
'name' => 'key',
'required' => true,
'type' => \ProtobufMessage::PB_TYPE_STRING,
),
self::VALUE => array(
'name' => 'value',
'required' => true,
'type' => \ProtobufMessage::PB_TYPE_STRING,
),
);
/**
* Constructs new message container and clears its internal state
*/
public function __construct()
{
$this->reset();
}
/**
* Clears message values and sets default ones
*
* @return null
*/
public function reset()
{
$this->values[self::KEY] = null;
$this->values[self::VALUE] = null;
}
/**
* Returns field descriptors
*
* @return array
*/
public function fields()
{
return self::$fields;
}
/**
* Sets value of 'key' property
*
* @param string $value Property value
*
* @return null
*/
public function setKey($value)
{
return $this->set(self::KEY, $value);
}
/**
* Returns value of 'key' property
*
* @return string
*/
public function getKey()
{
$value = $this->get(self::KEY);
return $value === null ? (string)$value : $value;
}
/**
* Sets value of 'value' property
*
* @param string $value Property value
*
* @return null
*/
public function setValue($value)
{
return $this->set(self::VALUE, $value);
}
/**
* Returns value of 'value' property
*
* @return string
*/
public function getValue()
{
$value = $this->get(self::VALUE);
return $value === null ? (string)$value : $value;
}
}
}
\ No newline at end of file
<?php
namespace Hdll\Services\Common\ClsLogger;
use Swoft\App;
use Swoole\Coroutine;
use Swoole\Coroutine\MySQL\Exception;
use Swoft\HttpClient\Client;
use Hdll\Services\Common\ClsLogger\Cls\LogGroupList;
use Hdll\Services\Common\ClsLogger\Cls\LogGroup;
use Hdll\Services\Common\ClsLogger\Cls\Log_Content;
use Hdll\Services\Common\ClsLogger\Cls\Log;
class ClsLog
{
const TOPICID_ERROR = '11b19b11-c6b3-45fc-ab1a-7a531558fb57';
const TOPICID_NOTICE = 'b84f9396-d17a-4e61-88a8-11e032755732';
public static function error($msgText, $key = ''){
$key = empty($key) ? APP_NAME : APP_NAME.':'.$key;
$pbData = self::createPbData($key, $msgText);
return self::uploadToCls(self::TOPICID_ERROR, $pbData);
}
public static function notice($msgText, $key = '') {
$key = empty($key) ? APP_NAME : APP_NAME.':'.$key;
$pbData = self::createPbData($key, $msgText);
return self::uploadToCls(self::TOPICID_NOTICE, $pbData);
}
private static function createPbData($key, $value)
{
$logGroupList = new LogGroupList;
$logGroup = new LogGroup;
$log = new Log;
$logContent = new Log_Content;
$logContent->setKey($key);
$logContent->setValue($value);
$log->appendContents($logContent);
$log->setTime(time());
$logGroup->appendLogs($log);
$logGroup->setSource(APP_NAME);
$logGroupList->appendLogGroupList($logGroup);
return $logGroupList->serializeToString();
}
private static function uploadToCls($topicId, $pbData) {
$authorization = ClsSignature::create();
$uri = 'http://ap-beijing.cls.myqcloud.com/structuredlog?topic_id='.$topicId;
$res = (new Client)->post($uri, [
'headers' => [
'Host' => 'ap-beijing.cls.myqcloud.com',
'Authorization' => $authorization,
'Content-Type' => 'application/x-protobuf',
],
'body'=>$pbData,
'timeout' => 20,
]);
if($res->getResponse()->getStatusCode() != 200) {
$msg = '上传腾讯云日志服务失败:'.$res->getResult();
self::writeClsErrors($msg);
return false;
}
return true;
}
/**
* 腾讯日志服务上传时产生错误,这种错误需要记录在本地文件
*
* @return void
*/
private static function writeClsErrors($messageText) {
$filename = 'cls_error.log';
$logFile = \alias('@runtime').'/logs/'.$filename;
if (App::isCoContext()) {
// 协程写
go(function () use ($logFile, $messageText) {
$res = Coroutine::writeFile($logFile, $messageText, FILE_APPEND);
if ($res === false) {
throw new \InvalidArgumentException("Unable to append to log file: {$filename}");
}
});
} else {
$fp = fopen($logFile, 'a');
if ($fp === false) {
throw new \InvalidArgumentException("Unable to append to log file: {$filename}");
}
flock($fp, LOCK_EX);
fwrite($fp, $messageText);
flock($fp, LOCK_UN);
fclose($fp);
}
}
}
<?php
namespace Hdll\Services\Common\ClsLogger;
class ClsSignature
{
public static function create(){
$signTime = (time()-10).';'.(time()+300);
$configs = include dirname(__FILE__, 2).'/Config/config.php';
$sha1edHttpString = sha1("post\n/structuredlog\n\n\n");
$stringToSign = "sha1\n{$signTime}\n{$sha1edHttpString}\n";
$signKey = hash_hmac('sha1', $signTime, $configs['cls']['secretKey']);
$signature = hash_hmac('sha1', $stringToSign, $signKey);
$authorization = 'q-sign-algorithm=sha1&q-ak='.$configs['cls']['secretId']
."&q-sign-time={$signTime}&q-key-time={$signTime}&q-header-list=&q-url-param-list=&q-signature={$signature}";
return $authorization;
}
}
<?php
namespace Hdll\Services\Common\ClsLogger;
use Monolog\Handler\AbstractProcessingHandler;
use Swoft\App;
use Swoole\Coroutine;
/**
* 自定义日志处理器,记录到腾讯云Cls
*
* @uses LogHandler
*/
class LogHandler extends AbstractProcessingHandler
{
/**
* @var array 输出包含日志级别集合
*/
protected $levels = [];
/**
* @var string 对应腾讯CLS的主题ID
*/
protected $topicId;
/**
* 批量输出日志
*
* @param array $records 日志记录集合
*
* @return bool
*/
public function handleBatch(array $records)
{
$records = $this->recordFilter($records);
if (empty($records)) {
return true;
}
$lines = array_column($records, 'formatted');
$this->write($lines);
}
/**
* 输出到腾讯云CLS
*
* @param array $records 日志记录集合
*/
protected function write(array $records)
{
$messageText = implode("<*|||*>", $records);
if($this->topicId == ClsLog::TOPICID_ERROR) {
ClsLog::error($messageText);
} else if($this->topicId == ClsLog::TOPICID_NOTICE) {
ClsLog::notice($messageText);
}
}
/**
* 记录过滤器
*
* @param array $records 日志记录集合
*
* @return array
*/
private function recordFilter(array $records)
{
$messages = [];
foreach ($records as $record) {
if (!isset($record['level'])) {
continue;
}
if (!$this->isHandling($record)) {
continue;
}
$record = $this->processRecord($record);
$record['formatted'] = $this->getFormatter()->format($record);
$messages[] = $record;
}
return $messages;
}
/**
* check是否输出日志
*
* @param array $record
*
* @return bool
*/
public function isHandling(array $record)
{
if (empty($this->levels)) {
return true;
}
return in_array($record['level'], $this->levels);
}
}
......@@ -11,5 +11,10 @@ return [
'alisms' => [
'accessKeyId' => 'EjBn9zQxyEkKHyAA',
'accessKeySecret' => 'AN276rwCcqCkFUVt1GLCbAy8jnj52t',
]
],
'cls' => [
'appid' => '1257143824 ',
'secretId' => 'AKIDseHj18kua0KTSJ4g9SadbVEnEUZVjvPj',
'secretKey' => 'IPL5g5PaaSAzd6NSO8gEmLxcN4pTzJSQ',
],
];
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment