test_transport.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. from typing import Any
  2. from unittest.mock import patch
  3. from minimetrics.core import CounterMetric, DistributionMetric, GaugeMetric, SetMetric
  4. from minimetrics.transport import MetricEnvelopeTransport, RelayStatsdEncoder
  5. from minimetrics.types import BucketKey
  6. def test_relay_encoder_with_counter():
  7. encoder = RelayStatsdEncoder()
  8. bucket_key: BucketKey = (
  9. 1693994400,
  10. "c",
  11. "button_click",
  12. "none",
  13. (
  14. ("browser", "Chrome"),
  15. ("browser.version", "1.0"),
  16. ),
  17. )
  18. metric = CounterMetric(first=2)
  19. flushed_metric = (bucket_key, metric)
  20. result = encoder.encode(flushed_metric)
  21. assert result == "button_click@none:2|c|#browser:Chrome,browser.version:1.0|T1693994400"
  22. def test_relay_encoder_with_distribution():
  23. encoder = RelayStatsdEncoder()
  24. bucket_key: BucketKey = (
  25. 1693994400,
  26. "d",
  27. "execution_time",
  28. "second",
  29. (
  30. ("browser", "Chrome"),
  31. ("browser.version", "1.0"),
  32. ),
  33. )
  34. metric = DistributionMetric(first=1.0)
  35. metric.add(0.5)
  36. metric.add(3.0)
  37. flushed_metric = (bucket_key, metric)
  38. result = encoder.encode(flushed_metric)
  39. assert (
  40. result
  41. == "execution_time@second:1.0:0.5:3.0|d|#browser:Chrome,browser.version:1.0|T1693994400"
  42. )
  43. def test_relay_encoder_with_set():
  44. encoder = RelayStatsdEncoder()
  45. bucket_key: BucketKey = (
  46. 1693994400,
  47. "s",
  48. "users",
  49. "none",
  50. (
  51. ("browser", "Chrome"),
  52. ("browser.version", "1.0"),
  53. ),
  54. )
  55. metric = SetMetric(first=123)
  56. metric.add(456)
  57. metric.add("riccardo")
  58. flushed_metric = (bucket_key, metric)
  59. result = encoder.encode(flushed_metric)
  60. pieces = result.split("|")
  61. m = pieces[0].split(":")
  62. assert m[0] == "users@none"
  63. assert sorted(m[1:]) == sorted(["123", "456", "3455635177"])
  64. assert pieces[1] == "s"
  65. assert pieces[2] == "#browser:Chrome,browser.version:1.0"
  66. assert pieces[3] == "T1693994400"
  67. def test_relay_encoder_with_gauge():
  68. encoder = RelayStatsdEncoder()
  69. bucket_key: BucketKey = (
  70. 1693994400,
  71. "g",
  72. "startup_time",
  73. "second",
  74. (
  75. ("browser", "Chrome"),
  76. ("browser.version", "1.0"),
  77. ),
  78. )
  79. metric = GaugeMetric(first=10.0)
  80. metric.add(5.0)
  81. metric.add(7.0)
  82. flushed_metric = (bucket_key, metric)
  83. result = encoder.encode(flushed_metric)
  84. assert (
  85. result
  86. == "startup_time@second:7.0:5.0:10.0:22.0:3|g|#browser:Chrome,browser.version:1.0|T1693994400"
  87. )
  88. def test_relay_encoder_with_invalid_chars():
  89. encoder = RelayStatsdEncoder()
  90. bucket_key: BucketKey = (
  91. 1693994400,
  92. "c",
  93. "büttòn_click",
  94. "second",
  95. (
  96. # Invalid tag key.
  97. ("browser\nname", "Chrome"),
  98. # Invalid tag value.
  99. ("browser.version", "\t1.\n0ô"),
  100. # Valid tag key and value.
  101. ("platform", "Android"),
  102. # Totally invalid tag key.
  103. ("\nöś", "Windows"),
  104. # Totally invalid tag value.
  105. ("version", "\n\t"),
  106. ),
  107. )
  108. metric = CounterMetric(first=1)
  109. flushed_metric = (bucket_key, metric)
  110. result = encoder.encode(flushed_metric)
  111. assert (
  112. result
  113. == "bttn_click@second:1|c|#browsername:Chrome,browser.version:1.0,platform:Android,version:|T1693994400"
  114. )
  115. bucket_key = (
  116. 1693994400,
  117. "c",
  118. "üòë",
  119. "second",
  120. (),
  121. )
  122. metric = CounterMetric(first=1)
  123. flushed_metric = (bucket_key, metric)
  124. assert encoder.encode(flushed_metric) == "invalid-metric-name@second:1|c|T1693994400"
  125. def test_relay_encoder_with_multiple_metrics():
  126. encoder = RelayStatsdEncoder()
  127. flushed_metric_1 = (
  128. (
  129. 1693994400,
  130. "g",
  131. "startup_time",
  132. "second",
  133. (
  134. ("browser", "Chrome"),
  135. ("browser.version", "1.0"),
  136. ),
  137. ),
  138. GaugeMetric(first=10.0),
  139. )
  140. flushed_metric_2 = (
  141. (
  142. 1693994400,
  143. "c",
  144. "button_click",
  145. "none",
  146. (
  147. ("browser", "Chrome"),
  148. ("browser.version", "1.0"),
  149. ),
  150. ),
  151. CounterMetric(first=1),
  152. )
  153. flushed_metric_3 = (
  154. (
  155. 1693994400,
  156. "c",
  157. # This name will be completely scraped, resulting in an invalid metric.
  158. "öüâ",
  159. "none",
  160. (
  161. ("browser", "Chrome"),
  162. ("browser.version", "1.0"),
  163. ),
  164. ),
  165. CounterMetric(first=1),
  166. )
  167. metrics: Any = [flushed_metric_1, flushed_metric_2, flushed_metric_3]
  168. result = encoder.encode_multiple(metrics)
  169. assert result == (
  170. "startup_time@second:10.0:10.0:10.0:10.0:1|g|#browser:Chrome,browser.version:1.0|T1693994400"
  171. + "\n"
  172. + "button_click@none:1|c|#browser:Chrome,browser.version:1.0|T1693994400"
  173. + "\n"
  174. + "invalid-metric-name@none:1|c|#browser:Chrome,browser.version:1.0|T1693994400"
  175. )
  176. @patch("minimetrics.transport.sentry_sdk")
  177. def test_send(sentry_sdk):
  178. flushed_metric = (
  179. (
  180. 1693994400,
  181. "c",
  182. "button_click",
  183. "none",
  184. (
  185. ("browser", "Chrome"),
  186. ("browser.version", "1.0"),
  187. ),
  188. ),
  189. CounterMetric(first=1),
  190. )
  191. transport = MetricEnvelopeTransport(RelayStatsdEncoder())
  192. metrics: Any = [flushed_metric]
  193. transport.send(metrics)
  194. args = sentry_sdk.Hub.current.client.transport.capture_envelope.call_args.args
  195. assert len(args) == 1
  196. arg = args[0]
  197. assert arg.items[0].type == "statsd"
  198. assert arg.items[0].data_category == "statsd"