新浪雲 SAE 新增即時日誌查詢介面,可透過 API 篩選、下載即時日誌,極大提升除錯效率。但官方僅發布 Python 版本,PHP 開發者無法直接使用。本文提供完整 PHP 版 SDK 實作。
SAE API 採用 HMAC-SHA256 簽名驗證,請求 Header 必須包含:
x-sae-accesskey:Access Keyx-sae-timestamp:Unix 時間戳Authorization:SAEV1_HMAC_SHA256 base64(hmac_sha256(canonical_string, secret_key))<?php
class SaeApiHandler {
private $accessKey, $secretKey, $timestamp;
public function __construct($key, $sec) {
$this->accessKey = $key;
$this->secretKey = $sec;
$this->timestamp = time();
}
// 魔術方法:支援陣列批次請求與單一請求
public function __call($name, $args) {
$ret = [];
if (is_array($args[0])) {
foreach ($args as $i => $arg) {
$ret[$i] = isset($arg['fop'])
? $this->$name($arg['service'], $arg['date'], $arg['ident'], $arg['fop'])
: $this->$name($arg['service'], $arg['date'], $arg['ident']);
}
} else {
$ret = isset($args[3])
? $this->$name($args[0], $args[1], $args[2], $args[3])
: $this->get($args[0], $args[1], $args[2]);
}
return $ret;
}
// 獲取日誌核心邏輯
private function getLog($service, $date, $ident, $fop = null) {
$uri = "/log/$service/$date/" . $_SERVER['HTTP_APPVERSION'] . "-$ident.log";
if ($fop) $uri .= "?$fop";
$ret = explode(PHP_EOL, $this->get($uri));
array_splice($ret, 0, 7); // 移除前 7 行 Header
array_pop($ret); // 移除最後空行
return $ret;
}
// 底層 HTTP GET 請求
private function get($uri) {
$ch = curl_init("https://g.sae.sina.com.cn$uri");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => $this->saeHeader($uri),
CURLOPT_HEADER => true,
]);
$ret = curl_exec($ch);
curl_close($ch);
return $ret;
}
// 構建 SAE 請求 Header
private function saeHeader($uri) {
return [
'Host: g.sae.sina.com.cn',
'Accept: text/plain',
'x-sae-accesskey: ' . $this->accessKey,
'x-sae-timestamp: ' . $this->timestamp,
'Authorization: ' . $this->getAuthorization($uri),
];
}
// 計算簽名 Authorization
private function getAuthorization($uri) {
$header = [
'x-sae-timestamp' => $this->timestamp,
'x-sae-accesskey' => strtolower($this->accessKey),
];
ksort($header);
$canonical = ['GET', $uri];
foreach ($header as $k => $v) $canonical[] = "$k:$v";
$stringToSign = implode(PHP_EOL, $canonical);
$signature = base64_encode(hash_hmac('sha256', $stringToSign, $this->secretKey, true));
return "SAEV1_HMAC_SHA256 $signature";
}
}
?>
<?php
define('SAE_ACCESSKEY', '你的AccessKey');
define('SAE_SECRETKEY', '你的SecretKey');
$api = new SaeApiHandler(SAE_ACCESSKEY, SAE_SECRETKEY);
// 單一請求
$log = $api->getLog('http', '2015-07-03', 'access', 'head/1/5');
// 批次請求(陣列參數)
$req1 = ['service'=>'http', 'date'=>'2015-07-03', 'ident'=>'access', 'fop'=>'head/1/5'];
$req2 = ['service'=>'http', 'date'=>'2015-07-03', 'ident'=>'error', 'fop'=>'tail/10'];
$logs = $api->getLog($req1, $req2);
var_dump($logs);
?>
| 參數 | 說明 | 範例 |
|---|---|---|
| service | 服務類型 | http / taskqueue / cron / mail / ... |
| date | 日誌日期 | 2015-07-03 |
| ident | 日誌標識 | access / error / notice |
| fop | 過濾操作 | head/1/5 (前5行) / tail/10 (後10行) / grep/keyword |