client.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. package telemetry
  2. import (
  3. "bytes"
  4. "fmt"
  5. "net/http"
  6. "time"
  7. "github.com/google/uuid"
  8. "github.com/seaweedfs/seaweedfs/telemetry/proto"
  9. "github.com/seaweedfs/seaweedfs/weed/glog"
  10. protobuf "google.golang.org/protobuf/proto"
  11. )
  12. type Client struct {
  13. url string
  14. enabled bool
  15. instanceID string
  16. httpClient *http.Client
  17. }
  18. // NewClient creates a new telemetry client
  19. func NewClient(url string, enabled bool) *Client {
  20. return &Client{
  21. url: url,
  22. enabled: enabled,
  23. instanceID: uuid.New().String(), // Generate UUID in memory only
  24. httpClient: &http.Client{
  25. Timeout: 10 * time.Second,
  26. },
  27. }
  28. }
  29. // IsEnabled returns whether telemetry is enabled
  30. func (c *Client) IsEnabled() bool {
  31. return c.enabled && c.url != ""
  32. }
  33. // SendTelemetry sends telemetry data synchronously using protobuf format
  34. func (c *Client) SendTelemetry(data *proto.TelemetryData) error {
  35. if !c.IsEnabled() {
  36. return nil
  37. }
  38. // Set the cluster ID
  39. data.ClusterId = c.instanceID
  40. return c.sendProtobuf(data)
  41. }
  42. // SendTelemetryAsync sends telemetry data asynchronously
  43. func (c *Client) SendTelemetryAsync(data *proto.TelemetryData) {
  44. if !c.IsEnabled() {
  45. return
  46. }
  47. go func() {
  48. if err := c.SendTelemetry(data); err != nil {
  49. glog.V(1).Infof("Failed to send telemetry: %v", err)
  50. }
  51. }()
  52. }
  53. // sendProtobuf sends data using protobuf format
  54. func (c *Client) sendProtobuf(data *proto.TelemetryData) error {
  55. req := &proto.TelemetryRequest{
  56. Data: data,
  57. }
  58. body, err := protobuf.Marshal(req)
  59. if err != nil {
  60. return fmt.Errorf("failed to marshal protobuf: %w", err)
  61. }
  62. httpReq, err := http.NewRequest("POST", c.url, bytes.NewBuffer(body))
  63. if err != nil {
  64. return fmt.Errorf("failed to create request: %w", err)
  65. }
  66. httpReq.Header.Set("Content-Type", "application/x-protobuf")
  67. httpReq.Header.Set("User-Agent", fmt.Sprintf("SeaweedFS/%s", data.Version))
  68. resp, err := c.httpClient.Do(httpReq)
  69. if err != nil {
  70. return fmt.Errorf("failed to send request: %w", err)
  71. }
  72. defer resp.Body.Close()
  73. if resp.StatusCode != http.StatusOK {
  74. return fmt.Errorf("server returned status %d", resp.StatusCode)
  75. }
  76. glog.V(2).Infof("Telemetry sent successfully via protobuf")
  77. return nil
  78. }
  79. // GetInstanceID returns the current instance ID
  80. func (c *Client) GetInstanceID() string {
  81. return c.instanceID
  82. }