Uncategorized

Adding Web Fonts to Tableau Server

Note: this is unsupported and adds things to the Tableau Server files, which also means you need to have a process to put it back in place with every upgrade. See CSS magic tricks with Embedded Tableau Server views and Disabling Browser and Apache Caching to See Your Changes to Tableau Server  which outline the necessary steps to make these types of CSS edits work.

You’ve got great design standards and awesome fonts, but you publish a beautiful viz to your Tableau Server and your end users end up seeing the default sans-serif or serif fonts that you’ve worked so hard to overcome. Tableau Server doesn’t have any in-built functionality for Web Fonts, but since it is just standard Apache serving up regular HTML5, JavaScript and CSS, you can easily add in anything you  want your users to have access to.

The secret is appending your web font CSS to vqlweb.css. I’ve already discussed how to edit the vqlweb.css file in the previous post mentioned in the warning at the top, and all the same rules apply. To get your font to display, you just need to add the appropriate Web Font css at the end. For example, Jeremy here built a kicking-rad viz with ‘Outrun future’.

Here’s the CSS I added to vqlweb.css:


@font-face {font-family: 'Outrun future';src: url("Outrun future.otf") format("opentype");}

The only other thing I had to do was copy the font file ‘Outrun future.otf’ to the /css/ directory (the same place where vqlweb.css lives).

Now go and add all the Web Fonts your heart desires (but make sure you can replicate your setup on each upgrade!)

Tableau and Behold our new guest blogger, Matt Miller!

Matt Miller has been an integral part of the sales engineer team at Tableau for several years now and he will be gracing us with an excellent series on the best ways of implementing Row Level Security when using Tableau Data Extracts.

Reminder that nothing here is official or supported by Tableau Software’s support team, regardless of who authors it, so please write things in the comments section and we’ll try our best to get back to you.

Defusing Row Level Security in Tableau Data Extracts (Before They Blow Up) Part 1

This documentation is for versions of Tableau prior to 2018.3

If you are using the 2018.3 version of Tableau or later, you’ll want to implement Row Level Security using Multi-Table Extracts and the “Standard” Method of Row Level Security. Read all about them at

How to set up your Database for Row Level Security in Tableau

If you are on a version prior to 2018.3, continue

Matt Miller works at Tableau as a sales engineer along with Bryant. He’s guest posting this excellent set of articles, with hopefully more to come.

Note: If you are looking at enterprise-level scaling with extracts, skip right to Part 2, then come back to read the background.

A wise man who runs a well-respected Tableau blog once wrote:tdebomb

To be secure and perform well, you must use a Live Connection to your database. Extracts will be too large if you join a security table that is one-to-many to your data table (we say they “blow up” to dissuade people).

What happens when a live connection is less than desirable for a use case, or downright impossible? Are we to let our Tableau Server users swim in a sea of insecure extracts (‘Do my columns look wide in this?’) ? Certainly not. The methods used to secure extracts differ from most currently published Row Level Security setups or walk-throughs, as the design is centered around minimizing duplication of rows to ensure performance in both creating and using them.

Since my education in uncountable infinite sets ended in undergrad, this blog won’t try to cover every niche business logic and data security use case, but instead provide ideas and tools to take back you your own environment and mold to your needs.

(more…)

How TDS files work

While the most preferred method for making variants of a Tableau Data Source is building the data source in Desktop then modifying the XML, there are some situations that warrant generating a full TDS file from scratch. At minimum, working through this process gives a much clearer view on what parts of the XML are responsible for various definitions and how they can be safely changed programmatically. Things like security calculations, filter variations, creating arbitrary data sources from any table, building infinite extract variations etc. should all be possible knowing how this works.

I’m implementing this all in actual code that is functioning and works right along as part of the tableau_rest_api library; I should have that available sometime soon. Read below the fold if you want to know how it all works (or at least what I’ve discovered so far):

(more…)

Programmatically Changing Filters on Tableau Extracts

