@@ -54,3 +54,20 @@ func (c *EsConfig) String() string { | |||||
b, _ := json.Marshal(c) | b, _ := json.Marshal(c) | ||||
return bytes.NewBuffer(b).String() | return bytes.NewBuffer(b).String() | ||||
} | } | ||||
type AliLSConfig struct { | |||||
Project string `json:"project"` | |||||
Endpoint string `json:"endpoint"` | |||||
KeyID string `json:"key_id"` | |||||
KeySecret string `json:"key_secret"` | |||||
LogStore string `json:"log_store"` | |||||
Topics []string `json:"topics"` | |||||
Source string `json:"source"` | |||||
Level Level `json:"level"` | |||||
FlushWhen int `json:"flush_when"` | |||||
} | |||||
func (c *AliLSConfig) String() string { | |||||
b, _ := json.Marshal(c) | |||||
return bytes.NewBuffer(b).String() | |||||
} |
@@ -49,4 +49,21 @@ var adatperMapper = map[Adapter]func(l *Logger, level Level) error{ | |||||
return l.SetLogger(logs.AdapterEs, c.String()) | return l.SetLogger(logs.AdapterEs, c.String()) | ||||
}, | }, | ||||
AdapterAliLs: func(l *Logger, level Level) error { | |||||
c := AliLSConfig{ | |||||
Project: "gaore-app-logstore", | |||||
Endpoint: "gaore-app-logstore.cn-shenzhen.log.aliyuncs.com", | |||||
KeyID: "LTAI4GCHwcqtrFD4DHRHxR4k", | |||||
KeySecret: "Ln19xfVYy6OMlJeF9aBvFl4fhRUKBl", | |||||
LogStore: "gaore-app-logstore", | |||||
Topics: nil, | |||||
Source: "", | |||||
Level: level, | |||||
FlushWhen: 0, | |||||
} | |||||
return l.SetLogger(logs.AdapterAliLS, c.String()) | |||||
}, | |||||
} | } |
@@ -1,7 +1,7 @@ | |||||
package grlogs | package grlogs | ||||
import ( | import ( | ||||
"fmt" | |||||
_ "golib.gaore.com/GaoreGo/grlogs/logs/alils" | |||||
_ "golib.gaore.com/GaoreGo/grlogs/logs/es" | _ "golib.gaore.com/GaoreGo/grlogs/logs/es" | ||||
"testing" | "testing" | ||||
"time" | "time" | ||||
@@ -32,6 +32,11 @@ func TestGetLogger(t *testing.T) { | |||||
Get("wifi").Critical("neoweiwoewe") | Get("wifi").Critical("neoweiwoewe") | ||||
} | } | ||||
func TestGetEs(t *testing.T) { | |||||
fmt.Println("hello world") | |||||
func TestGetAliLs(t *testing.T) { | |||||
l := Get("es").SetAdapter(LevelAll, AdapterAliLs) | |||||
l.Info("endport") | |||||
l.Info("endport") | |||||
l.Info("endport") | |||||
l.Info("endport") | |||||
time.Sleep(time.Millisecond * 500) | |||||
} | } |
@@ -2,23 +2,22 @@ package alils | |||||
import ( | import ( | ||||
"encoding/json" | "encoding/json" | ||||
"strings" | |||||
"sync" | |||||
"time" | |||||
"github.com/gogo/protobuf/proto" | |||||
"fmt" | |||||
"github.com/aliyun/aliyun-log-go-sdk/producer" | |||||
"golib.gaore.com/GaoreGo/grlogs/logs" | "golib.gaore.com/GaoreGo/grlogs/logs" | ||||
"time" | |||||
) | ) | ||||
const ( | |||||
// CacheSize set the flush size | |||||
CacheSize int = 64 | |||||
// Delimiter define the topic delimiter | |||||
Delimiter string = "##" | |||||
) | |||||
func NewAliLS() logs.Logger { | |||||
cw := &alilsLogger{ | |||||
Level: logs.LevelDebug, | |||||
} | |||||
return cw | |||||
} | |||||
// Config is the Config for Ali Log | |||||
type Config struct { | |||||
type alilsLogger struct { | |||||
producer *producer.Producer | |||||
callback *Callback | |||||
Project string `json:"project"` | Project string `json:"project"` | ||||
Endpoint string `json:"endpoint"` | Endpoint string `json:"endpoint"` | ||||
KeyID string `json:"key_id"` | KeyID string `json:"key_id"` | ||||
@@ -30,155 +29,49 @@ type Config struct { | |||||
FlushWhen int `json:"flush_when"` | FlushWhen int `json:"flush_when"` | ||||
} | } | ||||
// aliLSWriter implements LoggerInterface. | |||||
// it writes messages in keep-live tcp connection. | |||||
type aliLSWriter struct { | |||||
store *LogStore | |||||
group []*LogGroup | |||||
withMap bool | |||||
groupMap map[string]*LogGroup | |||||
lock *sync.Mutex | |||||
Config | |||||
} | |||||
// NewAliLS create a new Logger | |||||
func NewAliLS() logs.Logger { | |||||
alils := new(aliLSWriter) | |||||
alils.Level = logs.LevelTrace | |||||
return alils | |||||
} | |||||
// Init parse config and init struct | |||||
func (c *aliLSWriter) Init(jsonConfig string) (err error) { | |||||
func (a *alilsLogger) Init(jsonconfig string) error { | |||||
json.Unmarshal([]byte(jsonConfig), c) | |||||
if c.FlushWhen > CacheSize { | |||||
c.FlushWhen = CacheSize | |||||
} | |||||
prj := &LogProject{ | |||||
Name: c.Project, | |||||
Endpoint: c.Endpoint, | |||||
AccessKeyID: c.KeyID, | |||||
AccessKeySecret: c.KeySecret, | |||||
} | |||||
c.store, err = prj.GetLogStore(c.LogStore) | |||||
err := json.Unmarshal([]byte(jsonconfig), a) | |||||
if err != nil { | if err != nil { | ||||
return err | return err | ||||
} | } | ||||
// Create default Log Group | |||||
c.group = append(c.group, &LogGroup{ | |||||
Topic: proto.String(""), | |||||
Source: proto.String(c.Source), | |||||
Logs: make([]*Log, 0, c.FlushWhen), | |||||
}) | |||||
// Create other Log Group | |||||
c.groupMap = make(map[string]*LogGroup) | |||||
for _, topic := range c.Topics { | |||||
lg := &LogGroup{ | |||||
Topic: proto.String(topic), | |||||
Source: proto.String(c.Source), | |||||
Logs: make([]*Log, 0, c.FlushWhen), | |||||
} | |||||
c.group = append(c.group, lg) | |||||
c.groupMap[topic] = lg | |||||
} | |||||
if len(c.group) == 1 { | |||||
c.withMap = false | |||||
} else { | |||||
c.withMap = true | |||||
} | |||||
c.lock = &sync.Mutex{} | |||||
producerConfig := producer.GetDefaultProducerConfig() | |||||
producerConfig.Endpoint = a.Endpoint | |||||
producerConfig.AccessKeyID = a.KeyID | |||||
producerConfig.AccessKeySecret = a.KeySecret | |||||
producerConfig.LingerMs = 100 | |||||
a.producer = producer.InitProducer(producerConfig) | |||||
a.callback = &Callback{} | |||||
a.producer.Start() | |||||
return nil | return nil | ||||
} | } | ||||
// WriteMsg write message in connection. | |||||
// if connection is down, try to re-connect. | |||||
func (c *aliLSWriter) WriteMsg(when time.Time, msg string, level int, lable string, env string) (err error) { | |||||
if level > c.Level { | |||||
return nil | |||||
} | |||||
var topic string | |||||
var content string | |||||
var lg *LogGroup | |||||
if c.withMap { | |||||
// Topic,LogGroup | |||||
strs := strings.SplitN(msg, Delimiter, 2) | |||||
if len(strs) == 2 { | |||||
pos := strings.LastIndex(strs[0], " ") | |||||
topic = strs[0][pos+1 : len(strs[0])] | |||||
content = strs[0][0:pos] + strs[1] | |||||
lg = c.groupMap[topic] | |||||
} | |||||
// send to empty Topic | |||||
if lg == nil { | |||||
content = msg | |||||
lg = c.group[0] | |||||
} | |||||
} else { | |||||
content = msg | |||||
lg = c.group[0] | |||||
} | |||||
c1 := &LogContent{ | |||||
Key: proto.String("msg"), | |||||
Value: proto.String(content), | |||||
} | |||||
l := &Log{ | |||||
Time: proto.Uint32(uint32(when.Unix())), | |||||
Contents: []*LogContent{ | |||||
c1, | |||||
}, | |||||
} | |||||
c.lock.Lock() | |||||
lg.Logs = append(lg.Logs, l) | |||||
c.lock.Unlock() | |||||
if len(lg.Logs) >= c.FlushWhen { | |||||
c.flush(lg) | |||||
} | |||||
return nil | |||||
func (a *alilsLogger) WriteMsg(when time.Time, msg string, level int, lable string, env string) error { | |||||
vals := map[string]string{"msg": msg, "level": fmt.Sprintf("%d", level)} | |||||
vals["level_string"] = logs.GetLevelString(level) | |||||
vals["env"] = env | |||||
vals["lable"] = lable | |||||
vals["hostname"] = GetHostname() | |||||
vals["working_idr"] = Getwd() | |||||
vals["home_dir"] = GetUserHomename() | |||||
vals["hardware_addr"] = GetCurrentInterfaceHardwareAddr() | |||||
vals["client_addrs"] = GetCurrentInterfaceAddrs() | |||||
log := producer.GenerateLog(uint32(when.Unix()), vals) | |||||
err := a.producer.SendLog(a.Project, a.LogStore, "topic", "127.0.0.1", log) | |||||
return err | |||||
} | } | ||||
// Flush implementing method. empty. | |||||
func (c *aliLSWriter) Flush() { | |||||
// flush all group | |||||
for _, lg := range c.group { | |||||
c.flush(lg) | |||||
} | |||||
func (a *alilsLogger) Destroy() { | |||||
a.producer.Close(60) | |||||
a.producer.SafeClose() | |||||
} | } | ||||
// Destroy destroy connection writer and close tcp listener. | |||||
func (c *aliLSWriter) Destroy() { | |||||
} | |||||
func (c *aliLSWriter) flush(lg *LogGroup) { | |||||
c.lock.Lock() | |||||
defer c.lock.Unlock() | |||||
err := c.store.PutLogs(lg) | |||||
if err != nil { | |||||
return | |||||
} | |||||
func (a *alilsLogger) Flush() { | |||||
lg.Logs = make([]*Log, 0, c.FlushWhen) | |||||
} | } | ||||
func init() { | func init() { | ||||
@@ -0,0 +1,25 @@ | |||||
package alils | |||||
import ( | |||||
"fmt" | |||||
"github.com/aliyun/aliyun-log-go-sdk/producer" | |||||
) | |||||
type Callback struct { | |||||
} | |||||
func (callback *Callback) Success(result *producer.Result) { | |||||
attemptList := result.GetReservedAttempts() | |||||
for _, attempt := range attemptList { | |||||
fmt.Printf("%+v \n", attempt) | |||||
} | |||||
} | |||||
func (callback *Callback) Fail(result *producer.Result) { | |||||
fmt.Println(result.IsSuccessful()) | |||||
fmt.Println(result.GetErrorCode()) | |||||
fmt.Println(result.GetErrorMessage()) | |||||
fmt.Println(result.GetReservedAttempts()) | |||||
fmt.Println(result.GetRequestId()) | |||||
fmt.Println(result.GetTimeStampMs()) | |||||
} |
@@ -1,13 +0,0 @@ | |||||
package alils | |||||
const ( | |||||
version = "0.5.0" // SDK version | |||||
signatureMethod = "hmac-sha1" // Signature method | |||||
// OffsetNewest stands for the log head offset, i.e. the offset that will be | |||||
// assigned to the next message that will be produced to the shard. | |||||
OffsetNewest = "end" | |||||
// OffsetOldest stands for the oldest offset available on the logstore for a | |||||
// shard. | |||||
OffsetOldest = "begin" | |||||
) |
@@ -1,42 +0,0 @@ | |||||
package alils | |||||
// InputDetail define log detail | |||||
type InputDetail struct { | |||||
LogType string `json:"logType"` | |||||
LogPath string `json:"logPath"` | |||||
FilePattern string `json:"filePattern"` | |||||
LocalStorage bool `json:"localStorage"` | |||||
TimeFormat string `json:"timeFormat"` | |||||
LogBeginRegex string `json:"logBeginRegex"` | |||||
Regex string `json:"regex"` | |||||
Keys []string `json:"key"` | |||||
FilterKeys []string `json:"filterKey"` | |||||
FilterRegex []string `json:"filterRegex"` | |||||
TopicFormat string `json:"topicFormat"` | |||||
} | |||||
// OutputDetail define the output detail | |||||
type OutputDetail struct { | |||||
Endpoint string `json:"endpoint"` | |||||
LogStoreName string `json:"logstoreName"` | |||||
} | |||||
// LogConfig define Log Config | |||||
type LogConfig struct { | |||||
Name string `json:"configName"` | |||||
InputType string `json:"inputType"` | |||||
InputDetail InputDetail `json:"inputDetail"` | |||||
OutputType string `json:"outputType"` | |||||
OutputDetail OutputDetail `json:"outputDetail"` | |||||
CreateTime uint32 | |||||
LastModifyTime uint32 | |||||
project *LogProject | |||||
} | |||||
// GetAppliedMachineGroup returns applied machine group of this config. | |||||
func (c *LogConfig) GetAppliedMachineGroup(confName string) (groupNames []string, err error) { | |||||
groupNames, err = c.project.GetAppliedMachineGroups(c.Name) | |||||
return | |||||
} |
@@ -1,819 +0,0 @@ | |||||
/* | |||||
Package alils implements the SDK(v0.5.0) of Simple Log Service(abbr. SLS). | |||||
For more description about SLS, please read this article: | |||||
http://gitlab.alibaba-inc.com/sls/doc. | |||||
*/ | |||||
package alils | |||||
import ( | |||||
"encoding/json" | |||||
"fmt" | |||||
"io/ioutil" | |||||
"net/http" | |||||
"net/http/httputil" | |||||
) | |||||
// Error message in SLS HTTP response. | |||||
type errorMessage struct { | |||||
Code string `json:"errorCode"` | |||||
Message string `json:"errorMessage"` | |||||
} | |||||
// LogProject Define the Ali Project detail | |||||
type LogProject struct { | |||||
Name string // Project name | |||||
Endpoint string // IP or hostname of SLS endpoint | |||||
AccessKeyID string | |||||
AccessKeySecret string | |||||
} | |||||
// NewLogProject creates a new SLS project. | |||||
func NewLogProject(name, endpoint, AccessKeyID, accessKeySecret string) (p *LogProject, err error) { | |||||
p = &LogProject{ | |||||
Name: name, | |||||
Endpoint: endpoint, | |||||
AccessKeyID: AccessKeyID, | |||||
AccessKeySecret: accessKeySecret, | |||||
} | |||||
return p, nil | |||||
} | |||||
// ListLogStore returns all logstore names of project p. | |||||
func (p *LogProject) ListLogStore() (storeNames []string, err error) { | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": "0", | |||||
} | |||||
uri := fmt.Sprintf("/logstores") | |||||
r, err := request(p, "GET", uri, h, nil) | |||||
if err != nil { | |||||
return | |||||
} | |||||
buf, err := ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(buf, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to list logstore") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Printf("%s\n", dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
type Body struct { | |||||
Count int | |||||
LogStores []string | |||||
} | |||||
body := &Body{} | |||||
err = json.Unmarshal(buf, body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
storeNames = body.LogStores | |||||
return | |||||
} | |||||
// GetLogStore returns logstore according by logstore name. | |||||
func (p *LogProject) GetLogStore(name string) (s *LogStore, err error) { | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": "0", | |||||
} | |||||
r, err := request(p, "GET", "/logstores/"+name, h, nil) | |||||
if err != nil { | |||||
return | |||||
} | |||||
buf, err := ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(buf, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to get logstore") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Printf("%s\n", dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
s = &LogStore{} | |||||
err = json.Unmarshal(buf, s) | |||||
if err != nil { | |||||
return | |||||
} | |||||
s.project = p | |||||
return | |||||
} | |||||
// CreateLogStore creates a new logstore in SLS, | |||||
// where name is logstore name, | |||||
// and ttl is time-to-live(in day) of logs, | |||||
// and shardCnt is the number of shards. | |||||
func (p *LogProject) CreateLogStore(name string, ttl, shardCnt int) (err error) { | |||||
type Body struct { | |||||
Name string `json:"logstoreName"` | |||||
TTL int `json:"ttl"` | |||||
ShardCount int `json:"shardCount"` | |||||
} | |||||
store := &Body{ | |||||
Name: name, | |||||
TTL: ttl, | |||||
ShardCount: shardCnt, | |||||
} | |||||
body, err := json.Marshal(store) | |||||
if err != nil { | |||||
return | |||||
} | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)), | |||||
"Content-Type": "application/json", | |||||
"Accept-Encoding": "deflate", // TODO: support lz4 | |||||
} | |||||
r, err := request(p, "POST", "/logstores", h, body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
body, err = ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(body, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to create logstore") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Printf("%s\n", dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
return | |||||
} | |||||
// DeleteLogStore deletes a logstore according by logstore name. | |||||
func (p *LogProject) DeleteLogStore(name string) (err error) { | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": "0", | |||||
} | |||||
r, err := request(p, "DELETE", "/logstores/"+name, h, nil) | |||||
if err != nil { | |||||
return | |||||
} | |||||
body, err := ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(body, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to delete logstore") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Printf("%s\n", dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
return | |||||
} | |||||
// UpdateLogStore updates a logstore according by logstore name, | |||||
// obviously we can't modify the logstore name itself. | |||||
func (p *LogProject) UpdateLogStore(name string, ttl, shardCnt int) (err error) { | |||||
type Body struct { | |||||
Name string `json:"logstoreName"` | |||||
TTL int `json:"ttl"` | |||||
ShardCount int `json:"shardCount"` | |||||
} | |||||
store := &Body{ | |||||
Name: name, | |||||
TTL: ttl, | |||||
ShardCount: shardCnt, | |||||
} | |||||
body, err := json.Marshal(store) | |||||
if err != nil { | |||||
return | |||||
} | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)), | |||||
"Content-Type": "application/json", | |||||
"Accept-Encoding": "deflate", // TODO: support lz4 | |||||
} | |||||
r, err := request(p, "PUT", "/logstores", h, body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
body, err = ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(body, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to update logstore") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Printf("%s\n", dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
return | |||||
} | |||||
// ListMachineGroup returns machine group name list and the total number of machine groups. | |||||
// The offset starts from 0 and the size is the max number of machine groups could be returned. | |||||
func (p *LogProject) ListMachineGroup(offset, size int) (m []string, total int, err error) { | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": "0", | |||||
} | |||||
if size <= 0 { | |||||
size = 500 | |||||
} | |||||
uri := fmt.Sprintf("/machinegroups?offset=%v&size=%v", offset, size) | |||||
r, err := request(p, "GET", uri, h, nil) | |||||
if err != nil { | |||||
return | |||||
} | |||||
buf, err := ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(buf, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to list machine group") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Printf("%s\n", dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
type Body struct { | |||||
MachineGroups []string | |||||
Count int | |||||
Total int | |||||
} | |||||
body := &Body{} | |||||
err = json.Unmarshal(buf, body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
m = body.MachineGroups | |||||
total = body.Total | |||||
return | |||||
} | |||||
// GetMachineGroup retruns machine group according by machine group name. | |||||
func (p *LogProject) GetMachineGroup(name string) (m *MachineGroup, err error) { | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": "0", | |||||
} | |||||
r, err := request(p, "GET", "/machinegroups/"+name, h, nil) | |||||
if err != nil { | |||||
return | |||||
} | |||||
buf, err := ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(buf, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to get machine group:%v", name) | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Printf("%s\n", dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
m = &MachineGroup{} | |||||
err = json.Unmarshal(buf, m) | |||||
if err != nil { | |||||
return | |||||
} | |||||
m.project = p | |||||
return | |||||
} | |||||
// CreateMachineGroup creates a new machine group in SLS. | |||||
func (p *LogProject) CreateMachineGroup(m *MachineGroup) (err error) { | |||||
body, err := json.Marshal(m) | |||||
if err != nil { | |||||
return | |||||
} | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)), | |||||
"Content-Type": "application/json", | |||||
"Accept-Encoding": "deflate", // TODO: support lz4 | |||||
} | |||||
r, err := request(p, "POST", "/machinegroups", h, body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
body, err = ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(body, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to create machine group") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Printf("%s\n", dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
return | |||||
} | |||||
// UpdateMachineGroup updates a machine group. | |||||
func (p *LogProject) UpdateMachineGroup(m *MachineGroup) (err error) { | |||||
body, err := json.Marshal(m) | |||||
if err != nil { | |||||
return | |||||
} | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)), | |||||
"Content-Type": "application/json", | |||||
"Accept-Encoding": "deflate", // TODO: support lz4 | |||||
} | |||||
r, err := request(p, "PUT", "/machinegroups/"+m.Name, h, body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
body, err = ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(body, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to update machine group") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Printf("%s\n", dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
return | |||||
} | |||||
// DeleteMachineGroup deletes machine group according machine group name. | |||||
func (p *LogProject) DeleteMachineGroup(name string) (err error) { | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": "0", | |||||
} | |||||
r, err := request(p, "DELETE", "/machinegroups/"+name, h, nil) | |||||
if err != nil { | |||||
return | |||||
} | |||||
body, err := ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(body, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to delete machine group") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Printf("%s\n", dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
return | |||||
} | |||||
// ListConfig returns config names list and the total number of configs. | |||||
// The offset starts from 0 and the size is the max number of configs could be returned. | |||||
func (p *LogProject) ListConfig(offset, size int) (cfgNames []string, total int, err error) { | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": "0", | |||||
} | |||||
if size <= 0 { | |||||
size = 100 | |||||
} | |||||
uri := fmt.Sprintf("/configs?offset=%v&size=%v", offset, size) | |||||
r, err := request(p, "GET", uri, h, nil) | |||||
if err != nil { | |||||
return | |||||
} | |||||
buf, err := ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(buf, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to delete machine group") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Printf("%s\n", dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
type Body struct { | |||||
Total int | |||||
Configs []string | |||||
} | |||||
body := &Body{} | |||||
err = json.Unmarshal(buf, body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
cfgNames = body.Configs | |||||
total = body.Total | |||||
return | |||||
} | |||||
// GetConfig returns config according by config name. | |||||
func (p *LogProject) GetConfig(name string) (c *LogConfig, err error) { | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": "0", | |||||
} | |||||
r, err := request(p, "GET", "/configs/"+name, h, nil) | |||||
if err != nil { | |||||
return | |||||
} | |||||
buf, err := ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(buf, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to delete config") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Printf("%s\n", dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
c = &LogConfig{} | |||||
err = json.Unmarshal(buf, c) | |||||
if err != nil { | |||||
return | |||||
} | |||||
c.project = p | |||||
return | |||||
} | |||||
// UpdateConfig updates a config. | |||||
func (p *LogProject) UpdateConfig(c *LogConfig) (err error) { | |||||
body, err := json.Marshal(c) | |||||
if err != nil { | |||||
return | |||||
} | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)), | |||||
"Content-Type": "application/json", | |||||
"Accept-Encoding": "deflate", // TODO: support lz4 | |||||
} | |||||
r, err := request(p, "PUT", "/configs/"+c.Name, h, body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
body, err = ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(body, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to update config") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Printf("%s\n", dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
return | |||||
} | |||||
// CreateConfig creates a new config in SLS. | |||||
func (p *LogProject) CreateConfig(c *LogConfig) (err error) { | |||||
body, err := json.Marshal(c) | |||||
if err != nil { | |||||
return | |||||
} | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)), | |||||
"Content-Type": "application/json", | |||||
"Accept-Encoding": "deflate", // TODO: support lz4 | |||||
} | |||||
r, err := request(p, "POST", "/configs", h, body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
body, err = ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(body, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to update config") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Printf("%s\n", dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
return | |||||
} | |||||
// DeleteConfig deletes a config according by config name. | |||||
func (p *LogProject) DeleteConfig(name string) (err error) { | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": "0", | |||||
} | |||||
r, err := request(p, "DELETE", "/configs/"+name, h, nil) | |||||
if err != nil { | |||||
return | |||||
} | |||||
body, err := ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(body, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to delete config") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Printf("%s\n", dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
return | |||||
} | |||||
// GetAppliedMachineGroups returns applied machine group names list according config name. | |||||
func (p *LogProject) GetAppliedMachineGroups(confName string) (groupNames []string, err error) { | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": "0", | |||||
} | |||||
uri := fmt.Sprintf("/configs/%v/machinegroups", confName) | |||||
r, err := request(p, "GET", uri, h, nil) | |||||
if err != nil { | |||||
return | |||||
} | |||||
buf, err := ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(buf, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to get applied machine groups") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Printf("%s\n", dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
type Body struct { | |||||
Count int | |||||
Machinegroups []string | |||||
} | |||||
body := &Body{} | |||||
err = json.Unmarshal(buf, body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
groupNames = body.Machinegroups | |||||
return | |||||
} | |||||
// GetAppliedConfigs returns applied config names list according machine group name groupName. | |||||
func (p *LogProject) GetAppliedConfigs(groupName string) (confNames []string, err error) { | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": "0", | |||||
} | |||||
uri := fmt.Sprintf("/machinegroups/%v/configs", groupName) | |||||
r, err := request(p, "GET", uri, h, nil) | |||||
if err != nil { | |||||
return | |||||
} | |||||
buf, err := ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(buf, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to applied configs") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Printf("%s\n", dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
type Cfg struct { | |||||
Count int `json:"count"` | |||||
Configs []string `json:"configs"` | |||||
} | |||||
body := &Cfg{} | |||||
err = json.Unmarshal(buf, body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
confNames = body.Configs | |||||
return | |||||
} | |||||
// ApplyConfigToMachineGroup applies config to machine group. | |||||
func (p *LogProject) ApplyConfigToMachineGroup(confName, groupName string) (err error) { | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": "0", | |||||
} | |||||
uri := fmt.Sprintf("/machinegroups/%v/configs/%v", groupName, confName) | |||||
r, err := request(p, "PUT", uri, h, nil) | |||||
if err != nil { | |||||
return | |||||
} | |||||
buf, err := ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(buf, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to apply config to machine group") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Printf("%s\n", dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
return | |||||
} | |||||
// RemoveConfigFromMachineGroup removes config from machine group. | |||||
func (p *LogProject) RemoveConfigFromMachineGroup(confName, groupName string) (err error) { | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": "0", | |||||
} | |||||
uri := fmt.Sprintf("/machinegroups/%v/configs/%v", groupName, confName) | |||||
r, err := request(p, "DELETE", uri, h, nil) | |||||
if err != nil { | |||||
return | |||||
} | |||||
buf, err := ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(buf, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to remove config from machine group") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Printf("%s\n", dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
return | |||||
} |
@@ -1,271 +0,0 @@ | |||||
package alils | |||||
import ( | |||||
"encoding/json" | |||||
"fmt" | |||||
"io/ioutil" | |||||
"net/http" | |||||
"net/http/httputil" | |||||
"strconv" | |||||
lz4 "github.com/cloudflare/golz4" | |||||
"github.com/gogo/protobuf/proto" | |||||
) | |||||
// LogStore Store the logs | |||||
type LogStore struct { | |||||
Name string `json:"logstoreName"` | |||||
TTL int | |||||
ShardCount int | |||||
CreateTime uint32 | |||||
LastModifyTime uint32 | |||||
project *LogProject | |||||
} | |||||
// Shard define the Log Shard | |||||
type Shard struct { | |||||
ShardID int `json:"shardID"` | |||||
} | |||||
// ListShards returns shard id list of this logstore. | |||||
func (s *LogStore) ListShards() (shardIDs []int, err error) { | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": "0", | |||||
} | |||||
uri := fmt.Sprintf("/logstores/%v/shards", s.Name) | |||||
r, err := request(s.project, "GET", uri, h, nil) | |||||
if err != nil { | |||||
return | |||||
} | |||||
buf, err := ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(buf, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to list logstore") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Println(dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
var shards []*Shard | |||||
err = json.Unmarshal(buf, &shards) | |||||
if err != nil { | |||||
return | |||||
} | |||||
for _, v := range shards { | |||||
shardIDs = append(shardIDs, v.ShardID) | |||||
} | |||||
return | |||||
} | |||||
// PutLogs put logs into logstore. | |||||
// The callers should transform user logs into LogGroup. | |||||
func (s *LogStore) PutLogs(lg *LogGroup) (err error) { | |||||
body, err := proto.Marshal(lg) | |||||
if err != nil { | |||||
return | |||||
} | |||||
// Compresse body with lz4 | |||||
out := make([]byte, lz4.CompressBound(body)) | |||||
n, err := lz4.Compress(body, out) | |||||
if err != nil { | |||||
return | |||||
} | |||||
h := map[string]string{ | |||||
"x-sls-compresstype": "lz4", | |||||
"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)), | |||||
"Content-Type": "application/x-protobuf", | |||||
} | |||||
uri := fmt.Sprintf("/logstores/%v", s.Name) | |||||
r, err := request(s.project, "POST", uri, h, out[:n]) | |||||
if err != nil { | |||||
return | |||||
} | |||||
buf, err := ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(buf, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to put logs") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Println(dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
return | |||||
} | |||||
// GetCursor gets log cursor of one shard specified by shardID. | |||||
// The from can be in three form: a) unix timestamp in seccond, b) "begin", c) "end". | |||||
// For more detail please read: http://gitlab.alibaba-inc.com/sls/doc/blob/master/api/shard.md#logstore | |||||
func (s *LogStore) GetCursor(shardID int, from string) (cursor string, err error) { | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": "0", | |||||
} | |||||
uri := fmt.Sprintf("/logstores/%v/shards/%v?type=cursor&from=%v", | |||||
s.Name, shardID, from) | |||||
r, err := request(s.project, "GET", uri, h, nil) | |||||
if err != nil { | |||||
return | |||||
} | |||||
buf, err := ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(buf, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to get cursor") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Println(dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
type Body struct { | |||||
Cursor string | |||||
} | |||||
body := &Body{} | |||||
err = json.Unmarshal(buf, body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
cursor = body.Cursor | |||||
return | |||||
} | |||||
// GetLogsBytes gets logs binary data from shard specified by shardID according cursor. | |||||
// The logGroupMaxCount is the max number of logGroup could be returned. | |||||
// The nextCursor is the next curosr can be used to read logs at next time. | |||||
func (s *LogStore) GetLogsBytes(shardID int, cursor string, | |||||
logGroupMaxCount int) (out []byte, nextCursor string, err error) { | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": "0", | |||||
"Accept": "application/x-protobuf", | |||||
"Accept-Encoding": "lz4", | |||||
} | |||||
uri := fmt.Sprintf("/logstores/%v/shards/%v?type=logs&cursor=%v&count=%v", | |||||
s.Name, shardID, cursor, logGroupMaxCount) | |||||
r, err := request(s.project, "GET", uri, h, nil) | |||||
if err != nil { | |||||
return | |||||
} | |||||
buf, err := ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(buf, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to get cursor") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Println(dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
v, ok := r.Header["X-Sls-Compresstype"] | |||||
if !ok || len(v) == 0 { | |||||
err = fmt.Errorf("can't find 'x-sls-compresstype' header") | |||||
return | |||||
} | |||||
if v[0] != "lz4" { | |||||
err = fmt.Errorf("unexpected compress type:%v", v[0]) | |||||
return | |||||
} | |||||
v, ok = r.Header["X-Sls-Cursor"] | |||||
if !ok || len(v) == 0 { | |||||
err = fmt.Errorf("can't find 'x-sls-cursor' header") | |||||
return | |||||
} | |||||
nextCursor = v[0] | |||||
v, ok = r.Header["X-Sls-Bodyrawsize"] | |||||
if !ok || len(v) == 0 { | |||||
err = fmt.Errorf("can't find 'x-sls-bodyrawsize' header") | |||||
return | |||||
} | |||||
bodyRawSize, err := strconv.Atoi(v[0]) | |||||
if err != nil { | |||||
return | |||||
} | |||||
out = make([]byte, bodyRawSize) | |||||
err = lz4.Uncompress(buf, out) | |||||
if err != nil { | |||||
return | |||||
} | |||||
return | |||||
} | |||||
// LogsBytesDecode decodes logs binary data retruned by GetLogsBytes API | |||||
func LogsBytesDecode(data []byte) (gl *LogGroupList, err error) { | |||||
gl = &LogGroupList{} | |||||
err = proto.Unmarshal(data, gl) | |||||
if err != nil { | |||||
return | |||||
} | |||||
return | |||||
} | |||||
// GetLogs gets logs from shard specified by shardID according cursor. | |||||
// The logGroupMaxCount is the max number of logGroup could be returned. | |||||
// The nextCursor is the next curosr can be used to read logs at next time. | |||||
func (s *LogStore) GetLogs(shardID int, cursor string, | |||||
logGroupMaxCount int) (gl *LogGroupList, nextCursor string, err error) { | |||||
out, nextCursor, err := s.GetLogsBytes(shardID, cursor, logGroupMaxCount) | |||||
if err != nil { | |||||
return | |||||
} | |||||
gl, err = LogsBytesDecode(out) | |||||
if err != nil { | |||||
return | |||||
} | |||||
return | |||||
} |
@@ -1,91 +0,0 @@ | |||||
package alils | |||||
import ( | |||||
"encoding/json" | |||||
"fmt" | |||||
"io/ioutil" | |||||
"net/http" | |||||
"net/http/httputil" | |||||
) | |||||
// MachineGroupAttribute define the Attribute | |||||
type MachineGroupAttribute struct { | |||||
ExternalName string `json:"externalName"` | |||||
TopicName string `json:"groupTopic"` | |||||
} | |||||
// MachineGroup define the machine Group | |||||
type MachineGroup struct { | |||||
Name string `json:"groupName"` | |||||
Type string `json:"groupType"` | |||||
MachineIDType string `json:"machineIdentifyType"` | |||||
MachineIDList []string `json:"machineList"` | |||||
Attribute MachineGroupAttribute `json:"groupAttribute"` | |||||
CreateTime uint32 | |||||
LastModifyTime uint32 | |||||
project *LogProject | |||||
} | |||||
// Machine define the Machine | |||||
type Machine struct { | |||||
IP string | |||||
UniqueID string `json:"machine-uniqueid"` | |||||
UserdefinedID string `json:"userdefined-id"` | |||||
} | |||||
// MachineList define the Machine List | |||||
type MachineList struct { | |||||
Total int | |||||
Machines []*Machine | |||||
} | |||||
// ListMachines returns machine list of this machine group. | |||||
func (m *MachineGroup) ListMachines() (ms []*Machine, total int, err error) { | |||||
h := map[string]string{ | |||||
"x-sls-bodyrawsize": "0", | |||||
} | |||||
uri := fmt.Sprintf("/machinegroups/%v/machines", m.Name) | |||||
r, err := request(m.project, "GET", uri, h, nil) | |||||
if err != nil { | |||||
return | |||||
} | |||||
buf, err := ioutil.ReadAll(r.Body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if r.StatusCode != http.StatusOK { | |||||
errMsg := &errorMessage{} | |||||
err = json.Unmarshal(buf, errMsg) | |||||
if err != nil { | |||||
err = fmt.Errorf("failed to remove config from machine group") | |||||
dump, _ := httputil.DumpResponse(r, true) | |||||
fmt.Println(dump) | |||||
return | |||||
} | |||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message) | |||||
return | |||||
} | |||||
body := &MachineList{} | |||||
err = json.Unmarshal(buf, body) | |||||
if err != nil { | |||||
return | |||||
} | |||||
ms = body.Machines | |||||
total = body.Total | |||||
return | |||||
} | |||||
// GetAppliedConfigs returns applied configs of this machine group. | |||||
func (m *MachineGroup) GetAppliedConfigs() (confNames []string, err error) { | |||||
confNames, err = m.project.GetAppliedConfigs(m.Name) | |||||
return | |||||
} |
@@ -1,62 +0,0 @@ | |||||
package alils | |||||
import ( | |||||
"bytes" | |||||
"crypto/md5" | |||||
"fmt" | |||||
"net/http" | |||||
) | |||||
// request sends a request to SLS. | |||||
func request(project *LogProject, method, uri string, headers map[string]string, | |||||
body []byte) (resp *http.Response, err error) { | |||||
// The caller should provide 'x-sls-bodyrawsize' header | |||||
if _, ok := headers["x-sls-bodyrawsize"]; !ok { | |||||
err = fmt.Errorf("Can't find 'x-sls-bodyrawsize' header") | |||||
return | |||||
} | |||||
// SLS public request headers | |||||
headers["Host"] = project.Name + "." + project.Endpoint | |||||
headers["Date"] = nowRFC1123() | |||||
headers["x-sls-apiversion"] = version | |||||
headers["x-sls-signaturemethod"] = signatureMethod | |||||
if body != nil { | |||||
bodyMD5 := fmt.Sprintf("%X", md5.Sum(body)) | |||||
headers["Content-MD5"] = bodyMD5 | |||||
if _, ok := headers["Content-Type"]; !ok { | |||||
err = fmt.Errorf("Can't find 'Content-Type' header") | |||||
return | |||||
} | |||||
} | |||||
// Calc Authorization | |||||
// Authorization = "SLS <AccessKeyID>:<Signature>" | |||||
digest, err := signature(project, method, uri, headers) | |||||
if err != nil { | |||||
return | |||||
} | |||||
auth := fmt.Sprintf("SLS %v:%v", project.AccessKeyID, digest) | |||||
headers["Authorization"] = auth | |||||
// Initialize http request | |||||
reader := bytes.NewReader(body) | |||||
urlStr := fmt.Sprintf("http://%v.%v%v", project.Name, project.Endpoint, uri) | |||||
req, err := http.NewRequest(method, urlStr, reader) | |||||
if err != nil { | |||||
return | |||||
} | |||||
for k, v := range headers { | |||||
req.Header.Add(k, v) | |||||
} | |||||
// Get ready to do request | |||||
resp, err = http.DefaultClient.Do(req) | |||||
if err != nil { | |||||
return | |||||
} | |||||
return | |||||
} |
@@ -1,111 +0,0 @@ | |||||
package alils | |||||
import ( | |||||
"crypto/hmac" | |||||
"crypto/sha1" | |||||
"encoding/base64" | |||||
"fmt" | |||||
"net/url" | |||||
"sort" | |||||
"strings" | |||||
"time" | |||||
) | |||||
// GMT location | |||||
var gmtLoc = time.FixedZone("GMT", 0) | |||||
// NowRFC1123 returns now time in RFC1123 format with GMT timezone, | |||||
// eg. "Mon, 02 Jan 2006 15:04:05 GMT". | |||||
func nowRFC1123() string { | |||||
return time.Now().In(gmtLoc).Format(time.RFC1123) | |||||
} | |||||
// signature calculates a request's signature digest. | |||||
func signature(project *LogProject, method, uri string, | |||||
headers map[string]string) (digest string, err error) { | |||||
var contentMD5, contentType, date, canoHeaders, canoResource string | |||||
var slsHeaderKeys sort.StringSlice | |||||
// SignString = VERB + "\n" | |||||
// + CONTENT-MD5 + "\n" | |||||
// + CONTENT-TYPE + "\n" | |||||
// + DATE + "\n" | |||||
// + CanonicalizedSLSHeaders + "\n" | |||||
// + CanonicalizedResource | |||||
if val, ok := headers["Content-MD5"]; ok { | |||||
contentMD5 = val | |||||
} | |||||
if val, ok := headers["Content-Type"]; ok { | |||||
contentType = val | |||||
} | |||||
date, ok := headers["Date"] | |||||
if !ok { | |||||
err = fmt.Errorf("Can't find 'Date' header") | |||||
return | |||||
} | |||||
// Calc CanonicalizedSLSHeaders | |||||
slsHeaders := make(map[string]string, len(headers)) | |||||
for k, v := range headers { | |||||
l := strings.TrimSpace(strings.ToLower(k)) | |||||
if strings.HasPrefix(l, "x-sls-") { | |||||
slsHeaders[l] = strings.TrimSpace(v) | |||||
slsHeaderKeys = append(slsHeaderKeys, l) | |||||
} | |||||
} | |||||
sort.Sort(slsHeaderKeys) | |||||
for i, k := range slsHeaderKeys { | |||||
canoHeaders += k + ":" + slsHeaders[k] | |||||
if i+1 < len(slsHeaderKeys) { | |||||
canoHeaders += "\n" | |||||
} | |||||
} | |||||
// Calc CanonicalizedResource | |||||
u, err := url.Parse(uri) | |||||
if err != nil { | |||||
return | |||||
} | |||||
canoResource += url.QueryEscape(u.Path) | |||||
if u.RawQuery != "" { | |||||
var keys sort.StringSlice | |||||
vals := u.Query() | |||||
for k := range vals { | |||||
keys = append(keys, k) | |||||
} | |||||
sort.Sort(keys) | |||||
canoResource += "?" | |||||
for i, k := range keys { | |||||
if i > 0 { | |||||
canoResource += "&" | |||||
} | |||||
for _, v := range vals[k] { | |||||
canoResource += k + "=" + v | |||||
} | |||||
} | |||||
} | |||||
signStr := method + "\n" + | |||||
contentMD5 + "\n" + | |||||
contentType + "\n" + | |||||
date + "\n" + | |||||
canoHeaders + "\n" + | |||||
canoResource | |||||
// Signature = base64(hmac-sha1(UTF8-Encoding-Of(SignString),AccessKeySecret)) | |||||
mac := hmac.New(sha1.New, []byte(project.AccessKeySecret)) | |||||
_, err = mac.Write([]byte(signStr)) | |||||
if err != nil { | |||||
return | |||||
} | |||||
digest = base64.StdEncoding.EncodeToString(mac.Sum(nil)) | |||||
return | |||||
} |
@@ -0,0 +1,47 @@ | |||||
package alils | |||||
import ( | |||||
"fmt" | |||||
"net" | |||||
"os" | |||||
) | |||||
func GetCurrentInterface() *net.Interface { | |||||
if inter, err := net.InterfaceByName("eth0"); err == nil { | |||||
return inter | |||||
} else if inter, err := net.InterfaceByName("en0"); err == nil { | |||||
return inter | |||||
} | |||||
return nil | |||||
} | |||||
func GetCurrentInterfaceHardwareAddr() string { | |||||
if inter := GetCurrentInterface(); inter != nil { | |||||
return fmt.Sprintf("%s", inter.HardwareAddr) | |||||
} | |||||
return "" | |||||
} | |||||
func GetCurrentInterfaceAddrs() string { | |||||
if inter := GetCurrentInterface(); inter != nil { | |||||
if addrs, err := inter.Addrs(); err == nil { | |||||
return fmt.Sprintf("%s", addrs) | |||||
} | |||||
} | |||||
return "" | |||||
} | |||||
func GetHostname() string { | |||||
hostname, _ := os.Hostname() | |||||
return hostname | |||||
} | |||||
func GetUserHomename() string { | |||||
homedir, _ := os.UserHomeDir() | |||||
return homedir | |||||
} | |||||
func Getwd() string { | |||||
wd, _ := os.Getwd() | |||||
return wd | |||||
} |
@@ -21,4 +21,5 @@ const ( | |||||
AdapterConsole Adapter = "console" | AdapterConsole Adapter = "console" | ||||
AdapterSocket Adapter = "socket" | AdapterSocket Adapter = "socket" | ||||
AdapterElasticSearch Adapter = "es" | AdapterElasticSearch Adapter = "es" | ||||
AdapterAliLs Adapter = "alils" | |||||
) | ) |