高热共公日志库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

820 lines
17 KiB

  1. /*
  2. Package alils implements the SDK(v0.5.0) of Simple Log Service(abbr. SLS).
  3. For more description about SLS, please read this article:
  4. http://gitlab.alibaba-inc.com/sls/doc.
  5. */
  6. package alils
  7. import (
  8. "encoding/json"
  9. "fmt"
  10. "io/ioutil"
  11. "net/http"
  12. "net/http/httputil"
  13. )
  14. // Error message in SLS HTTP response.
  15. type errorMessage struct {
  16. Code string `json:"errorCode"`
  17. Message string `json:"errorMessage"`
  18. }
  19. // LogProject Define the Ali Project detail
  20. type LogProject struct {
  21. Name string // Project name
  22. Endpoint string // IP or hostname of SLS endpoint
  23. AccessKeyID string
  24. AccessKeySecret string
  25. }
  26. // NewLogProject creates a new SLS project.
  27. func NewLogProject(name, endpoint, AccessKeyID, accessKeySecret string) (p *LogProject, err error) {
  28. p = &LogProject{
  29. Name: name,
  30. Endpoint: endpoint,
  31. AccessKeyID: AccessKeyID,
  32. AccessKeySecret: accessKeySecret,
  33. }
  34. return p, nil
  35. }
  36. // ListLogStore returns all logstore names of project p.
  37. func (p *LogProject) ListLogStore() (storeNames []string, err error) {
  38. h := map[string]string{
  39. "x-sls-bodyrawsize": "0",
  40. }
  41. uri := fmt.Sprintf("/logstores")
  42. r, err := request(p, "GET", uri, h, nil)
  43. if err != nil {
  44. return
  45. }
  46. buf, err := ioutil.ReadAll(r.Body)
  47. if err != nil {
  48. return
  49. }
  50. if r.StatusCode != http.StatusOK {
  51. errMsg := &errorMessage{}
  52. err = json.Unmarshal(buf, errMsg)
  53. if err != nil {
  54. err = fmt.Errorf("failed to list logstore")
  55. dump, _ := httputil.DumpResponse(r, true)
  56. fmt.Printf("%s\n", dump)
  57. return
  58. }
  59. err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
  60. return
  61. }
  62. type Body struct {
  63. Count int
  64. LogStores []string
  65. }
  66. body := &Body{}
  67. err = json.Unmarshal(buf, body)
  68. if err != nil {
  69. return
  70. }
  71. storeNames = body.LogStores
  72. return
  73. }
  74. // GetLogStore returns logstore according by logstore name.
  75. func (p *LogProject) GetLogStore(name string) (s *LogStore, err error) {
  76. h := map[string]string{
  77. "x-sls-bodyrawsize": "0",
  78. }
  79. r, err := request(p, "GET", "/logstores/"+name, h, nil)
  80. if err != nil {
  81. return
  82. }
  83. buf, err := ioutil.ReadAll(r.Body)
  84. if err != nil {
  85. return
  86. }
  87. if r.StatusCode != http.StatusOK {
  88. errMsg := &errorMessage{}
  89. err = json.Unmarshal(buf, errMsg)
  90. if err != nil {
  91. err = fmt.Errorf("failed to get logstore")
  92. dump, _ := httputil.DumpResponse(r, true)
  93. fmt.Printf("%s\n", dump)
  94. return
  95. }
  96. err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
  97. return
  98. }
  99. s = &LogStore{}
  100. err = json.Unmarshal(buf, s)
  101. if err != nil {
  102. return
  103. }
  104. s.project = p
  105. return
  106. }
  107. // CreateLogStore creates a new logstore in SLS,
  108. // where name is logstore name,
  109. // and ttl is time-to-live(in day) of logs,
  110. // and shardCnt is the number of shards.
  111. func (p *LogProject) CreateLogStore(name string, ttl, shardCnt int) (err error) {
  112. type Body struct {
  113. Name string `json:"logstoreName"`
  114. TTL int `json:"ttl"`
  115. ShardCount int `json:"shardCount"`
  116. }
  117. store := &Body{
  118. Name: name,
  119. TTL: ttl,
  120. ShardCount: shardCnt,
  121. }
  122. body, err := json.Marshal(store)
  123. if err != nil {
  124. return
  125. }
  126. h := map[string]string{
  127. "x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
  128. "Content-Type": "application/json",
  129. "Accept-Encoding": "deflate", // TODO: support lz4
  130. }
  131. r, err := request(p, "POST", "/logstores", h, body)
  132. if err != nil {
  133. return
  134. }
  135. body, err = ioutil.ReadAll(r.Body)
  136. if err != nil {
  137. return
  138. }
  139. if r.StatusCode != http.StatusOK {
  140. errMsg := &errorMessage{}
  141. err = json.Unmarshal(body, errMsg)
  142. if err != nil {
  143. err = fmt.Errorf("failed to create logstore")
  144. dump, _ := httputil.DumpResponse(r, true)
  145. fmt.Printf("%s\n", dump)
  146. return
  147. }
  148. err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
  149. return
  150. }
  151. return
  152. }
  153. // DeleteLogStore deletes a logstore according by logstore name.
  154. func (p *LogProject) DeleteLogStore(name string) (err error) {
  155. h := map[string]string{
  156. "x-sls-bodyrawsize": "0",
  157. }
  158. r, err := request(p, "DELETE", "/logstores/"+name, h, nil)
  159. if err != nil {
  160. return
  161. }
  162. body, err := ioutil.ReadAll(r.Body)
  163. if err != nil {
  164. return
  165. }
  166. if r.StatusCode != http.StatusOK {
  167. errMsg := &errorMessage{}
  168. err = json.Unmarshal(body, errMsg)
  169. if err != nil {
  170. err = fmt.Errorf("failed to delete logstore")
  171. dump, _ := httputil.DumpResponse(r, true)
  172. fmt.Printf("%s\n", dump)
  173. return
  174. }
  175. err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
  176. return
  177. }
  178. return
  179. }
  180. // UpdateLogStore updates a logstore according by logstore name,
  181. // obviously we can't modify the logstore name itself.
  182. func (p *LogProject) UpdateLogStore(name string, ttl, shardCnt int) (err error) {
  183. type Body struct {
  184. Name string `json:"logstoreName"`
  185. TTL int `json:"ttl"`
  186. ShardCount int `json:"shardCount"`
  187. }
  188. store := &Body{
  189. Name: name,
  190. TTL: ttl,
  191. ShardCount: shardCnt,
  192. }
  193. body, err := json.Marshal(store)
  194. if err != nil {
  195. return
  196. }
  197. h := map[string]string{
  198. "x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
  199. "Content-Type": "application/json",
  200. "Accept-Encoding": "deflate", // TODO: support lz4
  201. }
  202. r, err := request(p, "PUT", "/logstores", h, body)
  203. if err != nil {
  204. return
  205. }
  206. body, err = ioutil.ReadAll(r.Body)
  207. if err != nil {
  208. return
  209. }
  210. if r.StatusCode != http.StatusOK {
  211. errMsg := &errorMessage{}
  212. err = json.Unmarshal(body, errMsg)
  213. if err != nil {
  214. err = fmt.Errorf("failed to update logstore")
  215. dump, _ := httputil.DumpResponse(r, true)
  216. fmt.Printf("%s\n", dump)
  217. return
  218. }
  219. err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
  220. return
  221. }
  222. return
  223. }
  224. // ListMachineGroup returns machine group name list and the total number of machine groups.
  225. // The offset starts from 0 and the size is the max number of machine groups could be returned.
  226. func (p *LogProject) ListMachineGroup(offset, size int) (m []string, total int, err error) {
  227. h := map[string]string{
  228. "x-sls-bodyrawsize": "0",
  229. }
  230. if size <= 0 {
  231. size = 500
  232. }
  233. uri := fmt.Sprintf("/machinegroups?offset=%v&size=%v", offset, size)
  234. r, err := request(p, "GET", uri, h, nil)
  235. if err != nil {
  236. return
  237. }
  238. buf, err := ioutil.ReadAll(r.Body)
  239. if err != nil {
  240. return
  241. }
  242. if r.StatusCode != http.StatusOK {
  243. errMsg := &errorMessage{}
  244. err = json.Unmarshal(buf, errMsg)
  245. if err != nil {
  246. err = fmt.Errorf("failed to list machine group")
  247. dump, _ := httputil.DumpResponse(r, true)
  248. fmt.Printf("%s\n", dump)
  249. return
  250. }
  251. err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
  252. return
  253. }
  254. type Body struct {
  255. MachineGroups []string
  256. Count int
  257. Total int
  258. }
  259. body := &Body{}
  260. err = json.Unmarshal(buf, body)
  261. if err != nil {
  262. return
  263. }
  264. m = body.MachineGroups
  265. total = body.Total
  266. return
  267. }
  268. // GetMachineGroup retruns machine group according by machine group name.
  269. func (p *LogProject) GetMachineGroup(name string) (m *MachineGroup, err error) {
  270. h := map[string]string{
  271. "x-sls-bodyrawsize": "0",
  272. }
  273. r, err := request(p, "GET", "/machinegroups/"+name, h, nil)
  274. if err != nil {
  275. return
  276. }
  277. buf, err := ioutil.ReadAll(r.Body)
  278. if err != nil {
  279. return
  280. }
  281. if r.StatusCode != http.StatusOK {
  282. errMsg := &errorMessage{}
  283. err = json.Unmarshal(buf, errMsg)
  284. if err != nil {
  285. err = fmt.Errorf("failed to get machine group:%v", name)
  286. dump, _ := httputil.DumpResponse(r, true)
  287. fmt.Printf("%s\n", dump)
  288. return
  289. }
  290. err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
  291. return
  292. }
  293. m = &MachineGroup{}
  294. err = json.Unmarshal(buf, m)
  295. if err != nil {
  296. return
  297. }
  298. m.project = p
  299. return
  300. }
  301. // CreateMachineGroup creates a new machine group in SLS.
  302. func (p *LogProject) CreateMachineGroup(m *MachineGroup) (err error) {
  303. body, err := json.Marshal(m)
  304. if err != nil {
  305. return
  306. }
  307. h := map[string]string{
  308. "x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
  309. "Content-Type": "application/json",
  310. "Accept-Encoding": "deflate", // TODO: support lz4
  311. }
  312. r, err := request(p, "POST", "/machinegroups", h, body)
  313. if err != nil {
  314. return
  315. }
  316. body, err = ioutil.ReadAll(r.Body)
  317. if err != nil {
  318. return
  319. }
  320. if r.StatusCode != http.StatusOK {
  321. errMsg := &errorMessage{}
  322. err = json.Unmarshal(body, errMsg)
  323. if err != nil {
  324. err = fmt.Errorf("failed to create machine group")
  325. dump, _ := httputil.DumpResponse(r, true)
  326. fmt.Printf("%s\n", dump)
  327. return
  328. }
  329. err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
  330. return
  331. }
  332. return
  333. }
  334. // UpdateMachineGroup updates a machine group.
  335. func (p *LogProject) UpdateMachineGroup(m *MachineGroup) (err error) {
  336. body, err := json.Marshal(m)
  337. if err != nil {
  338. return
  339. }
  340. h := map[string]string{
  341. "x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
  342. "Content-Type": "application/json",
  343. "Accept-Encoding": "deflate", // TODO: support lz4
  344. }
  345. r, err := request(p, "PUT", "/machinegroups/"+m.Name, h, body)
  346. if err != nil {
  347. return
  348. }
  349. body, err = ioutil.ReadAll(r.Body)
  350. if err != nil {
  351. return
  352. }
  353. if r.StatusCode != http.StatusOK {
  354. errMsg := &errorMessage{}
  355. err = json.Unmarshal(body, errMsg)
  356. if err != nil {
  357. err = fmt.Errorf("failed to update machine group")
  358. dump, _ := httputil.DumpResponse(r, true)
  359. fmt.Printf("%s\n", dump)
  360. return
  361. }
  362. err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
  363. return
  364. }
  365. return
  366. }
  367. // DeleteMachineGroup deletes machine group according machine group name.
  368. func (p *LogProject) DeleteMachineGroup(name string) (err error) {
  369. h := map[string]string{
  370. "x-sls-bodyrawsize": "0",
  371. }
  372. r, err := request(p, "DELETE", "/machinegroups/"+name, h, nil)
  373. if err != nil {
  374. return
  375. }
  376. body, err := ioutil.ReadAll(r.Body)
  377. if err != nil {
  378. return
  379. }
  380. if r.StatusCode != http.StatusOK {
  381. errMsg := &errorMessage{}
  382. err = json.Unmarshal(body, errMsg)
  383. if err != nil {
  384. err = fmt.Errorf("failed to delete machine group")
  385. dump, _ := httputil.DumpResponse(r, true)
  386. fmt.Printf("%s\n", dump)
  387. return
  388. }
  389. err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
  390. return
  391. }
  392. return
  393. }
  394. // ListConfig returns config names list and the total number of configs.
  395. // The offset starts from 0 and the size is the max number of configs could be returned.
  396. func (p *LogProject) ListConfig(offset, size int) (cfgNames []string, total int, err error) {
  397. h := map[string]string{
  398. "x-sls-bodyrawsize": "0",
  399. }
  400. if size <= 0 {
  401. size = 100
  402. }
  403. uri := fmt.Sprintf("/configs?offset=%v&size=%v", offset, size)
  404. r, err := request(p, "GET", uri, h, nil)
  405. if err != nil {
  406. return
  407. }
  408. buf, err := ioutil.ReadAll(r.Body)
  409. if err != nil {
  410. return
  411. }
  412. if r.StatusCode != http.StatusOK {
  413. errMsg := &errorMessage{}
  414. err = json.Unmarshal(buf, errMsg)
  415. if err != nil {
  416. err = fmt.Errorf("failed to delete machine group")
  417. dump, _ := httputil.DumpResponse(r, true)
  418. fmt.Printf("%s\n", dump)
  419. return
  420. }
  421. err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
  422. return
  423. }
  424. type Body struct {
  425. Total int
  426. Configs []string
  427. }
  428. body := &Body{}
  429. err = json.Unmarshal(buf, body)
  430. if err != nil {
  431. return
  432. }
  433. cfgNames = body.Configs
  434. total = body.Total
  435. return
  436. }
  437. // GetConfig returns config according by config name.
  438. func (p *LogProject) GetConfig(name string) (c *LogConfig, err error) {
  439. h := map[string]string{
  440. "x-sls-bodyrawsize": "0",
  441. }
  442. r, err := request(p, "GET", "/configs/"+name, h, nil)
  443. if err != nil {
  444. return
  445. }
  446. buf, err := ioutil.ReadAll(r.Body)
  447. if err != nil {
  448. return
  449. }
  450. if r.StatusCode != http.StatusOK {
  451. errMsg := &errorMessage{}
  452. err = json.Unmarshal(buf, errMsg)
  453. if err != nil {
  454. err = fmt.Errorf("failed to delete config")
  455. dump, _ := httputil.DumpResponse(r, true)
  456. fmt.Printf("%s\n", dump)
  457. return
  458. }
  459. err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
  460. return
  461. }
  462. c = &LogConfig{}
  463. err = json.Unmarshal(buf, c)
  464. if err != nil {
  465. return
  466. }
  467. c.project = p
  468. return
  469. }
  470. // UpdateConfig updates a config.
  471. func (p *LogProject) UpdateConfig(c *LogConfig) (err error) {
  472. body, err := json.Marshal(c)
  473. if err != nil {
  474. return
  475. }
  476. h := map[string]string{
  477. "x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
  478. "Content-Type": "application/json",
  479. "Accept-Encoding": "deflate", // TODO: support lz4
  480. }
  481. r, err := request(p, "PUT", "/configs/"+c.Name, h, body)
  482. if err != nil {
  483. return
  484. }
  485. body, err = ioutil.ReadAll(r.Body)
  486. if err != nil {
  487. return
  488. }
  489. if r.StatusCode != http.StatusOK {
  490. errMsg := &errorMessage{}
  491. err = json.Unmarshal(body, errMsg)
  492. if err != nil {
  493. err = fmt.Errorf("failed to update config")
  494. dump, _ := httputil.DumpResponse(r, true)
  495. fmt.Printf("%s\n", dump)
  496. return
  497. }
  498. err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
  499. return
  500. }
  501. return
  502. }
  503. // CreateConfig creates a new config in SLS.
  504. func (p *LogProject) CreateConfig(c *LogConfig) (err error) {
  505. body, err := json.Marshal(c)
  506. if err != nil {
  507. return
  508. }
  509. h := map[string]string{
  510. "x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
  511. "Content-Type": "application/json",
  512. "Accept-Encoding": "deflate", // TODO: support lz4
  513. }
  514. r, err := request(p, "POST", "/configs", h, body)
  515. if err != nil {
  516. return
  517. }
  518. body, err = ioutil.ReadAll(r.Body)
  519. if err != nil {
  520. return
  521. }
  522. if r.StatusCode != http.StatusOK {
  523. errMsg := &errorMessage{}
  524. err = json.Unmarshal(body, errMsg)
  525. if err != nil {
  526. err = fmt.Errorf("failed to update config")
  527. dump, _ := httputil.DumpResponse(r, true)
  528. fmt.Printf("%s\n", dump)
  529. return
  530. }
  531. err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
  532. return
  533. }
  534. return
  535. }
  536. // DeleteConfig deletes a config according by config name.
  537. func (p *LogProject) DeleteConfig(name string) (err error) {
  538. h := map[string]string{
  539. "x-sls-bodyrawsize": "0",
  540. }
  541. r, err := request(p, "DELETE", "/configs/"+name, h, nil)
  542. if err != nil {
  543. return
  544. }
  545. body, err := ioutil.ReadAll(r.Body)
  546. if err != nil {
  547. return
  548. }
  549. if r.StatusCode != http.StatusOK {
  550. errMsg := &errorMessage{}
  551. err = json.Unmarshal(body, errMsg)
  552. if err != nil {
  553. err = fmt.Errorf("failed to delete config")
  554. dump, _ := httputil.DumpResponse(r, true)
  555. fmt.Printf("%s\n", dump)
  556. return
  557. }
  558. err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
  559. return
  560. }
  561. return
  562. }
  563. // GetAppliedMachineGroups returns applied machine group names list according config name.
  564. func (p *LogProject) GetAppliedMachineGroups(confName string) (groupNames []string, err error) {
  565. h := map[string]string{
  566. "x-sls-bodyrawsize": "0",
  567. }
  568. uri := fmt.Sprintf("/configs/%v/machinegroups", confName)
  569. r, err := request(p, "GET", uri, h, nil)
  570. if err != nil {
  571. return
  572. }
  573. buf, err := ioutil.ReadAll(r.Body)
  574. if err != nil {
  575. return
  576. }
  577. if r.StatusCode != http.StatusOK {
  578. errMsg := &errorMessage{}
  579. err = json.Unmarshal(buf, errMsg)
  580. if err != nil {
  581. err = fmt.Errorf("failed to get applied machine groups")
  582. dump, _ := httputil.DumpResponse(r, true)
  583. fmt.Printf("%s\n", dump)
  584. return
  585. }
  586. err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
  587. return
  588. }
  589. type Body struct {
  590. Count int
  591. Machinegroups []string
  592. }
  593. body := &Body{}
  594. err = json.Unmarshal(buf, body)
  595. if err != nil {
  596. return
  597. }
  598. groupNames = body.Machinegroups
  599. return
  600. }
  601. // GetAppliedConfigs returns applied config names list according machine group name groupName.
  602. func (p *LogProject) GetAppliedConfigs(groupName string) (confNames []string, err error) {
  603. h := map[string]string{
  604. "x-sls-bodyrawsize": "0",
  605. }
  606. uri := fmt.Sprintf("/machinegroups/%v/configs", groupName)
  607. r, err := request(p, "GET", uri, h, nil)
  608. if err != nil {
  609. return
  610. }
  611. buf, err := ioutil.ReadAll(r.Body)
  612. if err != nil {
  613. return
  614. }
  615. if r.StatusCode != http.StatusOK {
  616. errMsg := &errorMessage{}
  617. err = json.Unmarshal(buf, errMsg)
  618. if err != nil {
  619. err = fmt.Errorf("failed to applied configs")
  620. dump, _ := httputil.DumpResponse(r, true)
  621. fmt.Printf("%s\n", dump)
  622. return
  623. }
  624. err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
  625. return
  626. }
  627. type Cfg struct {
  628. Count int `json:"count"`
  629. Configs []string `json:"configs"`
  630. }
  631. body := &Cfg{}
  632. err = json.Unmarshal(buf, body)
  633. if err != nil {
  634. return
  635. }
  636. confNames = body.Configs
  637. return
  638. }
  639. // ApplyConfigToMachineGroup applies config to machine group.
  640. func (p *LogProject) ApplyConfigToMachineGroup(confName, groupName string) (err error) {
  641. h := map[string]string{
  642. "x-sls-bodyrawsize": "0",
  643. }
  644. uri := fmt.Sprintf("/machinegroups/%v/configs/%v", groupName, confName)
  645. r, err := request(p, "PUT", uri, h, nil)
  646. if err != nil {
  647. return
  648. }
  649. buf, err := ioutil.ReadAll(r.Body)
  650. if err != nil {
  651. return
  652. }
  653. if r.StatusCode != http.StatusOK {
  654. errMsg := &errorMessage{}
  655. err = json.Unmarshal(buf, errMsg)
  656. if err != nil {
  657. err = fmt.Errorf("failed to apply config to machine group")
  658. dump, _ := httputil.DumpResponse(r, true)
  659. fmt.Printf("%s\n", dump)
  660. return
  661. }
  662. err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
  663. return
  664. }
  665. return
  666. }
  667. // RemoveConfigFromMachineGroup removes config from machine group.
  668. func (p *LogProject) RemoveConfigFromMachineGroup(confName, groupName string) (err error) {
  669. h := map[string]string{
  670. "x-sls-bodyrawsize": "0",
  671. }
  672. uri := fmt.Sprintf("/machinegroups/%v/configs/%v", groupName, confName)
  673. r, err := request(p, "DELETE", uri, h, nil)
  674. if err != nil {
  675. return
  676. }
  677. buf, err := ioutil.ReadAll(r.Body)
  678. if err != nil {
  679. return
  680. }
  681. if r.StatusCode != http.StatusOK {
  682. errMsg := &errorMessage{}
  683. err = json.Unmarshal(buf, errMsg)
  684. if err != nil {
  685. err = fmt.Errorf("failed to remove config from machine group")
  686. dump, _ := httputil.DumpResponse(r, true)
  687. fmt.Printf("%s\n", dump)
  688. return
  689. }
  690. err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
  691. return
  692. }
  693. return
  694. }