When you have a lot of Tableau extracts (TDEs), you want them to be as small as possible for both generation and performance in a workbook. If you are deploying extracts to a lot of different sites, you may have built an initial extract that is filtered down for Customer A on Site A, but want to publish it to Site B and have it filtered for Customer B. It’s not too difficult, although is does require working with the XML a bit.

(more…)

Limiting Concurrent Tableau Sessions

The concept of selling for “concurrent users” comes up with relative frequency at Tableau. I’m not in any position to speak about licensing models, but if you are doing single sign-on to your Tableau Server, it’s very possible to implement a concurrency limiter.

The Tableau Server Repository has a view called _sessions, which only shows current active sessions. Prior to your SSO process, you can build a process that checks the _sessions view to see if there are already more active sessions than you want to allow.

My suggested query is the following:


SELECT s.site_id, t.url_namespace, COUNT(s.user_id)
FROM _sessions s
JOIN _sites t ON s.site_id = t.id
GROUP BY s.site_id, t.url_namespace

 

url_namespace from the _sites view gives you the identifier for a given Site. If you are using Sites, you need this to log in any way (This is called “site_content_url” in the REST API). All of the useful views in the Repository are listed in the excellent Data Dictionary.

Now, because concurrency in Tableau is really more about interactivity than time sitting, you’ll want to drastically shorten the session timeout from the default of 240 minutes. I’d suggest something like 5 so you aren’t locking people out when there is plenty of server capacity.

Also, the _sessions view contains the session_id field which can be used to programmatically end any session using the REST API’s sign out method. Per Russell Christopher: If you pass the session_id in the header like “X-Tableau-Auth: session_id“, it will end that session.

Using Initial SQL to Pass Usernames to Stored Procedures or Views in SQL Server

Tableau 9.3 brings a wonderful new feature called Initial SQL with Parameters which allows you to declare a specific set of SQL commands to be run before any queries within a particular Tableau Server user’s session. One of the initial use cases is Oracle VPD. It can also be used in Microsoft SQL Server with a single technique to solve two issues:

  1. Passing the Tableau Username to a Stored Procedure (previously only possible using the JavaScript API )
  2. How to use the WHERE Method of row level security (see the Row Level Security post for full explanation), when the usernames you need for data security are not users in the database. If the usernames are users in the database on SQL Server, you can use Impersonate User in SQL Server as per the section in this post titled Recommendation: Use the JOIN Method unless the WHERE Method is “easy”. That is to say, this technique is only necessary when the usernames and entitlements exist only in the database tables, and not as part of the database security model.

(more…)

Managing Published Data Sources and Extracts

The Thinker, Rodin

The best analogy I’ve come up with that making a Tableau great data source is like making a great bronze sculpture. You make the original model that you keep for yourself in your workshop and then you cast new statues each time the outside world needs one. This process allows you make changes to the original model or even make a new model without replacing the existing statues (until necessary).

When used correctly, Data Sources, Extracts, and Tableau Data Server facilitate quick access to data with minimal effort. However, using the correct process and order can save tremendous amounts of time on initial setup and any subsequent changes. A fully thought out process will look something like this:

data source process

(more…)

Referential Integrity, Join Culling, and Performance

Unlike some traditional BI tools, Tableau dynamically writes the simplest query it can based on what the user drags and drops into the view, versus specifying a different unique optimized query per view. It also uses simple queries that take into account the full JOIN structure like (simplified pseudo-SQL here):

TOP 1 FROM (SELECT fields FROM table t1 JOIN t2 JOIN t3 JOIN t4) t0

to pull metadata information.

This strategy tends to work well for many of the systems Tableau runs on top of, but occasionally runs into trouble if the RDBMS’s query optimizer doesn’t cull out unnecessary JOINS before trying to work out the query. I’d say particularly for systems intended to be DWs the issue does arise (Redshift performance, for example, can be immensely affected if JOINs are not culled out, particularly when users try and include every possible table in the schema).

Join Culling and Referential Integrity

 

Tableau does have a feature called Join Culling which will remove unnecessary JOINs from any query, but it only works under the following conditions:

(more…)