Python で Azure の サブスクリプション毎に日単位で使用料金一覧を表示してみました


## 概要

Azure SDK for Python を利用して、Azureのサブスクリプション毎に日単位の使用料金とラグ情報「当日と前日/前々日/前々々日の利用料金差」を付加した一覧を取得表示するための Python プログラムです。

### ローカル環境

macOS Monterey 12.1
python 3.8.12

### 実行プログラム

```python:GetSubscriptionCostManagement_21.py
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


# 接続しているテナントのサブスクリプションを操作するオブジェクトを取得
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 LagDataframe(rowdf):
    # 'Subscription'+'Date'での集約
    lagdf = rowdf.groupby(['Subscription', 'Date']).sum()
    # print(lagdf)

    # 当日と前日/前々日/前々々日の利用料金差を表示
    lags = [1, 2, 3]
    for lag in lags :
        lagdf = pd.concat([lagdf, (lagdf['UsageCost'] - lagdf['UsageCost'].shift(lag)).rename('#Cost_'+str(lag))], axis=1)
    
    return lagdf


# サブスクリプション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()):
        # Subscription の CostManagement からコストを取得
        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')

            # Subscription項目の追加
            rowdf['Subscription'] = subs.display_name

            # ラグ情報の追加
            lagdf = LagDataframe(rowdf)
            
            print("\tサブスクリプション : {} ".format(subs.display_name))
            # print(lagdf)
                
            if n == 0 :
                df = lagdf
            else :
                df = df.append(lagdf)
    
    # オブジェクトのクローズ処理
    costmgmt_client.close()
    subscription_list.close()

    print("------------------------------------------------")
    post_str = df.to_string()
    print(post_str)
    

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_21.py
	サブスクリプション : iapp
	サブスクリプション : japp
	サブスクリプション : aaa 
	サブスクリプション : bbb 
	サブスクリプション : ccc 
	サブスクリプション : ddd 
	サブスクリプション : eee 
	サブスクリプション : fff 
	サブスクリプション : ggg 
	サブスクリプション : hhh 
	サブスクリプション : iii 
	サブスクリプション : jjj
	サブスクリプション : kkk
	サブスクリプション : MixixTeam 
------------------------------------------------
                          UsageCost    #Cost_1    #Cost_2    #Cost_3
Subscription  Date                                                  
iapp          2022-03-01     595.86        NaN        NaN        NaN
              2022-03-02     596.53       0.67        NaN        NaN
              2022-03-03     597.20       0.67       1.34        NaN
              2022-03-04     597.89       0.70       1.36       2.03
              2022-03-05     598.57       0.68       1.37       2.04
              2022-03-06   1,269.99     671.42     672.10     672.79
              2022-03-07     740.55    -529.44     141.98     142.66
              2022-03-08     709.95     -30.60    -560.04     111.38
              2022-03-09     710.62       0.67     -29.93    -559.37
              2022-03-10     716.45       5.83       6.51     -24.10
              2022-03-11     711.99      -4.46       1.37       2.04
              2022-03-12     712.67       0.68      -3.79       2.05
              2022-03-13     713.34       0.67       1.35      -3.11
              2022-03-14     710.47      -2.87      -2.20      -1.52
              2022-03-15     709.96      -0.51      -3.38      -2.71
              2022-03-16     710.63       0.67       0.16      -2.71
              2022-03-17     711.30       0.67       1.34       0.83
              2022-03-18   1,011.15     299.86     300.53     301.20
              2022-03-19   1,081.67      70.52     370.37     371.05
              2022-03-20   1,082.34       0.67      71.19     371.05
              2022-03-21   1,079.47      -2.88      -2.21      68.31
              2022-03-22   1,078.95      -0.51      -3.39      -2.72
              2022-03-23   1,079.63       0.67       0.16      -2.72
japp          2022-03-01     311.44        NaN        NaN        NaN
              2022-03-02     311.54       0.10        NaN        NaN
              2022-03-03     311.47      -0.06       0.03        NaN
              2022-03-04     302.30      -9.17      -9.24      -9.14
              2022-03-05     296.25      -6.06     -15.23     -15.29
              2022-03-06     297.43       1.18      -4.87     -14.04
              2022-03-07     309.26      11.83      13.02       6.96
                ：
                ：
                ：
MixixTeam     2022-03-01       1.12        NaN        NaN        NaN
              2022-03-02       1.12       0.00        NaN        NaN
              2022-03-03       1.12       0.00       0.00        NaN
              2022-03-04       1.12       0.00       0.00       0.00
              2022-03-05       1.12      -0.00      -0.00      -0.00
              2022-03-06       1.12      -0.00      -0.00      -0.00
              2022-03-07       1.12       0.00      -0.00      -0.00
              2022-03-08   2,077.66   2,076.54   2,076.54   2,076.54
              2022-03-09   1,188.42    -889.24   1,187.30   1,187.30
              2022-03-10       1.12  -1,187.30  -2,076.54       0.00
              2022-03-11       1.12       0.00  -1,187.30  -2,076.54
              2022-03-12       1.12       0.00       0.00  -1,187.30
              2022-03-13       1.12       0.00       0.00       0.00
              2022-03-14       1.12       0.00       0.00       0.00
              2022-03-15       1.12       0.00       0.00       0.00
              2022-03-16       1.12       0.00       0.00       0.00
              2022-03-17       1.12       0.00       0.00       0.00
              2022-03-18       1.12       0.00       0.00       0.00
              2022-03-19       1.12       0.00       0.00       0.00
              2022-03-20       1.12       0.00       0.00       0.00
              2022-03-21       1.12       0.00       0.00       0.00
              2022-03-22       1.12       0.00       0.00       0.00
              2022-03-23       1.12       0.00       0.00       0.00

 取得時間:95.63489103317261 [sec] 
```

---

### まとめ

Azure portal で確認する場合、いちいち画面を切り替えなければいけませんが、プログラムでゴリゴリするとサクッと一覧表示で取得できますね。

### 参考記事

以下の記事を参考にさせていただきました。感謝申し上げます。
[データ分析で頻出のPandas基本操作](https://qiita.com/ysdyt/items/9ccca82fc5b504e7913a)
[pandasのDataFrameデータを3桁区切りで表示する方法](https://jimaru.blog/programming/python/pandas-dataframe-digit-separator/)