test_transport.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. from unittest.mock import patch
  2. import pytest
  3. from minimetrics.core import CounterMetric, DistributionMetric, GaugeMetric, SetMetric
  4. from minimetrics.transport import EncodingError, MetricEnvelopeTransport, RelayStatsdEncoder
  5. from minimetrics.types import BucketKey, FlushedMetric
  6. def test_relay_encoder_with_counter():
  7. encoder = RelayStatsdEncoder()
  8. bucket_key = BucketKey(
  9. timestamp=1693994400,
  10. metric_type="c",
  11. metric_name="button_click",
  12. metric_unit="none",
  13. metric_tags=(
  14. ("browser", "Chrome"),
  15. ("browser.version", "1.0"),
  16. ),
  17. )
  18. metric = CounterMetric(first=2)
  19. flushed_metric = FlushedMetric(bucket_key=bucket_key, metric=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. timestamp=1693994400,
  26. metric_type="d",
  27. metric_name="execution_time",
  28. metric_unit="second",
  29. metric_tags=(
  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 = FlushedMetric(bucket_key=bucket_key, metric=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. timestamp=1693994400,
  47. metric_type="s",
  48. metric_name="users",
  49. metric_unit="none",
  50. metric_tags=(
  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 = FlushedMetric(bucket_key=bucket_key, metric=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. timestamp=1693994400,
  71. metric_type="g",
  72. metric_name="startup_time",
  73. metric_unit="second",
  74. metric_tags=(
  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 = FlushedMetric(bucket_key=bucket_key, metric=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. timestamp=1693994400,
  92. metric_type="c",
  93. metric_name="büttòn_click",
  94. metric_unit="second",
  95. metric_tags=(
  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 = FlushedMetric(bucket_key=bucket_key, metric=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 = BucketKey(
  116. timestamp=1693994400,
  117. metric_type="c",
  118. metric_name="üòë",
  119. metric_unit="second",
  120. metric_tags=(),
  121. )
  122. metric = CounterMetric(first=1)
  123. flushed_metric = FlushedMetric(bucket_key=bucket_key, metric=metric)
  124. with pytest.raises(EncodingError, match="The sanitized metric name üòë is empty"):
  125. encoder.encode(flushed_metric)
  126. def test_relay_encoder_with_multiple_metrics():
  127. encoder = RelayStatsdEncoder()
  128. flushed_metric_1 = FlushedMetric(
  129. bucket_key=BucketKey(
  130. timestamp=1693994400,
  131. metric_type="g",
  132. metric_name="startup_time",
  133. metric_unit="second",
  134. metric_tags=(
  135. ("browser", "Chrome"),
  136. ("browser.version", "1.0"),
  137. ),
  138. ),
  139. metric=GaugeMetric(first=10.0),
  140. )
  141. flushed_metric_2 = FlushedMetric(
  142. bucket_key=BucketKey(
  143. timestamp=1693994400,
  144. metric_type="c",
  145. metric_name="button_click",
  146. metric_unit="none",
  147. metric_tags=(
  148. ("browser", "Chrome"),
  149. ("browser.version", "1.0"),
  150. ),
  151. ),
  152. metric=CounterMetric(first=1),
  153. )
  154. flushed_metric_3 = FlushedMetric(
  155. bucket_key=BucketKey(
  156. timestamp=1693994400,
  157. metric_type="c",
  158. # This name will be completely scraped, resulting in no emission of the metric.
  159. metric_name="öüâ",
  160. metric_unit="none",
  161. metric_tags=(
  162. ("browser", "Chrome"),
  163. ("browser.version", "1.0"),
  164. ),
  165. ),
  166. metric=CounterMetric(first=1),
  167. )
  168. result = encoder.encode_multiple([flushed_metric_1, flushed_metric_2, flushed_metric_3])
  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. )
  174. @patch("minimetrics.transport.sentry_sdk")
  175. def test_send(sentry_sdk):
  176. flushed_metric = FlushedMetric(
  177. bucket_key=BucketKey(
  178. timestamp=1693994400,
  179. metric_type="c",
  180. metric_name="button_click",
  181. metric_unit="none",
  182. metric_tags=(
  183. ("browser", "Chrome"),
  184. ("browser.version", "1.0"),
  185. ),
  186. ),
  187. metric=CounterMetric(first=1),
  188. )
  189. transport = MetricEnvelopeTransport(RelayStatsdEncoder())
  190. transport.send([flushed_metric])
  191. args = sentry_sdk.Hub.current.client.transport.capture_envelope.call_args.args
  192. assert len(args) == 1
  193. arg = args[0]
  194. assert arg.items[0].type == "statsd"
  195. assert arg.items[0].data_category == "statsd"