Canvas Blog Stream

(Rashid Khan) #21

Hello Tinymath

The Goat News team is over here gearing up for ElasticON, so expect updates to be a bit behind. That said, 0.1.1825 is both Kibana 6.2.2 compatible AND brings with it our new math expression parser, Tinymath. MathJS served us well, but we needed something a bit more tailored to our needs. You'll find it used in math and pointseries. The syntax should be the same and we don't know of any breakages, but that doesn't mean they aren't there. Check out the Tinymath and the Tinymath function reference while we work on getting the Tinymath docs onto this site!

(Rashid Khan) #22

We heard you liked linking

Instead of just using the same URL and picking up where you left off using localstorage, Canvas now has proper routing! This means you can now link to workpads and share your work with other people. It also means that when you load Canvas in multiple browser windows, you no longer have odd state persistence issues. And because we're no longer relying on localstorage to persist the state of the Canvas app, we're making your browser do a lot less work, which should result in a significant speed up.

This is also the first entry that Rashid didn't write, which must be some kind of Milestone...

(Rashid Khan) #23

Café Canvas

If you attended Elastic{ON} '18 a couple weeks ago, you probably noticed that Canvas was used to power a lot of dashboards around the conference. Jamie Smith just wrote up a nice post about how the "Café Canvas" dashboard was created.

The workpad showed information about the coffee orders from attendees at the coffee bar and was displayed on several screens around the conference. In the post, Jamie goes into how the workpad was built, the hardware used to feed in data, and he even links off to some of the assets used so you can try setting it up yourself. Check it out!

(Rashid Khan) #24

More Example Workpads!

Interested in trying Canvas out but don't know where to start? I don't know about you but I find it much easier to get started with a good set of examples. For that very reason I put together a number of examples. In this zip file you will find four example workpads and a python script to generate weather data.


This workpad is a very basic template, similar to a PowerPoint or Keynote presentation. Feel free to click around the example, open up the code panel and see what Canvas is doing behind the scenes.

In order to generate the data, make sure you use makelogs to generate some fake data. You'll want to make sure the index pattern used in Kibana is logstash-*

User-Analytics.json & Finance-Report.json

These two example workpads are meant to be a bit more use case specific. You do not need to add any data sources, these are both powered completely by random data generated directly through the expression language. These examples show off the power of using Canvas without actually having data ingested. This makes for a very easy way to test your workpad concepts before introducing live data into the mix.


This workpad uses live weather data to conditionally control image assets. You will notice that as the weather changes both the background of the workpad and the icon will also adjust.

In order to generate the data, use the python script. You'll need to modify a few things in the script such as the elasticsearch URL, port, username / password, API key from and the place or places you'd like to pull data from. Make sure the index pattern used in Kibana is weather

Beware, this python code is terrible and meant for the copy and paste coder. Canvas is a no judgement zone :slight_smile:

(Rashid Khan) #25

A tiny release with a big feature

We've cut a couple new releases lately. There's been a bunch of little changes, but the one I like the most are these nifty live page previews

(Rashid Khan) #26

A better presenter mode

We never liked the fullscreen mode we were using. We've swapped it out for a version that let's you get to the tabs in the browser, so you can switch back and forth between canvas and other stuff easily. We also fix a bug in datasource UIs in version 1907, which is live now.

(Rashid Khan) #27

Pointseries isn't a number and calculating percentages

Did you know that the pointseries object used to be able to cast into a number? Yeah, what? Doesn't matter, it didn't really work, so we're removing it. I figured out it didn't work because we're pulling out a confusing setting from the pie chart that would group together tiny slices, by default under 3%, into a big "Other" group. This was a function of the pie chart library we were using and was sort of confusing because it couldn't be easily styled.

If you still want that functionality, you can transform data to achieve the same effect. This leads us into a fun little tutorial on using staticColumn and mapColumn. Come along and ride on a fantastic voyage...

| pointseries color="country" size="sum(price)" 
| staticColumn total value={math 'sum(size)'} 
| mapColumn percent fn=${math 'size/total * 100'} 
| mapColumn color 
    if {getCell percent | compare lt to=3} 
    else={getCell color}
