Select to view content in your preferred language

Is it possible to retrieve the "Last Used" property when viewing License Activity through the ArcGIS API for Python?

186
10
Jump to solution
a week ago
Labels (2)
Katie_Clark
MVP Alum

Hello,

I found this related post but no answer from it, wondering if there are any other insights.

I was hoping to be able to write a Notebook that would use the ArcGIS API for Python and query the license activity for ArcGIS Pro licenses in my organization. I am specifically interested in the "Last Used" property, which indicates when someone last opened a session within ArcGIS Pro. This information is different from their last login to ArcGIS Online.

I have not been able to find a way to access this info through the API - is it accessible anywhere programmatically?

Katie_Clark_0-1760032767730.png

 

Katie_Clark_1-1760032914605.png

Best,
Katie

If this answer helped you, please consider giving a kudos and/or marking as the accepted solution. Thanks!
1 Solution

Accepted Solutions
Clubdebambos
MVP Regular Contributor

Here's what I found. This does it for the last 90 days. You could use a start time for the 90 days prior to that last 90 days for more info and combine.

from arcgis.gis import GIS
from datetime import datetime

## access agol
agol = GIS("home")

## generate a report for applications
report = agol.admin.usage_reports.applications(time_frame = "90days")

## we are only interested in ArcGIS Pro usage
arcgispro_report = [entry for entry in report["data"] if entry["appId"] == "arcgisprodesktop"]

## for each user report
for user in arcgispro_report:
    print(user["username"])

    ## get when the last usage of ArcGIS Pro occured
    last_usage = None

    for epoch, usage in reversed(user["num"]):
        if int(usage) > 0:
            last_usage = int(epoch)
            break

    if last_usage:
        last_usage_date = datetime.utcfromtimestamp(last_usage / 1000).strftime("%d/%m/%Y")
    else:
        last_usage_date = "More than 90 days"

    print("\t", last_usage_date)

 

I hope that helps.

All the best,

Glen

~ learn.finaldraftmapping.com

View solution in original post

10 Replies
Clubdebambos
MVP Regular Contributor

I haven't opened ArcGIS Pro today, yet when I check my last used it says today.

~ learn.finaldraftmapping.com
0 Kudos
Katie_Clark
MVP Alum

Interesting.... do you know if there's another method of getting this information, then? 

Best,
Katie

If this answer helped you, please consider giving a kudos and/or marking as the accepted solution. Thanks!
0 Kudos
Clubdebambos
MVP Regular Contributor

I did a bit of a dive into it and came up with nothing that conclusively states the last time someone opened ArcGIS Pro. If I come across anything I'll be sure to share as I am also interested in that detail for reporting. It is interesting that in AGOL you can see the amount of time someone has spent using ArcGIS Pro so there must be a mechanism for start and end times per session that can possibly be tapped into. 

~ learn.finaldraftmapping.com
0 Kudos
Clubdebambos
MVP Regular Contributor

Here's what I found. This does it for the last 90 days. You could use a start time for the 90 days prior to that last 90 days for more info and combine.

from arcgis.gis import GIS
from datetime import datetime

## access agol
agol = GIS("home")

## generate a report for applications
report = agol.admin.usage_reports.applications(time_frame = "90days")

## we are only interested in ArcGIS Pro usage
arcgispro_report = [entry for entry in report["data"] if entry["appId"] == "arcgisprodesktop"]

## for each user report
for user in arcgispro_report:
    print(user["username"])

    ## get when the last usage of ArcGIS Pro occured
    last_usage = None

    for epoch, usage in reversed(user["num"]):
        if int(usage) > 0:
            last_usage = int(epoch)
            break

    if last_usage:
        last_usage_date = datetime.utcfromtimestamp(last_usage / 1000).strftime("%d/%m/%Y")
    else:
        last_usage_date = "More than 90 days"

    print("\t", last_usage_date)

 

I hope that helps.

All the best,

Glen

~ learn.finaldraftmapping.com
Katie_Clark
MVP Alum

This is brilliant, thank you so much!

In case it helps others who come across this post, I'll share what I added - this prints out a formatted report and sorts by usage date, with the oldest usage dates on top.

from arcgis.gis import GIS
from datetime import datetime
agol = GIS("home")

# Generate a report for applications
report = agol.admin.usage_reports.applications(time_frame = "90days")

# We are only interested in ArcGIS Pro usage
arcgispro_report = [entry for entry in report["data"] if entry["appId"] == "arcgisprodesktop"]

user_data = []

