test_transport.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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. assert (
  61. result == "users@none:456:123:3455635177|s|#browser:Chrome,browser.version:1.0|T1693994400"
  62. )
  63. def test_relay_encoder_with_gauge():
  64. encoder = RelayStatsdEncoder()
  65. bucket_key = BucketKey(
  66. timestamp=1693994400,
  67. metric_type="g",
  68. metric_name="startup_time",
  69. metric_unit="second",
  70. metric_tags=(
  71. ("browser", "Chrome"),
  72. ("browser.version", "1.0"),
  73. ),
  74. )
  75. metric = GaugeMetric(first=10.0)
  76. metric.add(5.0)
  77. metric.add(7.0)
  78. flushed_metric = FlushedMetric(bucket_key=bucket_key, metric=metric)
  79. result = encoder.encode(flushed_metric)
  80. assert (
  81. result
  82. == "startup_time@second:7.0:5.0:10.0:22.0:3|g|#browser:Chrome,browser.version:1.0|T1693994400"
  83. )
  84. def test_relay_encoder_with_invalid_chars():
  85. encoder = RelayStatsdEncoder()
  86. bucket_key = BucketKey(
  87. timestamp=1693994400,
  88. metric_type="c",
  89. metric_name="büttòn_click",
  90. metric_unit="second",
  91. metric_tags=(
  92. # Invalid tag key.
  93. ("browser\nname", "Chrome"),
  94. # Invalid tag value.
  95. ("browser.version", "\t1.\n0ô"),
  96. # Valid tag key and value.
  97. ("platform", "Android"),
  98. # Totally invalid tag key.
  99. ("\nöś", "Windows"),
  100. # Totally invalid tag value.
  101. ("version", "\n\t"),
  102. ),
  103. )
  104. metric = CounterMetric(first=1)
  105. flushed_metric = FlushedMetric(bucket_key=bucket_key, metric=metric)
  106. result = encoder.encode(flushed_metric)
  107. assert (
  108. result
  109. == "bttn_click@second:1|c|#browsername:Chrome,browser.version:1.0,platform:Android,version:|T1693994400"
  110. )
  111. bucket_key = BucketKey(
  112. timestamp=1693994400,
  113. metric_type="c",
  114. metric_name="üòë",
  115. metric_unit="second",
  116. metric_tags=(),
  117. )
  118. metric = CounterMetric(first=1)
  119. flushed_metric = FlushedMetric(bucket_key=bucket_key, metric=metric)
  120. with pytest.raises(EncodingError, match="The sanitized metric name üòë is empty"):
  121. encoder.encode(flushed_metric)
  122. def test_relay_encoder_with_multiple_metrics():
  123. encoder = RelayStatsdEncoder()
  124. flushed_metric_1 = FlushedMetric(
  125. bucket_key=BucketKey(
  126. timestamp=1693994400,
  127. metric_type="g",
  128. metric_name="startup_time",
  129. metric_unit="second",
  130. metric_tags=(
  131. ("browser", "Chrome"),
  132. ("browser.version", "1.0"),
  133. ),
  134. ),
  135. metric=GaugeMetric(first=10.0),
  136. )
  137. flushed_metric_2 = FlushedMetric(
  138. bucket_key=BucketKey(
  139. timestamp=1693994400,
  140. metric_type="c",
  141. metric_name="button_click",
  142. metric_unit="none",
  143. metric_tags=(
  144. ("browser", "Chrome"),
  145. ("browser.version", "1.0"),
  146. ),
  147. ),
  148. metric=CounterMetric(first=1),
  149. )
  150. flushed_metric_3 = FlushedMetric(
  151. bucket_key=BucketKey(
  152. timestamp=1693994400,
  153. metric_type="c",
  154. # This name will be completely scraped, resulting in no emission of the metric.
  155. metric_name="öüâ",
  156. metric_unit="none",
  157. metric_tags=(
  158. ("browser", "Chrome"),
  159. ("browser.version", "1.0"),
  160. ),
  161. ),
  162. metric=CounterMetric(first=1),
  163. )
  164. result = encoder.encode_multiple([flushed_metric_1, flushed_metric_2, flushed_metric_3])
  165. assert result == (
  166. "startup_time@second:10.0:10.0:10.0:10.0:1|g|#browser:Chrome,browser.version:1.0|T1693994400"
  167. + "\n"
  168. + "button_click@none:1|c|#browser:Chrome,browser.version:1.0|T1693994400"
  169. )
  170. @patch("minimetrics.transport.sentry_sdk")
  171. def test_send(sentry_sdk):
  172. flushed_metric = FlushedMetric(
  173. bucket_key=BucketKey(
  174. timestamp=1693994400,
  175. metric_type="c",
  176. metric_name="button_click",
  177. metric_unit="none",
  178. metric_tags=(
  179. ("browser", "Chrome"),
  180. ("browser.version", "1.0"),
  181. ),
  182. ),
  183. metric=CounterMetric(first=1),
  184. )
  185. transport = MetricEnvelopeTransport(RelayStatsdEncoder())
  186. transport.send([flushed_metric])
  187. args = sentry_sdk.Hub.current.client.transport.capture_envelope.call_args.args
  188. assert len(args) == 1
  189. arg = args[0]
  190. assert arg.items[0].type == "statsd"
  191. assert arg.items[0].data_category == "statsd"