Skip to content

Commit

Permalink
Merge pull request #60 from qiniu/develop
Browse files Browse the repository at this point in the history
QCOS-0 Release 2.1.0
  • Loading branch information
nowenL authored Dec 26, 2016
2 parents 463918b + baf859c commit 33e79cd
Show file tree
Hide file tree
Showing 6 changed files with 294 additions and 8 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
# vNext

# 2.1.0
- 新增应用平台user权限的接口
- 修改日志搜索返回结果字段及其Tag

# Release 2.0.0
- 新增app授权和撤销授权功能
- Service SCALING 状态拆分为 SCALING-UP SCALING-DOWN
- 日志搜索结果添加CollectedAtNano字段
- 日志搜索结果添加CollectedAtNano字段
- 添加 GetWebProxy 方法

# Release 1.2.0
Expand Down
45 changes: 45 additions & 0 deletions kirksdk/account_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,24 @@ type AccountClient interface {

// GetGrantedAppKey 获取被授权应用的key
GetGrantedAppKey(ctx context.Context, appURI string) (ret GrantedAppKey, err error)

// GetAppspecs 获得应用模板信息
GetAppspecs(ctx context.Context, specURI string) (ret SpecInfo, err error)

// ListPublicspecs 列出公开应用的模板
ListPublicspecs(ctx context.Context) (ret []SpecInfo, err error)

// ListGrantedspecs 列出被授权应用的模板
ListGrantedspecs(ctx context.Context) (ret []SpecInfo, err error)

// GetVendorManagedAppStatus 获得VendorManaged应用运行状态
GetVendorManagedAppStatus(ctx context.Context, appURI string) (ret VendorManagedAppStatus, err error)

// GetVendorManagedAppEntry 获得VendorManaged应用入口地址
GetVendorManagedAppEntry(ctx context.Context, appURI string) (ret VendorManagedAppEntry, err error)

// VendorManagedAppRepair 尝试修复VendorManaged应用
VendorManagedAppRepair(ctx context.Context, appURI string) (err error)
}

// AccountConfig 包含创建 AccountClient 所需的信息
Expand Down Expand Up @@ -205,3 +223,30 @@ type GrantedAppKey struct {
Ak string `json:"ak"`
Sk string `json:"sk"`
}

// SpecInfo 包含 Spec 的相关信息
type SpecInfo struct {
URI string `json:"uri"`
Owner string `json:"owner"`
Title string `json:"title"`
Ver uint32 `json:"ver"`
Verstr string `json:"verstr"`
Desc string `json:"desc,omitempty"`
Brief string `json:"brief"`
Icon string `json:"icon"`
Seedimg string `json:"seedimg"`
Entryport uint16 `json:"entryport"`
Ctime time.Time `json:"ctime"`
Mtime time.Time `json:"mtime"`
}

// VendorManagedAppStatus 包含应用运行状态信息
type VendorManagedAppStatus struct {
Status string `json:"status"`
Details string `json:"details"`
}

// VendorManagedAppEntry 包含应用入口地址
type VendorManagedAppEntry struct {
Entry string `json:"entry"`
}
36 changes: 36 additions & 0 deletions kirksdk/account_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,42 @@ func (p *accountClientImp) GetGrantedAppKey(ctx context.Context, appURI string)
return
}

func (p *accountClientImp) GetAppspecs(ctx context.Context, specURI string) (ret SpecInfo, err error) {
url := fmt.Sprintf("%s%s/appspecs/%s", p.host, appVersionPrefix, specURI)
err = p.client.Call(ctx, &ret, "GET", url)
return
}

func (p *accountClientImp) ListPublicspecs(ctx context.Context) (ret []SpecInfo, err error) {
url := fmt.Sprintf("%s%s/publicspecs", p.host, appVersionPrefix)
err = p.client.Call(ctx, &ret, "GET", url)
return
}

func (p *accountClientImp) ListGrantedspecs(ctx context.Context) (ret []SpecInfo, err error) {
url := fmt.Sprintf("%s%s/grantedspecs", p.host, appVersionPrefix)
err = p.client.Call(ctx, &ret, "GET", url)
return
}