| pointseries size="sum(percent)" color=color
| pie

Let's break this down. The first two lines are pretty standard, grab some data and model it:

| pointseries color="country" size="sum(price)" 

From there we need to calculate percentages so we can figure out which slices are less than 3%. To get a percentage we need to know the total. pointseries will cast into a datatable here:

| staticColumn total value={math 'sum(size)'} 

Then we need to divide each size column by that total, and multiply that number by 100

| mapColumn percent fn=${math 'size/total * 100'} 

At this point, we have 2 new columns: total and percent. Now we need to change the color property of any row in which percent is less than 3. So we'll map over each row applying a conditional. That conditional will getCell the value of percent, and compare it with 3, if it's less, then color will be set to Other, if not, we'll getCell whatever is already in color

| mapColumn color 
    if {getCell percent | compare lt to=3} 
    else={getCell color}

Now we pipe the whole thing back into pointseries, making sure to sum(percent) as we now have a bunch of Other values which need to be totaled

| pointseries size="sum(percent)" color=color
| pie

And the you go. you have a pie chart with a giant Other slice.

And what about the preview image. What application is that? Sort of looks ike Canvas and the Dev Tools console have been spending too much time together. What's up with the schedule tab? That's a story for another day.

(Rashid Khan) #28

Refreshes will soon feel even faster

This isn't available yet, but I was working on it and wanted to share. Canvas will soon resolve all of the expression on the current page before moving on to resolve the rest of the pages. Keep your eye on the middle image, that's the currently selected page. This makes ad-hoc refreshes feel a good bit faster.

(Rashid Khan) #29

Switch and case for complex conditionals

Just released 1936 with support for switch & case functions. This makes it a lot easier todo complex multi-conditional elements and columns. For example, something like this:

