Forum Discussion

Ray_Brosius's avatar
Ray_Brosius
Helper III
2 years ago
Solved

Power BI Get Activity REST API

I had obtained this "code" from the BI Elite team via a very cool Youtube Series on how to build a Power BI Usage Repot. This was working an jsut stopped some months ago. (** is there a way to uplo...
  • Ray_Brosius's avatar
    2 years ago

    I was able to solve the problem.

    1) I setup the Azure APP to be a member of the security group that is configured in the PBI Admin Console to have access to the REST APIs

    2) I have a PBI file that can go and get the last 30 days of activity, but as is mentioned here that was always just a rolling 30 day window.  IF that works for you then that is an option for sure.. 

    3) I edited the "GET TOKEN" function to the below: ..

             () =>
             let
            body = " grant_type=client_credentials&
                       resource=https://analysis.windows.net/powerbi/api&
                       client_id=CLIENT_ID&
                      username=USERNAME&
                     password=PASSWORD&
                    client_secret=CLIENT_SECRET",
                    Data=Json.Document(
                                 Web.Contents("https://login.microsoftonline.com/YOUR_TENNANT_ID/oauth2/token/",
                                        [ Headers=[#"Content-Type"="application/x-www-form-urlencoded"],
                                         Content=Text.ToBinary(body)
                                        ])),
             access_token = Data[access_token]
    in
             access_token
     
    4) Lastly and the key to this is I found an excellent source for the Python code to build a process that will get the activities from the day prior and save the results into a csv file.  I edited that code to save the data to our SNOWFLAKE database table.
    https://pbi-guy.com/2022/03/10/power-bi-and-activity-logs-with-python/
     
    here is the Python code .. you will need to replace with your parameters as appropriate.

     

     

    #Import necessary libraries
    import msal
    import requests
    import json
    import pandas as pd
    from datetime import date, timedelta
    import snowflake.connector
    import sqlalchemy
    
    # Function to insert a row into the Snowflake table
    def insert_row(row):
        sql_insert = f"INSERT INTO DATABASE.SCHEMA.TABLE(Id, RecordType, CreationTime, Operation, OrganizationId, UserType, UserKey, Workload, UserId, ClientIP, UserAgent, Activity, IsSuccess, RequestId, ActivityId, ItemName, WorkSpaceName, DatasetName, ReportName, WorkspaceId, ObjectId, DatasetId, ReportId, ReportType, DistributionMethod, ConsumptionMethod) VALUES ('{row['Id']}','{row['RecordType']}','{row['CreationTime']}','{row['Operation']}','{row['OrganizationId']}','{row['UserType']}','{row['UserKey']}','{row['Workload']}','{row['UserId']}','{row['ClientIP']}','{row['UserAgent']}','{row['Activity']}','{row['IsSuccess']}','{row['RequestId']}','{row['ActivityId']}','{row['ItemName']}','{row['WorkSpaceName']}','{row['DatasetName']}','{row['ReportName']}','{row['WorkspaceId']}','{row['ObjectId']}','{row['DatasetId']}','{row['ReportId']}','{row['ReportType']}','{row['DistributionMethod']}','{row['ConsumptionMethod']}')"
        cursor.execute(sql_insert)
    
    #Set SnowFlake parameters and create Connection
    con = snowflake.connector.connect(
        account="SNOWFLAKE ACCOUNT",
        user= "USER",
        password= "PASSWORD",
        warehouse= "WAREHOUSE",
        database= "DATABASE",
        schema= "SCHEMA"
        )
    
    #Get yesterdays date and convert to string
    activityDate = date.today() - timedelta(days=1)
    activityDate = activityDate.strftime("%Y-%m-%d")
    
    # Replace with your Azure AD app details
    client_id = 'CLIENT_ID'
    client_secret = 'CLIENT_SECRET'
    tenant_id = 'TENNANT_ID'
    authority_url = "https://login.microsoftonline.com/YOURDOMAIN"
    scope = ["https://analysis.windows.net/powerbi/api/.default"]
    
    #Set Power BI REST API to get Activities for today
    url = "https://api.powerbi.com/v1.0/myorg/admin/activityevents?startDateTime='" + activityDate + "T00:00:00'&endDateTime='" + activityDate + "T23:59:59'"
    
    
    #Use MSAL to grab token
    app = msal.ConfidentialClientApplication(client_id, authority=authority_url, client_credential=client_secret)
    result = app.acquire_token_for_client(scopes=scope)
    
    #Get latest Power BI Activities
    if 'access_token' in result:
        access_token = result['access_token']
        header = {'Content-Type':'application/json', 'Authorization':f'Bearer {access_token}'}
        api_call = requests.get(url=url, headers=header)
        
        #Specify empty Dataframe with all columns
        column_names = ['Id', 'RecordType', 'CreationTime', 'Operation', 'OrganizationId', 'UserType', 'UserKey', 'Workload', 'UserId', 'ClientIP', 'UserAgent', 'Activity', 'IsSuccess', 'RequestId', 'ActivityId', 'ItemName', 'WorkSpaceName', 'DatasetName', 'ReportName', 'WorkspaceId', 'ObjectId', 'DatasetId', 'ReportId', 'ReportType', 'DistributionMethod', 'ConsumptionMethod']
        df = pd.DataFrame(columns=column_names)
    
        #Set continuation URL
        contUrl = api_call.json()['continuationUri']
        
        #Get all Activities for first hour, save to dataframe (df1) and append to empty created df
        result = api_call.json()['activityEventEntities']
        df1 = pd.DataFrame(result)
        pd.concat([df, df1])
    
        #Call Continuation URL as long as results get one back to get all activities through the day
        while contUrl is not None:        
            api_call_cont = requests.get(url=contUrl, headers=header)
            contUrl = api_call_cont.json()['continuationUri']
            result = api_call_cont.json()['activityEventEntities']
            df2 = pd.DataFrame(result)
            df = pd.concat([df, df2])
        
        #Set Cursor for Snowflake 
        cursor = con.cursor()  
        # Apply the function to each row of the DataFrame
        df.apply(insert_row, axis=1)
        
        # Commit the transaction to save the changes
        con.commit()
        con.close()