Tutorial: Mengekspor data pengoptimalan karbon menggunakan skrip Python

Tutorial ini menjelaskan cara Anda menggunakan skrip Python untuk mengekspor data emisi pengoptimalan Azure Carbon sebagai output JSON. Skrip Python menjalankan permintaan jaringan CARBON Service REST API untuk mendapatkan data emisi untuk sumber daya Azure Anda. Skrip menyederhanakan proses kueri API dan menangani respons. Anda menjalankan skrip untuk menghasilkan file JSON lalu menggunakannya untuk analisis dan pelaporan terperinci.

Tutorial ini mencakup langkah-langkah yang diperlukan untuk mengekspor data emisi pengoptimalan karbon di komputer Windows lokal Anda.

Ada beberapa langkah untuk menyelesaikan tutorial ini:

  • Tinjau prasyarat dan instal komponen yang hilang
  • Mengunduh dan menginstal Python
  • Menginstal paket Python yang diperlukan
  • Memeriksa dan memperbarui contoh skrip Python
  • Jalankan skrip Python
  • Meninjau file output JSON

Prasyarat

Sebelum Anda menggunakan skrip Python, pastikan Anda memiliki:

Menginstal Azure PowerShell

Jika Anda tidak menginstal Azure PowerShell di komputer Windows lokal Anda, ikuti langkah-langkah berikut:

Luncurkan Windows PowerShell 5.1 sebagai administrator dan jalankan perintah berikut untuk memperbarui PowerShellGet dengan menggunakan galeri PowerShell:

Install-Module -Name PowerShellGet -Force

Atur kebijakan eksekusi PowerShell ke ditandatangani dari jarak jauh atau kurang ketat:

  • Periksa kebijakan eksekusi PowerShell:
    Get-ExecutionPolicy -List
    
  • Atur kebijakan eksekusi PowerShell ke ditandatangani dari jarak jauh:
    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
    
    

Gunakan cmdlet Install-Module untuk menginstal modul Az PowerShell:

Install-Module -Name Az -Repository PSGallery -Force

Anda mungkin perlu memulai ulang PowerShell setelah penginstalan selesai.

Untuk informasi selengkapnya tentang menginstal Azure PowerShell, termasuk penginstalan pada platform yang berbeda, lihat Cara menginstal Azure PowerShell.

Masuk ke Azure

Untuk mulai mengelola sumber daya Azure Anda dengan modul Az PowerShell, luncurkan sesi PowerShell dan jalankan Connect-AzAccount untuk masuk ke Azure:

Connect-AzAccount

Gunakan kredensial masuk akun Azure Anda untuk masuk ke jendela browser yang terbuka.

Anda perlu mengulangi langkah ini untuk setiap sesi PowerShell baru yang Anda mulai.

Menginstal Azure CLI

Jika Anda tidak menginstal Azure CLI di komputer Windows lokal Anda, ikuti langkah-langkah berikut:

  1. Tinjau informasi di Menginstal Azure CLI di Windows.
  2. Pilih metode penginstalan lalu jalankan alat penginstal yang paling cocok untuk komputer lokal Anda.
  3. Setelah penginstalan selesai, buka perintah baru atau jendela PowerShell (dengan hak istimewa administrator) masuk ke akun Azure Anda:
    az login
    

Mengunduh dan menginstal Python

Jika Anda tidak menginstal Python di komputer Windows lokal Anda, ikuti langkah-langkah berikut:

  1. Tinjau informasi di unduhan Python.
  2. Pilih, unduh, dan jalankan alat penginstal untuk rilis Python yang paling cocok untuk komputer lokal Anda.

Menginstal paket Python yang diperlukan

Di prompt perintah atau jendela PowerShell Anda (dengan hak istimewa administrator), jalankan perintah berikut untuk menginstal paket Python yang diperlukan:

pip install azure-identity azure-mgmt-carbonoptimization

Memeriksa dan memperbarui contoh skrip Python

  1. Salin contoh skrip Python berikut dan simpan secara lokal. Misalnya, simpan sebagai export_carbon_emission_data.py
  2. Tinjau skrip dan ganti semua instans Subscription_ID_XXX dengan ID langganan Azure Anda yang sebenarnya. Tambahkan atau hapus contoh langganan, seperlunya. Mendukung hingga 100 ID langganan.
  3. Simpan file tersebut.

