scraper_test.go 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. package apachesparkreceiver
  4. import (
  5. "context"
  6. "encoding/json"
  7. "errors"
  8. "path/filepath"
  9. "testing"
  10. "github.com/stretchr/testify/mock"
  11. "github.com/stretchr/testify/require"
  12. "go.opentelemetry.io/collector/config/confighttp"
  13. "go.opentelemetry.io/collector/pdata/pmetric"
  14. "go.opentelemetry.io/collector/receiver/receivertest"
  15. "go.opentelemetry.io/collector/receiver/scrapererror"
  16. "go.opentelemetry.io/collector/receiver/scraperhelper"
  17. "go.uber.org/zap"
  18. "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/golden"
  19. "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest/pmetrictest"
  20. "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/apachesparkreceiver/internal/metadata"
  21. "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/apachesparkreceiver/internal/mocks"
  22. "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/apachesparkreceiver/internal/models"
  23. )
  24. const (
  25. clusterStatsResponseFile = "cluster_stats_response.json"
  26. appsStatsResponseFile = "apps_stats_response.json"
  27. stagesStatsResponseFile = "stages_stats_response.json"
  28. executorsStatsResponseFile = "executors_stats_response.json"
  29. jobsStatsResponseFile = "jobs_stats_response.json"
  30. )
  31. func TestScraper(t *testing.T) {
  32. testcases := []struct {
  33. desc string
  34. setupMockClient func(t *testing.T) client
  35. expectedMetricGen func(t *testing.T) pmetric.Metrics
  36. config *Config
  37. expectedErr error
  38. }{
  39. {
  40. desc: "Exits on failure to get app ids",
  41. setupMockClient: func(t *testing.T) client {
  42. mockClient := mocks.MockClient{}
  43. mockClient.On("Applications").Return(nil, errors.New("could not retrieve app ids"))
  44. return &mockClient
  45. },
  46. expectedMetricGen: func(t *testing.T) pmetric.Metrics {
  47. return pmetric.NewMetrics()
  48. },
  49. config: createDefaultConfig().(*Config),
  50. expectedErr: errFailedAppIDCollection,
  51. },
  52. {
  53. desc: "No Matching Allowed Apps",
  54. setupMockClient: func(t *testing.T) client {
  55. mockClient := mocks.MockClient{}
  56. mockClient.On("Applications").Return([]models.Application{}, nil)
  57. return &mockClient
  58. },
  59. expectedMetricGen: func(t *testing.T) pmetric.Metrics {
  60. return pmetric.NewMetrics()
  61. },
  62. config: &Config{ScraperControllerSettings: scraperhelper.ScraperControllerSettings{
  63. CollectionInterval: defaultCollectionInterval,
  64. },
  65. ApplicationNames: []string{"local-123", "local-987"},
  66. HTTPClientSettings: confighttp.HTTPClientSettings{
  67. Endpoint: defaultEndpoint,
  68. },
  69. MetricsBuilderConfig: metadata.DefaultMetricsBuilderConfig(),
  70. },
  71. expectedErr: errNoMatchingAllowedApps,
  72. },
  73. {
  74. desc: "Successful Full Empty Collection",
  75. setupMockClient: func(t *testing.T) client {
  76. mockClient := mocks.MockClient{}
  77. mockClient.On("ClusterStats").Return(&models.ClusterProperties{}, nil)
  78. mockClient.On("Applications").Return([]models.Application{}, nil)
  79. mockClient.On("StageStats", mock.Anything).Return([]models.Stage{}, nil)
  80. mockClient.On("ExecutorStats", mock.Anything).Return([]models.Executor{}, nil)
  81. mockClient.On("JobStats", mock.Anything).Return([]models.Job{}, nil)
  82. return &mockClient
  83. },
  84. expectedMetricGen: func(t *testing.T) pmetric.Metrics {
  85. goldenPath := filepath.Join("testdata", "expected_metrics", "metrics_empty_golden.yaml")
  86. expectedMetrics, err := golden.ReadMetrics(goldenPath)
  87. require.NoError(t, err)
  88. return expectedMetrics
  89. },
  90. config: createDefaultConfig().(*Config),
  91. expectedErr: nil,
  92. },
  93. {
  94. desc: "Successful Partial Collection",
  95. setupMockClient: func(t *testing.T) client {
  96. mockClient := mocks.MockClient{}
  97. data := loadAPIResponseData(t, clusterStatsResponseFile)
  98. var clusterStats *models.ClusterProperties
  99. err := json.Unmarshal(data, &clusterStats)
  100. require.NoError(t, err)
  101. mockClient.On("ClusterStats").Return(clusterStats, nil)
  102. data = loadAPIResponseData(t, appsStatsResponseFile)
  103. var apps []models.Application
  104. err = json.Unmarshal(data, &apps)
  105. require.NoError(t, err)
  106. mockClient.On("Applications").Return(apps, nil)
  107. mockClient.On("StageStats", mock.Anything).Return(nil, errors.New("stage api error"))
  108. mockClient.On("ExecutorStats", mock.Anything).Return(nil, errors.New("executor api error"))
  109. mockClient.On("JobStats", mock.Anything).Return(nil, errors.New("jobs api error"))
  110. return &mockClient
  111. },
  112. expectedMetricGen: func(t *testing.T) pmetric.Metrics {
  113. goldenPath := filepath.Join("testdata", "expected_metrics", "metrics_partial_golden.yaml")
  114. expectedMetrics, err := golden.ReadMetrics(goldenPath)
  115. require.NoError(t, err)
  116. return expectedMetrics
  117. },
  118. config: createDefaultConfig().(*Config),
  119. expectedErr: scrapererror.NewPartialScrapeError(errors.New("stage api error; executor api error; jobs api error"), 0),
  120. },
  121. {
  122. desc: "Successful Full Collection",
  123. setupMockClient: func(t *testing.T) client {
  124. mockClient := mocks.MockClient{}
  125. data := loadAPIResponseData(t, clusterStatsResponseFile)
  126. var clusterStats *models.ClusterProperties
  127. err := json.Unmarshal(data, &clusterStats)
  128. require.NoError(t, err)
  129. mockClient.On("ClusterStats").Return(clusterStats, nil)
  130. data = loadAPIResponseData(t, appsStatsResponseFile)
  131. var apps []models.Application
  132. err = json.Unmarshal(data, &apps)
  133. require.NoError(t, err)
  134. mockClient.On("Applications").Return(apps, nil)
  135. data = loadAPIResponseData(t, stagesStatsResponseFile)
  136. var stages []models.Stage
  137. err = json.Unmarshal(data, &stages)
  138. require.NoError(t, err)
  139. mockClient.On("StageStats", mock.Anything).Return(stages, nil)
  140. data = loadAPIResponseData(t, executorsStatsResponseFile)
  141. var executors []models.Executor
  142. err = json.Unmarshal(data, &executors)
  143. require.NoError(t, err)
  144. mockClient.On("ExecutorStats", mock.Anything).Return(executors, nil)
  145. data = loadAPIResponseData(t, jobsStatsResponseFile)
  146. var jobs []models.Job
  147. err = json.Unmarshal(data, &jobs)
  148. require.NoError(t, err)
  149. mockClient.On("JobStats", mock.Anything).Return(jobs, nil)
  150. return &mockClient
  151. },
  152. expectedMetricGen: func(t *testing.T) pmetric.Metrics {
  153. goldenPath := filepath.Join("testdata", "expected_metrics", "metrics_golden.yaml")
  154. expectedMetrics, err := golden.ReadMetrics(goldenPath)
  155. require.NoError(t, err)
  156. return expectedMetrics
  157. },
  158. config: createDefaultConfig().(*Config),
  159. expectedErr: nil,
  160. },
  161. {
  162. desc: "Successfully allowing apps",
  163. setupMockClient: func(t *testing.T) client {
  164. mockClient := mocks.MockClient{}
  165. data := loadAPIResponseData(t, clusterStatsResponseFile)
  166. var clusterStats *models.ClusterProperties
  167. err := json.Unmarshal(data, &clusterStats)
  168. require.NoError(t, err)
  169. mockClient.On("ClusterStats").Return(clusterStats, nil)
  170. data = loadAPIResponseData(t, appsStatsResponseFile)
  171. var apps []models.Application
  172. err = json.Unmarshal(data, &apps)
  173. require.NoError(t, err)
  174. mockClient.On("Applications").Return(apps, nil)
  175. data = loadAPIResponseData(t, stagesStatsResponseFile)
  176. var stages []models.Stage
  177. err = json.Unmarshal(data, &stages)
  178. require.NoError(t, err)
  179. mockClient.On("StageStats", mock.Anything).Return(stages, nil)
  180. data = loadAPIResponseData(t, executorsStatsResponseFile)
  181. var executors []models.Executor
  182. err = json.Unmarshal(data, &executors)
  183. require.NoError(t, err)
  184. mockClient.On("ExecutorStats", mock.Anything).Return(executors, nil)
  185. data = loadAPIResponseData(t, jobsStatsResponseFile)
  186. var jobs []models.Job
  187. err = json.Unmarshal(data, &jobs)
  188. require.NoError(t, err)
  189. mockClient.On("JobStats", mock.Anything).Return(jobs, nil)
  190. return &mockClient
  191. },
  192. expectedMetricGen: func(t *testing.T) pmetric.Metrics {
  193. goldenPath := filepath.Join("testdata", "expected_metrics", "metrics_golden.yaml")
  194. expectedMetrics, err := golden.ReadMetrics(goldenPath)
  195. require.NoError(t, err)
  196. return expectedMetrics
  197. },
  198. config: &Config{ScraperControllerSettings: scraperhelper.ScraperControllerSettings{
  199. CollectionInterval: defaultCollectionInterval,
  200. },
  201. ApplicationNames: []string{"streaming-example"},
  202. HTTPClientSettings: confighttp.HTTPClientSettings{
  203. Endpoint: defaultEndpoint,
  204. },
  205. MetricsBuilderConfig: metadata.DefaultMetricsBuilderConfig(),
  206. },
  207. expectedErr: nil,
  208. },
  209. }
  210. for _, tc := range testcases {
  211. t.Run(tc.desc, func(t *testing.T) {
  212. scraper := newSparkScraper(zap.NewNop(), tc.config, receivertest.NewNopCreateSettings())
  213. scraper.client = tc.setupMockClient(t)
  214. actualMetrics, err := scraper.scrape(context.Background())
  215. if tc.expectedErr == nil {
  216. require.NoError(t, err)
  217. } else {
  218. require.EqualError(t, err, tc.expectedErr.Error())
  219. }
  220. expectedMetrics := tc.expectedMetricGen(t)
  221. err = pmetrictest.CompareMetrics(expectedMetrics, actualMetrics,
  222. pmetrictest.IgnoreMetricDataPointsOrder(),
  223. pmetrictest.IgnoreResourceMetricsOrder(), pmetrictest.IgnoreStartTimestamp(),
  224. pmetrictest.IgnoreTimestamp())
  225. require.NoError(t, err)
  226. })
  227. }
  228. }