cancel
Showing results for 
Search instead for 
Did you mean: 
nardell
Community Participant

Using Canvas API to find external tool usage

Jump to solution

As Canvas admins we have a need to track external tool usage, getting a report of which courses and, in particular which teachers, appear to be using the external tools, typically enabled at the Account context. For example, if we know that a particular tool has a technical problem or concern, we need to be able to find the teachers to contact about the problem, so they will not be surprised about a maintenance outage, etc.

Initially I thought the LTI Tool Report and/or the External Tool API would be all that would be required (in addition to leveraging enrollment and user data to associate courses-ids to the appropriate Teacher and her email address). However, the External Tool API only seems effective at finding tools in course shells if the tool was installed at the course context. It seems that what I really need to do is query against external tools (to catalog external tools installed at account context) then use the Tabs API(Tabs - Canvas LMS REST API Documentation ) and also the Modules API (Modules - Canvas LMS REST API Documentation ), filtering for items returned of type='external'.  

I am unsure if I am indeed on the right track, or if there is some other API I need to also query against for more complete coverage. Any advice much appreciated. 

Regards,

Michael Nardell

1 Solution

Accepted Solutions
nardell
Community Participant

This has been on bit of a back-burner. But I seem to have the skeleton of something that works. Here is the heart of my code in Python:

#---- Specify API Generators -------------------------------------------------------------------
all_courses = api_wrapper_function(all_courses_endpoint, authorization=authZ, context_id='self')
course_tabs = api_wrapper_function(course_tabs_endpoint, authZ,
                                   filter_fn=is_active_xtool)
course_xtools = api_wrapper_function(course_tools_endpoint,authZ, )
course_modules = api_wrapper_function(course_modules_endpoint, authZ, )
course_assignments = api_wrapper_function(course_assignments_endpoint, authZ,
                                          filter_fn=is_active_xtool)

#----Iterate over all courses ---------------------------
for c in all_courses():
    print(c['course_code'], c['name'], )
    #---- And for each course, retreive all instsalled x-tools, tabs, modules, and assigments
    print("---------XTOOL INSTALLS-----------")
    for x in course_xtools(c['id']):
        print:smileyx:

    print("---------TABS---------------------")
    for t in course_tabs(c['id']):
        print (t)

    print("---------MODULES---------------------")
    for m in course_modules(c['id']):
        #print (n['items_url'])
        module_items = api_wrapper_function(direct_url=m['items_url'], authorization=authZ, filter_fn=is_active_xtool)
        for i in module_items():
            print:smileyinfo:

    print("---------Assignments---------------------")
    for a in course_assignments(c['id']):
        print(a)

This code makes heavy use of the api_wrapper_function, which I wrote as a general-purpose api tool that takes all the parameters you would expect (endpoint url, auth token) also a filter function (used here so we are only retrieving external tools). Once specified with appropriate parameters, the api_wrapper_function returns a Python generator that allows you to iterate over all items for the particular api. It handles the pagination and link following, so we can iterate and forget. In the block of code I have pasted in, for loop iterates over all courses in the root account, and then provides the id for the sub-iterators to dig-up any elements that are external tools. Modules require going one more level down,since we need to find external tool module-items under each module. 

Still working on this. Of course the real deal is to aggregate the data returned into a report of external tool and the courses that are using them. Would be interested in any input. Also,since others have already written Python Canvas API code may re-write to use that. Admittedly my idiosyncratic functional approach maybe a turn-off for some folks.

Mike

View solution in original post

4 Replies
pklove
Community Champion

Unfortunately, like you have found, it looks like there isn't an easy way of doing this.  I think you are on the right track, but you might need to add one more place to look: Assignments.  You might have to use the assignment endpoint to find external assignments.  They show up with "external_tool_tag_attributes".

Would be great to hear back on how it all goes.

nardell
Community Participant

This has been on bit of a back-burner. But I seem to have the skeleton of something that works. Here is the heart of my code in Python:

#---- Specify API Generators -------------------------------------------------------------------
all_courses = api_wrapper_function(all_courses_endpoint, authorization=authZ, context_id='self')
course_tabs = api_wrapper_function(course_tabs_endpoint, authZ,
                                   filter_fn=is_active_xtool)
course_xtools = api_wrapper_function(course_tools_endpoint,authZ, )
course_modules = api_wrapper_function(course_modules_endpoint, authZ, )
course_assignments = api_wrapper_function(course_assignments_endpoint, authZ,
                                          filter_fn=is_active_xtool)

#----Iterate over all courses ---------------------------
for c in all_courses():
    print(c['course_code'], c['name'], )
    #---- And for each course, retreive all instsalled x-tools, tabs, modules, and assigments
    print("---------XTOOL INSTALLS-----------")
    for x in course_xtools(c['id']):
        print:smileyx:

    print("---------TABS---------------------")
    for t in course_tabs(c['id']):
        print (t)

    print("---------MODULES---------------------")
    for m in course_modules(c['id']):
        #print (n['items_url'])
        module_items = api_wrapper_function(direct_url=m['items_url'], authorization=authZ, filter_fn=is_active_xtool)
        for i in module_items():
            print:smileyinfo:

    print("---------Assignments---------------------")
    for a in course_assignments(c['id']):
        print(a)

This code makes heavy use of the api_wrapper_function, which I wrote as a general-purpose api tool that takes all the parameters you would expect (endpoint url, auth token) also a filter function (used here so we are only retrieving external tools). Once specified with appropriate parameters, the api_wrapper_function returns a Python generator that allows you to iterate over all items for the particular api. It handles the pagination and link following, so we can iterate and forget. In the block of code I have pasted in, for loop iterates over all courses in the root account, and then provides the id for the sub-iterators to dig-up any elements that are external tools. Modules require going one more level down,since we need to find external tool module-items under each module. 

Still working on this. Of course the real deal is to aggregate the data returned into a report of external tool and the courses that are using them. Would be interested in any input. Also,since others have already written Python Canvas API code may re-write to use that. Admittedly my idiosyncratic functional approach maybe a turn-off for some folks.

Mike

View solution in original post

nardell
Community Participant

Peter, thanks again for advice on this. Working on a blog post in Canvas developers that goes into more detail on how it is going. Slowly cleaning up my code which will put on Github if people find it useful.

Mike

pklove
Community Champion