Secara default, skrip hanya menghasilkan data selama sebulan penuh terakhir. Anda dapat memperbarui skrip untuk rentang waktu kustom (bulan penuh) untuk beberapa laporan. Tinjau komentar skrip untuk melihat apakah laporan mendukung rentang kustom. Cari contoh:

    date_range = DateRange(
        start=date.fromisoformat(available_date_range.start_date),
        end=date.fromisoformat(available_date_range.end_date),
    )

Kemudian perbarui seperti contoh berikut:

    date_range = DateRange(
        start=date.fromisoformat("YYYY-MM-DD"),
        end=date.fromisoformat("YYYY-MM-DD"),
    )
"""
Azure Carbon Optimization

This script queries Azure Carbon Optimization reports by using the Python azure-mgmt-carbonoptimization(https://pypi.org/project/azure-mgmt-carbonoptimization/) SDK.

"""

import os
import json
import logging
import time
from datetime import datetime, timezone, date
from typing import List, Dict, Any, Optional
from pathlib import Path

from azure.identity import DefaultAzureCredential
from azure.mgmt.carbonoptimization import CarbonOptimizationMgmtClient
from azure.mgmt.carbonoptimization.models import CarbonEmissionDataAvailableDateRange, CategoryTypeEnum, SortDirectionEnum,\
    OrderByColumnEnum, ReportTypeEnum, ResponseDataTypeEnum, CarbonEmissionItemDetailData, DateRange, EmissionScopeEnum,\
    CarbonEmissionData, ResourceCarbonEmissionItemDetailData, ResourceGroupCarbonEmissionItemDetailData, \
    ItemDetailsQueryFilter, MonthlySummaryReportQueryFilter, TopItemsSummaryReportQueryFilter, \
    TopItemsMonthlySummaryReportQueryFilter, OverallSummaryReportQueryFilter, CarbonEmissionDataListResult

from azure.core.exceptions import (
    ClientAuthenticationError, 
    HttpResponseError, 
    ResourceNotFoundError
)


# Initialize Azure CarbonOptimization SDK clients
credential = DefaultAzureCredential()
client = CarbonOptimizationMgmtClient(credential=credential)
carbon_service = client.carbon_service


def query_item_detail_data_by_category_type(category_type: CategoryTypeEnum) -> None :
    # get latest available carbon data date range
    available_date_range = carbon_service.query_carbon_emission_data_available_date_range()

    # Get latest month

    date_range = DateRange(
        start=date.fromisoformat(available_date_range.end_date),
        end=date.fromisoformat(available_date_range.end_date),
    )

    # Build query filter for item detail report
    item_detail_query_filter = ItemDetailsQueryFilter(date_range=date_range,
                                                      subscription_list=[
                                                          "Subscription_ID_001", "Subscription_ID_002", "Subscription_ID_100"
                                                      ], # suggest to put 100 subscription id 
                                                      carbon_scope_list=[EmissionScopeEnum.SCOPE1, EmissionScopeEnum.SCOPE2, EmissionScopeEnum.SCOPE3],
                                                      category_type=category_type,
                                                      order_by=OrderByColumnEnum.ITEM_NAME,
                                                      sort_direction=SortDirectionEnum.DESC,
                                                      page_size=50  # suggest with 2000 as pageSize
                                                      )

    with open(f"carbon_emission_{str(category_type.value).lower()}_item_detail_report.json", "a", encoding="utf-8") as f:
        while True:
            result_list = carbon_service.query_carbon_emission_reports(item_detail_query_filter)

            for item in result_list.value:
                f.write(json.dumps(item.as_dict(), ensure_ascii=False))
                f.write("\n")

            if not result_list.skip_token:
            # no more pages, break
                print("all data retrieved")
                break
        
            # set the continuation token for the next page
            item_detail_query_filter.skip_token = result_list.skip_token
            print("continue to get next page data")


