httpstats_test.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package misc
  15. import (
  16. "testing"
  17. "time"
  18. "yunion.io/x/jsonutils"
  19. "yunion.io/x/pkg/util/timeutils"
  20. )
  21. func TestUnmarshalHttpStats(t *testing.T) {
  22. input := `{"duration.2XX":4532188.710192006, "duration.4XX":196870.22898800002, "duration.5XX":32787.14909299999, "hit.2XX":88678, "hit.4XX":1748, "hit.5XX":179, "paths":[{"duration.2XX":150, "duration.4XX":250, "duration.5XX":310, "hit.2XX":1500, "hit.4XX":2500, "hit.5XX":3500, "method":"GET", "path":"/servers", "name":"list_servers"}, {"duration.2XX":150, "duration.4XX":250, "duration.5XX":350, "hit.2XX":1500, "hit.4XX":2500, "hit.5XX":3500, "method":"POST", "path":"/servers", "name":"create_servers"}]}`
  23. inputJson, err := jsonutils.ParseString(input)
  24. if err != nil {
  25. t.Fatal(err)
  26. }
  27. t.Logf("json: %s", inputJson.PrettyString())
  28. var stats sApiHttpStats
  29. err = inputJson.Unmarshal(&stats)
  30. if err != nil {
  31. t.Fatal(err)
  32. }
  33. if stats.HttpCode2xx != 4532188.710192006 {
  34. t.Fatalf("duration.2XX: %f", stats.HttpCode2xx)
  35. }
  36. if stats.HttpCode4xx != 196870.22898800002 {
  37. t.Fatalf("duration.4XX: %f", stats.HttpCode4xx)
  38. }
  39. if stats.HttpCode5xx != 32787.14909299999 {
  40. t.Fatalf("duration.5XX: %f", stats.HttpCode5xx)
  41. }
  42. if stats.HitHttpCode2xx != 88678 {
  43. t.Fatalf("hit.2XX: %d", stats.HitHttpCode2xx)
  44. }
  45. if stats.HitHttpCode4xx != 1748 {
  46. t.Fatalf("hit.4XX: %d", stats.HitHttpCode4xx)
  47. }
  48. if stats.HitHttpCode5xx != 179 {
  49. t.Fatalf("hit.5XX: %d", stats.HitHttpCode5xx)
  50. }
  51. }
  52. func TestHttpStats(t *testing.T) {
  53. cases := []struct {
  54. prevTime time.Time
  55. nowTime time.Time
  56. prevStats *sApiHttpStats
  57. nowStats sApiHttpStats
  58. }{
  59. {
  60. nowTime: func() time.Time {
  61. tm, _ := timeutils.ParseTimeStr("2025-06-01 00:01:00")
  62. return tm
  63. }(),
  64. nowStats: sApiHttpStats{
  65. SHttpStats: SHttpStats{
  66. HttpCode2xx: 400,
  67. HttpCode4xx: 700,
  68. HttpCode5xx: 1000,
  69. HitHttpCode2xx: 4000,
  70. HitHttpCode4xx: 7000,
  71. HitHttpCode5xx: 10000,
  72. },
  73. Paths: []SHttpStats{
  74. {
  75. HttpCode2xx: 150,
  76. HttpCode4xx: 250,
  77. HttpCode5xx: 310,
  78. HitHttpCode2xx: 1500,
  79. HitHttpCode4xx: 2500,
  80. HitHttpCode5xx: 3500,
  81. Method: "GET",
  82. Path: "/servers",
  83. Name: "list_servers",
  84. },
  85. {
  86. HttpCode2xx: 150,
  87. HttpCode4xx: 250,
  88. HttpCode5xx: 350,
  89. HitHttpCode2xx: 1500,
  90. HitHttpCode4xx: 2500,
  91. HitHttpCode5xx: 3500,
  92. Method: "POST",
  93. Path: "/servers",
  94. Name: "create_servers",
  95. },
  96. {
  97. HttpCode2xx: 100,
  98. HttpCode4xx: 200,
  99. HttpCode5xx: 300,
  100. HitHttpCode2xx: 1000,
  101. HitHttpCode4xx: 2000,
  102. HitHttpCode5xx: 3000,
  103. Method: "PUT",
  104. Path: "/servers/*",
  105. Name: "update_servers",
  106. },
  107. },
  108. },
  109. },
  110. {
  111. prevTime: func() time.Time {
  112. tm, _ := timeutils.ParseTimeStr("2025-06-01 00:00:00")
  113. return tm
  114. }(),
  115. nowTime: func() time.Time {
  116. tm, _ := timeutils.ParseTimeStr("2025-06-01 00:01:00")
  117. return tm
  118. }(),
  119. prevStats: &sApiHttpStats{
  120. SHttpStats: SHttpStats{
  121. HttpCode2xx: 200,
  122. HttpCode4xx: 400,
  123. HttpCode5xx: 600,
  124. HitHttpCode2xx: 2000,
  125. HitHttpCode4xx: 4000,
  126. HitHttpCode5xx: 6000,
  127. },
  128. Paths: []SHttpStats{
  129. {
  130. HttpCode2xx: 100,
  131. HttpCode4xx: 200,
  132. HttpCode5xx: 300,
  133. HitHttpCode2xx: 1000,
  134. HitHttpCode4xx: 2000,
  135. HitHttpCode5xx: 3000,
  136. Method: "GET",
  137. Path: "/servers",
  138. Name: "list_servers",
  139. },
  140. {
  141. HttpCode2xx: 100,
  142. HttpCode4xx: 200,
  143. HttpCode5xx: 300,
  144. HitHttpCode2xx: 1000,
  145. HitHttpCode4xx: 2000,
  146. HitHttpCode5xx: 3000,
  147. Method: "POST",
  148. Path: "/servers",
  149. Name: "create_servers",
  150. },
  151. },
  152. },
  153. nowStats: sApiHttpStats{
  154. SHttpStats: SHttpStats{
  155. HttpCode2xx: 400,
  156. HttpCode4xx: 700,
  157. HttpCode5xx: 1000,
  158. HitHttpCode2xx: 4000,
  159. HitHttpCode4xx: 7000,
  160. HitHttpCode5xx: 10000,
  161. },
  162. Paths: []SHttpStats{
  163. {
  164. HttpCode2xx: 150,
  165. HttpCode4xx: 250,
  166. HttpCode5xx: 310,
  167. HitHttpCode2xx: 1500,
  168. HitHttpCode4xx: 2500,
  169. HitHttpCode5xx: 3500,
  170. Method: "GET",
  171. Path: "/servers",
  172. Name: "list_servers",
  173. },
  174. {
  175. HttpCode2xx: 150,
  176. HttpCode4xx: 250,
  177. HttpCode5xx: 350,
  178. HitHttpCode2xx: 1500,
  179. HitHttpCode4xx: 2500,
  180. HitHttpCode5xx: 3500,
  181. Method: "POST",
  182. Path: "/servers",
  183. Name: "create_servers",
  184. },
  185. {
  186. HttpCode2xx: 100,
  187. HttpCode4xx: 200,
  188. HttpCode5xx: 300,
  189. HitHttpCode2xx: 1000,
  190. HitHttpCode4xx: 2000,
  191. HitHttpCode5xx: 3000,
  192. Method: "PUT",
  193. Path: "/servers/*",
  194. Name: "update_servers",
  195. },
  196. },
  197. },
  198. },
  199. }
  200. for _, c := range cases {
  201. var prev *sHttpStatsSnapshot
  202. if c.prevStats != nil {
  203. prev = c.prevStats.convertSnapshot(c.prevTime)
  204. }
  205. curr := c.nowStats.convertSnapshot(c.nowTime)
  206. diff := calculateHttpStatsDiff(prev, curr)
  207. metrics := diff.metrics("test", "test", "test", "test")
  208. t.Log(jsonutils.Marshal(metrics).PrettyString())
  209. }
  210. }