概要
この記事 のPython プログラムを変更し、Microsoft Teams に サブスクリプション毎の使用料金合計一覧表と日毎の使用料金一覧表(Teamsで水平スクロールができないので、2つに分割)を1つのText項目として Post(Webhook) してみました。 Postするにあたり、データは markdown 形式に変換しています(html形式にもトライしましたが、大変見にくかった)。
ローカル環境
macOS Monterey 12.1
python 3.8.12
実行プログラム
GetSubscriptionCostManagement_23.py
import os
import json
import requests
import time
import argparse
from azure.identity import AzureCliCredential, DefaultAzureCredential
from azure.mgmt.resource import SubscriptionClient
from azure.mgmt.costmanagement import CostManagementClient
import pandas as pd
from datetime import datetime, date, timedelta
# teams_endpoint = 'Microsoft Teamsの チャネルエンドポイント(Webhook)'
TEAMS_ENDPOINT = {
"TECH_TEST": os.environ['ENDPOINT_TECH_TEST']
}
# 接続しているテナントのサブスクリプションを操作するオブジェクトを取得
def GetSubscriptionObject():
subscription_client = SubscriptionClient(
# credential=AzureCliCredential()
credential=DefaultAzureCredential()
)
return subscription_client
# CostManagement情報 を操作するオブジェクトを取得
def GetCostManagementObject():
costmgmt_client = CostManagementClient(
# credential=AzureCliCredential()
credential=DefaultAzureCredential()
)
return costmgmt_client
# 指定した Subscription について CostManagement からコストを取得
def GetCostManagement(costmgmt_client, subs_id):
# Query costmanagement
SCOPE = '/subscriptions/{}'.format(subs_id)
costmanagement = costmgmt_client.query.usage(
SCOPE,
{
"type": "Usage",
"timeframe": "MonthToDate",
"dataset": {
"granularity": "Daily",
"aggregation": {
"totalCost": {
"name": "PreTaxCost",
"function": "Sum"
}
},
"grouping": [
{
"type": "Dimension",
"name": "ResourceGroup"
}
]
}
}
)
return costmanagement
# 合計行の追加
def append_sum_row_label(df):
df.loc['Total'] = df.sum(numeric_only=True)
return df
# 日単位のサブスクリプション毎の一覧表
def Report_Daily(df):
# Teamsで水平スクロールができないのでデータを2つに分割
df1 = df.loc[:,['jjj', 'eee', 'bbb', 'ggg', 'ffff', 'ddd', 'hhh', 'ccc']]
df2 = df.loc[:,['japp', 'iapp', 'aaa', 'kkk', 'MixixTeam', 'iii']]
# reset_indexする
df1.reset_index(inplace=True)
df2.reset_index(inplace=True)
# 合計行の追加
df1 = append_sum_row_label(df1)
df2 = append_sum_row_label(df2)
# html形式への変換例
# post_str1 = df1.to_html(float_format='{:,.0f}'.format)
# markdown形式への変換
post_str1 = df1.astype(str).to_markdown(floatfmt=",.0f")
post_str2 = df2.astype(str).to_markdown(floatfmt=",.0f")
print("\n------------------------------------------------\n")
print(post_str1)
print("\n------------------------------------------------\n")
print(post_str2)
return post_str1, post_str2
# サブスクリプションの合計一覧表(利用料金での降順)
def Report_Summury(tdf):
# 利用料金で降順のソート
tdf = tdf.sort_values(by=['UsageCost'], ascending=False)
# カラムの順番を変更
tdf = tdf.loc[:,['Subscription', 'UsageCost']]
# reset_indexする
tdf.reset_index(inplace=True)
# 不要カラムの削除
tdf = tdf.drop(['Date'], axis=1)
# markdown形式への変換
post_str0 = tdf.to_markdown(floatfmt=",.0f")
print("\n------------------------------------------------\n")
print(post_str0)
return post_str0
# TeamsEndpointへのデータPOST
def teams_endpoint_post(post_str1, post_str2, post_str0, totalcost):
# 前日の日付の取得
day0 = (date.today() + timedelta(days=-1)).isoformat()
# Microsoft Teams へ送信する下ごしらえ
request = {
'title': '【 Azure : ' + day0 + ' 】 合計: ¥ ' + totalcost,
'text': post_str0 + '\n\n' + post_str1 + '\n\n' + post_str2
}
# Microsoft Teams へ送信する
response = requests.post(TEAMS_ENDPOINT['TECH_TEST'], json.dumps(request))
print(response)
# サブスクリプションIDを指定しリソースグループ毎に CostManagement情報を取得
def GetSubscriptionCsotManagement():
# サブスクリプションを操作するオブジェクトの取得
subscription_list = GetSubscriptionObject()
# CostManagementを操作するオブジェクトの取得
costmgmt_client = GetCostManagementObject()
# 取得項目の定義
row_list = ['UsageCost', 'Date', 'ResourceGroup', 'Currency']
# 小数点以下の桁数:2(デフォルト:6)+コンマ区切りの挿入 を定義
pd.options.display.float_format = '{:,.2f}'.format
# サブスクリプション毎に CostManagement からコストを取得
for n, subs in enumerate(subscription_list.subscriptions.list()):
# print("\nサブスクリプション : {} {}".format(subs.subscription_id, subs.display_name))
costmanagement = GetCostManagement(costmgmt_client, subs.subscription_id)
# 表示させるデータのDataFrame化
if len(costmanagement.rows) > 0 :
# DataFrame型でデータの取得
rowdf = pd.DataFrame(costmanagement.rows, columns = row_list)
# 不必要項目の削除
rowdf = rowdf.drop(['Currency', 'ResourceGroup'], axis=1)
# Date項目の型をdatetime型に変換
rowdf['Date'] = pd.to_datetime(rowdf['Date'].astype(str), format='%Y-%m-%d')
# インデックス化
rowdf.set_index('Date', inplace=True)
# resampleメソッドで、日単位で集計
dsumdf = rowdf.resample('D').sum()
# resampleメソッドで、月単位で集計
msumdf = rowdf.resample('M').sum()
msumdf['Subscription'] = subs.display_name
print("\tサブスクリプション : {} ".format(subs.display_name))
if n == 0 :
df = dsumdf
df.rename(columns={'UsageCost': subs.display_name}, inplace=True)
tdf = msumdf
else :
df[subs.display_name] = dsumdf['UsageCost']
tdf = tdf.append(msumdf)
# オブジェクトのクローズ処理
costmgmt_client.close()
subscription_list.close()
# 日単位のサブスクリプション毎の一覧表
post_str1, post_str2 = Report_Daily(df)
### サブスクリプションの合計一覧表(利用料金での降順)
post_str0 = Report_Summury(tdf)
# resampleメソッドで、月単位で集計
totalcost = tdf['UsageCost'].sum()
# TeamsEndpointへのデータPOST
teams_endpoint_post(post_str1, post_str2, post_str0, '{:,.0f}'.format(round(totalcost)))
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Subscription の 日々のコスト取得')
args = parser.parse_args()
start = time.time()
GetSubscriptionCsotManagement()
generate_time = time.time() - start
print("\n 取得時間:{0}".format(generate_time) + " [sec] \n")
プログラムの実行
$ python GetSubscriptionCostManagement_23.py
サブスクリプション : iapp
サブスクリプション : japp
サブスクリプション : aaa
サブスクリプション : bbb
サブスクリプション : ccc
サブスクリプション : ddd
サブスクリプション : eee
サブスクリプション : fff
サブスクリプション : ggg
サブスクリプション : hhh
サブスクリプション : iii
サブスクリプション : jjj
サブスクリプション : kkk
サブスクリプション : MixixTeam
------------------------------------------------
| | Subscription | UsageCost |
|---:|:---------------|------------:|
| 0 | bbb | 144,455 |
| 1 | ddd | 75,169 |
| 2 | cccc | 43,630 |
| 3 | aaa | 41,474 |
| 4 | ggg | 36,264 |
| 5 | kkk | 34,875 |
| 6 | iapp | 22,780 |
| 7 | hhh | 18,500 |
| 8 | fff | 18,066 |
| 9 | japp | 8,204 |
| 10 | jjj | 6,682 |
| 11 | eee | 5,174 |
| 12 | MixedTeam | 3,294 |
| 13 | iii | 2,899 |
------------------------------------------------
| | Date | jjj | eee | bbb | ggg | fff | ddd | hhh | ccc |
|:------|:-----------|---------:|---------:|----------:|----------:|----------:|----------:|---------:|---------:|
| 0 | 2022-03-01 | 192 | 192 | 4,579 | 1,521 | 314 | 13,840 | 473 | 1,619 |
| 1 | 2022-03-02 | 429 | 192 | 5,066 | 1,524 | 314 | 3,839 | 473 | 1,619 |
| 2 | 2022-03-03 | 657 | 192 | 6,022 | 1,863 | 314 | 3,839 | 530 | 1,619 |
| 3 | 2022-03-04 | 828 | 192 | 5,779 | 1,699 | 314 | 3,839 | 512 | 1,619 |
| 4 | 2022-03-05 | 221 | 192 | 4,541 | 854 | 314 | 3,839 | 509 | 1,619 |
| 5 | 2022-03-06 | 221 | 192 | 4,539 | 846 | 314 | 3,839 | 509 | 1,620 |
| 6 | 2022-03-07 | 262 | 192 | 4,665 | 848 | 307 | 3,673 | 509 | 1,619 |
| 7 | 2022-03-08 | 221 | 192 | 5,718 | 3,476 | 5 | 1,099 | 509 | 1,620 |
| 8 | 2022-03-09 | 195 | 192 | 6,617 | 2,500 | 5 | 1,099 | 507 | 1,619 |
| 9 | 2022-03-10 | 192 | 192 | 6,696 | 2,059 | 6,045 | 1,099 | 763 | 1,619 |
| 10 | 2022-03-11 | 192 | 192 | 2,060 | 1,311 | 1,470 | 1,099 | 709 | 1,619 |
| 11 | 2022-03-12 | 192 | 192 | 6,379 | 1,017 | 914 | 1,099 | 540 | 1,619 |
| 12 | 2022-03-13 | 189 | 192 | 6,370 | 1,018 | 914 | 1,099 | 540 | 1,620 |
| 13 | 2022-03-14 | 192 | 192 | 7,036 | 1,019 | 914 | 1,099 | 540 | 1,619 |
| 14 | 2022-03-15 | 189 | 192 | 6,726 | 1,499 | 914 | 1,098 | 540 | 1,619 |
| 15 | 2022-03-16 | 192 | 192 | 5,143 | 1,516 | 2,807 | 1,098 | 540 | 1,619 |
| 16 | 2022-03-17 | 192 | 192 | 6,952 | 3,141 | 1,839 | 1,095 | 540 | 1,620 |
| 17 | 2022-03-18 | 192 | 192 | 7,104 | 1,815 | 5 | 1,095 | 509 | 1,619 |
| 18 | 2022-03-19 | 192 | 192 | 3,860 | 774 | 5 | 1,095 | 508 | 1,619 |
| 19 | 2022-03-20 | 189 | 192 | 3,846 | 602 | 5 | 1,095 | 508 | 1,620 |
| 20 | 2022-03-21 | 188 | 192 | 3,841 | 600 | 5 | 1,095 | 508 | 1,618 |
| 21 | 2022-03-22 | 192 | 192 | 8,337 | 685 | 5 | 1,095 | 1,082 | 1,620 |
| 22 | 2022-03-23 | 191 | 192 | 2,190 | 823 | 5 | 1,094 | 1,523 | 1,619 |
| 23 | 2022-03-24 | 191 | 192 | 3,723 | 957 | 5 | 1,095 | 1,156 | 1,620 |
| 24 | 2022-03-25 | 223 | 192 | 8,700 | 1,034 | 5 | 2,923 | 1,186 | 1,619 |
| 25 | 2022-03-26 | 191 | 192 | 4,102 | 646 | 5 | 3,568 | 1,163 | 1,620 |
| 26 | 2022-03-27 | 183 | 184 | 3,865 | 617 | 5 | 13,323 | 1,114 | 1,527 |
| Total | NaT | 6,682 | 5,174 | 144,455 | 36,264 | 18,066 | 75,169 | 18,500 | 43,630 |
------------------------------------------------
| | Date | japp | iapp | aaa | kkk | MixixTeam | iii |
|:------|:-----------|------------:|----------:|----------------:|-----------:|------------:|---------------:|
| 0 | 2022-03-01 | 311 | 596 | 1,619 | 727 | 1 | 102 |
| 1 | 2022-03-02 | 312 | 597 | 1,619 | 727 | 1 | 102 |
| 2 | 2022-03-03 | 311 | 597 | 1,619 | 727 | 1 | 102 |
| 3 | 2022-03-04 | 302 | 598 | 1,626 | 727 | 1 | 102 |
| 4 | 2022-03-05 | 296 | 599 | 1,619 | 727 | 1 | 102 |
| 5 | 2022-03-06 | 297 | 1,270 | 1,619 | 727 | 1 | 102 |
| 6 | 2022-03-07 | 309 | 741 | 1,619 | 854 | 1 | 102 |
| 7 | 2022-03-08 | 309 | 710 | 1,619 | 1,294 | 2,078 | 102 |
| 8 | 2022-03-09 | 309 | 711 | 1,619 | 727 | 1,188 | 102 |
| 9 | 2022-03-10 | 309 | 716 | 1,620 | 727 | 1 | 102 |
| 10 | 2022-03-11 | 301 | 712 | 1,446 | 727 | 1 | 102 |
| 11 | 2022-03-12 | 296 | 713 | 1,260 | 727 | 1 | 102 |
| 12 | 2022-03-13 | 296 | 713 | 1,257 | 727 | 1 | 102 |
| 13 | 2022-03-14 | 308 | 710 | 1,260 | 727 | 1 | 102 |
| 14 | 2022-03-15 | 310 | 710 | 1,257 | 727 | 1 | 243 |
| 15 | 2022-03-16 | 311 | 711 | 1,581 | 727 | 1 | 102 |
| 16 | 2022-03-17 | 310 | 711 | 1,572 | 727 | 1 | 102 |
| 17 | 2022-03-18 | 302 | 1,011 | 1,573 | 727 | 1 | 102 |
| 18 | 2022-03-19 | 297 | 1,082 | 1,573 | 727 | 1 | 102 |
| 19 | 2022-03-20 | 297 | 1,082 | 1,570 | 727 | 1 | 102 |
| 20 | 2022-03-21 | 297 | 1,079 | 1,568 | 727 | 1 | 102 |
| 21 | 2022-03-22 | 310 | 1,079 | 1,573 | 802 | 1 | 102 |
| 22 | 2022-03-23 | 310 | 1,080 | 1,574 | 733 | 1 | 102 |
| 23 | 2022-03-24 | 309 | 1,080 | 1,573 | 1,594 | 1 | 102 |
| 24 | 2022-03-25 | 302 | 1,081 | 1,573 | 13,429 | 1 | 102 |
| 25 | 2022-03-26 | 297 | 1,082 | 1,573 | 1,395 | 1 | 102 |
| 26 | 2022-03-27 | 285 | 1,010 | 1,492 | 960 | 1 | 98 |
| Total | NaT | 8,204 | 22,780 | 41,474 | 34,875 | 3,294 | 2,899 |
<Response [200]>
取得時間:99.73083806037903 [sec]
TeamsへのPost(投稿)結果
- 以下の内容で投稿されます
- タイトル:
- 【 Azure : yyyy-mm-dd 】 合計: ¥ xxx,xxx
- 本文:
- 上記アウトプットと同じ内容(ただし、3つの表の間は改行は1つのみで少し見にくいです)
- タイトル:
まとめ
Teamsへのmarkdown形式でのPostにおいて、「改行が1行しか有効にならない」「水平スクロールができない」状況です。どなたかこの2の解決策をご存知でしたらご教示ください。