Compare commits

..
208 Commits
Author SHA1 Message Date
github-action-benchmark 1b01c102cc add Benchmark (go) benchmark result for da8ec5f21d 2025-12-03 10:30:19 +00:00
github-action-benchmark 848fcf91c2 add Benchmark (go) benchmark result for 3d80f457d3 2025-12-03 03:33:36 +00:00
github-action-benchmark 8b791f80e7 add Benchmark (go) benchmark result for 09c3e4cd95 2025-12-02 03:35:51 +00:00
github-action-benchmark 0e9eac89be add Benchmark (go) benchmark result for d07ee4090c 2025-11-29 15:59:48 +00:00
github-action-benchmark 8eafe6cd8e add Benchmark (go) benchmark result for b1045b8bc2 2025-11-29 15:43:02 +00:00
github-action-benchmark 5162dc966b add Benchmark (go) benchmark result for cc35031db9 2025-11-29 14:58:36 +00:00
github-action-benchmark 1041b05c4d add Benchmark (go) benchmark result for 6a69694ab3 2025-11-29 14:38:19 +00:00
github-action-benchmark 03a9325238 add Benchmark (go) benchmark result for b210627fb7 2025-11-27 11:10:06 +00:00
github-action-benchmark 6617d83581 add Benchmark (go) benchmark result for b210627fb7 2025-11-27 03:29:59 +00:00
github-action-benchmark f3ce948b29 add Benchmark (go) benchmark result for edcabe3cf0 2025-11-25 03:31:32 +00:00
github-action-benchmark 2a82aab3ee add Benchmark (go) benchmark result for c99bf2b245 2025-11-22 17:17:41 +00:00
github-action-benchmark 989616dd03 add Benchmark (go) benchmark result for 28223b40da 2025-11-20 03:29:23 +00:00
github-action-benchmark 23ace05d83 add Benchmark (go) benchmark result for ee5618c699 2025-11-19 03:30:05 +00:00
github-action-benchmark 707c516464 add Benchmark (go) benchmark result for 94c097bc6c 2025-11-18 17:34:42 +00:00
github-action-benchmark 7c6c6a5660 add Benchmark (go) benchmark result for 4e84cd7461 2025-11-18 17:10:03 +00:00
github-action-benchmark 30d9ad2ec1 add Benchmark (go) benchmark result for ae60370ec2739ba7879bdcd0d9510c3e3069415b 2025-11-18 16:44:22 +00:00
github-action-benchmark 22746b3486 add Benchmark (go) benchmark result for 9fbee0d9a1 2025-11-18 03:30:26 +00:00
github-action-benchmark 30742a4f04 add Benchmark (go) benchmark result for 7df651c17a 2025-11-12 03:30:33 +00:00
github-action-benchmark c62e185753 add Benchmark (go) benchmark result for 7ada94e4fa 2025-11-11 10:49:20 +00:00
github-action-benchmark f3d4c44f10 add Benchmark (go) benchmark result for c510c29a8f 2025-11-11 03:31:17 +00:00
github-action-benchmark e82d3d5335 add Benchmark (go) benchmark result for 370602858a 2025-11-09 03:30:34 +00:00
github-action-benchmark bfa8c504b9 add Benchmark (go) benchmark result for 6261be6e53 2025-11-06 17:01:48 +00:00
github-action-benchmark e1d6c61172 add Benchmark (go) benchmark result for 5ae4ea1e25 2025-11-05 23:01:26 +00:00
github-action-benchmark 019145cc86 add Benchmark (go) benchmark result for fd30dc0890 2025-11-05 22:03:07 +00:00
github-action-benchmark f0b7d52dcd add Benchmark (go) benchmark result for 2966661054 2025-11-05 21:54:00 +00:00
github-action-benchmark edd1a3c272 add Benchmark (go) benchmark result for 0f23f10e2f 2025-11-05 21:40:54 +00:00
github-action-benchmark 89c687b13e add Benchmark (go) benchmark result for ce39dc1bee 2025-11-05 21:05:16 +00:00
github-action-benchmark 9daf2a8f6a add Benchmark (go) benchmark result for f864e8edcf 2025-11-05 20:34:55 +00:00
github-action-benchmark bdb7897587 add Benchmark (go) benchmark result for e36cdf099e 2025-11-05 11:05:18 +00:00
github-action-benchmark b874f664d4 add Benchmark (go) benchmark result for e2c3d03661 2025-11-04 03:29:01 +00:00
github-action-benchmark 436798dd5f add Benchmark (go) benchmark result for 9de8b7bcaa 2025-10-30 03:29:07 +00:00
github-action-benchmark c6e1e1477a add Benchmark (go) benchmark result for 163fc5ac42 2025-10-27 03:35:52 +00:00
github-action-benchmark 8ff03604a8 add Benchmark (go) benchmark result for 758412e54e 2025-10-24 03:24:34 +00:00
github-action-benchmark 3c284713df add Benchmark (go) benchmark result for 2f3909c5b0 2025-10-23 03:26:05 +00:00
github-action-benchmark db45b660f7 add Benchmark (go) benchmark result for 737e349b66 2025-10-21 03:29:24 +00:00
github-action-benchmark c535e3377e add Benchmark (go) benchmark result for 55c6843c8c 2025-10-19 03:32:30 +00:00
github-action-benchmark 30faa96ac6 add Benchmark (go) benchmark result for d6534ed519 2025-10-15 03:25:33 +00:00
github-action-benchmark 0cd280ac60 add Benchmark (go) benchmark result for d471948e19 2025-10-10 03:23:29 +00:00
github-action-benchmark fa4bca5da4 add Benchmark (go) benchmark result for a8959b6afa 2025-10-09 03:22:58 +00:00
github-action-benchmark d655f7b84f add Benchmark (go) benchmark result for bb4979587b 2025-10-08 03:20:53 +00:00
github-action-benchmark 808e4ea8b7 add Benchmark (go) benchmark result for 58f511103d 2025-10-07 03:21:18 +00:00
github-action-benchmark 574ea91a97 add Benchmark (go) benchmark result for 9b74334a15 2025-10-03 03:20:12 +00:00
github-action-benchmark 0f5a56331b add Benchmark (go) benchmark result for 63e2e46578 2025-10-01 03:28:33 +00:00
github-action-benchmark 118bbc23fe add Benchmark (go) benchmark result for e3e9f7d181 2025-09-30 23:31:50 +00:00
github-action-benchmark 0b86e9b8cf add Benchmark (go) benchmark result for 0fc776228f 2025-09-30 23:27:17 +00:00
github-action-benchmark e8e138a5a2 add Benchmark (go) benchmark result for cedee416a8 2025-09-30 17:36:24 +00:00
github-action-benchmark ccbc8107a0 add Benchmark (go) benchmark result for 3bd96cbd8a 2025-08-27 03:24:51 +00:00
github-action-benchmark bca60e9829 add Benchmark (go) benchmark result for 39ab54c813 2025-08-26 03:27:38 +00:00
github-action-benchmark 395b7fdac6 add Benchmark (go) benchmark result for e46ca12cfb 2025-08-21 03:26:49 +00:00
github-action-benchmark 4dfb5cd07e add Benchmark (go) benchmark result for c37f0fa754 2025-08-20 03:27:00 +00:00
github-action-benchmark 3cc03bc4a7 add Benchmark (go) benchmark result for 43a0309280 2025-08-19 03:27:32 +00:00
github-action-benchmark 394aadc063 add Benchmark (go) benchmark result for a74a6c7624 2025-08-15 03:35:18 +00:00
github-action-benchmark 7a9b3abb22 add Benchmark (go) benchmark result for d44e8a99a7 2025-08-14 03:36:06 +00:00
github-action-benchmark 74c02a37ac add Benchmark (go) benchmark result for 58932d27da 2025-08-12 03:32:27 +00:00
github-action-benchmark 9f9cbe9763 add Benchmark (go) benchmark result for add5700298 2025-08-08 03:39:16 +00:00
github-action-benchmark 65722929cb add Benchmark (go) benchmark result for 3d18b2fcd4 2025-08-06 03:39:29 +00:00
github-action-benchmark 6d86feb95f add Benchmark (go) benchmark result for 789a1a4511 2025-08-05 03:39:26 +00:00
github-action-benchmark af4569e35b add Benchmark (go) benchmark result for 8432e5ca03 2025-08-04 03:44:45 +00:00
github-action-benchmark 0a50c97455 add Benchmark (go) benchmark result for 3feb16a89a 2025-08-01 03:44:38 +00:00
github-action-benchmark 200c182128 add Benchmark (go) benchmark result for 7144ce717e 2025-07-29 03:40:58 +00:00
github-action-benchmark 9b5876e104 add Benchmark (go) benchmark result for c76c1f2487 2025-07-24 03:37:42 +00:00
github-action-benchmark 61219dbfd7 add Benchmark (go) benchmark result for 0603a5463f 2025-07-23 03:38:17 +00:00
github-action-benchmark f44dddb537 add Benchmark (go) benchmark result for 335f8767ac 2025-07-22 03:37:26 +00:00
github-action-benchmark fa95413879 add Benchmark (go) benchmark result for 274b8f1349 2025-07-17 03:37:22 +00:00
github-action-benchmark ad6c43a986 add Benchmark (go) benchmark result for aed6508091 2025-07-16 03:37:38 +00:00
github-action-benchmark 5c0080557b add Benchmark (go) benchmark result for bcf2cc9621 2025-07-11 03:37:18 +00:00
github-action-benchmark 39440e852b add Benchmark (go) benchmark result for 66c2dfac29 2025-07-08 03:33:25 +00:00
github-action-benchmark e46c6d5e2b add Benchmark (go) benchmark result for b4b2fd92aa 2025-07-01 03:38:02 +00:00
github-action-benchmark 1a525aaf42 add Benchmark (go) benchmark result for 6dbfe97bc7 2025-06-27 03:32:50 +00:00
github-action-benchmark 4839f4f77c add Benchmark (go) benchmark result for c4eff8e230 2025-06-25 03:33:19 +00:00
github-action-benchmark 34324b02a8 add Benchmark (go) benchmark result for ee57c998fa 2025-06-24 03:33:02 +00:00
github-action-benchmark bcaa6e96fb add Benchmark (go) benchmark result for f727af1208 2025-06-18 03:30:55 +00:00
github-action-benchmark b38ce4f93b add Benchmark (go) benchmark result for 1187c467b6 2025-06-14 03:28:37 +00:00
github-action-benchmark 35c09b6c10 add Benchmark (go) benchmark result for fa117b5a9a 2025-06-07 03:28:29 +00:00
github-action-benchmark 2c720cf813 add Benchmark (go) benchmark result for e44d5dfe6b 2025-06-06 03:30:18 +00:00
github-action-benchmark 9b5d6e1a4f add Benchmark (go) benchmark result for fa952d95df 2025-05-28 03:27:55 +00:00
github-action-benchmark 7b5a7fdeb4 add Benchmark (go) benchmark result for 4594f897e7 2025-05-27 03:26:49 +00:00
github-action-benchmark 72c81650b3 add Benchmark (go) benchmark result for 5290557bb0 2025-05-24 03:25:36 +00:00
github-action-benchmark 7de5aa622c add Benchmark (go) benchmark result for 4334482bae 2025-05-22 03:27:53 +00:00
github-action-benchmark 677dcc8ccf add Benchmark (go) benchmark result for f7620a21d8 2025-05-18 03:30:27 +00:00
github-action-benchmark dce7768968 add Benchmark (go) benchmark result for 62a5167438 2025-05-15 03:26:36 +00:00
github-action-benchmark 8c984e2e52 add Benchmark (go) benchmark result for 8eeca7d61e 2025-05-14 03:26:59 +00:00
github-action-benchmark 4eb690e9b1 add Benchmark (go) benchmark result for 8822afd6bf 2025-05-08 03:26:54 +00:00
github-action-benchmark 1a9f3efb76 add Benchmark (go) benchmark result for 93a9eb52c9 2025-05-06 03:25:37 +00:00
github-action-benchmark cd92cf5927 add Benchmark (go) benchmark result for daf0a8e9a5 2025-05-01 03:29:17 +00:00
github-action-benchmark 491282439c add Benchmark (go) benchmark result for 98a641f4b4 2025-04-29 03:24:18 +00:00
github-action-benchmark 79df459063 add Benchmark (go) benchmark result for a794f06a8a 2025-04-23 03:23:33 +00:00
github-action-benchmark b16f8554df add Benchmark (go) benchmark result for bd70516414 2025-04-15 03:23:30 +00:00
github-action-benchmark a4b407b137 add Benchmark (go) benchmark result for 9b8fc53f01 2025-04-10 03:22:53 +00:00
github-action-benchmark eb3ea3d0f7 add Benchmark (go) benchmark result for 57a4211f0a 2025-04-09 03:22:13 +00:00
github-action-benchmark 2e5619b0df add Benchmark (go) benchmark result for b84765ff6b 2025-04-08 03:21:45 +00:00
github-action-benchmark ac6cd9589f add Benchmark (go) benchmark result for e83086c06d 2025-04-03 03:21:45 +00:00
github-action-benchmark f09c8de547 add Benchmark (go) benchmark result for 07d4c715b1 2025-04-02 03:21:14 +00:00
github-action-benchmark 2540318a48 add Benchmark (go) benchmark result for 0a816a2810 2025-03-29 03:19:42 +00:00
github-action-benchmark e27389011b add Benchmark (go) benchmark result for 37ac050c30 2025-03-26 11:16:06 +00:00
github-action-benchmark 22c1479104 add Benchmark (go) benchmark result for 37ac050c30 2025-03-26 03:19:36 +00:00
github-action-benchmark ba8d6d7edc add Benchmark (go) benchmark result for 6abf5e6410 2025-03-22 03:18:44 +00:00
github-action-benchmark bb2b676ea1 add Benchmark (go) benchmark result for 76950408ae 2025-03-21 09:45:56 +00:00
github-action-benchmark 7ce62819ed add Benchmark (go) benchmark result for 339efc249a 2025-03-21 03:19:38 +00:00
github-action-benchmark a7ed11dc13 add Benchmark (go) benchmark result for 94388d7f4a 2025-03-14 03:16:57 +00:00
github-action-benchmark 76f34cc0aa add Benchmark (go) benchmark result for 227bdae2e0 2025-03-12 03:17:28 +00:00
github-action-benchmark 7faccea2cc add Benchmark (go) benchmark result for 4f6a5a8b46 2025-03-07 03:17:25 +00:00
github-action-benchmark 8521749740 add Benchmark (go) benchmark result for 8fe185f9e3 2025-03-06 03:17:00 +00:00
github-action-benchmark 79b0222a2f add Benchmark (go) benchmark result for c9bd5b050e 2025-03-05 03:16:42 +00:00
github-action-benchmark 76f2f81dd6 add Benchmark (go) benchmark result for d74748bb18 2025-03-01 03:19:08 +00:00
github-action-benchmark efc4c93904 add Benchmark (go) benchmark result for ac43b24da1 2025-02-28 19:15:25 +00:00
github-action-benchmark 78df0b080c add Benchmark (go) benchmark result for 7f8260d5c3 2025-02-26 03:13:33 +00:00
github-action-benchmark 011aef96c6 add Benchmark (go) benchmark result for 66c8fef24d 2025-02-26 00:50:33 +00:00
github-action-benchmark 77ba78d322 add Benchmark (go) benchmark result for da577e8a02 2025-02-25 03:17:18 +00:00
github-action-benchmark 4e70d49eb7 add Benchmark (go) benchmark result for 71c94084d3 2025-02-22 03:11:45 +00:00
github-action-benchmark 64dd6f9d79 add Benchmark (go) benchmark result for 136148c4d2 2025-02-20 03:13:52 +00:00
github-action-benchmark bec3832f4d add Benchmark (go) benchmark result for 30ec0ce177 2025-02-19 03:12:46 +00:00
github-action-benchmark f3eae859a4 add Benchmark (go) benchmark result for 34f189b6b4 2025-02-18 03:11:47 +00:00
github-action-benchmark a8507e3fe7 add Benchmark (go) benchmark result for 0c4ccd61bf 2025-02-13 03:13:53 +00:00
github-action-benchmark 2fcc220325 add Benchmark (go) benchmark result for 3a9260a60b 2025-02-12 03:11:41 +00:00
github-action-benchmark 9d782ae628 add Benchmark (go) benchmark result for d39a42bf50 2025-02-11 03:12:38 +00:00
github-action-benchmark 2cca794730 add Benchmark (go) benchmark result for f8d31b3cf6 2025-02-08 03:10:58 +00:00
github-action-benchmark 0b1e2aff4f add Benchmark (go) benchmark result for 93e078971c 2025-02-07 03:12:42 +00:00
github-action-benchmark e9f918f00e add Benchmark (go) benchmark result for 589f22fe33 2025-02-06 03:13:24 +00:00
github-action-benchmark cc363502ed add Benchmark (go) benchmark result for e43d6f8df3 2025-02-05 03:11:22 +00:00
github-action-benchmark 473006c20a add Benchmark (go) benchmark result for 97a74c9603 2025-01-29 03:10:20 +00:00
github-action-benchmark f217d4167d add Benchmark (go) benchmark result for 79605280f7 2025-01-28 03:10:54 +00:00
github-action-benchmark b53a380e5c add Benchmark (go) benchmark result for 7cb6aa05a8 2025-01-25 03:09:43 +00:00
github-action-benchmark 4be440ee23 add Benchmark (go) benchmark result for e42b494d1c 2025-01-24 03:10:13 +00:00
github-action-benchmark c6b1365d18 add Benchmark (go) benchmark result for 89582d368d 2025-01-22 03:11:43 +00:00
github-action-benchmark 85930dbe09 add Benchmark (go) benchmark result for 06bf63613b 2025-01-18 03:09:03 +00:00
github-action-benchmark 6c93bc0e65 add Benchmark (go) benchmark result for 36f163de8f 2025-01-17 03:10:33 +00:00
github-action-benchmark f253192cb4 add Benchmark (go) benchmark result for 197201363f 2025-01-14 03:09:01 +00:00
github-action-benchmark f3663ec883 add Benchmark (go) benchmark result for 0e35e24829 2025-01-11 03:13:26 +00:00
github-action-benchmark c0c38c714e add Benchmark (go) benchmark result for 7a064935c6 2025-01-09 03:25:57 +00:00
github-action-benchmark 885a341df5 add Benchmark (go) benchmark result for 6af5aefe54 2025-01-08 18:36:27 +00:00
github-action-benchmark 7e7fd446fd add Benchmark (go) benchmark result for dda7044284 2025-01-08 03:12:28 +00:00
github-action-benchmark eadf97fc53 add Benchmark (go) benchmark result for 4a20ce2fba 2025-01-07 03:14:50 +00:00
github-action-benchmark e38ae7cfc3 add Benchmark (go) benchmark result for 8a65a692b7 2025-01-06 03:15:13 +00:00
github-action-benchmark ff26e696c7 add Benchmark (go) benchmark result for 8a2c96f6ce 2025-01-05 03:15:58 +00:00
github-action-benchmark d2ed23e19f add Benchmark (go) benchmark result for 932b780503 2025-01-01 03:17:00 +00:00
github-action-benchmark 0a4dac225f add Benchmark (go) benchmark result for 14a7ed80d9 2024-12-22 03:15:54 +00:00
github-action-benchmark c640eb5c93 add Benchmark (go) benchmark result for 55cb61cc07 2024-12-20 03:12:45 +00:00
github-action-benchmark dc18cf0173 add Benchmark (go) benchmark result for 8bd2bdfd9c 2024-12-19 18:54:24 +00:00
github-action-benchmark cfad6cb3cf add Benchmark (go) benchmark result for 55e7d99b6a 2024-12-19 03:17:49 +00:00
github-action-benchmark e902fd0560 add Benchmark (go) benchmark result for 241c985bb4 2024-12-13 03:23:58 +00:00
github-action-benchmark d364e9e3a5 add Benchmark (go) benchmark result for 19b3b3e596 2024-12-12 03:22:33 +00:00
github-action-benchmark af12d47b89 add Benchmark (go) benchmark result for 5852a4c356 2024-12-11 03:21:26 +00:00
github-action-benchmark 76d34d17f9 add Benchmark (go) benchmark result for e814345069 2024-12-10 03:24:14 +00:00
github-action-benchmark d80ceb9a03 add Benchmark (go) benchmark result for 5799f8ca7c 2024-12-06 13:27:27 +00:00
github-action-benchmark 106314c9e9 add Benchmark (go) benchmark result for e54bbe8249 2024-12-06 12:09:17 +00:00
github-action-benchmark 1092b7ad39 add Benchmark (go) benchmark result for 6a52a9f673 2024-12-06 11:55:15 +00:00
github-action-benchmark 4b4800085a add Benchmark (go) benchmark result for 1ca05a7a2a 2024-12-06 11:34:18 +00:00
github-action-benchmark 625fe939be add Benchmark (go) benchmark result for 2190744729 2024-12-06 03:21:43 +00:00
github-action-benchmark f476c4349b add Benchmark (go) benchmark result for 0a96d139b6 2024-12-05 03:22:22 +00:00
github-action-benchmark 7fcfa70884 add Benchmark (go) benchmark result for 1c1ac06e11 2024-11-10 03:13:29 +00:00
github-action-benchmark 1c31134dfc add Benchmark (go) benchmark result for b2a67df3b6 2024-11-09 03:10:35 +00:00
github-action-benchmark 7683665982 add Benchmark (go) benchmark result for 3805e63f95 2024-11-08 03:11:23 +00:00
github-action-benchmark 98b0c4cccc add Benchmark (go) benchmark result for 8abf731867 2024-10-29 03:15:07 +00:00
github-action-benchmark 9cb17a74f0 add Benchmark (go) benchmark result for 4e9db9a5c7 2024-10-18 03:13:59 +00:00
github-action-benchmark 922fa189de add Benchmark (go) benchmark result for 615836ab36 2024-10-15 03:15:10 +00:00
github-action-benchmark c78558799e add Benchmark (go) benchmark result for a51f37c0a2 2024-10-12 03:11:23 +00:00
github-action-benchmark 0e6131b10e add Benchmark (go) benchmark result for 6b31e5c4c0 2024-10-10 09:39:13 +00:00
github-action-benchmark 2fbd57fc53 add Benchmark (go) benchmark result for d919a1df75 2024-10-10 03:14:28 +00:00
github-action-benchmark e71af3513b add Benchmark (go) benchmark result for 71216bc247 2024-10-06 03:15:39 +00:00
github-action-benchmark 16f9857f51 add Benchmark (go) benchmark result for e07ac59aee 2024-10-05 03:11:44 +00:00
github-action-benchmark 98496e769c add Benchmark (go) benchmark result for baa30bfba9 2024-10-04 03:12:43 +00:00
github-action-benchmark 65f75777a6 add Benchmark (go) benchmark result for f210f51e17 2024-10-03 03:13:19 +00:00
github-action-benchmark ee133d16d5 add Benchmark (go) benchmark result for b09821a0b1 2024-09-29 03:16:17 +00:00
github-action-benchmark b6a239c82b add Benchmark (go) benchmark result for f835ad4e42 2024-09-25 03:15:43 +00:00
github-action-benchmark 88229087a0 add Benchmark (go) benchmark result for 659e27bbf6 2024-09-24 03:12:35 +00:00
github-action-benchmark dd87c2771c add Benchmark (go) benchmark result for 7726be1aed 2024-09-16 20:49:42 +00:00
github-action-benchmark 95f89fa1be add Benchmark (go) benchmark result for 2e1ca3584d 2024-09-13 20:48:01 +00:00
github-action-benchmark 2390852a8e add Benchmark (go) benchmark result for 54d24ff59d 2024-09-11 03:08:45 +00:00
github-action-benchmark 3e58c7ca47 add Benchmark (go) benchmark result for a1742e9aa5 2024-09-08 03:10:51 +00:00
github-action-benchmark c84878aff9 add Benchmark (go) benchmark result for cb385d1595 2024-09-07 03:08:29 +00:00
github-action-benchmark ad72465d6f add Benchmark (go) benchmark result for 1ebe3c4d65 2024-09-06 03:09:24 +00:00
github-action-benchmark 6060d3bea9 add Benchmark (go) benchmark result for 5260c34f8e 2024-09-05 03:08:42 +00:00
github-action-benchmark 57c1bd2c37 add Benchmark (go) benchmark result for 68526ddfd4 2024-08-20 12:20:27 +00:00
github-action-benchmark 33f2645aa9 add Benchmark (go) benchmark result for 427ed49d62 2024-08-20 11:28:35 +00:00
github-action-benchmark 216a57ee69 add Benchmark (go) benchmark result for 9150b25227 2024-08-20 10:44:32 +00:00
github-action-benchmark d87c7eda79 add Benchmark (go) benchmark result for 839e211790 2024-08-19 14:57:39 +00:00
github-action-benchmark e6e124fda8 add Benchmark (go) benchmark result for ae9a44033b 2024-08-19 14:49:35 +00:00
github-action-benchmark 7c59b320ea add Benchmark (go) benchmark result for dc9e0906fd 2024-08-19 10:33:24 +00:00
github-action-benchmark 9a26644c25 add Benchmark (go) benchmark result for 016374722d 2024-08-10 03:08:18 +00:00
github-action-benchmark ab684f562c add Benchmark (go) benchmark result for 7e503a70fd 2024-08-09 03:08:20 +00:00
github-action-benchmark 43dcb594d8 add Benchmark (go) benchmark result for 75270008dc 2024-08-08 03:08:07 +00:00
github-action-benchmark 6cf5058982 add Benchmark (go) benchmark result for 3e0dffb898 2024-08-07 03:08:12 +00:00
github-action-benchmark c18d360925 add Benchmark (go) benchmark result for 3eed8b24c4 2024-08-06 03:08:55 +00:00
github-action-benchmark 3d6d5b4d14 add Benchmark (go) benchmark result for 71589f93f1 2024-08-05 03:07:57 +00:00
github-action-benchmark 09a09822c8 add Benchmark (go) benchmark result for 50fde94e13 2024-08-01 03:08:23 +00:00
github-action-benchmark 63cbc1ec39 add Benchmark (go) benchmark result for 8bf7a279a5 2024-07-26 03:08:40 +00:00
github-action-benchmark 473e9dafbb add Benchmark (go) benchmark result for 08cc0f9942 2024-07-23 03:08:15 +00:00
github-action-benchmark 17c922cb94 add Benchmark (go) benchmark result for 771724bfee 2024-07-20 03:08:03 +00:00
github-action-benchmark 78b799e6b9 add Benchmark (go) benchmark result for f69b03d12c 2024-07-17 03:08:30 +00:00
github-action-benchmark 47838d0489 add Benchmark (go) benchmark result for 82b0004cc6 2024-07-16 03:08:49 +00:00
github-action-benchmark 33d0e8ff92 add Benchmark (go) benchmark result for 4a2ce95dfa 2024-07-13 03:08:11 +00:00
github-action-benchmark e28c4ab681 add Benchmark (go) benchmark result for 53933f218b 2024-07-11 03:09:57 +00:00
github-action-benchmark e7a36ec5b1 add Benchmark (go) benchmark result for 306139fcef 2024-07-10 03:08:23 +00:00
github-action-benchmark 674aefac4e add Benchmark (go) benchmark result for ab703d331e 2024-07-06 03:08:21 +00:00
github-action-benchmark 66466d031c add Benchmark (go) benchmark result for a2986dfc1a 2024-07-05 03:09:12 +00:00
github-action-benchmark fc1eec3875 add Benchmark (go) benchmark result for cb862ae4b1 2024-07-03 03:08:09 +00:00
github-action-benchmark d3b14a4cfc add Benchmark (go) benchmark result for e28da35ca4 2024-07-01 03:08:16 +00:00
github-action-benchmark fc3182363b add Benchmark (go) benchmark result for 8bdc151c7e 2024-06-30 03:09:42 +00:00
github-action-benchmark a436aec94c add Benchmark (go) benchmark result for dfd3b02014 2024-06-29 09:03:53 +00:00
github-action-benchmark 5c5329b702 add Benchmark (go) benchmark result for a24e6c8c4d 2024-06-29 07:58:13 +00:00
github-action-benchmark b9dbbddbf2 add Benchmark (go) benchmark result for d141fe3c04 2024-06-28 20:53:59 +00:00
github-action-benchmark 9aa107576e add Benchmark (go) benchmark result for 162c4acd7c 2024-06-28 17:10:57 +00:00
github-action-benchmark fe4094265f add Benchmark (go) benchmark result for b1ffffd545 2024-06-28 16:54:58 +00:00
lukaszraczylo 434f0c6939 fixup! fixup! Initial commit on gh-pages 2024-06-28 14:13:39 +01:00
github-action-benchmark 27e51ba175 add Benchmark (go) benchmark result for 4ca8ce5751 2024-06-28 13:05:26 +00:00
lukaszraczylo 6c0ec93cdd fixup! Initial commit on gh-pages 2024-06-28 13:57:10 +01:00
lukaszraczylo b6dfc176ed Initial commit on gh-pages 2024-06-28 13:51:49 +01:00
18 changed files with 136217 additions and 542 deletions
-17
View File
@@ -1,17 +0,0 @@
name: Test and release
on:
workflow_dispatch:
push:
paths-ignore:
- '**.md'
branches:
- "*"
jobs:
shared:
uses: telegram-bot-app/ci-scripts/.github/workflows/build-test-publish-inject.yaml@main
with:
enable-code-scans: false
secrets:
ghcr-token: ${{ secrets.GHCR_TOKEN }}
+1
View File
@@ -1,2 +1,3 @@
graphql-proxy
test.sh
banned.json*
-8
View File
@@ -1,8 +0,0 @@
FROM alpine:latest
RUN apk add --no-cache ca-certificates
WORKDIR /go/src/app
ARG TARGETARCH
ARG TARGETOS
ADD dist/bot-$TARGETOS-$TARGETARCH /go/src/app/graphql-proxy
RUN chmod +x /go/src/app/graphql-proxy
ENTRYPOINT ["/go/src/app/graphql-proxy"]
-34
View File
@@ -1,34 +0,0 @@
CI_RUN?=false
ADDITIONAL_BUILD_FLAGS=""
ifeq ($(CI_RUN), true)
ADDITIONAL_BUILD_FLAGS="-test.short"
endif
.PHONY: help
help: ## display this help
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n\nTargets:\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 }' $(MAKEFILE_LIST)
.PHONY: run
run: ## run application
@LOG_LEVEL=debug JWT_USER_CLAIM_PATH="Hasura.x-hasura-user-id" HOST_GRAPHQL=https://hasura8.lan/v1/graphql go run *.go
.PHONY: build
build: ## build the binary
go build -o graphql-proxy *.go
.PHONY: test
test: ## run tests on library
@LOG_LEVEL=debug go test $(ADDITIONAL_BUILD_FLAGS) -v -cover ./... -race
.PHONY: test-packages
test-packages: ## run tests on packages
@go test -v -cover ./pkg/...
.PHONY: all
all: test-packages test
.PHONY: update
update: ## update dependencies
@go get -u -v ./...
@go mod tidy -v
+309 -11
View File
@@ -1,22 +1,320 @@
## graphql monitoring proxy
Creates a passthrough proxy to a graphql endpoint(s), allowing you for analysis of the queries and responses, producing the prometheus metrics at a fraction of the cost - because as we know - $0 is a fair price.
Creates a passthrough proxy to a graphql endpoint(s), allowing you to analyse the queries and responses, producing the Prometheus metrics at a fraction of the cost - because, as we know - $0 is a fair price.
This project is in active use by [telegram-bot.app](https://telegram-bot.app), and was tested with 30k queries per second on a single instance, consuming 10 MB of RAM and 0.1% CPU. [Benchmarks](https://lukaszraczylo.github.io/graphql-monitoring-proxy/dev/bench/) are available.
![Example of monitoring dashboard](static/monitoring-at-glance.png?raw=true)
- [graphql monitoring proxy](#graphql-monitoring-proxy)
- [Why this project exists](#why-this-project-exists)
- [How to deploy](#how-to-deploy)
- [Note on websocket support](#note-on-websocket-support)
- [Endpoints](#endpoints)
- [Features](#features)
- [Configuration](#configuration)
- [Speed](#speed)
- [Caching](#caching)
- [Read-only endpoint](#read-only-endpoint)
- [Maintenance](#maintenance)
- [Hasura event cleaner](#hasura-event-cleaner)
- [Security](#security)
- [Role-based rate limiting](#role-based-rate-limiting)
- [Read-only mode](#read-only-mode)
- [Allowing access to listed URLs](#allowing-access-to-listed-urls)
- [Blocking introspection](#blocking-introspection)
- [API endpoints](#api-endpoints)
- [Ban or unban the user](#ban-or-unban-the-user)
- [Cache operations](#cache-operations)
- [General](#general)
- [Metrics which matter](#metrics-which-matter)
- [Healthcheck](#healthcheck)
- [Monitoring endpoint](#monitoring-endpoint)
### Why this project exists
I wanted to monitor the queries and responses of our graphql endpoint. Still, we didn't want to pay the price of the graphql server itself ( and I will not point fingers at a particular well-known project), as monitoring and basic security features should be a standard, free functionality.
### How to deploy
You can find the example of the Kubernetes manifest in the [example standalone deployment](static/kubernetes-deployment.yaml) or [example combined deployment](static/kubernetes-single-deployment.yaml) files. Observed advantage of multideployment is that it allows the network requests to travel via localhost, without leaving the deployment which brings quite significant network performance boost.
#### Note on websocket support
Proxy in its current version 0.5.30 does not support websockets. If you need to proxy the websocket requests - you can use following trick whilst setting up the proxy. As I'm a big fan of Traefik - there's an example which works with the mentioned above combined deployment.
<details>
<summary>Click to show working Traefik Ingress Route example.</summary>
```yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: hasura-internal
spec:
entryPoints:
- websecure
routes:
# NON WEBSOCKET CONNECTION
- kind: Rule
match: Host(`example.com`) && PathPrefix(`/v1/graphql`) && !HeadersRegexp(`Upgrade`, `websocket`)
services:
- name: hasura-w-proxy-internal
port: proxy
middlewares:
- name: compression
namespace: default
# WEBSOCKET CONNECTION
- kind: Rule
match: Host(`example.com`) && PathPrefix(`/v1/graphql`) && HeadersRegexp(`Upgrade`, `websocket`)
services:
- name: hasura-w-proxy-internal
port: hasura
middlewares:
- name: compression
namespace: default
```
In this case, both proxy and websockets will be available under the `/v1/graphql` path, and the websocket connection will be proxied directly to the hasura service, bypassing the proxy.
</details>
### Endpoints
/v1/graphql - the graphql endpoint
/metrics - the prometheus metrics endpoint
/healthz - the healthcheck endpoint
* `:8080/*` - the graphql passthrough endpoint
* `:9393/metrics` - the prometheus metrics endpoint
* `:8080/healthz` - the healthcheck endpoint
* `:8080/livez` - the liveness probe endpoint
* `:9090/api/*` - the monitoring proxy API endpoint
### Features
| Category | Detail |
|------------|-----------------------------------------------------------------------|
| monitor | Prometheus / VictoriaMetrics metrics |
| monitor | Extracting user id from JWT token and adding it as a label to metrics |
| monitor | Extracting the query name and type and adding it as a label to metrics|
| monitor | Calculating the query duration and adding it to the metrics |
| speed | Caching the queries, together with per-query cache and TTL |
| speed | Support for READ ONLY graphql endpoint |
| security | Blocking schema introspection |
| security | Rate limiting queries based on user role |
| security | Blocking mutations in read-only mode |
| security | Allow access only to listed URLs |
| security | Ban / unban specific user from accessing the application |
| maintenance | Hasura event cleaner |
### Configuration
`MONITORING_PORT` - the port to expose the metrics endpoint on (default: 9393)
`PORT_GRAPHQL` - the port to expose the graphql endpoint on (default: 8080)
`HOST_GRAPHQL` - the host to proxy the graphql endpoint to (default: `localhost/v1/graphql`)
All the environment variables **should** be prefixed with `GMP_` to avoid conflicts with other applications.
If `GMP_` prefixed environment variable is present - it will take precedence over the non-prefixed one.
You can still use the non-prefixed environment variables in the spirit of the backward compatibility, but it's not recommended.
`JWT_USER_CLAIM_PATH` - the path to the user claim in the JWT token (default: ``)
| Parameter | Description | Default Value |
|---------------------------|------------------------------------------|----------------------------|
| `MONITORING_PORT` | The port to expose the metrics endpoint | `9393` |
| `PORT_GRAPHQL` | The port to expose the graphql endpoint | `8080` |
| `HOST_GRAPHQL` | The host to proxy the graphql endpoint | `http://localhost/` |
| `HOST_GRAPHQL_READONLY` | The host to proxy the read-only graphql endpoint | `` |
| `HEALTHCHECK_GRAPHQL_URL` | The URL to check the health of the graphql endpoint | `` |
| `JWT_USER_CLAIM_PATH` | Path to the user claim in the JWT token | `` |
| `JWT_ROLE_CLAIM_PATH` | Path to the role claim in the JWT token | `` |
| `ROLE_FROM_HEADER` | Header name to extract the role from | `` |
| `ROLE_RATE_LIMIT` | Enable request rate limiting based on role| `false` |
| `ENABLE_GLOBAL_CACHE` | Enable the cache | `false` |
| `CACHE_TTL` | The cache TTL | `60` |
| `ENABLE_REDIS_CACHE` | Enable distributed Redis cache | `false` |
| `CACHE_REDIS_URL` | URL to redis server / cluster endpoint | `localhost:6379` |
| `CACHE_REDIS_PASSWORD` | Redis connection password | `` |
| `CACHE_REDIS_DB` | Redis DB id | `0` |
| `LOG_LEVEL` | The log level | `info` |
| `BLOCK_SCHEMA_INTROSPECTION`| Blocks the schema introspection | `false` |
| `ALLOWED_INTROSPECTION` | Allow only certain queries in introspection | `` |
| `ENABLE_ACCESS_LOG` | Enable the access log | `false` |
| `READ_ONLY_MODE` | Enable the read only mode | `false` |
| `ALLOWED_URLS` | Allow access only to certain URLs | `/v1/graphql,/v1/version` |
| `ENABLE_API` | Enable the monitoring API | `false` |
| `API_PORT` | The port to expose the monitoring API | `9090` |
| `BANNED_USERS_FILE` | The path to the file with banned users | `/go/src/app/banned_users.json` |
| `PROXIED_CLIENT_TIMEOUT` | The timeout for the proxied client in seconds | `120` |
| `PURGE_METRICS_ON_CRAWL` | Purge metrics on each /metrics crawl | `false` |
| `PURGE_METRICS_ON_TIMER` | Purge metrics every x seconds. `0` - disabled | `0` |
| `HASURA_EVENT_CLEANER` | Enable the hasura event cleaner | `false` |
| `HASURA_EVENT_CLEANER_OLDER_THAN` | The interval for the hasura event cleaner (in days) | `1` |
| `HASURA_EVENT_METADATA_DB` | URL to the hasura metadata database | `postgresql://localhost:5432/hasura` |
`ENABLE_CACHE` - enable the cache (default: `false`)
`CACHE_TTL` - the cache TTL (default: `60s`)
### Speed
`LOG_LEVEL` - the log level (default: `info`)
#### Caching
The cache engine is enabled in the background by default, using no additional resources.
You can then start using the cache by setting the `ENABLE_GLOBAL_CACHE` or `ENABLE_REDIS_CACHE` environment variable to `true` - which will enable the cache for all queries without introspection. You can leave the global cache disabled and enable the cache for specific queries by adding the `@cached` directive to the query.
In the case of the `@cached` you can add additional parameters to the directive which will set the cache for specific queries to the provided time.
For example, `query MyCachedQuery @cached(ttl: 90) ....` will set the cache for the query to 90 seconds.
You can also set cache for specific query by using `X-Cache-Graphql-Query` header, which will set the cache for the query to the provided time, for example `X-Cache-Graphql-Query: 90` will set the cache for the query to 90 seconds.
You can also force refresh of the cache by using `@cached(refresh: true)` directive in the query, for example:
```
query MyProducts @cached(refresh: true) {
products {
id
name
}
}
```
Since version `0.5.30` the cache is gzipped in the memory, which should optimise the memory usage quite significantly.
Since version `0.15.48` the you can also use the distributed Redis cache.
#### Read-only endpoint
You can now specify the read-only GraphQL endpoint by setting the `HOST_GRAPHQL_READONLY` environment variable. The default value is empty, preventing the proxy from using the read-only endpoint for the queries and directing all the requests to the main endpoint specified as `HOST_GRAPHQL`. If the `HOST_GRAPHQL_READONLY` is set, the proxy will use the read-only endpoint for the queries with the `query` type and the main endpoint for the `mutation` type queries. Format of the read-only endpoint is the same as `HOST_GRAPHQL` endpoint, for example `http://localhost:8080/`.
You can check out the [example of combined deployment with RW and read-only hasura](static/kubernetes-single-deployment-with-ro.yaml).
### Maintenance
#### Hasura event cleaner
When enabled via `HASURA_EVENT_CLEANER=true` - proxy needs to have a direct access to the database to execute simple delete queries on schedule. You can specify number of days the logs should be kept for using `HASURA_EVENT_CLEANER_OLDER_THAN`, for example `HASURA_EVENT_CLEANER_OLDER_THAN=14` will keep 14 days of event execution logs. Ticker managing the cleaner routine will be executed every hour.
Following tables are being cleaned:
- `hdb_catalog.event_invocation_logs`
- `hdb_catalog.event_log`
- `hdb_catalog.hdb_action_log`
- `hdb_catalog.hdb_cron_event_invocation_logs`
- `hdb_catalog.hdb_scheduled_event_invocation_logs`
### Security
#### Role-based rate limiting
You can rate limit requests using the `ROLE_RATE_LIMIT` environment variable. If enabled, the proxy will rate limit the requests based on the role claim in the JWT token. You can then provide the JSON file in the following format to specify the limits.
The default interval is `second`, but you can use other values as well. If you want to disable the rate limiting for a specific role, you can set the `req` to `0`.
Available values:
`nano`, `micro`, `milli`, `second`, `minute`, `hour`, `day`
To define path in JWT token where the current user role is present, use the `JWT_ROLE_CLAIM_PATH` environment variable.
You can also set up the `ROLE_FROM_HEADER` environment variable to extract the role from the header instead of the JWT token. This is useful if you want to rate limit the requests for unauthenticated users. It's worth mentioning that `ROLE_FROM_HEADER` takes a priority over the `JWT_ROLE_CLAIM_PATH` environment variable and if its set, the proxy will not try to extract the role from the JWT token.
*Default/sample configuration:*
```json
{
"ratelimit": {
"admin": {
"req": 100,
"interval": "second"
},
"guest": {
"req": 50,
"interval": "minute"
},
"-": {
"req": 100,
"interval": "day"
}
}
}
```
If you'd like to change it - mount your configmap as `/app/ratelimit.json` file.
Remember to include the `-` role, which is used for unauthenticated users or when claim can't be found for any reason.
If rate limit has been reached - the proxy will return `429 Too Many Requests` error.
#### Read-only mode
You can enable the read-only mode by setting the `READ_ONLY_MODE` environment variable to `true` - which will block all the `mutation` queries.
#### Allowing access to listed URLs
You can allow access only to certain URLs by setting the `ALLOWED_URLS` environment variable to a comma-separated list of URLs. If enabled - other URLs will return `403 Forbidden` error and request will **not** reach the proxied service.
#### Blocking introspection
You can block the schema introspection by setting the `BLOCK_SCHEMA_INTROSPECTION` environment variable to `true` - which will block all the queries with introspection parts, like:
`__schema`, `__type`, `__typename`, `__directive`, `__directivelocation`, `__field`, `__inputvalue`, `__enumvalue`, `__typekind`, `__fieldtype`, `__inputobjecttype`, `__enumtype`, `__uniontype`, `__scalars`, `__objects`, `__interfaces`, `__unions`, `__enums`, `__inputobjects`, `__directives`
If you'd like to keep blocking of the schema introspection on but allow one or more of from the list of above for any reason, you can use the `ALLOWED_INTROSPECTION` environment variable to specify the list of allowed queries.
`ALLOWED_INTROSPECTION="__typename,__type"`
### API endpoints
#### Ban or unban the user
Your monitoring system can detect user misbehaving, for example trying to extract / scrap the data. To prevent user from doing so you can use the simple API to ban the user from accessing the application.
To do so - you need to enable the api by setting env variable `ENABLE_API=true` which will expose the API on the port `API_PORT=9090`. Nedless to say - keep it secure and don't expose it outside of your cluster.
Then you can use the following endpoints:
* `POST /api/user-ban` - ban the user from accessing the application
* `POST /api/user-unban` - unban the user from accessing the application
#### Cache operations
* `POST /api/cache-clear` - clear the cache
* `GET /api/cache-stats` - get the cache statistics ( hits, misses, size )
Both endpoints require the `user_id` parameter to be present in the request body and allow you to provide the reason for the ban.
Example request:
```bash
curl -X POST \
http://localhost:9090/api/user-ban \
-H 'Content-Type: application/json' \
-d '{
"user_id": "1337",
"reason": "Scraping data"
}'
```
Ban details will be stored in the `banned_users.json` file, which you can mount as a file or configmap to the `/go/src/app/banned_users.json` path ( or use `BANNED_USERS_FILE` environment variable to specify the path to the file). The file operation is important if you have multiple instances of the proxy running, as it will allow you to ban the user from accessing the application on all instances.
### General
#### Metrics which matter
You can always enable `PURGE_METRICS_ON_CRAWL` environment variable to purge the metrics on each `/metrics` crawl. This will allow you to see only the current metrics, without potential leftovers from the previous crawls. This is useful if you want to monitor the metrics in real-time and / or limit the amount of data ingested into the monitoring system. When enabled you will most likely need to update your monitoring queries.
With the `PURGE_METRICS_ON_CRAWL` enabled, the `graphql_proxy_requests_failed`, `graphql_proxy_requests_skipped` and `graphql_proxy_requests_succesful` metrics will remain between resets.
If you prefer more control over the metrics purging - you can enable `PURGE_METRICS_ON_TIMER` environment variable and set the interval in seconds. This will allow you to purge the metrics on a regular basis, for example every 90 seconds. It could be better solution if you have multiple crawlers checking the metrics endpoints and you want to avoid the situation when metrics are purged by for example healthcheck.
#### Healthcheck
If you'd like the `/healthz` endpoint to perform actual check for the connectivity to the graphql endpoint - set the `HEALTHCHECK_GRAPHQL_URL` environment variable to the exact URL of the graphql endpoint. The query executed will be `query { __typename }` and if the response is not `200 OK` - the healthcheck will fail. Remember that the endpoint is a full URL which you'd like to check, so it should include the protocol, host and path - for example `http://localhost:8080/v1/graphql` and it's NOT the same as value of `HOST_GRAPHQL` environment variable which should provide only the host, without path, ending with slash.
#### Monitoring endpoint
Example metrics produced by the proxy:
```
graphql_proxy_timed_query_bucket{cached="false",user_id="-",op_type="mutation",op_name="updateUserDetails",vmrange="1.000e-02...1.136e-02"} 6
graphql_proxy_timed_query_count{op_name="",cached="false",user_id="-",op_type=""} 78
graphql_proxy_timed_query_bucket{op_name="MyQuery",cached="false",user_id="-",op_type="query",vmrange="5.995e+00...6.813e+00"} 1
graphql_proxy_timed_query_sum{op_name="MyQuery",cached="false",user_id="-",op_type="query"} 6
graphql_proxy_timed_query_count{op_name="MyQuery",cached="false",user_id="-",op_type="query"} 1
graphql_proxy_executed_query{user_id="-",op_type="mutation",op_name="updateKnownSpammer",cached="false"} 1486
graphql_proxy_executed_query{user_id="-",op_type="query",op_name="checkIfAdminsNeedRefreshing",cached="false"} 13167
graphql_proxy_executed_query{user_id="1337",op_type="query",op_name="checkIfKnownMedia",cached="false"} 429
graphql_proxy_executed_query{user_id="-",op_type="query",op_name="checkIfSpamAIRequiresUpdate",cached="false"} 8891
graphql_proxy_requests_failed 324
graphql_proxy_requests_skipped 0
graphql_proxy_requests_succesful 454823
graphql_proxy_cache_hit{microservice="graphql_proxy",pod="hasura-w-proxy-internal-6b5f4b4bbb-9xwfc"} 7
graphql_proxy_cache_hit{pod="hasura-w-proxy-internal-6b5f4b4bbb-9xwfc",microservice="graphql_proxy"} 1
graphql_proxy_cache_miss{microservice="graphql_proxy",pod="hasura-w-proxy-internal-6b5f4b4bbb-9xwfc"} 23
```
-33
View File
@@ -1,33 +0,0 @@
package main
import (
"fmt"
"time"
"github.com/akyoto/cache"
fiber "github.com/gofiber/fiber/v2"
"github.com/gookit/goutil/strutil"
)
func calculateHash(c *fiber.Ctx) string {
return strutil.Md5(fmt.Sprintf("%s", c.Body()))
}
func enableCache() {
var err error
cfg.Cache.CacheClient = cache.New(time.Duration(cfg.Cache.CacheTTL) * time.Second * 2)
if err != nil {
cfg.Logger.Critical("Can't create cache client", map[string]interface{}{"error": err.Error()})
panic(err)
}
}
func cacheLookup(hash string) []byte {
if cfg.Cache.CacheClient != nil {
obj, found := cfg.Cache.CacheClient.Get(hash)
if found {
return obj.([]byte)
}
}
return nil
}
-38
View File
@@ -1,38 +0,0 @@
package main
import (
"encoding/base64"
"strings"
"github.com/lukaszraczylo/ask"
libpack_monitoring "github.com/telegram-bot-app/libpack/monitoring"
)
func extractClaimsFromJWTHeader(authorization string) (usr string) {
tokenParts := strings.Split(authorization, ".")
if len(tokenParts) != 3 {
cfg.Monitoring.Increment(libpack_monitoring.MetricsFailed, nil)
cfg.Logger.Error("Can't split the token", map[string]interface{}{"token": authorization})
return
}
claim, err := base64.RawURLEncoding.DecodeString(tokenParts[1])
if err != nil {
cfg.Monitoring.Increment(libpack_monitoring.MetricsFailed, nil)
cfg.Logger.Error("Can't decode the token", map[string]interface{}{"token": authorization})
return
}
var claimMap map[string]interface{}
err = json.Unmarshal(claim, &claimMap)
if err != nil {
cfg.Monitoring.Increment(libpack_monitoring.MetricsFailed, nil)
cfg.Logger.Error("Can't unmarshal the claim", map[string]interface{}{"token": authorization})
return
}
usr, ok := ask.For(claimMap, cfg.Client.JWTUserClaimPath).String("-")
if !ok {
cfg.Monitoring.Increment(libpack_monitoring.MetricsFailed, nil)
cfg.Logger.Error("Can't find the user id", map[string]interface{}{"claim_map": claimMap, "path": cfg.Client.JWTUserClaimPath})
return
}
return usr
}
+135626
View File
File diff suppressed because one or more lines are too long
+281
View File
@@ -0,0 +1,281 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=yes" />
<style>
html {
font-family: BlinkMacSystemFont,-apple-system,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",Helvetica,Arial,sans-serif;
-webkit-font-smoothing: antialiased;
background-color: #fff;
font-size: 16px;
}
body {
color: #4a4a4a;
margin: 8px;
font-size: 1em;
font-weight: 400;
}
header {
margin-bottom: 8px;
display: flex;
flex-direction: column;
}
main {
width: 100%;
display: flex;
flex-direction: column;
}
a {
color: #3273dc;
cursor: pointer;
text-decoration: none;
}
a:hover {
color: #000;
}
button {
color: #fff;
background-color: #3298dc;
border-color: transparent;
cursor: pointer;
text-align: center;
}
button:hover {
background-color: #2793da;
flex: none;
}
.spacer {
flex: auto;
}
.small {
font-size: 0.75rem;
}
footer {
margin-top: 16px;
display: flex;
align-items: center;
}
.header-label {
margin-right: 4px;
}
.benchmark-set {
margin: 8px 0;
width: 100%;
display: flex;
flex-direction: column;
}
.benchmark-title {
font-size: 3rem;
font-weight: 600;
word-break: break-word;
text-align: center;
}
.benchmark-graphs {
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
flex-wrap: wrap;
width: 100%;
}
.benchmark-chart {
max-width: 1000px;
}
</style>
<title>Benchmarks</title>
</head>
<body>
<header id="header">
<div class="header-item">
<strong class="header-label">Last Update:</strong>
<span id="last-update"></span>
</div>
<div class="header-item">
<strong class="header-label">Repository:</strong>
<a id="repository-link" rel="noopener"></a>
</div>
</header>
<main id="main"></main>
<footer>
<button id="dl-button">Download data as JSON</button>
<div class="spacer"></div>
<div class="small">Powered by <a rel="noopener" href="https://github.com/marketplace/actions/continuous-benchmark">github-action-benchmark</a></div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/Chart.min.js"></script>
<script src="data.js"></script>
<script id="main-script">
'use strict';
(function() {
// Colors from https://github.com/github/linguist/blob/master/lib/linguist/languages.yml
const toolColors = {
cargo: '#dea584',
go: '#00add8',
benchmarkjs: '#f1e05a',
benchmarkluau: '#000080',
pytest: '#3572a5',
googlecpp: '#f34b7d',
catch2: '#f34b7d',
julia: '#a270ba',
jmh: '#b07219',
benchmarkdotnet: '#178600',
customBiggerIsBetter: '#38ff38',
customSmallerIsBetter: '#ff3838',
_: '#333333'
};
function init() {
function collectBenchesPerTestCase(entries) {
const map = new Map();
for (const entry of entries) {
const {commit, date, tool, benches} = entry;
for (const bench of benches) {
const result = { commit, date, tool, bench };
const arr = map.get(bench.name);
if (arr === undefined) {
map.set(bench.name, [result]);
} else {
arr.push(result);
}
}
}
return map;
}
const data = window.BENCHMARK_DATA;
// Render header
document.getElementById('last-update').textContent = new Date(data.lastUpdate).toString();
const repoLink = document.getElementById('repository-link');
repoLink.href = data.repoUrl;
repoLink.textContent = data.repoUrl;
// Render footer
document.getElementById('dl-button').onclick = () => {
const dataUrl = 'data:,' + JSON.stringify(data, null, 2);
const a = document.createElement('a');
a.href = dataUrl;
a.download = 'benchmark_data.json';
a.click();
};
// Prepare data points for charts
return Object.keys(data.entries).map(name => ({
name,
dataSet: collectBenchesPerTestCase(data.entries[name]),
}));
}
function renderAllChars(dataSets) {
function renderGraph(parent, name, dataset) {
const canvas = document.createElement('canvas');
canvas.className = 'benchmark-chart';
parent.appendChild(canvas);
const color = toolColors[dataset.length > 0 ? dataset[0].tool : '_'];
const data = {
labels: dataset.map(d => d.commit.id.slice(0, 7)),
datasets: [
{
label: name,
data: dataset.map(d => d.bench.value),
borderColor: color,
backgroundColor: color + '60', // Add alpha for #rrggbbaa
}
],
};
const options = {
scales: {
xAxes: [
{
scaleLabel: {
display: true,
labelString: 'commit',
},
}
],
yAxes: [
{
scaleLabel: {
display: true,
labelString: dataset.length > 0 ? dataset[0].bench.unit : '',
},
ticks: {
beginAtZero: true,
}
}
],
},
tooltips: {
callbacks: {
afterTitle: items => {
const {index} = items[0];
const data = dataset[index];
return '\n' + data.commit.message + '\n\n' + data.commit.timestamp + ' committed by @' + data.commit.committer.username + '\n';
},
label: item => {
let label = item.value;
const { range, unit } = dataset[item.index].bench;
label += ' ' + unit;
if (range) {
label += ' (' + range + ')';
}
return label;
},
afterLabel: item => {
const { extra } = dataset[item.index].bench;
return extra ? '\n' + extra : '';
}
}
},
onClick: (_mouseEvent, activeElems) => {
if (activeElems.length === 0) {
return;
}
// XXX: Undocumented. How can we know the index?
const index = activeElems[0]._index;
const url = dataset[index].commit.url;
window.open(url, '_blank');
},
};
new Chart(canvas, {
type: 'line',
data,
options,
});
}
function renderBenchSet(name, benchSet, main) {
const setElem = document.createElement('div');
setElem.className = 'benchmark-set';
main.appendChild(setElem);
const nameElem = document.createElement('h1');
nameElem.className = 'benchmark-title';
nameElem.textContent = name;
setElem.appendChild(nameElem);
const graphsElem = document.createElement('div');
graphsElem.className = 'benchmark-graphs';
setElem.appendChild(graphsElem);
for (const [benchName, benches] of benchSet.entries()) {
renderGraph(graphsElem, benchName, benches)
}
}
const main = document.getElementById('main');
for (const {name, dataSet} of dataSets) {
renderBenchSet(name, dataSet, main);
}
}
renderAllChars(init()); // Start
})();
</script>
</body>
</html>
-45
View File
@@ -1,45 +0,0 @@
module github.com/lukaszraczylo/graphql-monitoring-proxy
go 1.21
require (
github.com/akyoto/cache v1.0.6
github.com/gofiber/fiber/v2 v2.49.2
github.com/gookit/goutil v0.6.12
github.com/graphql-go/graphql v0.8.1
github.com/json-iterator/go v1.1.12
github.com/lukaszraczylo/ask v0.0.0-20230927103145-2ff1123b4415
github.com/lukaszraczylo/go-simple-graphql v1.1.31
github.com/telegram-bot-app/libpack v0.0.0-20231007021518-909ce2741a36
)
require (
dario.cat/mergo v1.0.0 // indirect
github.com/VictoriaMetrics/metrics v1.24.0 // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/avast/retry-go/v4 v4.5.0 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/gookit/color v1.5.4 // indirect
github.com/klauspost/compress v1.17.0 // indirect
github.com/lukaszraczylo/pandati v0.0.29 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/rs/zerolog v1.31.0 // indirect
github.com/telegram-bot-app/lib-logging v0.0.19 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.50.0 // indirect
github.com/valyala/fastrand v1.1.0 // indirect
github.com/valyala/histogram v1.2.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
github.com/wI2L/jsondiff v0.4.0 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
golang.org/x/net v0.16.0 // indirect
golang.org/x/sync v0.4.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/term v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
)
-99
View File
@@ -1,99 +0,0 @@
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
github.com/VictoriaMetrics/metrics v1.24.0 h1:ILavebReOjYctAGY5QU2F9X0MYvkcrG3aEn2RKa1Zkw=
github.com/VictoriaMetrics/metrics v1.24.0/go.mod h1:eFT25kvsTidQFHb6U0oa0rTrDRdz4xTYjpL8+UPohys=
github.com/akyoto/cache v1.0.6 h1:5XGVVYoi2i+DZLLPuVIXtsNIJ/qaAM16XT0LaBaXd2k=
github.com/akyoto/cache v1.0.6/go.mod h1:WfxTRqKhfgAG71Xh6E3WLpjhBtZI37O53G4h5s+3iM4=
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/avast/retry-go/v4 v4.5.0 h1:QoRAZZ90cj5oni2Lsgl2GW8mNTnUCnmpx/iKpwVisHg=
github.com/avast/retry-go/v4 v4.5.0/go.mod h1:7hLEXp0oku2Nir2xBAsg0PTphp9z71bN5Aq1fboC3+I=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofiber/fiber/v2 v2.49.2 h1:ONEN3/Vc+dUCxxDgZZwpqvhISgHqb+bu+isBiEyKEQs=
github.com/gofiber/fiber/v2 v2.49.2/go.mod h1:gNsKnyrmfEWFpJxQAV0qvW6l70K1dZGno12oLtukcts=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
github.com/gookit/goutil v0.6.12 h1:73vPUcTtVGXbhSzBOFcnSB1aJl7Jq9np3RAE50yIDZc=
github.com/gookit/goutil v0.6.12/go.mod h1:g6krlFib8xSe3G1h02IETowOtrUGpAmetT8IevDpvpM=
github.com/graphql-go/graphql v0.8.1 h1:p7/Ou/WpmulocJeEx7wjQy611rtXGQaAcXGqanuMMgc=
github.com/graphql-go/graphql v0.8.1/go.mod h1:nKiHzRM0qopJEwCITUuIsxk9PlVlwIiiI8pnJEhordQ=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/lukaszraczylo/ask v0.0.0-20230927103145-2ff1123b4415 h1:lvI8Wlbg4PxkRcg2f10wgoaRpfN19v+YdRek3+dLtlM=
github.com/lukaszraczylo/ask v0.0.0-20230927103145-2ff1123b4415/go.mod h1:M+UVdyqZs++xtEPrascaVmZdOMhCnxjZ2SgH+xHpR0c=
github.com/lukaszraczylo/go-simple-graphql v1.1.31 h1:UA3f8M1cV+XnO8UZlAqveW0qF/2NN512eB/gRqe+BHs=
github.com/lukaszraczylo/go-simple-graphql v1.1.31/go.mod h1:MyftQ8jTdtkYImPXJpHoxz6+E53Ydv+7q9+Jr+eT8WU=
github.com/lukaszraczylo/pandati v0.0.29 h1:WUEWm1+hWjE5KJbIL8OctG00x2dk4XKGJSlrjhxZ55k=
github.com/lukaszraczylo/pandati v0.0.29/go.mod h1:+DyTWKFaXd+jIfe7GW5w2S5PyTko/RXxMyOa+Vl713A=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A=
github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/telegram-bot-app/lib-logging v0.0.19 h1:zbyFr2ygeBY+yuaB9moXyOGk8dIBCn0jPJQjvx7YvLE=
github.com/telegram-bot-app/lib-logging v0.0.19/go.mod h1:n8d29fRUTdgJhC4RZ8s4lP2RHiGCCRYEj2ENEClUGc8=
github.com/telegram-bot-app/libpack v0.0.0-20231007021518-909ce2741a36 h1:DqXg0y57Q7BziHDu85OXgo/b8OlP7/+gDZvASQCkaW0=
github.com/telegram-bot-app/libpack v0.0.0-20231007021518-909ce2741a36/go.mod h1:W2kWHcfNNS0r++dJ1T2XX/C4cTSxI3MsoiMbOtyqu+I=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.50.0 h1:H7fweIlBm0rXLs2q0XbalvJ6r0CUPFWK3/bB4N13e9M=
github.com/valyala/fasthttp v1.50.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
github.com/valyala/fastrand v1.1.0 h1:f+5HkLW4rsgzdNoleUOB69hyT9IlD2ZQh9GyDMfb5G8=
github.com/valyala/fastrand v1.1.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ=
github.com/valyala/histogram v1.2.0 h1:wyYGAZZt3CpwUiIb9AU/Zbllg1llXyrtApRS815OLoQ=
github.com/valyala/histogram v1.2.0/go.mod h1:Hb4kBwb4UxsaNbbbh+RRz8ZR6pdodR57tzWUS3BUzXY=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
github.com/wI2L/jsondiff v0.4.0 h1:iP56F9tK83eiLttg3YdmEENtZnwlYd3ezEpNNnfZVyM=
github.com/wI2L/jsondiff v0.4.0/go.mod h1:nR/vyy1efuDeAtMwc3AF6nZf/2LD1ID8GTyyJ+K8YB0=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos=
golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-46
View File
@@ -1,46 +0,0 @@
package main
import (
fiber "github.com/gofiber/fiber/v2"
"github.com/graphql-go/graphql/language/ast"
"github.com/graphql-go/graphql/language/parser"
libpack_monitoring "github.com/telegram-bot-app/libpack/monitoring"
)
func parseGraphQLQuery(c *fiber.Ctx) (operationType, operationName string, cacheRequest bool) {
m := make(map[string]interface{})
err := json.Unmarshal(c.Body(), &m)
if err != nil {
cfg.Logger.Error("Can't unmarshal the request", map[string]interface{}{"error": err.Error(), "body": string(c.Body())})
cfg.Monitoring.Increment(libpack_monitoring.MetricsFailed, nil)
return
}
// get the query
query, ok := m["query"].(string)
if !ok {
cfg.Logger.Error("Can't find the query", map[string]interface{}{"query": query, "m_val": m})
cfg.Monitoring.Increment(libpack_monitoring.MetricsSkipped, nil)
return
}
p, err := parser.Parse(parser.ParseParams{Source: query})
if err != nil {
cfg.Logger.Error("Can't parse the query", map[string]interface{}{"query": query, "m_val": m})
cfg.Monitoring.Increment(libpack_monitoring.MetricsFailed, nil)
return
}
operationName = "undefined"
for _, d := range p.Definitions {
if oper, ok := d.(*ast.OperationDefinition); ok {
operationType = oper.Operation
operationName = oper.Name.Value
for _, dir := range oper.Directives {
if dir.Name.Value == "cached" {
cacheRequest = true
}
}
}
}
return
}
-32
View File
@@ -1,32 +0,0 @@
package main
import (
"github.com/gookit/goutil/envutil"
graphql "github.com/lukaszraczylo/go-simple-graphql"
libpack_config "github.com/telegram-bot-app/libpack/config"
libpack_logging "github.com/telegram-bot-app/libpack/logging"
)
var cfg *config
func parseConfig() {
libpack_config.PKG_NAME = "graphql_proxy"
var c config
c.Server.PortGraphQL = envutil.GetInt("PORT_GRAPHQL", 8080)
c.Server.PortMonitoring = envutil.GetInt("MONITORING_PORT", 9393)
c.Server.HostGraphQL = envutil.Getenv("HOST_GRAPHQL", "localhost/v1/graphql")
c.Client.JWTUserClaimPath = envutil.Getenv("JWT_USER_CLAIM_PATH", "")
c.Cache.CacheEnable = envutil.GetBool("CACHE_ENABLE", false)
c.Cache.CacheTTL = envutil.GetInt("CACHE_TTL", 60)
c.Logger = libpack_logging.NewLogger()
c.Client.GQLClient = graphql.NewConnection()
c.Client.GQLClient.SetEndpoint(c.Server.HostGraphQL)
cfg = &c
enableCache() // takes close to no resources, but can be used with dynamic query cache
}
func main() {
parseConfig()
StartMonitoringServer()
StartHTTPProxy()
}
-11
View File
@@ -1,11 +0,0 @@
package main
import (
libpack_monitoring "github.com/telegram-bot-app/libpack/monitoring"
)
func StartMonitoringServer() {
cfg.Monitoring = libpack_monitoring.NewMonitoring()
cfg.Monitoring.AddMetricsPrefix("graphql_proxy")
cfg.Monitoring.RegisterDefaultMetrics()
}
-28
View File
@@ -1,28 +0,0 @@
package main
import (
"crypto/tls"
fiber "github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/proxy"
libpack_monitoring "github.com/telegram-bot-app/libpack/monitoring"
)
func proxyTheRequest(c *fiber.Ctx) error {
c.Request().Header.Add("X-Real-IP", c.IP())
c.Request().Header.Add("X-Forwarded-For", c.IP())
proxy.WithTlsConfig(&tls.Config{
InsecureSkipVerify: true,
})
err := proxy.DoRedirects(c, cfg.Server.HostGraphQL, 3)
if err != nil {
cfg.Logger.Error("Can't proxy the request", map[string]interface{}{"error": err.Error()})
cfg.Monitoring.Increment(libpack_monitoring.MetricsFailed, nil)
return err
}
c.Response().Header.Del(fiber.HeaderServer)
return nil
}
-14
View File
@@ -1,14 +0,0 @@
version: 1
force:
existing: true
strict: false
wording:
patch:
- update
- initial
- fix
minor:
- change
- improve
major:
- breaking
-94
View File
@@ -1,94 +0,0 @@
package main
import (
"fmt"
"time"
fiber "github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors"
jsoniter "github.com/json-iterator/go"
libpack_monitoring "github.com/telegram-bot-app/libpack/monitoring"
)
var json = jsoniter.ConfigCompatibleWithStandardLibrary
// StartHTTPProxy starts the HTTP and points it to the GraphQL server.
func StartHTTPProxy() {
server := fiber.New()
server.Use(cors.New(cors.Config{
AllowOrigins: "*",
}))
server.Post("/v1/graphql", processGraphQLRequest)
server.Get("/healthz", healthCheck)
err := server.Listen(fmt.Sprintf(":%d", cfg.Server.PortGraphQL))
if err != nil {
cfg.Logger.Critical("Can't start the service", map[string]interface{}{"error": err.Error()})
}
}
func healthCheck(c *fiber.Ctx) error {
query := `{ __typename }`
_, err := cfg.Client.GQLClient.Query(query, nil, nil)
if err != nil {
cfg.Logger.Error("Can't reach the GraphQL server", map[string]interface{}{"error": err.Error()})
cfg.Monitoring.Increment(libpack_monitoring.MetricsFailed, nil)
return c.SendStatus(500)
}
return c.SendStatus(200)
}
func processGraphQLRequest(c *fiber.Ctx) error {
t := time.Now()
var extracted_user_id string = "-"
var query_cache_hash string = ""
authorization := c.Request().Header.Peek("Authorization")
if authorization != nil && len(cfg.Client.JWTUserClaimPath) > 0 {
extracted_user_id = extractClaimsFromJWTHeader(string(authorization))
}
opType, opName, cache_from_query := parseGraphQLQuery(c)
was_cached := false
if cache_from_query || cfg.Cache.CacheEnable {
cfg.Logger.Debug("Cache enabled", map[string]interface{}{"via_query": cache_from_query, "via_env": cfg.Cache.CacheEnable})
query_cache_hash = calculateHash(c)
cachedResponse := cacheLookup(query_cache_hash)
if cachedResponse != nil {
cfg.Logger.Debug("Cache hit", map[string]interface{}{"hash": query_cache_hash, "user_id": extracted_user_id})
c.Send(cachedResponse)
was_cached = true
} else {
cfg.Logger.Debug("Cache miss", map[string]interface{}{"hash": query_cache_hash, "user_id": extracted_user_id})
proxyTheRequest(c)
cfg.Cache.CacheClient.Set(query_cache_hash, c.Response().Body(), time.Duration(cfg.Cache.CacheTTL)*time.Second)
c.Send(c.Response().Body())
}
} else {
proxyTheRequest(c)
}
time_taken := time.Since(t)
cfg.Logger.Info("Request processed", map[string]interface{}{"ip": c.IP(), "user_id": extracted_user_id, "op_type": opType, "op_name": opName, "time": time_taken, "cache": was_cached})
cfg.Monitoring.Increment(libpack_monitoring.MetricsSucceeded, nil)
labels := map[string]string{
"op_type": opType,
"op_name": opName,
"cached": fmt.Sprintf("%t", was_cached),
"user_id": extracted_user_id,
}
cfg.Monitoring.Increment("executed_query", labels)
if !was_cached {
cfg.Monitoring.UpdateDuration("timed_query", labels, t)
cfg.Monitoring.Update("timed_query", labels, float64(time_taken.Milliseconds()))
}
// // cfg.Monitoring.Set("timed_query", time_taken.Milliseconds())
return nil
}
-32
View File
@@ -1,32 +0,0 @@
package main
import (
"github.com/akyoto/cache"
graphql "github.com/lukaszraczylo/go-simple-graphql"
libpack_logging "github.com/telegram-bot-app/libpack/logging"
libpack_monitoring "github.com/telegram-bot-app/libpack/monitoring"
)
// config is a struct that holds the configuration of the application.
type config struct {
Logger *libpack_logging.LogConfig
Monitoring *libpack_monitoring.MetricsSetup
// Server holds the configuration of the server _ONLY_.
Server struct {
PortGraphQL int
PortMonitoring int
HostGraphQL string
}
Client struct {
JWTUserClaimPath string
GQLClient *graphql.BaseClient
}
Cache struct {
CacheEnable bool
CacheTTL int
CacheClient *cache.Cache
}
}