Forum Discussion
Power BI Get Activity REST API
- 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: ..
() =>letbody = " 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]inaccess_token4) 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()
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: ..
#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()