{"id":321505,"date":"2021-04-15T15:00:49","date_gmt":"2021-04-15T15:00:49","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=321505"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=321505","title":{"rendered":"\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0437\u0430\u0442\u0440\u0430\u0442\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e AWS Cost Explorer"},"content":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/568\/f14\/aed\/568f14aeda6d5551717124a19f23fe2c.png\" width=\"782\" height=\"488\"><figcaption><\/figcaption><\/figure>\n<p>\u0423 Amazon Web Services \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u0439 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u043f\u0430\u043a\u0435\u0442:&nbsp;\u0445\u043e\u0440\u043e\u0448\u0438\u0439 \u043d\u0430\u0431\u043e\u0440 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0438 \u0449\u0435\u0434\u0440\u0430\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0430 \u043a\u0440\u0435\u0434\u0438\u0442\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432. \u042f \u0431\u044b\u043b \u0443\u0432\u0435\u0440\u0435\u043d: \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 \u043e\u043f\u043b\u0430\u0442\u043e\u0439 \u043c\u043e\u0435\u0433\u043e \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043d\u0435 \u0431\u0443\u0434\u0435\u0442, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e \u0440\u0430\u0441\u0445\u043e\u0434\u0430\u0445 \u043d\u0435 \u0431\u0435\u0441\u043f\u043e\u043a\u043e\u0438\u043b\u0441\u044f. \u041c\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 100% serverless, \u0438 \u044f \u0432\u0441\u0435\u0433\u0434\u0430 \u0443\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u043b\u0441\u044f \u0432 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f, \u0442\u0430\u043a \u0447\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043b \u0432\u043e\u043f\u0440\u043e\u0441 \u043e\u043f\u043b\u0430\u0442\u044b. \u0412 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u044f \u0440\u0430\u0441\u0441\u043b\u0430\u0431\u0438\u043b\u0441\u044f \u0438 \u043f\u043e\u0442\u0435\u0440\u044f\u043b \u0431\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c.<\/p>\n<p>\u041f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u043c\u043e\u0439 \u043f\u0440\u043e\u0434\u0443\u043a\u0442 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0441\u044f \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u0435\u0435, \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0441\u0442\u0430\u043b\u043e \u0431\u043e\u043b\u044c\u0448\u0435\u2026 \u0438 \u044f \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u0441\u0447\u0435\u0442 \u043d\u0430 62$. \u041f\u0435\u0440\u0435\u0436\u0438\u0442\u044c \u043c\u043e\u0436\u043d\u043e, \u043d\u043e \u044f \u0437\u0430\u0434\u0443\u043c\u0430\u043b\u0441\u044f \u043e \u0442\u0435\u043c\u043f\u0430\u0445 \u0440\u043e\u0441\u0442\u0430: \u043c\u043e\u0451 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0435 \u0431\u044b\u043b\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0434\u043b\u044f \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0438\u044f \u0437\u0430\u0442\u0440\u0430\u0442, \u0442\u0430\u043a \u043a\u0430\u043a \u044f \u043e\u0431 \u044d\u0442\u043e\u043c \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0437\u0430\u0434\u0443\u043c\u044b\u0432\u0430\u043b\u0441\u044f. \u0427\u0442\u043e \u0436, \u043f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0437\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u0435\u043c \u0440\u0430\u0441\u0445\u043e\u0434\u043e\u0432.<\/p>\n<h2>AWS Cost Explorer<\/h2>\n<p>\u0421\u0435\u0440\u0432\u0438\u0441 <a href=\"https:\/\/docs.aws.amazon.com\/awsaccountbilling\/latest\/aboutv2\/billing-what-is.html\" rel=\"noopener noreferrer nofollow\">AWS Billing dashboard<\/a> \u0445\u043e\u0440\u043e\u0448\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u043e\u043f\u043b\u0430\u0442\u044b \u0441\u0447\u0435\u0442\u043e\u0432 \u0438 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0433\u0440\u0430\u0444\u0438\u043a \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0430 \u0441\u0447\u0435\u0442\u043e\u0432 \u0437\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043c\u0435\u0441\u044f\u0446. \u041d\u043e \u044d\u0442\u043e\u0442 \u0441\u0435\u0440\u0432\u0438\u0441 \u0435\u0434\u0432\u0430 \u043b\u0438 \u043f\u0440\u0435\u0442\u0435\u043d\u0434\u0443\u0435\u0442 \u043d\u0430 \u0437\u0432\u0430\u043d\u0438\u0435 \u043b\u0443\u0447\u0448\u0435\u0433\u043e \u0432 AWS. \u041c\u0435\u0441\u044f\u0447\u043d\u044b\u0439 \u043f\u0440\u043e\u0433\u043d\u043e\u0437 \u0447\u0430\u0441\u0442\u043e \u0432\u0440\u0435\u0442, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043b\u0443\u0447\u0448\u0435 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432\u043e\u0432\u0441\u0435.<\/p>\n<p>\u041f\u043e\u043c\u0438\u043c\u043e Billing Dashboard, \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0439 Cost Explorer \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0440\u043e\u0448\u0443\u044e \u0434\u0435\u0442\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u041a\u0440\u043e\u043c\u0435 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0440\u0430\u0437\u0431\u0438\u0432\u043a\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044f \u0432 AWS, \u043c\u043e\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u0434 \u043f\u043e\u0434 Cost Explorer, \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u044f \u043c\u043d\u043e\u0433\u043e \u0446\u0435\u043d\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438. \u0418 \u043c\u043d\u0435 \u044d\u0442\u043e \u0434\u0435\u043b\u043e \u0437\u0430\u0448\u043b\u043e.<\/p>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f Cost Explorer, \u044f \u0441\u043c\u043e\u0433 \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0443\u044f\u0437\u0432\u0438\u043c\u044b\u0435 \u043c\u0435\u0441\u0442\u0430 \u0438 \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0438\u0445 \u0437\u0430\u0434\u043e\u043b\u0433\u043e \u0434\u043e \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0441 \u043c\u0435\u043d\u044f \u043d\u0430\u0447\u043d\u0443\u0442 \u0441\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0437\u0430 \u043d\u0438\u0445 \u0434\u0435\u043d\u044c\u0433\u0438. \u0415\u0449\u0435 \u0440\u0430\u0437 \u0441\u043f\u0430\u0441\u0438\u0431\u043e AWS.<\/p>\n<h2>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441<\/h2>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043d\u0430\u0447\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c, \u043d\u0430\u0434\u043e \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c \u0432\u0438\u0434\u043e\u043c \u043a\u043e\u043d\u0441\u043e\u043b\u0438 Billing Dashboard. \u041d\u0443\u0436\u043d\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0435\u0451, \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u0442\u043e\u0438\u0442\u044c \u0434\u0435\u043d\u0435\u0433. \u041b\u0443\u0447\u0448\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0437\u0430\u0440\u0430\u043d\u0435\u0435, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u043e\u043c \u043d\u0435 \u0431\u044b\u043b\u043e \u043c\u0443\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0431\u043e\u043b\u044c\u043d\u043e. \u0423 \u043a\u043e\u0433\u043e \u043c\u043d\u043e\u0433\u043e \u043e\u0441\u0442\u0430\u0442\u043a\u0443, \u0442\u043e\u0442 \u043d\u0435 \u0431\u043e\u0438\u0442\u0441\u044f \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0443!<\/p>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0438\u043d\u0442\u0443\u0438\u0442\u0438\u0432\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0439: \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0435 \u043e\u0442\u0447\u0435\u0442\u044b \u043f\u043e \u0434\u043d\u044f\u043c \/ \u0443\u0441\u043b\u0443\u0433\u0435; \u0438\u043b\u0438 \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \/ \u0440\u0435\u0433\u0438\u043e\u043d\u0443 \/ \u0443\u0441\u043b\u0443\u0433\u0435 \u2013 \u0438 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/2ee\/f02\/af1\/2eef02af1ec14ba13af3479c20e38f63.png\" width=\"983\" height=\"369\"><figcaption><\/figcaption><\/figure>\n<p>\u042d\u0442\u043e \u043c\u043e\u0439 \u0433\u0440\u0430\u0444\u0438\u043a \u043f\u043e\u0442\u0440\u0430\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u0437\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0441\u044f\u0446\u0435\u0432.<\/p>\n<h3>\u041e\u0442\u0447\u0435\u0442\u044b<\/h3>\n<p>\u0412 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 reports \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u043e\u0442\u0447\u0435\u0442\u043e\u0432. AWS \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0435\u043f\u043b\u043e\u0445\u043e\u0439 \u043d\u0430\u0431\u043e\u0440 \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u0434\u043b\u044f \u043e\u0442\u0447\u0435\u0442\u043e\u0432, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u0441 \u043d\u0443\u043b\u044f.<\/p>\n<h3>\u0411\u044e\u0434\u0436\u0435\u0442\u044b<\/h3>\n<p>Cost Explorer \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f&nbsp;\u043e\u0442\u0447\u0435\u0442\u0430\u043c\u0438 \u0438 \u0433\u0440\u0430\u0444\u0438\u043a\u0430\u043c\u0438. \u0427\u0430\u0449\u0435&nbsp;\u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442 \u043e\u0441\u0432\u0430\u0438\u0432\u0430\u0442\u044c AWS \u0441 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0431\u044e\u0434\u0436\u0435\u0442\u043e\u0432 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0445 \u043f\u043e\u0434 \u043d\u0438\u0445 \u043e\u043f\u043e\u0432\u0435\u0449\u0435\u043d\u0438\u0439, \u043d\u043e \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0431\u043e\u043b\u044c\u0448\u0435. \u041c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0442\u044c \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u0435 \u0431\u044e\u0434\u0436\u0435\u0442\u044b (\u043f\u043e \u0441\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u0438 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e) \u0434\u043b\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u0438 \u0434\u0430\u0436\u0435 \u0434\u043b\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u043e\u0432 \u0438\u043b\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430.  <\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0431\u044e\u0434\u0436\u0435\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043c \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 DynamoDB \u0438 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0430\u0442\u044c \u0432\u0430\u0441 \u043f\u0440\u0438 \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u0438 \u043f\u043e\u0440\u043e\u0433\u043e\u0432\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/549\/259\/bbb\/549259bbb0e6051d00b44b0ff3dd005c.png\" width=\"839\" height=\"393\"><figcaption><\/figcaption><\/figure>\n<h3>\u041e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0430\u043d\u043e\u043c\u0430\u043b\u0438\u0439<\/h3>\n<p>\u042d\u0442\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u0441\u0438\u0441\u0442\u0435\u043c \u0441 \u0440\u0430\u0432\u043d\u043e\u043c\u0435\u0440\u043d\u043e\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439, \u0430 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f \u043f\u043e\u043c\u043e\u0433\u0443\u0442 \u0432\u0430\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u044b\u0439 \u0440\u0430\u0441\u0445\u043e\u0434 \u043a\u0430\u043a \u0437\u0430\u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e. \u041c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u00ab\u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0438\u00bb, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043b\u0435\u0434\u044f\u0442 \u0437\u0430 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c\u0438 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f\u043c\u0438. \u041c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u044e\u0442 \u0442\u0435\u043a\u0443\u0449\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044f \u0441 \u0438\u0441\u0442\u043e\u0440\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0434\u0438\u0442\u044c \u043e\u0431 \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u0438\u0438 \u043e\u0442 \u0442\u0440\u0435\u043d\u0434\u043e\u0432.<\/p>\n<h3>Cost Explorer API<\/h3>\n<p>\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0432\u0438\u0434 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u0435\u043d\u044f \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u2013 \u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u044d\u043f\u0438\u0437\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u043b\u0435\u043d\u0438\u044f. \u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u0435\u0447\u0442\u043e \u0431\u043e\u043b\u044c\u0448\u0435\u0435, AWS \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u0439 API. \u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 <a href=\"https:\/\/github.com\/aws-samples\" rel=\"noopener noreferrer nofollow\">AWS Samples Github<\/a> \u0434\u0430\u0435\u0442 \u043d\u0430\u043c \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a API Cost Explorer.<\/p>\n<p>\u041c\u043e\u0439 \u043a\u043e\u0434 \u043e\u0441\u043d\u043e\u0432\u0430\u043d \u043d\u0430 \u044d\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435, \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043e\u0442\u0447\u0435\u0442 \u0434\u043b\u044f Cost Explorer\u2019a.<\/p>\n<h2>\u041a\u043e\u0434 Lambda \u0444\u0443\u043d\u043a\u0446\u0438\u0438<\/h2>\n<pre><code class=\"python\">import os import sys # Required to load modules from vendored subfolder (for clean development env) sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), \".\/vendored\"))  import boto3 import datetime import logging import pandas as pd #For date from dateutil.relativedelta import relativedelta #For email from email.mime.application import MIMEApplication from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.utils import COMMASPACE, formatdate  SES_REGION=\"ap-south-1\"  CURRENT_MONTH = True  #Default exclude support, as for Enterprise Support #as support billing is finalised later in month so skews trends     INC_SUPPORT = os.environ.get('INC_SUPPORT') if INC_SUPPORT == \"true\":     INC_SUPPORT = True else:     INC_SUPPORT = False  TAG_VALUE_FILTER = os.environ.get('TAG_VALUE_FILTER') or '*' TAG_KEY = os.environ.get('TAG_KEY')  class CostExplorer:     \"\"\"Retrieves BillingInfo checks from CostExplorer API     &gt;&gt;&gt; costexplorer = CostExplorer()     &gt;&gt;&gt; costexplorer.addReport(GroupBy=[{\"Type\": \"DIMENSION\",\"Key\": \"SERVICE\"}])     &gt;&gt;&gt; costexplorer.generateExcel()     \"\"\"         def __init__(self, CurrentMonth=False):         #Array of reports ready to be output to Excel.         self.reports = []         self.client = boto3.client('ce', region_name='us-east-1')         # self.end = datetime.date.today().replace(day=1)         self.riend = datetime.date.today()         self.end = self.riend          # Default is last 12 months         self.start = (datetime.date.today() - relativedelta(months=+12)).replace(day=1) #1st day of month 12 months ago          self.ristart = (datetime.date.today() - relativedelta(months=+11)).replace(day=1) #1st day of month 11 months ago         self.sixmonth = (datetime.date.today() - relativedelta(months=+6)).replace(day=1) #1st day of month 6 months ago, so RI util has savings values         self.accounts = {}      def addRiReport(self, Name='RICoverage', Savings=False, PaymentOption='PARTIAL_UPFRONT', Service='Amazon Elastic Compute Cloud - Compute'): #Call with Savings True to get Utilization report in dollar savings         type = 'chart' #other option table         if Name == \"RICoverage\":             results = []             response = self.client.get_reservation_coverage(                 TimePeriod={                     'Start': self.ristart.isoformat(),                     'End': self.riend.isoformat()                 },                 Granularity='MONTHLY'             )             results.extend(response['CoveragesByTime'])             while 'nextToken' in response:                 nextToken = response['nextToken']                 response = self.client.get_reservation_coverage(                     TimePeriod={                         'Start': self.ristart.isoformat(),                         'End': self.riend.isoformat()                     },                     Granularity='MONTHLY',                     NextPageToken=nextToken                 )                 results.extend(response['CoveragesByTime'])                 if 'nextToken' in response:                     nextToken = response['nextToken']                 else:                     nextToken = False              rows = []             for v in results:                 row = {'date':v['TimePeriod']['Start']}                 row.update({'Coverage%':float(v['Total']['CoverageHours']['CoverageHoursPercentage'])})                 rows.append(row)                df = pd.DataFrame(rows)             df.set_index(\"date\", inplace= True)             df = df.fillna(0.0)             df = df.T         elif Name in ['RIUtilization','RIUtilizationSavings']:             #Only Six month to support savings             results = []             response = self.client.get_reservation_utilization(                 TimePeriod={                     'Start': self.sixmonth.isoformat(),                     'End': self.riend.isoformat()                 },                 Granularity='MONTHLY'             )             results.extend(response['UtilizationsByTime'])             while 'nextToken' in response:                 nextToken = response['nextToken']                 response = self.client.get_reservation_utilization(                     TimePeriod={                         'Start': self.sixmonth.isoformat(),                         'End': self.riend.isoformat()                     },                     Granularity='MONTHLY',                     NextPageToken=nextToken                 )                 results.extend(response['UtilizationsByTime'])                 if 'nextToken' in response:                     nextToken = response['nextToken']                 else:                     nextToken = False              rows = []             if results:                 for v in results:                     row = {'date':v['TimePeriod']['Start']}                     if Savings:                         row.update({'Savings$':float(v['Total']['NetRISavings'])})                     else:                         row.update({'Utilization%':float(v['Total']['UtilizationPercentage'])})                     rows.append(row)                    df = pd.DataFrame(rows)                 df.set_index(\"date\", inplace= True)                 df = df.fillna(0.0)                 df = df.T                 type = 'chart'             else:                 df = pd.DataFrame(rows)                 type = 'table' #Dont try chart empty result         elif Name == 'RIRecommendation':             results = []             response = self.client.get_reservation_purchase_recommendation(                 #AccountId='string', May use for Linked view                 LookbackPeriodInDays='SIXTY_DAYS',                 TermInYears='ONE_YEAR',                 PaymentOption=PaymentOption,                 Service=Service             )             results.extend(response['Recommendations'])             while 'nextToken' in response:                 nextToken = response['nextToken']                 response = self.client.get_reservation_purchase_recommendation(                     #AccountId='string', May use for Linked view                     LookbackPeriodInDays='SIXTY_DAYS',                     TermInYears='ONE_YEAR',                     PaymentOption=PaymentOption,                     Service=Service,                     NextPageToken=nextToken                 )                 results.extend(response['Recommendations'])                 if 'nextToken' in response:                     nextToken = response['nextToken']                 else:                     nextToken = False              rows = []             for i in results:                 for v in i['RecommendationDetails']:                     row = v['InstanceDetails'][list(v['InstanceDetails'].keys())[0]]                     row['Recommended']=v['RecommendedNumberOfInstancesToPurchase']                     row['Minimum']=v['MinimumNumberOfInstancesUsedPerHour']                     row['Maximum']=v['MaximumNumberOfInstancesUsedPerHour']                     row['Savings']=v['EstimatedMonthlySavingsAmount']                     row['OnDemand']=v['EstimatedMonthlyOnDemandCost']                     row['BreakEvenIn']=v['EstimatedBreakEvenInMonths']                     row['UpfrontCost']=v['UpfrontCost']                     row['MonthlyCost']=v['RecurringStandardMonthlyCost']                     rows.append(row)                 df = pd.DataFrame(rows)             df = df.fillna(0.0)             type = 'table' #Dont try chart this         self.reports.append({'Name':Name,'Data':df, 'Type':type})       def addReport(self, Name=\"Default\",GroupBy=[{\"Type\": \"DIMENSION\",\"Key\": \"SERVICE\"},],      Style='Total', NoCredits=True, CreditsOnly=False, RefundOnly=False, UpfrontOnly=False, IncSupport=False):         type = 'chart' #other option table         results = []         if not NoCredits:             response = self.client.get_cost_and_usage(                 TimePeriod={                     'Start': self.start.isoformat(),                     'End': self.end.isoformat()                 },                 Granularity='MONTHLY',                 Metrics=[                     'UnblendedCost',                 ],                 GroupBy=GroupBy             )         else:             Filter = {\"And\": []}              Dimensions={\"Not\": {\"Dimensions\": {\"Key\": \"RECORD_TYPE\",\"Values\": [\"Credit\", \"Refund\", \"Upfront\", \"Support\"]}}}             if INC_SUPPORT or IncSupport: #If global set for including support, we dont exclude it                 Dimensions={\"Not\": {\"Dimensions\": {\"Key\": \"RECORD_TYPE\",\"Values\": [\"Credit\", \"Refund\", \"Upfront\"]}}}             if CreditsOnly:                 Dimensions={\"Dimensions\": {\"Key\": \"RECORD_TYPE\",\"Values\": [\"Credit\",]}}             if RefundOnly:                 Dimensions={\"Dimensions\": {\"Key\": \"RECORD_TYPE\",\"Values\": [\"Refund\",]}}             if UpfrontOnly:                 Dimensions={\"Dimensions\": {\"Key\": \"RECORD_TYPE\",\"Values\": [\"Upfront\",]}}              tagValues = None             if TAG_KEY:                 tagValues = self.client.get_tags(                     SearchString=TAG_VALUE_FILTER,                     TimePeriod = {                         'Start': self.start.isoformat(),                         'End': datetime.date.today().isoformat()                     },                     TagKey=TAG_KEY                 )              if tagValues:                 Filter[\"And\"].append(Dimensions)                 if len(tagValues[\"Tags\"]) &gt; 0:                     Tags = {\"Tags\": {\"Key\": TAG_KEY, \"Values\": tagValues[\"Tags\"]}}                     Filter[\"And\"].append(Tags)             else:                 Filter = Dimensions.copy()              response = self.client.get_cost_and_usage(                 TimePeriod={                     'Start': self.start.isoformat(),                     'End': self.end.isoformat()                 },                 Granularity='MONTHLY',                 Metrics=[                     'UnblendedCost',                 ],                 GroupBy=GroupBy,                 Filter=Filter             )          if response:             results.extend(response['ResultsByTime'])              while 'nextToken' in response:                 nextToken = response['nextToken']                 response = self.client.get_cost_and_usage(                     TimePeriod={                         'Start': self.start.isoformat(),                         'End': self.end.isoformat()                     },                     Granularity='MONTHLY',                     Metrics=[                         'UnblendedCost',                     ],                     GroupBy=GroupBy,                     NextPageToken=nextToken                 )                  results.extend(response['ResultsByTime'])                 if 'nextToken' in response:                     nextToken = response['nextToken']                 else:                     nextToken = False         rows = []         sort = ''         for v in results:             row = {'date':v['TimePeriod']['Start']}             sort = v['TimePeriod']['Start']             for i in v['Groups']:                 key = i['Keys'][0]                 if key in self.accounts:                     key = self.accounts[key][ACCOUNT_LABEL]                 row.update({key:float(i['Metrics']['UnblendedCost']['Amount'])})              if not v['Groups']:                 row.update({'Total':float(v['Total']['UnblendedCost']['Amount'])})             rows.append(row)            df = pd.DataFrame(rows)         df.set_index(\"date\", inplace= True)         df = df.fillna(0.0)          if Style == 'Change':             dfc = df.copy()             lastindex = None             for index, row in df.iterrows():                 if lastindex:                     for i in row.index:                         try:                             df.at[index,i] = dfc.at[index,i] - dfc.at[lastindex,i]                         except:                             logging.exception(\"Error\")                             df.at[index,i] = 0                 lastindex = index         df = df.T         df = df.sort_values(sort, ascending=False)         self.reports.append({'Name':Name,'Data':df, 'Type':type})       def generateExcel(self):         # Create a Pandas Excel writer using XlsxWriter as the engine.\\         os.chdir('\/tmp')         writer = pd.ExcelWriter('cost_explorer_report.xlsx', engine='xlsxwriter')         workbook = writer.book         for report in self.reports:             print(report['Name'],report['Type'])             report['Data'].to_excel(writer, sheet_name=report['Name'])             worksheet = writer.sheets[report['Name']]             if report['Type'] == 'chart':                  # Create a chart object.                 chart = workbook.add_chart({'type': 'column', 'subtype': 'stacked'})                   chartend=13                 for row_num in range(1, len(report['Data']) + 1):                     chart.add_series({                         'name':       [report['Name'], row_num, 0],                         'categories': [report['Name'], 0, 1, 0, chartend],                         'values':     [report['Name'], row_num, 1, row_num, chartend],                     })                 chart.set_y_axis({'label_position': 'low'})                 chart.set_x_axis({'label_position': 'low'})                 worksheet.insert_chart('O2', chart, {'x_scale': 2.0, 'y_scale': 2.0})         writer.save()          #Time to deliver the file to S3         if os.environ.get('S3_BUCKET'):             s3 = boto3.client('s3')             s3.upload_file(\"cost_explorer_report.xlsx\", os.environ.get('S3_BUCKET'), \"cost_explorer_report.xlsx\")         if os.environ.get('SES_SEND'):             #Email logic             msg = MIMEMultipart()             msg['From'] = os.environ.get('SES_FROM')             msg['To'] = COMMASPACE.join(os.environ.get('SES_SEND').split(\",\"))             msg['Date'] = formatdate(localtime=True)             msg['Subject'] = \"Cost Explorer Report\"             text = \"Find your Cost Explorer report attached\\n\\n\"             msg.attach(MIMEText(text))             with open(\"cost_explorer_report.xlsx\", \"rb\") as fil:                 part = MIMEApplication(                     fil.read(),                     Name=\"cost_explorer_report.xlsx\"                 )             part['Content-Disposition'] = 'attachment; filename=\"%s\"' % \"cost_explorer_report.xlsx\"             msg.attach(part)             #SES Sending             ses = boto3.client('ses', region_name=SES_REGION)             result = ses.send_raw_email(                 Source=msg['From'],                 Destinations=os.environ.get('SES_SEND').split(\",\"),                 RawMessage={'Data': msg.as_string()}             )        def lambda_handler(event, context):     costexplorer = CostExplorer(CurrentMonth=False)     #Default addReport has filter to remove Support \/ Credits \/ Refunds \/ UpfrontRI     #Overall Billing Reports     costexplorer.addReport(Name=\"Total\", GroupBy=[],Style='Total',IncSupport=True)     costexplorer.addReport(Name=\"TotalChange\", GroupBy=[],Style='Change')     costexplorer.addReport(Name=\"TotalInclCredits\", GroupBy=[],Style='Total',NoCredits=False,IncSupport=True)     costexplorer.addReport(Name=\"TotalInclCreditsChange\", GroupBy=[],Style='Change',NoCredits=False)     costexplorer.addReport(Name=\"Credits\", GroupBy=[],Style='Total',CreditsOnly=True)     costexplorer.addReport(Name=\"Refunds\", GroupBy=[],Style='Total',RefundOnly=True)     costexplorer.addReport(Name=\"RIUpfront\", GroupBy=[],Style='Total',UpfrontOnly=True)     #GroupBy Reports     costexplorer.addReport(Name=\"Services\", GroupBy=[{\"Type\": \"DIMENSION\",\"Key\": \"SERVICE\"}],Style='Total',IncSupport=True)     costexplorer.addReport(Name=\"ServicesChange\", GroupBy=[{\"Type\": \"DIMENSION\",\"Key\": \"SERVICE\"}],Style='Change')     costexplorer.addReport(Name=\"Accounts\", GroupBy=[{\"Type\": \"DIMENSION\",\"Key\": \"LINKED_ACCOUNT\"}],Style='Total')     costexplorer.addReport(Name=\"AccountsChange\", GroupBy=[{\"Type\": \"DIMENSION\",\"Key\": \"LINKED_ACCOUNT\"}],Style='Change')     costexplorer.addReport(Name=\"Regions\", GroupBy=[{\"Type\": \"DIMENSION\",\"Key\": \"REGION\"}],Style='Total')     costexplorer.addReport(Name=\"RegionsChange\", GroupBy=[{\"Type\": \"DIMENSION\",\"Key\": \"REGION\"}],Style='Change')     if os.environ.get('COST_TAGS'): #Support for multiple\/different Cost Allocation tags         for tagkey in os.environ.get('COST_TAGS').split(','):             tabname = tagkey.replace(\":\",\".\") #Remove special chars from Excel tabname             costexplorer.addReport(Name=\"{}\".format(tabname)[:31], GroupBy=[{\"Type\": \"TAG\",\"Key\": tagkey}],Style='Total')             costexplorer.addReport(Name=\"Change-{}\".format(tabname)[:31], GroupBy=[{\"Type\": \"TAG\",\"Key\": tagkey}],Style='Change')     #RI Reports     costexplorer.addRiReport(Name=\"RICoverage\")     costexplorer.addRiReport(Name=\"RIUtilization\")     costexplorer.addRiReport(Name=\"RIUtilizationSavings\", Savings=True)     costexplorer.addRiReport(Name=\"RIRecommendation\") #Service supported value(s): Amazon Elastic Compute Cloud - Compute, Amazon Relational Database Service     costexplorer.generateExcel()     return \"Report Generated\" <\/code><\/pre>\n<h2>IAM Role<\/h2>\n<p>\u0427\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f, Lambda \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u043e\u0431\u043b\u0430\u0434\u0430\u0442\u044c \u0440\u043e\u043b\u044c\u044e \u0441 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u043c\u0438 \u043d\u0438\u0436\u0435 \u043f\u0440\u0430\u0432\u0430\u043c\u0438:<\/p>\n<h3>\u0411\u0430\u0437\u043e\u0432\u0430\u044f \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0430 Lambda<\/h3>\n<pre><code class=\"json\">{     \"Version\": \"2012-10-17\",     \"Statement\": [         {             \"Effect\": \"Allow\",             \"Action\": [                 \"logs:CreateLogGroup\",                 \"logs:CreateLogStream\",                 \"logs:PutLogEvents\"             ],             \"Resource\": \"*\"         }     ] }<\/code><\/pre>\n<h3>\u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u043e\u0442\u0447\u0435\u0442\u043e\u0432 \u0432 S3 \u0431\u0430\u043a\u0435\u0442<\/h3>\n<pre><code class=\"json\">{     \"Version\": \"2012-10-17\",     \"Statement\": [         {             \"Sid\": \"VisualEditor0\",             \"Effect\": \"Allow\",             \"Action\": [                 \"s3:PutObject\",                 \"s3:GetObject\"             ],             \"Resource\": \"arn:aws:s3:::account.admin\/*\"         }     ] }<\/code><\/pre>\n<h3>Simple Email Service<\/h3>\n<pre><code class=\"json\">{     \"Version\": \"2012-10-17\",     \"Statement\": [         {             \"Sid\": \"VisualEditor0\",             \"Effect\": \"Allow\",             \"Action\": [                 \"ses:SendEmail\",                 \"ses:SendRawEmail\"             ],             \"Resource\": \"*\"         }     ] }<\/code><\/pre>\n<h3>Cost Explorer<\/h3>\n<pre><code class=\"json\">{     \"Version\": \"2012-10-17\",     \"Statement\": [         {             \"Sid\": \"VisualEditor0\",             \"Effect\": \"Allow\",             \"Action\": \"ce:*\",             \"Resource\": \"*\"         }     ] }<\/code><\/pre>\n<h2>\u0417\u0430\u043f\u0443\u0441\u043a \u043d\u0430 Event Bridge<\/h2>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u043c\u044b \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u043d\u0430\u0448\u0435\u0439 Lambda \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0430 Event Bridge, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, 5 \u0447\u0438\u0441\u043b\u0430 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043c\u0435\u0441\u044f\u0446\u0430. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u0441\u0435\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u044f \u0431\u0443\u0434\u0443 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c email \u0441 \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u043d\u044b\u043c XLS-\u043e\u0442\u0447\u0435\u0442\u043e\u043c. \u0422\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u0435\u0436\u0435\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u043e \u0438 \u0434\u0430\u0436\u0435 \u043d\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u0434\u043d\u0438 \u043d\u0435\u0434\u0435\u043b\u0438, \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438.<\/p>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/552462\/\"> https:\/\/habr.com\/ru\/post\/552462\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0423 Amazon Web Services \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u0439 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u043f\u0430\u043a\u0435\u0442:&nbsp;\u0445\u043e\u0440\u043e\u0448\u0438\u0439 \u043d\u0430\u0431\u043e\u0440 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0438 \u0449\u0435\u0434\u0440\u0430\u044f \u0440\u0430\u0437\u0434\u0430\u0447\u0430 \u043a\u0440\u0435\u0434\u0438\u0442\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432. \u042f \u0431\u044b\u043b \u0443\u0432\u0435\u0440\u0435\u043d: \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 \u043e\u043f\u043b\u0430\u0442\u043e\u0439 \u043c\u043e\u0435\u0433\u043e \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043d\u0435 \u0431\u0443\u0434\u0435\u0442, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e \u0440\u0430\u0441\u0445\u043e\u0434\u0430\u0445 \u043d\u0435 \u0431\u0435\u0441\u043f\u043e\u043a\u043e\u0438\u043b\u0441\u044f. \u041c\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 100% serverless, \u0438 \u044f \u0432\u0441\u0435\u0433\u0434\u0430 \u0443\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u043b\u0441\u044f \u0432 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f, \u0442\u0430\u043a \u0447\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043b \u0432\u043e\u043f\u0440\u043e\u0441 \u043e\u043f\u043b\u0430\u0442\u044b. \u0412 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u044f \u0440\u0430\u0441\u0441\u043b\u0430\u0431\u0438\u043b\u0441\u044f \u0438 \u043f\u043e\u0442\u0435\u0440\u044f\u043b \u0431\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c.<\/p>\n<p>\u041f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u043c\u043e\u0439 \u043f\u0440\u043e\u0434\u0443\u043a\u0442 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0441\u044f \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u0435\u0435, \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0441\u0442\u0430\u043b\u043e \u0431\u043e\u043b\u044c\u0448\u0435\u2026 \u0438 \u044f \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u0441\u0447\u0435\u0442 \u043d\u0430 62$. \u041f\u0435\u0440\u0435\u0436\u0438\u0442\u044c \u043c\u043e\u0436\u043d\u043e, \u043d\u043e \u044f \u0437\u0430\u0434\u0443\u043c\u0430\u043b\u0441\u044f \u043e \u0442\u0435\u043c\u043f\u0430\u0445 \u0440\u043e\u0441\u0442\u0430: \u043c\u043e\u0451 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0435 \u0431\u044b\u043b\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0434\u043b\u044f \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0438\u044f \u0437\u0430\u0442\u0440\u0430\u0442, \u0442\u0430\u043a \u043a\u0430\u043a \u044f \u043e\u0431 \u044d\u0442\u043e\u043c \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0437\u0430\u0434\u0443\u043c\u044b\u0432\u0430\u043b\u0441\u044f. \u0427\u0442\u043e \u0436, \u043f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0437\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u0435\u043c \u0440\u0430\u0441\u0445\u043e\u0434\u043e\u0432.<\/p>\n<h2>AWS Cost Explorer<\/h2>\n<p>\u0421\u0435\u0440\u0432\u0438\u0441 <a href=\"https:\/\/docs.aws.amazon.com\/awsaccountbilling\/latest\/aboutv2\/billing-what-is.html\" rel=\"noopener noreferrer nofollow\">AWS Billing dashboard<\/a> \u0445\u043e\u0440\u043e\u0448\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u043e\u043f\u043b\u0430\u0442\u044b \u0441\u0447\u0435\u0442\u043e\u0432 \u0438 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0433\u0440\u0430\u0444\u0438\u043a \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0430 \u0441\u0447\u0435\u0442\u043e\u0432 \u0437\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043c\u0435\u0441\u044f\u0446. \u041d\u043e \u044d\u0442\u043e\u0442 \u0441\u0435\u0440\u0432\u0438\u0441 \u0435\u0434\u0432\u0430 \u043b\u0438 \u043f\u0440\u0435\u0442\u0435\u043d\u0434\u0443\u0435\u0442 \u043d\u0430 \u0437\u0432\u0430\u043d\u0438\u0435 \u043b\u0443\u0447\u0448\u0435\u0433\u043e \u0432 AWS. \u041c\u0435\u0441\u044f\u0447\u043d\u044b\u0439 \u043f\u0440\u043e\u0433\u043d\u043e\u0437 \u0447\u0430\u0441\u0442\u043e \u0432\u0440\u0435\u0442, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043b\u0443\u0447\u0448\u0435 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432\u043e\u0432\u0441\u0435.<\/p>\n<p>\u041f\u043e\u043c\u0438\u043c\u043e Billing Dashboard, \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0439 Cost Explorer \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0440\u043e\u0448\u0443\u044e \u0434\u0435\u0442\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u041a\u0440\u043e\u043c\u0435 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0440\u0430\u0437\u0431\u0438\u0432\u043a\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044f \u0432 AWS, \u043c\u043e\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u0434 \u043f\u043e\u0434 Cost Explorer, \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u044f \u043c\u043d\u043e\u0433\u043e \u0446\u0435\u043d\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438. \u0418 \u043c\u043d\u0435 \u044d\u0442\u043e \u0434\u0435\u043b\u043e \u0437\u0430\u0448\u043b\u043e.<\/p>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f Cost Explorer, \u044f \u0441\u043c\u043e\u0433 \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0443\u044f\u0437\u0432\u0438\u043c\u044b\u0435 \u043c\u0435\u0441\u0442\u0430 \u0438 \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0438\u0445 \u0437\u0430\u0434\u043e\u043b\u0433\u043e \u0434\u043e \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0441 \u043c\u0435\u043d\u044f \u043d\u0430\u0447\u043d\u0443\u0442 \u0441\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0437\u0430 \u043d\u0438\u0445 \u0434\u0435\u043d\u044c\u0433\u0438. \u0415\u0449\u0435 \u0440\u0430\u0437 \u0441\u043f\u0430\u0441\u0438\u0431\u043e AWS.<\/p>\n<h2>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441<\/h2>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043d\u0430\u0447\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c, \u043d\u0430\u0434\u043e \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c \u0432\u0438\u0434\u043e\u043c \u043a\u043e\u043d\u0441\u043e\u043b\u0438 Billing Dashboard. \u041d\u0443\u0436\u043d\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0435\u0451, \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u0442\u043e\u0438\u0442\u044c \u0434\u0435\u043d\u0435\u0433. \u041b\u0443\u0447\u0448\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0437\u0430\u0440\u0430\u043d\u0435\u0435, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u043e\u043c \u043d\u0435 \u0431\u044b\u043b\u043e \u043c\u0443\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0431\u043e\u043b\u044c\u043d\u043e. \u0423 \u043a\u043e\u0433\u043e \u043c\u043d\u043e\u0433\u043e \u043e\u0441\u0442\u0430\u0442\u043a\u0443, \u0442\u043e\u0442 \u043d\u0435 \u0431\u043e\u0438\u0442\u0441\u044f \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0443!<\/p>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0438\u043d\u0442\u0443\u0438\u0442\u0438\u0432\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0439: \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0435 \u043e\u0442\u0447\u0435\u0442\u044b \u043f\u043e \u0434\u043d\u044f\u043c \/ \u0443\u0441\u043b\u0443\u0433\u0435; \u0438\u043b\u0438 \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \/ \u0440\u0435\u0433\u0438\u043e\u043d\u0443 \/ \u0443\u0441\u043b\u0443\u0433\u0435 \u2013 \u0438 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u042d\u0442\u043e \u043c\u043e\u0439 \u0433\u0440\u0430\u0444\u0438\u043a \u043f\u043e\u0442\u0440\u0430\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u0437\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0441\u044f\u0446\u0435\u0432.<\/p>\n<h3>\u041e\u0442\u0447\u0435\u0442\u044b<\/h3>\n<p>\u0412 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 reports \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u043e\u0442\u0447\u0435\u0442\u043e\u0432. AWS \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0435\u043f\u043b\u043e\u0445\u043e\u0439 \u043d\u0430\u0431\u043e\u0440 \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u0434\u043b\u044f \u043e\u0442\u0447\u0435\u0442\u043e\u0432, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u0441 \u043d\u0443\u043b\u044f.<\/p>\n<h3>\u0411\u044e\u0434\u0436\u0435\u0442\u044b<\/h3>\n<p>Cost Explorer \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f&nbsp;\u043e\u0442\u0447\u0435\u0442\u0430\u043c\u0438 \u0438 \u0433\u0440\u0430\u0444\u0438\u043a\u0430\u043c\u0438. \u0427\u0430\u0449\u0435&nbsp;\u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442 \u043e\u0441\u0432\u0430\u0438\u0432\u0430\u0442\u044c AWS \u0441 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0431\u044e\u0434\u0436\u0435\u0442\u043e\u0432 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0445 \u043f\u043e\u0434 \u043d\u0438\u0445 \u043e\u043f\u043e\u0432\u0435\u0449\u0435\u043d\u0438\u0439, \u043d\u043e \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0431\u043e\u043b\u044c\u0448\u0435. \u041c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0442\u044c \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u0435 \u0431\u044e\u0434\u0436\u0435\u0442\u044b (\u043f\u043e \u0441\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u0438 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e) \u0434\u043b\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u0438 \u0434\u0430\u0436\u0435 \u0434\u043b\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u043e\u0432 \u0438\u043b\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430.  <\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0431\u044e\u0434\u0436\u0435\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043c \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 DynamoDB \u0438 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0430\u0442\u044c \u0432\u0430\u0441 \u043f\u0440\u0438 \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u0438 \u043f\u043e\u0440\u043e\u0433\u043e\u0432\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<h3>\u041e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0430\u043d\u043e\u043c\u0430\u043b\u0438\u0439<\/h3>\n<p>\u042d\u0442\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u0441\u0438\u0441\u0442\u0435\u043c \u0441 \u0440\u0430\u0432\u043d\u043e\u043c\u0435\u0440\u043d\u043e\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439, \u0430 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f \u043f\u043e\u043c\u043e\u0433\u0443\u0442 \u0432\u0430\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u044b\u0439 \u0440\u0430\u0441\u0445\u043e\u0434 \u043a\u0430\u043a \u0437\u0430\u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e. \u041c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u00ab\u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0438\u00bb, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043b\u0435\u0434\u044f\u0442 \u0437\u0430 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c\u0438 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f\u043c\u0438. \u041c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u044e\u0442 \u0442\u0435\u043a\u0443\u0449\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044f \u0441 \u0438\u0441\u0442\u043e\u0440\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0434\u0438\u0442\u044c \u043e\u0431 \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u0438\u0438 \u043e\u0442 \u0442\u0440\u0435\u043d\u0434\u043e\u0432.<\/p>\n<h3>Cost Explorer API<\/h3>\n<p>\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0432\u0438\u0434 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u0435\u043d\u044f \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u2013 \u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u044d\u043f\u0438\u0437\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u043b\u0435\u043d\u0438\u044f. \u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u0435\u0447\u0442\u043e \u0431\u043e\u043b\u044c\u0448\u0435\u0435, AWS \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u0439 API. \u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 <a href=\"https:\/\/github.com\/aws-samples\" rel=\"noopener noreferrer nofollow\">AWS Samples Github<\/a> \u0434\u0430\u0435\u0442 \u043d\u0430\u043c \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a API Cost Explorer.<\/p>\n<p>\u041c\u043e\u0439 \u043a\u043e\u0434 \u043e\u0441\u043d\u043e\u0432\u0430\u043d \u043d\u0430 \u044d\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435, \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043e\u0442\u0447\u0435\u0442 \u0434\u043b\u044f Cost Explorer\u2019a.<\/p>\n<h2>\u041a\u043e\u0434 Lambda \u0444\u0443\u043d\u043a\u0446\u0438\u0438<\/h2>\n<pre><code class=\"python\">import os import sys # Required to load modules from vendored subfolder (for clean development env) sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), \".\/vendored\"))  import boto3 import datetime import logging import pandas as pd #For date from dateutil.relativedelta import relativedelta #For email from email.mime.application import MIMEApplication from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.utils import COMMASPACE, formatdate  SES_REGION=\"ap-south-1\"  CURRENT_MONTH = True  #Default exclude support, as for Enterprise Support #as support billing is finalised later in month so skews trends     INC_SUPPORT = os.environ.get('INC_SUPPORT') if INC_SUPPORT == \"true\":     INC_SUPPORT = True else:     INC_SUPPORT = False  TAG_VALUE_FILTER = os.environ.get('TAG_VALUE_FILTER') or '*' TAG_KEY = os.environ.get('TAG_KEY')  class CostExplorer:     \"\"\"Retrieves BillingInfo checks from CostExplorer API     &gt;&gt;&gt; costexplorer = CostExplorer()     &gt;&gt;&gt; costexplorer.addReport(GroupBy=[{\"Type\": \"DIMENSION\",\"Key\": \"SERVICE\"}])     &gt;&gt;&gt; costexplorer.generateExcel()     \"\"\"         def __init__(self, CurrentMonth=False):         #Array of reports ready to be output to Excel.         self.reports = []         self.client = boto3.client('ce', region_name='us-east-1')         # self.end = datetime.date.today().replace(day=1)         self.riend = datetime.date.today()         self.end = self.riend          # Default is last 12 months         self.start = (datetime.date.today() - relativedelta(months=+12)).replace(day=1) #1st day of month 12 months ago          self.ristart = (datetime.date.today() - relativedelta(months=+11)).replace(day=1) #1st day of month 11 months ago         self.sixmonth = (datetime.date.today() - relativedelta(months=+6)).replace(day=1) #1st day of month 6 months ago, so RI util has savings values         self.accounts = {}      def addRiReport(self, Name='RICoverage', Savings=False, PaymentOption='PARTIAL_UPFRONT', Service='Amazon Elastic Compute Cloud - Compute'): #Call with Savings True to get Utilization report in dollar savings         type = 'chart' #other option table         if Name == \"RICoverage\":             results = []             response = self.client.get_reservation_coverage(                 TimePeriod={                     'Start': self.ristart.isoformat(),                     'End': self.riend.isoformat()                 },                 Granularity='MONTHLY'             )             results.extend(response['CoveragesByTime'])             while 'nextToken' in response:                 nextToken = response['nextToken']                 response = self.client.get_reservation_coverage(                     TimePeriod={                         'Start': self.ristart.isoformat(),                         'End': self.riend.isoformat()                     },                     Granularity='MONTHLY',                     NextPageToken=nextToken                 )                 results.extend(response['CoveragesByTime'])                 if 'nextToken' in response:                     nextToken = response['nextToken']                 else:                     nextToken = False              rows = []             for v in results:                 row = {'date':v['TimePeriod']['Start']}                 row.update({'Coverage%':float(v['Total']['CoverageHours']['CoverageHoursPercentage'])})                 rows.append(row)                df = pd.DataFrame(rows)             df.set_index(\"date\", inplace= True)             df = df.fillna(0.0)             df = df.T         elif Name in ['RIUtilization','RIUtilizationSavings']:             #Only Six month to support savings             results = []             response = self.client.get_reservation_utilization(                 TimePeriod={                     'Start': self.sixmonth.isoformat(),                     'End': self.riend.isoformat()                 },                 Granularity='MONTHLY'             )             results.extend(response['UtilizationsByTime'])             while 'nextToken' in response:                 nextToken = response['nextToken']                 response = self.client.get_reservation_utilization(                     TimePeriod={                         'Start': self.sixmonth.isoformat(),                         'End': self.riend.isoformat()                     },                     Granularity='MONTHLY',                     NextPageToken=nextToken                 )                 results.extend(response['UtilizationsByTime'])                 if 'nextToken' in response:                     nextToken = response['nextToken']                 else:                     nextToken = False              rows = []             if results:                 for v in results:                     row = {'date':v['TimePeriod']['Start']}                     if Savings:                         row.update({'Savings$':float(v['Total']['NetRISavings'])})                     else:                         row.update({'Utilization%':float(v['Total']['UtilizationPercentage'])})                     rows.append(row)                    df = pd.DataFrame(rows)                 df.set_index(\"date\", inplace= True)                 df = df.fillna(0.0)                 df = df.T                 type = 'chart'             else:                 df = pd.DataFrame(rows)                 type = 'table' #Dont try chart empty result         elif Name == 'RIRecommendation':             results = []             response = self.client.get_reservation_purchase_recommendation(                 #AccountId='string', May use for Linked view                 LookbackPeriodInDays='SIXTY_DAYS',                 TermInYears='ONE_YEAR',                 PaymentOption=PaymentOption,                 Service=Service             )             results.extend(response['Recommendations'])             while 'nextToken' in response:                 nextToken = response['nextToken']                 response = self.client.get_reservation_purchase_recommendation(                     #AccountId='string', May use for Linked view                     LookbackPeriodInDays='SIXTY_DAYS',                     TermInYears='ONE_YEAR',                     PaymentOption=PaymentOption,                     Service=Service,                     NextPageToken=nextToken                 )                 results.extend(response['Recommendations'])                 if 'nextToken' in response:                     nextToken = response['nextToken']                 else:                     nextToken = False              rows = []             for i in results:                 for v in<\/code><\/pre>\n<p><\/br><\/p>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-321505","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/321505","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=321505"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/321505\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=321505"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=321505"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=321505"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}