def query_top_items_monthly_report_by_category_type(category_type: CategoryTypeEnum) -> None :
    # get latest available carbon data date range
    available_date_range = carbon_service.query_carbon_emission_data_available_date_range()

    date_range = DateRange(
        start=date.fromisoformat(available_date_range.start_date),
        end=date.fromisoformat(available_date_range.end_date),
    )

    # Build query filter for top items monthly report
    item_detail_query_filter = TopItemsMonthlySummaryReportQueryFilter(
        date_range=date_range,
        subscription_list=[
            "Subscription_ID_001", "Subscription_ID_002", "Subscription_ID_100"
        ], # suggest to put 100 subscription id 
        carbon_scope_list=[EmissionScopeEnum.SCOPE1, EmissionScopeEnum.SCOPE2, EmissionScopeEnum.SCOPE3],
        category_type=category_type,
        top_items=5
    )

    with open(f"carbon_emission_{str(category_type.value).lower()}_top_items_monthly_report.json", "a", encoding="utf-8") as f:
        result_list = carbon_service.query_carbon_emission_reports(item_detail_query_filter)

        for item in result_list.value:
            f.write(json.dumps(item.as_dict(), ensure_ascii=False))
            f.write("\n")

def query_top_items_report_by_category_type(category_type: CategoryTypeEnum) -> None :
    # get latest available carbon data date range
    available_date_range = carbon_service.query_carbon_emission_data_available_date_range()

    # only set one month for Top Items Report
    date_range = DateRange(
        start=date.fromisoformat(available_date_range.end_date),
        end=date.fromisoformat(available_date_range.end_date),
    )

    # Build query filter for top items report
    item_detail_query_filter = TopItemsSummaryReportQueryFilter(
        date_range=date_range,
        subscription_list=[
            "Subscription_ID_001", "Subscription_ID_002", "Subscription_ID_100"
        ], # suggest to put 100 subscription id 
        carbon_scope_list=[EmissionScopeEnum.SCOPE1, EmissionScopeEnum.SCOPE2, EmissionScopeEnum.SCOPE3],
        category_type=category_type,
        top_items=5
    )

    with open(f"carbon_emission_{str(category_type.value).lower()}_top_items_report.json", "a", encoding="utf-8") as f:
        result_list = carbon_service.query_carbon_emission_reports(item_detail_query_filter)

        for item in result_list.value:
            f.write(json.dumps(item.as_dict(), ensure_ascii=False))
            f.write("\n")

def query_overall_summary_report_by_category_type() -> None :
    # get latest available carbon data date range
    available_date_range = carbon_service.query_carbon_emission_data_available_date_range()

    date_range = DateRange(
        start=date.fromisoformat(available_date_range.start_date),
        end=date.fromisoformat(available_date_range.end_date),
    )

    # Build query filter for overall summary report
    item_detail_query_filter = OverallSummaryReportQueryFilter(
        date_range=date_range,
        subscription_list=[
            "Subscription_ID_001", "Subscription_ID_002", "Subscription_ID_100"
        ], # suggest to put 100 subscription id 
        carbon_scope_list=[EmissionScopeEnum.SCOPE1, EmissionScopeEnum.SCOPE2, EmissionScopeEnum.SCOPE3]
    )

    with open(f"carbon_emission_overall_summary_report.json", "a", encoding="utf-8") as f:
        result_list = carbon_service.query_carbon_emission_reports(item_detail_query_filter)

        for item in result_list.value:
            f.write(json.dumps(item.as_dict(), ensure_ascii=False))
            f.write("\n")

def query_monthly_overall_summary_report_by_category_type() -> None :
    # get latest available carbon data date range
    available_date_range = carbon_service.query_carbon_emission_data_available_date_range()

    date_range = DateRange(
        start=date.fromisoformat(available_date_range.start_date),
        end=date.fromisoformat(available_date_range.end_date),
    )

    # Build query filter for monthly overall summary report
    item_detail_query_filter = MonthlySummaryReportQueryFilter(
        date_range=date_range,
        subscription_list=[
            "Subscription_ID_001", "Subscription_ID_002", "Subscription_ID_100"
        ], # suggest to put 100 subscription id 
        carbon_scope_list=[EmissionScopeEnum.SCOPE1, EmissionScopeEnum.SCOPE2, EmissionScopeEnum.SCOPE3]
    )

    with open(f"carbon_emission_monthly_overall_summary_report.json", "a", encoding="utf-8") as f:
        result_list = carbon_service.query_carbon_emission_reports(item_detail_query_filter)

        for item in result_list.value:
            f.write(json.dumps(item.as_dict(), ensure_ascii=False))
            f.write("\n")