demodata | mapColumn value 
  fn=${getCell price | switch 
    {case if={compare lt to=50} then=Cheap}
    {case if={compare lt to=55} then=Reasonable}
    {case if={compare lt to=60} then=Expensive}
    default="Too expensive"

(Rashid Khan) #30

Interpreter architecture review

As we work towards getting Canvas into GA, we're pouring over the architecture and making some changes. Most of those changes will be feature based, but in other places we're making things more reliable, faster, more flexible.

One of our next big projects is bringing threading to the Canvas interpreter. This will let us do heavy lifting operations faster and bring additional safety to the the Canvas system. There's 2 sides to this issue, the server and the client. We'll take roughly the same approach on both.The server will fork a set of worker processes, and the browser will defer to web workers that it can defer to for functions that don't need access to anything in the Canvas environment, just the data.

We'll try to keep you updated over here as we progress.

(Rashid Khan) #31

Some screenshots

We demoed Canvas at a meetup a few days ago, thought I'd share a few slides from it:

This is a slightly different take on the race car demo we did at Elastic{ON} 18. At ElasticON we know we're going to have massive, high resolution, high quality screens, so we can go with more complex graphics. I'm never quite sure what I'll have at a meetup, so I shoot for bolder colors and try to avoid things like grey scale. It turned out the screens were wonderful, but I still like this aesthetic.

This one was a bit useless, but the goal was to show the sort of things you could create. This is a "coffee clock". On the left the mugs stack of as the seconds of a minute pass. The mug on the right fills up as the seconds pass.

(Rashid Khan) #32

And the workpad itself

And if you want the actual workpad, here it is. This isn't the exact workpad, since that would require my data and, trust me, you don't want to deal with setting all that up. Instead I've hacked this one up and replaced the places where data is required with calls to math 'random()'. Enjoy!

(Rashid Khan) #33

Blog changes

As part of our transition to the main site, you have noticed the blog looks a bit different. That's because it's now powered from The posts here are really just replies to the Canvas Blog Stream topic.

More changes are on the way as we ramp up to merge Canvas into Elastic's X-Pack!

(Joe Fleming) #34

Image previews in sidebar

This just in! Like, I literally just merged it. Images used in elements now show up in the sidebar. This gives you a quick association between what you see in the element and the controls you see in the sidebar.


Image preview is now available in build 1949.

(Rashid Khan) #35

This layout engine is going to be rad

The layout engine is the thing that lets you move, resize and rotate elements in Canvas. The version we have now is just ok, but Robert has been working on an all new version that is looking amazing. The first iteration of it will be functionality identical to the current system, with the addition of keyboard commands, but Robert has built all sort of awesome stuff under the covers. Like these rad 3D transforms:


(Rashid Khan) #36

Markdown + Handlebars + Dots

We're still sorting out what we want to do with dots in Canvas column names, but if you're using esdocs you almost certainly have some. For the most part dots work everywhere, but this morning Tim noticed that didn't work in the markdown element's handlebars templating system. For example, something like this does not work:

esdocs index=tweets | markdown "
{{#each rows}}

  - {{user.screen_name}}


The reason being that user.screen_name is trying to access the screen_name property on the user object, which isn't a thing. We want to access the row["user.screen_name"] which we can't do in this implementation.

But no worries, there exists a work around since you can easily rename columns in Canvas. We just need to add an alterColumn, to rename the column to something without dots, after esdocs:

esdocs index=tweets 
| alterColumn user.screen_name name=userScreenName
| markdown "
{{#each rows}}

  - {{userScreenName}}


We're still working on better ways of handling that, but this will do for now.

(Catherine Liu) #37

Canvas is Getting a Facelift!

In the oncoming weeks, you may notice a few changes in the overall look and feel of Canvas. We're converting all our UI components to EUI (Elastic's in-house UI framework). I just merged a few changes to the workpad header and workpad/page settings for the next release!

Here's a sample of what's in-store.

Stay tuned for more EUIfication!

(Tim Sullivan) #38

Creating a percentage distribution chart using a Canvas expression

Awhile ago I got a question from a Kibana user, essentially on how to "plot percentiles in Kibana." Looking at an example chart of what they wanted, it became clear they were trying to make a percentage distribution chart - in other words, the shape of the data shows relative of occurrence of each term, but instead of an absolute count for the y-axis values, the y-axis is scaled to percentages. If this doesn't make sense now, it will soon.

Unfortunately, scaling y-axis to percentage isn't possible to do with the current built-in visualizations tools in Kibana yet, but it is pretty simple to do with a Canvas expression.

Using the demodata source, we can see what an expression to render a bar chart with each "age" shown comparatively as percentages:

| ply by=age fn=${rowCount | as count}
| staticColumn total value={math 'sum(count)'}
| mapColumn percentage fn=${math 'count/total * 100'}
| sort age
| pointseries x=age y=percentage
| plot defaultStyle={seriesStyle points=0 lines=5} 

Gives us a nice bar chart where ages are sorted on the x-axis, and the y-axis shows the percentage of each age's occurrence:

For a more real-life example, I whipped up this sample data that might show percentage of sales contributed by different sales people:

Let's see what this expression looks like:

esdocs index="sales" fields="salesperson" sort="@date, desc" count=1000
| ply by="salesperson" fn=${rowCount | as "count"}
| staticColumn "total" value={math "sum(count)"}
| mapColumn "percentage" fn=${math "count/total * 100"}
| sort "percentage" reverse=true
| pointseries x="salesperson" y="percentage"
| plot defaultStyle={seriesStyle points="0" lines="0" bars="0.5"} xaxis={axisConfig position="bottom"}
| render css=".canvas__element .flot-text .flot-x-axis .flot-tick-label { transform: rotate(-30deg) translate(12px, -20px); }"

Pretty much the same as the top example, only this uses an Elasticsearch index for the data, providing options on how I want the data sorted and how much data I want. The sort and count properties are telling Canvas to get me the newest 1000 documents from my sales index. That lines up to what my data should look like, because "Florinda" was heavily weighted in my sample data generator.

With my salespeople's names along the x-axis, the names could easily crowd into each other. That's why I'm using the css parameter to the render function to slightly rotate my x-axis tick labels.

Hope this quick example helps you see how powerful expression in Canvas can be!