client.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. package rabbitmqreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/rabbitmqreceiver"
  4. import (
  5. "context"
  6. "encoding/json"
  7. "fmt"
  8. "io"
  9. "net/http"
  10. "go.opentelemetry.io/collector/component"
  11. "go.uber.org/zap"
  12. "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/rabbitmqreceiver/internal/models"
  13. )
  14. // queuePath is the path to queues endpoint
  15. const queuePath = "/api/queues"
  16. type client interface {
  17. // GetQueues calls "/api/queues" endpoint to get list of queues for the target node
  18. GetQueues(ctx context.Context) ([]*models.Queue, error)
  19. }
  20. var _ client = (*rabbitmqClient)(nil)
  21. type rabbitmqClient struct {
  22. client *http.Client
  23. hostEndpoint string
  24. creds rabbitmqCredentials
  25. logger *zap.Logger
  26. }
  27. type rabbitmqCredentials struct {
  28. username string
  29. password string
  30. }
  31. func newClient(cfg *Config, host component.Host, settings component.TelemetrySettings, logger *zap.Logger) (client, error) {
  32. httpClient, err := cfg.ToClient(host, settings)
  33. if err != nil {
  34. return nil, fmt.Errorf("failed to create HTTP Client: %w", err)
  35. }
  36. return &rabbitmqClient{
  37. client: httpClient,
  38. hostEndpoint: cfg.Endpoint,
  39. creds: rabbitmqCredentials{
  40. username: cfg.Username,
  41. password: string(cfg.Password),
  42. },
  43. logger: logger,
  44. }, nil
  45. }
  46. func (c *rabbitmqClient) GetQueues(ctx context.Context) ([]*models.Queue, error) {
  47. var queues []*models.Queue
  48. if err := c.get(ctx, queuePath, &queues); err != nil {
  49. c.logger.Debug("Failed to retrieve queues", zap.Error(err))
  50. return nil, err
  51. }
  52. return queues, nil
  53. }
  54. func (c *rabbitmqClient) get(ctx context.Context, path string, respObj any) error {
  55. // Construct endpoint and create request
  56. url := c.hostEndpoint + path
  57. req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, http.NoBody)
  58. if err != nil {
  59. return fmt.Errorf("failed to create get request for path %s: %w", path, err)
  60. }
  61. // Set user/pass authentication
  62. req.SetBasicAuth(c.creds.username, c.creds.password)
  63. // Make request
  64. resp, err := c.client.Do(req)
  65. if err != nil {
  66. return fmt.Errorf("failed to make http request: %w", err)
  67. }
  68. // Defer body close
  69. defer func() {
  70. if closeErr := resp.Body.Close(); closeErr != nil {
  71. c.logger.Warn("failed to close response body", zap.Error(closeErr))
  72. }
  73. }()
  74. // Check for OK status code
  75. if resp.StatusCode != http.StatusOK {
  76. c.logger.Debug("rabbitMQ API non-200", zap.Error(err), zap.Int("status_code", resp.StatusCode))
  77. // Attempt to extract the error payload
  78. payloadData, err := io.ReadAll(resp.Body)
  79. if err != nil {
  80. c.logger.Debug("failed to read payload error message", zap.Error(err))
  81. } else {
  82. c.logger.Debug("rabbitMQ API Error", zap.ByteString("api_error", payloadData))
  83. }
  84. return fmt.Errorf("non 200 code returned %d", resp.StatusCode)
  85. }
  86. // Decode the payload into the passed in response object
  87. if err := json.NewDecoder(resp.Body).Decode(respObj); err != nil {
  88. return fmt.Errorf("failed to decode response payload: %w", err)
  89. }
  90. return nil
  91. }