This is a last part of a series of 3 blog posts about monitoring REST API requests on Tableau server and it focuses around the final output – tableau dashboard.

Part 1 here

Part 2 here

The Vizportal Workbook from Logshark primarily displays data for all administrative tasks on the server and as default looks like this:

Our task is to differentiate REST API calls from all other calls.

When taking a closer look at the dataset, we can see that the value in the Message field is very similar to the URI we initially constructed:

Message field value:

“Request completed: 

/3.0/sites/68ac1484-cff4-44a9-bb97-f8a14ff8c9a7/views/409c9924-91b0-4e19-a10e-dd4d297d7992/pdf with status 200”

Our initial .pdf download URI from part 1 of this post:


We can see that in order to identify REST API calls we might simply look for API versions in the string. I created a calculated field with regex as below and applied it in Tableau as a data source filter set to: TRUE.


Now our dataset is purely REST API calls – at least that’s what I think – please let me know if you have an idea on how to do it differently!

The next step is to flag PDF downloads and other requests we are interested in. For this purpose, we need to revisit a webpage with all methods available

Then look for URIs we are interested in and then look for similar keywords in the Message field with the formula. In my case I have written down the following formula, as the client was most interested to see if there were any unauthorised uploads and downloads.

IF CONTAINS([Message],’pdf’) then ‘PDF’ 

elseif CONTAINS([Message],’/databases/’) then ‘Database operations’

elseif (CONTAINS([Message],’/workbooks?overwrite’) or CONTAINS([Message],’/workbooks?skip’)

    or CONTAINS([Message],’/workbooks?upload’)) then ‘Workbook upload’

//looks for different upload URI but if URI is plain PUT (…) workbook it will be returned in yellow as ‘OTHER’

elseif (CONTAINS([Message],’/signout’) OR CONTAINS([Message],’/signin’) ) then ‘sign in/out’ 

elseif (CONTAINS([Message],’/datasources?overwrite’) or CONTAINS([Message],’/datasources?append’)

    or CONTAINS([Message],’/datasources?upload’)) then ‘Datasource upload’

//looks for different upload URI but if URI is plain PUT (…) datasources it will be returned in yellow as ‘OTHER’

elseif REGEXP_MATCH([Message], ‘\/workbooks\/.*\/content’) then ‘Workbook download’

elseif REGEXP_MATCH([Message], ‘\/datasources\/.*\/content’) then ‘Datasources download’

//need to use regex as only looking for ‘workbooks’/’datasources’ in URI together with ‘content’ give us certainty its a download URI

else ‘OTHER’ END

There is one problem with this approach. In the message field we don’t receive information about what type of HTTP verb was used to describe the action being requested.

GET (read information)

POST (create new resources)

PUT (update existing resources)

DELETE (remove resources or configurations)

This is particularly troublesome in the following example:

It is useful to monitor such calls in a sequence where they occurred to have more context – I reflected it in the second chart on my dashboard.

I didn’t get to the bottom of it eventually, so I can’t confirm whether the HTTP verb is included in logs at all. In order to troubleshoot it it would be best to have a peek at REST API requests coming in live and see how they’re registered in logs. 

In command prompt go to location


Then run the ‘tail -f nameoflogfile’ command

Then make a REST API call to see how it comes through.

Then look for a pattern in logs and parse them directly rather than using Logshark. Going with Logshark could be annoying if you would like to refresh the dashboard frequently and don’t have an engineer who would be able to help to automate the process.

And that’s how the dashboard looks like:

And this is a sample on Tableau Public:

Thanks for reading!