func (p *accountClientImp) GetVendorManagedAppStatus(ctx context.Context, appURI string) (ret VendorManagedAppStatus, err error) {
url := fmt.Sprintf("%s%s/apps/%s/status", p.host, appVersionPrefix, appURI)
err = p.client.Call(ctx, &ret, "PUT", url)
return
}

func (p *accountClientImp) GetVendorManagedAppEntry(ctx context.Context, appURI string) (ret VendorManagedAppEntry, err error) {
url := fmt.Sprintf("%s%s/apps/%s/entry", p.host, appVersionPrefix, appURI)
err = p.client.Call(ctx, &ret, "PUT", url)
return
}

func (p *accountClientImp) VendorManagedAppRepair(ctx context.Context, appURI string) (err error) {
url := fmt.Sprintf("%s%s/apps/%s/repair", p.host, appVersionPrefix, appURI)
err = p.client.Call(ctx, nil, "PUT", url)
return
}

func (p *accountClientImp) GetIndexClient(ctx context.Context) (client IndexClient, err error) {
accountInfo, err := p.GetAccountInfo(ctx)
if err != nil {
Expand Down
176 changes: 176 additions & 0 deletions kirksdk/example/search_container_logs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package example

import (
"fmt"
"io"
"os"
"strings"
"time"

"golang.org/x/net/context"
"qiniupkg.com/kirk/kirksdk"
)

// A simple example of how to use the sdk to search logs, including container logs and access logs.
// In addition, this example shows how to search more than 10,000 logs in a single search.
// Because the logs search api limits the maximum search size as 10,000, so we will use the field
// collectedAtNano to achieve this goal.

func SearchContainerLogsExample() {
client := kirksdk.NewQcosClient(kirksdk.QcosConfig{
AccessKey: "test_fake_ak",
SecretKey: "test_fake_sk",
Host: "test_fake_host",
})

err := SearchContainerLogs(client, "access", "", time.Now().Add(time.Hour*time.Duration(-72)), time.Now(), true, 25000, os.Stdout)
if err != nil {
fmt.Println(err)
}
}

func SearchContainerLogs(client kirksdk.QcosClient, repoType, queryString string, fromTime, toTime time.Time, tail bool, size int, out io.Writer) (err error) {

args := kirksdk.SearchContainerLogsArgs{
RepoType: repoType,
}

var query string
// query is a string template, but not the final query string in SearchContainerLogsArgs
if tail {
query = addClause(query, fmt.Sprintf("collectedAtNano:[%d TO %%d]", fromTime.UnixNano()))
} else {
query = addClause(query, fmt.Sprintf("collectedAtNano:[%%d TO %d]", toTime.UnixNano()))
}

if len(queryString) > 0 {
// we will use fmt.Sprintf to format the query string later,
// so the raw % should be replaced into %% to prevent BADPREC MISSING error from fmt.Sprintf
query = addClause(query, strings.NewReplacer("%", "%%").Replace(queryString))
}

if tail {
args.Sort = "collectedAtNano:desc"
args.Query = fmt.Sprintf(query, toTime.UnixNano())
} else {
args.Sort = "collectedAtNano:asc"
args.Query = fmt.Sprintf(query, fromTime.UnixNano())
}

expectedSize := size
maxSizePerRequest := 10000
if expectedSize > maxSizePerRequest {
args.Size = maxSizePerRequest
} else {
args.Size = expectedSize
}

result, err := client.SearchContainerLogs(context.TODO(), args)
if err != nil {
return err
}

total := result.Total
logs := make([]string, 0)
logs = append(logs, formatLogs(result.Data, repoType)...)

// We cannot get logs more than total.
if total < expectedSize {
expectedSize = total
}

for {
expectedSize -= len(result.Data)
if expectedSize <= 0 {
break
}

if expectedSize > maxSizePerRequest {
args.Size = maxSizePerRequest
} else {
args.Size = expectedSize
}
if tail {
args.Query = fmt.Sprintf(query, result.Data[len(result.Data)-1].CollectedAtNano-1)
} else {
args.Query = fmt.Sprintf(query, result.Data[len(result.Data)-1].CollectedAtNano+1)
}
result, err = client.SearchContainerLogs(context.TODO(), args)
if err != nil {
return err
}
if len(result.Data) <= 0 {
break
}
logs = append(logs, formatLogs(result.Data, repoType)...)
}

count := len(logs)

if err != nil {
fmt.Printf("search container logs err: %s\n", err)
} else {
if tail {
for i := len(logs) - 1; i >= 0; i-- {
fmt.Fprintln(out, logs[i])
}
} else {
for _, log := range logs {
fmt.Fprintln(out, log)
}
}
fmt.Fprintf(out, "\nSummary: %d/%d\n", count, total)
}

return
}

func formatLogs(hits []kirksdk.Hit, repoType string) (logs []string) {
var log string
logs = make([]string, 0)
for _, hit := range hits {
if repoType == "access" {
// access log does not have log field, so we need to format access log by using other fields
log = formatAccessLogField(hit)
} else {
log = hit.Log
}
logs = append(logs, log)
}
return
}

func formatAccessLogField(hit kirksdk.Hit) string {
if hit.Method == "" {
hit.Method = "-"
}
if hit.Url == "" {
hit.Url = "-"
}
if hit.RequestHeader == "" {
hit.RequestHeader = "-"
}
if hit.RequestParams == "" {
hit.RequestParams = "-"
}
if hit.RequestBody == "" {
hit.RequestBody = "-"
}
if hit.ResponseHeader == "" {
hit.ResponseHeader = "-"
}
if hit.ResponseBody == "" {
hit.ResponseBody = "-"
}
return fmt.Sprintf("%s\t%s\t%s\t%s\t%s\t%s\t%d\t%s\t%s\t%gms", hit.StartAt.Format("2006-01-02 15:04:05.000000Z07:00"), hit.Method, hit.Url, hit.RequestHeader, hit.RequestParams, hit.RequestBody, hit.StatusCode, hit.ResponseHeader, hit.ResponseBody, float64(hit.ElapsedNano)/1e6)
}

func addClause(q string, clause string) string {
if q == "" {
return clause
}
if clause == "" {
return q
}
return fmt.Sprintf("%s AND %s", q, clause)
}
2 changes: 1 addition & 1 deletion kirksdk/kirksdk.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package kirksdk

const Version = "2.0.0"
const Version = "2.1.0"
37 changes: 31 additions & 6 deletions kirksdk/qcos_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -752,13 +752,38 @@ type LogsSearchResult struct {
}

type Hit struct {
Log string `json:"log"`
CollectedAt time.Time `json:"collectedAt"`
CollectedAt time.Time `json:"collectedAt" repo:"pod,access"`
CollectedAtNano int64 `json:"collectedAtNano"`
PodIP string `json:"podIp"`
ProcessName string `json:"processName"`
GateID string `json:"gateId"`
Domain string `json:"domain"`
Host string `json:"host"`

Log string `json:"log" repo:"pod"`
Path string `json:"path" repo:"pod"`
Pattern string `json:"pattern" repo:"pod"`
ContainerId string `json:"containerId"`
ContainerName string `json:"containerName"`
JobInstance string `json:"jobInstance" repo:"pod"`
JobTask string `json:"jobTask" repo:"pod"`
PodIp string `json:"podIp" repo:"pod"`
PodName string `json:"podName" repo:"pod"`
PodVer string `json:"podVer"`
ProcessName string `json:"processName"`
Sip string `json:"sip"`
Source string `json:"source" repo:"pod"`

Type string `json:"type" repo:"access"`
RequestApp string `json:"requestApp" repo:"access"`
GateId string `json:"gateId" repo:"access"`
StartAt time.Time `json:"startAt" repo:"access"`
Method string `json:"method" repo:"access"`
Url string `json:"url" repo:"access"`
ReqId string `json:"reqId" repo:"access"`
StatusCode int64 `json:"statusCode" repo:"access"`
ElapsedNano int64 `json:"elapsedNano" repo:"access"`
RequestHeader string `json:"requestHeader" repo:"access"`
RequestParams string `json:"requestParams" repo:"access"`
RequestBody string `json:"requestBody" repo:"access"`
ResponseHeader string `json:"responseHeader" repo:"access"`
ResponseBody string `json:"responseBody" repo:"access"`
}

var (
Expand Down

0 comments on commit 33e79cd

Please sign in to comment.