Tutorial: Exportar dados de otimização de carbono usando um script Python

Este tutorial explica como você usa um script Python para exportar dados de emissões de otimização de carbono do Azure como saída JSON. O script Python executa solicitações de rede da API REST do Serviço de Carbono para obter dados de emissões para seus recursos do Azure. O script simplifica o processo de consultar a API e lidar com a resposta. Execute o script para gerar os arquivos JSON e, em seguida, use-os para análise e relatórios detalhados.

Este tutorial aborda as etapas necessárias para exportar dados de emissões de otimização de carbono em seu computador Windows local.

Há várias etapas para concluir este tutorial:

  • Examinar os pré-requisitos e instalar componentes ausentes
  • Baixar e instalar o Python
  • Instalar pacotes do Python necessários
  • Examinar e atualizar o exemplo de script do Python
  • Executar o script Python
  • Examinar os arquivos de saída JSON

Pré-requisitos

Antes de usar o script Python, verifique se você tem:

  • Permissões apropriadas do Azure (Carbon Optimization Reader, Subscription Owner, ou Subscription Contributor função)
  • Uma lista de IDs de assinatura válidas do Azure para as quais você deseja obter dados de emissões
  • Uma compreensão dos escopos de emissão de carbono (Scope1, Scope2, Scope3)
  • Pelo menos um mês inteiro de dados de emissões disponíveis para exportação (os dados estão disponíveis para o mês anterior até o dia 19 do mês atual)

Instalar o Azure PowerShell

Se você não tiver o Azure PowerShell instalado em seu computador Windows local, siga estas etapas:

Inicie o Windows PowerShell 5.1 como administrador e execute o seguinte comando para atualizar o PowerShellGet usando a galeria do PowerShell:

Install-Module -Name PowerShellGet -Force

Defina a política de execução do PowerShell como remota assinada ou menos restritiva:

  • Verifique a política de execução do PowerShell:
    Get-ExecutionPolicy -List
    
  • Defina a política de execução do PowerShell como assinada remotamente:
    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
    
    

Use o cmdlet Install-Module para instalar o módulo do Az PowerShell:

Install-Module -Name Az -Repository PSGallery -Force

Talvez seja necessário reiniciar o PowerShell após a conclusão da instalação.

Para obter mais informações sobre como instalar o Azure PowerShell, incluindo a instalação em diferentes plataformas, consulte Como instalar o Azure PowerShell.

Entrar no Azure

Para começar a gerenciar seus recursos do Azure com o módulo do Az PowerShell, inicie uma sessão do PowerShell e execute Connect-AzAccount para entrar no Azure:

Connect-AzAccount

Use as credenciais de entrada da conta do Azure para fazer logon na janela do navegador que é aberta.

Você precisa repetir esta etapa para cada nova sessão do PowerShell iniciada.

Instalar a CLI do Azure.

Se você não tiver a CLI do Azure instalada no computador Windows local, siga estas etapas:

  1. Examine as informações em Instalar a CLI do Azure no Windows.
  2. Escolha um método de instalação e execute o instalador mais adequado para seu computador local.
  3. Após a conclusão da instalação, abra um novo prompt de comando ou uma janela do PowerShell (com privilégios de administrador) para entrar em sua conta do Azure:
    az login
    

Baixar e instalar o Python

Se você não tiver o Python instalado no computador Windows local, siga estas etapas:

  1. Examine as informações nos downloads do Python.
  2. Escolha, baixe e execute o instalador para uma versão do Python mais adequada para seu computador local.

Instalar pacotes do Python necessários

No prompt de comando ou na janela do PowerShell (com privilégios de administrador), execute o seguinte comando para instalar os pacotes necessários do Python:

pip install azure-identity azure-mgmt-carbonoptimization

Examinar e atualizar o exemplo de script do Python

  1. Copie o seguinte script de exemplo do Python e salve-o localmente. Por exemplo, salve-o como export_carbon_emission_data.py
  2. Examine o script e substitua todas as instâncias de Subscription_ID_XXX, por suas IDs reais de assinatura do Azure. Adicione ou remova assinaturas de exemplo, conforme necessário. Há suporte para até 100 IDs de assinatura.
  3. Salve o arquivo.

Por padrão, o script só gera dados para o último mês completo. Você pode atualizar o script para um intervalo de tempo personalizado (meses completos) para alguns relatórios. Examine os comentários de script para ver se um relatório dá suporte a um intervalo personalizado. Busque instâncias de:

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

Em seguida, atualize como o seguinte exemplo:

    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()

Executar o script Python

Execute o script Python no prompt de comando ou na janela do PowerShell (com privilégios de administrador):

python export_carbon_emission_data.py

Os arquivos de saída JSON são criados no mesmo diretório que o script. Os arquivos são nomeados por tipo de relatório.

Aqui está uma lista dos arquivos de saída que são criados:

  • 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

Examinar os arquivos de saída JSON

Aqui está um exemplo de saída para o relatório de resumo geral mensal do arquivo carbon_emission_overall_summary_report.json.

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

Para obter mais informações sobre os relatórios e os dados que eles contêm, consulte Referência da API de exportação de emissões.

Próxima etapa

Referência da API de exportação de emissões