def get_latest_available_carbon_data_date_range() -> CarbonEmissionDataAvailableDateRange:
    """
    Query the latest available carbon data date range.
    """
    available_date_range = carbon_service.query_carbon_emission_data_available_date_range()

    print(f"Available date range: {available_date_range.start_date} to {available_date_range.end_date}")

    return available_date_range

if __name__ == "__main__":
    # get latest available carbon data date range
    get_latest_available_carbon_data_date_range()

    # get carbon emission item detail report
    query_item_detail_data_by_category_type(CategoryTypeEnum.RESOURCE)
    query_item_detail_data_by_category_type(CategoryTypeEnum.LOCATION)
    query_item_detail_data_by_category_type(CategoryTypeEnum.RESOURCE_TYPE)
    query_item_detail_data_by_category_type(CategoryTypeEnum.RESOURCE_GROUP)
    query_item_detail_data_by_category_type(CategoryTypeEnum.SUBSCRIPTION)

    # get top items monthly report
    query_top_items_monthly_report_by_category_type(CategoryTypeEnum.RESOURCE)
    query_top_items_monthly_report_by_category_type(CategoryTypeEnum.RESOURCE_GROUP)
    query_top_items_monthly_report_by_category_type(CategoryTypeEnum.LOCATION)
    query_top_items_monthly_report_by_category_type(CategoryTypeEnum.RESOURCE_TYPE)
    query_top_items_monthly_report_by_category_type(CategoryTypeEnum.SUBSCRIPTION)

    # get top items report
    query_top_items_report_by_category_type(CategoryTypeEnum.RESOURCE)
    query_top_items_report_by_category_type(CategoryTypeEnum.RESOURCE_GROUP)
    query_top_items_report_by_category_type(CategoryTypeEnum.LOCATION)
    query_top_items_report_by_category_type(CategoryTypeEnum.RESOURCE_TYPE)
    query_top_items_report_by_category_type(CategoryTypeEnum.SUBSCRIPTION)

    # get overall summary report
    query_overall_summary_report_by_category_type()

    # get monthly overall summary report
    query_monthly_overall_summary_report_by_category_type()

Jalankan skrip Python

Jalankan skrip Python dari prompt perintah atau jendela PowerShell Anda (dengan hak istimewa administrator):

python export_carbon_emission_data.py

File output JSON dibuat dalam direktori yang sama dengan skrip. File diberi nama menurut jenis laporan.

Berikut adalah daftar file output yang dibuat:

  • carbon_emission_location_item_detail_report.json
  • carbon_emission_location_top_items_monthly_report.json
  • carbon_emission_location_top_items_report.json
  • carbon_emission_monthly_overall_summary_report.json
  • carbon_emission_overall_summary_report.json
  • carbon_emission_resourcegroup_item_detail_report.json
  • carbon_emission_resourcegroup_top_items_monthly_report.json
  • carbon_emission_resourcegroup_top_items_report.json
  • carbon_emission_resourcetype_item_detail_report.json
  • carbon_emission_resourcetype_top_items_monthly_report.json
  • carbon_emission_resourcetype_top_items_report.json
  • carbon_emission_resource_item_detail_report.json
  • carbon_emission_resource_top_items_monthly_report.json
  • carbon_emission_resource_top_items_report.json
  • carbon_emission_subscription_item_detail_report.json
  • carbon_emission_subscription_top_items_monthly_report.json
  • carbon_emission_subscription_top_items_report.json

Meninjau file output JSON

Berikut adalah contoh output untuk laporan ringkasan keseluruhan bulanan, dari carbon_emission_overall_summary_report.json file.

{"dataType": "OverallSummaryData", "latestMonthEmissions": 13871.2808902499, "previousMonthEmissions": 14007.1957894844, "monthOverMonthEmissionsChangeRatio": -0.00970321977912344, "monthlyEmissionsChangeValue": -135.91489923458}

Untuk informasi selengkapnya tentang laporan dan data yang dikandungnya, lihat Referensi API ekspor emisi.

Langkah selanjutnya