# Collect all user data with their last usage dates
for user in arcgispro_report:
    username = user["username"]
    
    last_usage = None

    # search through user data in reverse chronological order
    for epoch, usage in reversed(user["num"]):
        if int(usage) > 0:
            last_usage = int(epoch)
            break

    if last_usage:
        last_usage_date = datetime.utcfromtimestamp(last_usage / 1000).strftime("%m/%d/%Y")
        sort_timestamp = last_usage
        has_usage = True
    else:
        last_usage_date = "More than 90 days"
        sort_timestamp = 0
        has_usage = False
    
    user_data.append({
        'username': username,
        'last_usage_date': last_usage_date,
        'sort_timestamp': sort_timestamp,
        'has_usage': has_usage
    })

# Sort: first by has_usage (False first), then by sort_timestamp (ascending)
user_data.sort(key=lambda x: (x['has_usage'], x['sort_timestamp']))

# Print formatted table
print("\n" + "=" * 100)
print(" " * 30 + "ARCGIS PRO USAGE REPORT - LAST 90 DAYS")
print("=" * 100)
print(f"{'#':<3} {'Username':<55} {'Last Usage':<15} {'Days Ago':<10} {'Status':<12}")
print("-" * 100)

for i, user_info in enumerate(user_data, 1):
    username = user_info['username']
    last_usage_date = user_info['last_usage_date']
    
    if not user_info['has_usage']:
        status = "INACTIVE"
        days_ago = "90+"
    else:
        days_since = (datetime.now() - datetime.utcfromtimestamp(user_info['sort_timestamp'] / 1000)).days
        days_ago = str(days_since)
        if days_since <= 7:
            status = "ACTIVE"
        elif days_since <= 30:
            status = "RECENT"
        else:
            status = "STALE"
    
    print(f"{i:<3} {username:<55} {last_usage_date:<15} {days_ago:<10} {status:<12}")

print("-" * 100)
print(f"Total Users: {len(user_data)}")
print(f"Active Users (≤7 days): {len([u for u in user_data if u['has_usage'] and (datetime.now() - datetime.utcfromtimestamp(u['sort_timestamp'] / 1000)).days <= 7])}")
print(f"Recent Users (8-30 days): {len([u for u in user_data if u['has_usage'] and 8 <= (datetime.now() - datetime.utcfromtimestamp(u['sort_timestamp'] / 1000)).days <= 30])}")
print(f"Stale Users (31-90 days): {len([u for u in user_data if u['has_usage'] and 31 <= (datetime.now() - datetime.utcfromtimestamp(u['sort_timestamp'] / 1000)).days <= 90])}")
print(f"Inactive Users (>90 days): {len([u for u in user_data if not u['has_usage']])}")
print("=" * 100)
Best,
Katie

If this answer helped you, please consider giving a kudos and/or marking as the accepted solution. Thanks!
DavidColey
MVP Frequent Contributor

Hi @Katie_Clark and @Clubdebambos - this is great, thank you both for posting.  We adopted Named User model this week and as such I just began looking into usage reports and this will help greatly. I was wondering however if either of you have come across anything that can force a session close.  

I began looking into the api here

https://developers.arcgis.com/python/latest/api-reference/arcgis.auth.html#arcgis.auth.api.EsriSessi...

but so far have not come across anything to loop through open pro sessions and close them down as way to make certain we don't have any users connected to SDE and/or network directory locations while in pro that may produce locks on file gdb layers. 

Not quite sure where to initiate an EsriSEssion.close(). If I come across anything I'll post a new question, and reference you guys and this post....Otherwise, if you come across anything that would be great.

Clubdebambos
MVP Regular Contributor

Hi @DavidColey,

I haven't come across anything that forces an ArcGIS Pro session close. About 8 years ago with ArcMap I had a script that would remove all locks on an SDE connection, but that's as far as I went. I will certainly keep an eye out and when I have time look more into the link you provided.

All the best,

Glen

~ learn.finaldraftmapping.com
0 Kudos
DavidColey
MVP Frequent Contributor

Hi Glen, thanks.  Yeah we have arcpy code to disconnect users from sde so like you we are ok there.  From what I can read in the auth package the EsriSession.close() method works off something called the EsriSession.adapters property, but I have no idea how to get to that and so I don't know what that dictionary would even list.  

@Clubdebambos 

0 Kudos
Katie_Clark
MVP Alum

From what I can tell, closing the "session" here is referring to closing the Python-side http session, so it would be useful for ending a script's authenticated connection to the GIS account. 

If you are able to have remote control over someone's machine, you could maybe utilize psutil and kill the session on that machine? 

Best,
Katie

If this answer helped you, please consider giving a kudos and/or marking as the accepted solution. Thanks!