<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>InfluxData Blog - Nathaniel Cook</title>
    <description>Posts by Nathaniel Cook on the InfluxData Blog</description>
    <link>https://www.influxdata.com/blog/author/nathanielc/</link>
    <language>en-us</language>
    <lastBuildDate>Thu, 03 Nov 2022 07:00:00 +0000</lastBuildDate>
    <pubDate>Thu, 03 Nov 2022 07:00:00 +0000</pubDate>
    <ttl>1800</ttl>
    <item>
      <title>What to Expect from Flux 1.0</title>
      <description>&lt;p&gt;&lt;em&gt;(&lt;strong&gt;Update&lt;/strong&gt;: &lt;a href="https://www.influxdata.com/products/influxdb-overview/"&gt;InfluxDB 3.0&lt;/a&gt; moved away from Flux and a built-in task engine. Users can use external tools, like Python-based &lt;a href="https://www.quix.io/kapacitor-alternative"&gt;Quix&lt;/a&gt;, to create tasks in InfluxDB 3.0.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This week at InfluxDays we &lt;a href="https://www.influxdata.com/blog/influxdays-new-platform-enhancements/"&gt;announced&lt;/a&gt; that Flux 1.0 is coming soon. Version 1.0 of &lt;a href="https://www.influxdata.com/products/flux/"&gt;Flux&lt;/a&gt; lang is a commitment to no longer make breaking changes to the Flux language. Importantly, today’s Flux scripts will work on Flux 1.0, and no breaking changes will be introduced between now and the release of Flux 1.0. Along with version 1.0, we have some features we are also releasing soon. Here are the features we have coming and a short explanation of why you might want to leverage them:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Modules:&lt;/strong&gt; Share Flux code within your organization and build useful abstractions over common queries.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Editions:&lt;/strong&gt; Opt into new features of Flux without the risk of breaking changes.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Label Polymorphism:&lt;/strong&gt; Write Flux code that can abstract over the schema of your data.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Dynamic Type:&lt;/strong&gt; Work with &lt;a href="https://www.influxdata.com/blog/tldr-influxdb-tech-tips-handling-json-objects-mapping-arrays/"&gt;JSON data&lt;/a&gt; that is fully dynamic without limitations.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Dynamic Type feature is available today and you can try it out in the cloud. Now let’s dive into some of these features in more detail.&lt;/p&gt;

&lt;h2 id="how-to-use-modules"&gt;How to use modules&lt;/h2&gt;

&lt;p&gt;Flux modules are a system that allows you to publish Flux code to a registry that’s private to your organization. Then you can import that code and reuse it anywhere from &lt;a href="https://www.influxdata.com/blog/tldr-influxdb-tech-tips-debugging-and-monitoring-tasks-with-influxdb/"&gt;tasks&lt;/a&gt; to &lt;a href="https://www.influxdata.com/blog/5-dashboard-design-best-practices/"&gt;dashboard cells&lt;/a&gt; and within your application’s Flux code.&lt;/p&gt;

&lt;p&gt;&lt;img src="//images.ctfassets.net/o7xu9whrs0u9/1Qj35IIu3tQ5OtVC17RRxl/38943edd95c5f95d328c7ddc62604f0a/Dynamic_Type.png" alt="Dynamic Type" /&gt;&lt;/p&gt;

&lt;figcaption&gt;Graphic illustrating Flux modules and sharing code&lt;/figcaption&gt;

&lt;p&gt;Here’s an example of how modules will work once they are released. A common use case we see is that organizations will tag their data with a value that really represents much more data than is present in the tag alone. For example, you might have an &lt;code&gt;env&lt;/code&gt; tag on your data that represents the data center where the metrics originated. There are properties of that environment not present in other tags, for example which cloud provider hosts that environment or whether the environment is production or not. Using modules, you can encode this information into a Flux dictionary and then leverage it to annotate data with that extra information.&lt;/p&gt;

&lt;p&gt;The first step to using modules is to define a Flux script:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-javascript"&gt;// Notice we give this script a package name since it will be part of a module.
package env

import "dict"

// Map envs to their cloud provider.
providers =
	[
    	"prod01": "aws",
    	"prod02": "aws",
    	"prod03": "gcp",
    	"prod04": "azure",
    	"stag01": "aws",
    	"stag02": "gcp",
	]

// Map envs to their purpose.
// We could just regex match on the name,
// but sometimes it’s important to be explicit.
kinds =
	[
    	"prod01": "production",
    	"prod02": "production",
    	"prod03": "production",
    	"prod04": "production",
    	"stag01": "staging",
    	"stag02": "staging",
	]

// annotate adds extra information about the env to the table.
//
// ## Parameters
// - tables: Input data. Default is piped-forward data (`&amp;lt;-`).
//
annotate = (tables=&amp;lt;-) =&amp;gt;
	tables
    	|&amp;gt; map(
        	fn: (r) =&amp;gt;
            	({r with provider: dict.get(dict: providers, key: r.env, default: "unknown"),
                	kind: dict.get(dict: kinds, key: r.env, default: "unknown"),
            	}),
    	)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then we publish this module using the API. More details on the publish process will be coming with the release of modules. After publishing, we can import this module in a dashboard cell and make it easy to group the data by cloud provider and filter out the staging environments.&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-javascript"&gt;import "modules/env"

// Render median request duration grouped by provider in only production envs
from(bucket: "request")
	|&amp;gt; range(start: v.timeRangeStart, stop: v.timeRangeStop)
	|&amp;gt; filter(fn: (r) =&amp;gt; r._measurement == "duration")
	|&amp;gt; env.annotate()
	|&amp;gt; filter(fn: (r) =&amp;gt; r.kind == "production")
	|&amp;gt; group(columns: ["provider"])
	|&amp;gt; aggregateWindow(every: v.windowPeriod, fn: median)&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="editions-and-breaking-changes"&gt;Editions and breaking changes&lt;/h2&gt;

&lt;p&gt;Editions are a key component of the Flux 1.0 release. With 1.0 we will no longer make breaking changes to Flux. However, on occasion there are valuable features that we should add to Flux that would constitute breaking changes. We need a way to safely add these features without breaking Flux scripts. This is where editions come in. An edition is a set of features that are disabled by default. You can opt-in to an edition which will enable those features, but if you do not opt-in nothing will change and your scripts will continue to work without breaking. Because editions are opt-in, you can update your scripts before updating to a new edition to ensure they continue to work as expected. An edition can be selected on a per-script basis or enabled via the API or organization-level settings, providing flexibility in upgrading scripts.&lt;/p&gt;

&lt;p&gt;Creating new editions will be a rare event and we anticipate creating at most one new edition per year. Therefore we are naming editions after the year in which they are created. The first edition of Flux will be called &lt;code class="language-html"&gt;2022.1&lt;/code&gt;. We’ll likely cut a second edition of Flux next year and it will be called &lt;code class="language-html"&gt;2023.1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Users can enable a new edition by specifying it in their scripts like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-javascript"&gt;// Enable a specific edition with this line as the first line in the script
#edition("2023.1")

// The rest of the script follows&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="what-to-expect-from-label-polymorphism"&gt;What to expect from label polymorphism&lt;/h2&gt;

&lt;p&gt;Label polymorphism is one of the first features that we will release behind an edition because the feature adds a new syntax to Flux that is breaking.&lt;/p&gt;

&lt;p&gt;Label polymorphism allows users to abstract over the schema of their data. Have you ever wanted to write a Flux function that takes a column name as an argument and then uses that name dynamically within the function? This has been a long requested feature of Flux and it’s coming soon as part of the second edition of Flux.&lt;/p&gt;

&lt;p&gt;Let’s look at the same example we used earlier showing modules. We wrote this function in the &lt;code class="language-javascript"&gt;env&lt;/code&gt; package:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-javascript"&gt;// annotate adds extra information about the env to the table.
//
// ## Parameters
// - tables: Input data. Default is piped-forward data (`&amp;lt;-`).
//
annotate = (tables=&amp;lt;-) =&amp;gt;
	tables
    	|&amp;gt; map(
        	fn: (r) =&amp;gt;
            	({r with provider: dict.get(dict: providers, key: r.env, default: "unknown"),
                	kind: dict.get(dict: kinds, key: r.env, default: "unknown"),
            	}),
    	)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we look closely at this function, we realize that it hard-codes a lot of information about the schema of the data. It assumes that the &lt;code class="language-javascript"&gt;env&lt;/code&gt; tag can be accessed as &lt;code class="language-javascript"&gt;r.env&lt;/code&gt;, and additionally it hard-codes the columns &lt;code class="language-javascript"&gt;provider&lt;/code&gt; and &lt;code class="language-javascript"&gt;kind&lt;/code&gt; on the output table. What if we have data that comes from inconsistent systems that sometimes use &lt;code class="language-javascript"&gt;env&lt;/code&gt; and other times use &lt;code class="language-javascript"&gt;environment&lt;/code&gt;? We can use &lt;code class="language-javascript"&gt;labels&lt;/code&gt; to abstract away which columns we are using like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-javascript"&gt;// We need to enable the edition in order to use labels
#edition("2023.1")

// annotate adds extra information about the env to the table.
//
// ## Parameters
// - env: Label for the environment column. Default `env`.
// - provider: Output label for the provider column. Default `provider`.
// - kind: Output label for the kind column. Default `kind`.
// - tables: Input data. Default is piped-forward data (`&amp;lt;-`).
//
annotate = (tables=&amp;lt;-, env=.env, provider=.provider, kind=.kind) =&amp;gt;
	tables
    	|&amp;gt; map(
        	fn: (r) =&amp;gt;
            	({r with [provider]: dict.get(dict: providers, key: r[env], default: "unknown"),
                	[kind]: dict.get(dict: kinds, key: r[env], default: "unknown"),
            	}),
    	)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are three new syntax elements here. First we have &lt;code class="language-javascript"&gt;.env&lt;/code&gt; which defines a label with the value &lt;code class="language-javascript"&gt;env&lt;/code&gt; and the &lt;code class="language-javascript"&gt;.&lt;/code&gt; which tells Flux it’s a label. We use a label value as the default for each of the three column parameters we added to the function. Second, we see &lt;code class="language-javascript"&gt;r[env]&lt;/code&gt;. This is how we access the &lt;code class="language-javascript"&gt;env&lt;/code&gt; column on the record &lt;code class="language-javascript"&gt;r&lt;/code&gt;. Finally, in the output record we see &lt;code class="language-javascript"&gt;[provider]&lt;/code&gt; and &lt;code class="language-javascript"&gt;[kind]&lt;/code&gt;, which adds columns on the output record based on the values of the &lt;code class="language-javascript"&gt;provider&lt;/code&gt; and &lt;code class="language-javascript"&gt;kind&lt;/code&gt; labels.&lt;/p&gt;

&lt;p&gt;Here’s what it looks like to call this new function, given we are working with a legacy system that uses &lt;code class="language-javascript"&gt;environment&lt;/code&gt; instead of &lt;code class="language-javascript"&gt;env&lt;/code&gt; and already has a tag named &lt;code class="language-javascript"&gt;kind&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-javascript"&gt;// We need to enable the edition in order to use labels
#edition("2023.1")

import "modules/env"

// Render median request duration grouped by provider in all production envs
from(bucket: "legacy_request")
	|&amp;gt; range(start: v.timeRangeStart, stop: v.timeRangeStop)
	|&amp;gt; filter(fn: (r) =&amp;gt; r._measurement == "duration")
	// We can specify the column names when calling the annotate function
	|&amp;gt; env.annotate(env: .environment, kind: .env_kind)
	|&amp;gt; filter(fn: (r) =&amp;gt; r.env_kind == "production")
	|&amp;gt; group(columns: ["provider"])
	|&amp;gt; aggregateWindow(every: v.windowPeriod, fn: median)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Neither labels nor edition &lt;code class="language-html"&gt;2023.1&lt;/code&gt; have been released yet, so the above script will error on existing Flux, but keep an eye out for these features coming soon.&lt;/p&gt;

&lt;h2 id="dynamic-type-for-json-data"&gt;Dynamic type for JSON data&lt;/h2&gt;

&lt;p&gt;Dynamic type is another new type added to Flux that allows any JSON data to be accurately represented with Flux data types. Flux is a statically typed language that requires container types (i.e. arrays, records, and dictionaries) to contain data of a consistent type. For example, a list of integers is a consistent type, but a list of strings and integers is not. JSON doesn’t have these restrictions, and with the new dynamic type feature we can represent JSON within Flux correctly. Flux is still statically typed, but we’ve added a new type called “dynamic” that allows Flux to handle dynamically typed data.&lt;/p&gt;

&lt;p&gt;For example, this JSON was not possible to represent in Flux previously:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-json"&gt;{
  "items":  [
  	{"name": "a", "pos": {"x": 10, "y": 10}},
  	{"name": "b", "pos": {"x": 30}},
  	{"name": "c", "pos": {}},
  	{"name": "d"}
	]
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Unlike these other features, dynamic type is available today.&lt;/p&gt;

&lt;p&gt;You can now parse the above JSON without error using the new &lt;code class="language-javascript"&gt;experimental/dynamic&lt;/code&gt; package.&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-javascript"&gt;import "experimental/dynamic"

parsed = dynamic.parseJSON(data: jsonDataAsBytes)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is possible because the function &lt;code class="language-json"&gt;dynamic.parseJSON&lt;/code&gt; returns a Flux value with type &lt;code class="language-json"&gt;dynamic&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A dynamic value represents a value whose type is not known until runtime. Flux also can have containers (i.e. arrays etc.) of dynamic values.&lt;/p&gt;

&lt;p&gt;Dynamic values aren’t allowed inside Flux tables, so we explicitly convert a dynamic value to a value with a statically known type. This conversion makes use of the &lt;code class="language-json"&gt;array&lt;/code&gt; package helper functions and some new functions in the &lt;code class="language-json"&gt;dynamic&lt;/code&gt; package.&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-javascript"&gt;import "array"
import "experimental/dynamic"

parsed = dynamic.parseJSON(data: jsonDataAsBytes)

// parsed is dynamic so parsed.items is also dynamic
parsed.items
	// convert the plain dynamic value to an array of dynamic values
	|&amp;gt; dynamic.asArray()
	// map over each dynamic value in the array and construct a record
	|&amp;gt; array.map(fn: (r) =&amp;gt; ({
    	name: string(v: x.name),
    	posX: int(v: x.pos.x),
    	posY: int(v: x.pos.y),
	}))
	// convert the array of records (no longer containing any dynamic values) into a table
	|&amp;gt; array.from()&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For the JSON rows that did not have a &lt;code class="language-javascript"&gt;pos&lt;/code&gt; value, the table will contain &lt;code class="language-javascript"&gt;nulls&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id="final-thoughts"&gt;Final thoughts&lt;/h2&gt;

&lt;p&gt;There’s a lot included in Flux 1.0. Many new features are coming soon and dynamic type is available today. Keep an eye out for the Flux 1.0 release and new editions of Flux. In the meantime, you can check out my session from InfluxDays 2022.&lt;/p&gt;

&lt;div class="youtube-container"&gt;
  &lt;iframe class="responsive-iframe" src="https://www.youtube.com/embed/PsCZySgBraw" title="IScripting Languages Demonstration: Flux"&gt;&lt;/iframe&gt;
&lt;/div&gt;
</description>
      <pubDate>Thu, 03 Nov 2022 07:00:00 +0000</pubDate>
      <link>https://www.influxdata.com/blog/what-expect-flux-1-0/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/what-expect-flux-1-0/</guid>
      <category>Product</category>
      <author>Nathaniel Cook (InfluxData)</author>
    </item>
    <item>
      <title>Flux and Static Analysis</title>
      <description>&lt;p&gt;Have you seen this when using the Flux code editor&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/legacy-uploads/flux-code-editor.gif" alt="flux code editor" width="768" height="147" /&gt;&lt;/p&gt;

&lt;p&gt;Pretty neat to be able to get that much help from an editor while writing code.&lt;/p&gt;

&lt;p&gt;Have you ever wondered how that worked? Today, I’ll take us on a bit of a deep dive on the behind-the-scenes that enable these autocompletion features in the editor.&lt;/p&gt;

&lt;h2&gt;How does a code editor know enough about the code you write in order to help you out&lt;/h2&gt;

&lt;p&gt;The answer is something called &lt;a href="https://en.wikipedia.org/wiki/Static_program_analysis"&gt;static analysis&lt;/a&gt; through which we can analyze a &lt;a href="/products/flux/"&gt;Flux&lt;/a&gt; script and learn lots of information about what the code does without actually running the code. It is important that we do not have to run the code to learn about it because - as the author of the code - you may not be ready to run the code yet as it may edit a file or write data to a database. That is why the technique is called static analysis; the analysis is performed on only static inputs, i.e. the Flux code.&lt;/p&gt;

&lt;h2&gt;What do we want to learn about the code when we analyze it&lt;/h2&gt;

&lt;p&gt;The primary information we are trying to learn when we analyze the code are the types of the expressions in the code. For example, if you have this line in the code &lt;code class="language-javascript"&gt;threshold = 42&lt;/code&gt;, we learn that there is a variable named &lt;code class="language-javascript"&gt;threshold&lt;/code&gt; and that its type is an integer. In the animation above, you can see that the editor was able to suggest the arguments to the &lt;code class="language-javascript"&gt;aggregateWindow&lt;/code&gt; function. This is possible because we know the type of the function &lt;code class="language-javascript"&gt;aggregateWindow&lt;/code&gt; and the type includes the information about what arguments the function accepts.&lt;/p&gt;

&lt;p&gt;Types are a way of specifying which values make sense in what contexts. So when you type &lt;code class="language-javascript"&gt;aggregateWindow&lt;/code&gt; we know that the name &lt;code class="language-javascript"&gt;aggregateWindow&lt;/code&gt; is a variable in the program scope that has the function type, so we can make suggestions for how to complete the rest of the code using that type.&lt;/p&gt;

&lt;h2&gt;How does static analysis algorithm learn the types of the expressions and variables in the code&lt;/h2&gt;

&lt;p&gt;We use a static analysis technique called type inference, which is the idea that looking at the code you can infer the types based on how you see the code used. For example given this code, what do you think the type of the &lt;code class="language-javascript"&gt;m&lt;/code&gt; variable is&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;m = "Hello World"
print(m)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The variable &lt;code class="language-javascript"&gt;m&lt;/code&gt; is a string. It is clear from the code even though the word &lt;code class="language-javascript"&gt;string&lt;/code&gt; is not present in the code. Contrast that code with the Go code equivalent:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-go"&gt;var string m = "Hello World"
print(m)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code class="language-javascript"&gt;string&lt;/code&gt; keyword tells the Go compiler that the variable &lt;code class="language-javascript"&gt;m&lt;/code&gt; has the string type.&lt;/p&gt;

&lt;p&gt;Type inference is the idea that Flux can infer the type of the values within the program based on the context that those values are used. This means that authors of the code do not need to explicitly state the types of variables in their code.&lt;/p&gt;

&lt;p&gt;If you are familiar with Go, you may be thinking that you can use the &lt;code class="language-javascript"&gt;:=&lt;/code&gt; syntax instead. That is correct and is in fact a limited case of type inference within Go as well.&lt;/p&gt;

&lt;p&gt;Flux does not require type annotations in the code because it can infer the type of any value without them.&lt;/p&gt;

&lt;p&gt;While the above examples are simple to infer the types, in general it’s not easy to determine what the types are for an arbitrary Flux script by just looking at it. In order to consistently and accurately determine the types in any Flux program, we need a set of rules (i.e. an algorithm) to define how types can be inferred. The Flux team uses a specific algorithm for type inference known as &lt;em&gt;&lt;strong&gt;Algorithm W&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The specifics of Algorithm W are very nuanced, so we will hand-wave away most of those details. Instead, we will cover here just the raw structure of the algorithm.&lt;/p&gt;

&lt;p&gt;To understand how Algorithm W works, let’s first look at another problem that may be familiar to you. Remember algebra and solving a system of equations? It’s those problems where they gave two equations that had two variables, and you had to solve for both variables. Those problems are solved in a very similar manner to how Flux solves for the types in a program using Algorithm W. For example, given these two equations with variables &lt;code class="language-javascript"&gt;x&lt;/code&gt; and &lt;code class="language-javascript"&gt;y&lt;/code&gt;, you can solve for the variables.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;2x + y = 5
y = 2 + x&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The process of solving these variables involves substituting one variable equation into the other equations. We have an equation of what &lt;code class="language-javascript"&gt;y&lt;/code&gt; is equal to, so we can substitute all values of &lt;code class="language-javascript"&gt;y&lt;/code&gt; in the first equation with the right-hand side of the &lt;code class="language-javascript"&gt;y =&lt;/code&gt; equation like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;2x + (2 + x) = 5&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now that we have only a single variable &lt;code class="language-javascript"&gt;x&lt;/code&gt; in the equation, we solve for &lt;code class="language-javascript"&gt;x&lt;/code&gt; using the rules of algebra. Here are the steps explicitly:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;2x + (2 + x) = 5
3x + 2 = 5
3x = 3
x = 1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We have solved for &lt;code class="language-javascript"&gt;x&lt;/code&gt; and learned its value is &lt;code class="language-javascript"&gt;1&lt;/code&gt;. Now we can use the equation for &lt;code class="language-javascript"&gt;y&lt;/code&gt; to determine its value.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;y = 2 + x
y = 3&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Using this process, we have solved for the values of &lt;code class="language-javascript"&gt;x&lt;/code&gt; and &lt;code class="language-javascript"&gt;y&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Type inference is similar except that instead of solving a system of algebraic equations, we solve equations about types. We use substitution and the rules of the types to solve for the type of every expression in a Flux program.&lt;/p&gt;

&lt;p&gt;Here is an overview of the process:&lt;/p&gt;

&lt;ol&gt;
 	&lt;li&gt;?Assign a type variable to each Flux expression in the program.&lt;/li&gt;
 	&lt;li&gt;Generate all the equations about the types.&lt;/li&gt;
 	&lt;li&gt;Solve that set of equations.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;First, for each expression in a Flux script, we assign it a new type variable. (We call them type variables because they represent types; we do not know which type until we solve for them.)&lt;/p&gt;

&lt;p&gt;Our goal is to solve for those type variables. To do so, we need some equations. We get those equations by looking at how each type variable is used within the Flux program.&lt;/p&gt;

&lt;p&gt;Once we have collected all the equations, we can solve them. We do this the same way we solve an algebraic equation, by rearranging the equations according to the rules and using substitution to replace variables in the equations until we have a simple &lt;code class="language-javascript"&gt;X = Type&lt;/code&gt; equation for each type variable.&lt;/p&gt;

&lt;p&gt;Here is a simple hello world Flux program that will print “hello world” when run via the REPL.&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-javascript"&gt;a = "hello "
b = "world"
a + b&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can follow the process that type inference takes to know the types of all of the expressions in this program. I have chosen this example because all expressions in this program have the type string, and this makes it easy to see the solution we are working towards as we take each step.&lt;/p&gt;

&lt;p&gt;The first step is to assign the type variables to the expressions. This program has three expressions: one for each line. Let’s give these type variables the names &lt;code class="language-javascript"&gt;X&lt;/code&gt;, &lt;code class="language-javascript"&gt;Y&lt;/code&gt; and &lt;code class="language-javascript"&gt;Z&lt;/code&gt; for each line in order.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;a = "hello " // X
b = "world"  // Y
a + b        // Z&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice that we are talking about two different kinds of variables:&lt;/p&gt;

&lt;ol&gt;
 	&lt;li&gt;Variables in the Flux program itself like &lt;code class="language-javascript" style="font-style: inherit; font-weight: inherit;"&gt;a&lt;/code&gt; and &lt;code class="language-javascript" style="font-style: inherit; font-weight: inherit;"&gt;b&lt;/code&gt;&lt;/li&gt;
 	&lt;li&gt;Type variables like &lt;code class="language-javascript"&gt;X&lt;/code&gt;,  &lt;code class="language-javascript"&gt;Y&lt;/code&gt; and &lt;code class="language-javascript"&gt;Z&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To help differentiate between the two, I will use upper case letters for type variables and lowercase letters for program variables.&lt;/p&gt;

&lt;p&gt;Next, we need to gather all the equations we know about those type variables.&lt;/p&gt;

&lt;p&gt;First, we have the type variable &lt;code class="language-javascript"&gt;X&lt;/code&gt; with the expression:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-javascript"&gt;a = "hello "&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since we see that only a string literal is used, we know that the expression must have a string type. We can write down an equation for &lt;code class="language-javascript"&gt;X&lt;/code&gt; stating that &lt;code class="language-javascript"&gt;X&lt;/code&gt; must be equal to the type &lt;code class="language-javascript"&gt;string&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;X = string&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We also see that we assigned a value to the program variable &lt;code class="language-javascript" style="font-style: inherit; font-weight: inherit;"&gt;a&lt;/code&gt;, so we write down the type variable that is associated with the normal variable like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;a -&amp;gt; X&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We track the association of the program variables to their corresponding type variables so we can look them up whenever they are used in other expressions.&lt;/p&gt;

&lt;p&gt;The next expression for type variable &lt;code class="language-javascript"&gt;Y&lt;/code&gt; is:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;b = "world"&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is the same as &lt;code class="language-javascript"&gt;X&lt;/code&gt; from a type perspective; therefore, we get the following equation and type variable association.&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-javascript"&gt;Y = string
b -&amp;gt; Y&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, we need to write down an equation for &lt;code class="language-javascript"&gt;Z&lt;/code&gt;, remember its expression:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;a + b&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This expression doesn’t have any hints as to what type it is because only program variables are used. However, we can still learn something useful from the expression.&lt;/p&gt;

&lt;p&gt;We know that both sides of the &lt;code class="language-javascript"&gt;+&lt;/code&gt; operator must be the same type. This is what we mean by using the rules of types: certain operators must be used in specific ways, and we write down equations to capture those constraints.&lt;/p&gt;

&lt;p&gt;Since we don’t know the type yet, we create a new type variable &lt;code class="language-javascript"&gt;W&lt;/code&gt; as a placeholder for now. Now, we can write down some more equations using &lt;code class="language-javascript"&gt;W&lt;/code&gt; and the &lt;code class="language-javascript"&gt;lookup&lt;/code&gt; function to indicate we need to lookup the association of a program variable to its type variable.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;W = lookup(a)
W = lookup(b)
Z = W&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can lookup the type variable for &lt;code class="language-javascript" style="font-style: inherit; font-weight: inherit;"&gt;a&lt;/code&gt; and &lt;code class="language-javascript" style="font-style: inherit; font-weight: inherit;"&gt;b&lt;/code&gt; and update the equations.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;W = X
W = Y
Z = W&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we have examined all the expressions in the program, and we can move onto the next step to solve those equations. This part proceeds in the same way as solving the algebraic equations. We start substituting variables for their equation until we learn the type of every variable.&lt;/p&gt;

&lt;p&gt;Here are all the equations we know at this point:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;X = string
Y = string
W = X
W = Y
Z = W&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can substitute the type variables &lt;code class="language-javascript"&gt;X&lt;/code&gt; and &lt;code class="language-javascript"&gt;Y&lt;/code&gt; and get these simplified equations.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;W = string
W = string
Z = W&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we know a value for &lt;code class="language-javascript"&gt;W&lt;/code&gt; and can substitute it in the equation for &lt;code class="language-javascript"&gt;Z&lt;/code&gt; like so:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;Z = string&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We now have a set of equations and have solved for all type variables.&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-javascript"&gt;X = string
Y = string
Z = string
W = string&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can now say that all expressions in the Flux script are strings as we expected when we first saw the program.&lt;/p&gt;

&lt;p&gt;?Taking a step back, we can start to see how to systematically solve for the types of expressions within a Flux program. We can also see how we can find errors in programs. For example, take this slightly modified example program:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;a = "hello "
b = 1
a + b&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When creating the type equations for this program, we would get the following:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;X = string
Y = integer
W = X
W = Y
Z = W&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Using substitution, we would get:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-javascript"&gt;W = string
W = integer&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At this point, we have discovered a type error because &lt;code class="language-javascript"&gt;W&lt;/code&gt; cannot be both equal to a string and an integer. When there is not a valid solution to the type equations, then there is a type error in the program. This error is valuable because it tells us about a mistake in our program before we ran it.&lt;/p&gt;

&lt;p&gt;That’s type inference in a nutshell; generate a bunch of equations based on how the expressions are used within the Flux program and then solve that set of equations for all the type variables. Hopefully, this has shed some light on how we perform static analysis (i.e. type inference) in order to learn the types in a Flux program. Armed with the knowledge of types, an editor can then use those types to provide helpful suggestions and error messages when developing Flux scripts.&lt;/p&gt;

&lt;h2&gt;Want to learn more about type inference&lt;/h2&gt;

&lt;p&gt;Naturally, type inference is more complex in practice since even simple Flux programs have lots of expressions, and therefore, lots of equations to solve. Solving a large number of equations can be very difficult to do efficiently and accurately. Imagine trying to solve a system of hundreds of algebra equations. That would be very tedious and easy to make a mistake.&lt;/p&gt;

&lt;p&gt;Additionally, as you may remember from algebra class, picking which equations to substitute into which other equations can make solving the problem either easy or extremely difficult. For algebra this becomes a bit of an intuitive art that students get good at with practice. Unfortunately, computers are not good at intuition. That is where Algorithm W comes in. It is a specific algorithm for how to generate and solve type equations efficiently and correctly.&lt;/p&gt;

&lt;p&gt;If you want to learn more, there are decades of research and literature on these topics. Here are a few pointers to get you started.&lt;/p&gt;

&lt;ul&gt;
 	&lt;li&gt;Algorithm W is a class of type inference algorithms known as Hindley-Milner.&lt;/li&gt;
 	&lt;li&gt;We also use an extension to Algorithm W for extensible records see the &lt;a href="https://www.microsoft.com/en-us/research/publication/extensible-records-with-scoped-labels/"&gt;paper&lt;/a&gt;.&lt;/li&gt;
 	&lt;li&gt;Try out the language SML it has a very simple type system based on Hindley-Milner and is a quick language to learn. It's similar to Haskel and OCaml but drastically easier to learn and simpler to understand.&lt;/li&gt;
 	&lt;li&gt;There are several implementations of various type inference algorithms along with their research in a &lt;a href="https://github.com/tomprimozic/type-systems"&gt;GitHub repo&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I personally found no shortcuts in trying to learn type inference; most of the literature assumes some basic understanding of the concepts of types and computational theory. I would start with lambda calculus as all literature about Hindley-Milner assumes familiarity with lambda calculus. Then follow up with experimentation and practice on your part.&lt;/p&gt;

&lt;p&gt;Additionally, I haven’t mentioned yet the Flux language server which is responsible for using the type information learned from static analysis and translating that into suggestions the editor can then present. It’s the critical piece that makes this all work. Check out the &lt;a href="https://github.com/influxdata/flux-lsp"&gt;Flux LSP implementation&lt;/a&gt; on GitHub.&lt;/p&gt;

&lt;p&gt;That’s all for today, thanks for following along.&lt;/p&gt;
</description>
      <pubDate>Mon, 01 Jun 2020 07:00:55 -0700</pubDate>
      <link>https://www.influxdata.com/blog/flux-and-static-analysis/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/flux-and-static-analysis/</guid>
      <category>Use Cases</category>
      <category>Developer</category>
      <category>Product</category>
      <author>Nathaniel Cook (InfluxData)</author>
    </item>
    <item>
      <title>Announcing Flux (formerly IFQL) v0.0.5 with 12+ New Functions</title>
      <description>&lt;p&gt;This release represents a big leap forward for Flux.&lt;/p&gt;

&lt;p&gt;In the first part of the release cycle, we focused on formalizing the way query operations are chained within Flux. Once that was complete we tried it out, and quickly found that it was easy to add new functions to Flux by composing existing functions together. We were able to add nearly a dozen functions to the language using only Flux code—no Go code was required. In addition we added a handful of new functions backed by specialized Go implementations.&lt;/p&gt;

&lt;p&gt;The new functions in the release include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;top&lt;/li&gt;
  &lt;li&gt;bottom&lt;/li&gt;
  &lt;li&gt;highestMax&lt;/li&gt;
  &lt;li&gt;highestAverage&lt;/li&gt;
  &lt;li&gt;highestCurrent&lt;/li&gt;
  &lt;li&gt;lowestMin&lt;/li&gt;
  &lt;li&gt;lowestAverage&lt;/li&gt;
  &lt;li&gt;lowestCurrent&lt;/li&gt;
  &lt;li&gt;stateCount&lt;/li&gt;
  &lt;li&gt;stateDuration&lt;/li&gt;
  &lt;li&gt;distinct&lt;/li&gt;
  &lt;li&gt;percentile&lt;/li&gt;
  &lt;li&gt;median&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From that list only stateCount, stateDuration, percentile, and distinct required specialized Go implementations. The rest are pure Flux functions.&lt;/p&gt;

&lt;p&gt;This large batch of functions is in part due to how we have formalized the way functions are chained in Flux. Every query function accepts a table object and returns a table object. In order to chain them, the functions are called using the return values of the previous functions.&lt;/p&gt;

&lt;p&gt;For example, to chain a range operation off the &lt;code class="language-markup"&gt;from&lt;/code&gt; operation it looks like this:&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-markup"&gt;range(table:from(db:"telegraf"), start:-1m)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nesting functions in this way has the potential to result in a very long query which is difficult to read and even harder to debug. That is why we have introduced a new syntax to the language to make it easier to describe these chains of operations. The pipe forward operator looks like this &lt;code class="language-markup"&gt;|&amp;gt;&lt;/code&gt; and allows chaining functions by passing the left hand result to the right hand function call.&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-markup"&gt;// These two lines are equivalent
range(table:from(db:"telegraf"), start:-1m)
from(db:"telegraf") |&amp;gt; range(start: -1m)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then to apply a filter to the above operations simply add a new &lt;code class="language-markup"&gt;|&amp;gt;&lt;/code&gt; and &lt;code class="language-markup"&gt;filter&lt;/code&gt; function call.&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-markup"&gt;from(db:"telegraf") |&amp;gt; range(start: -1m) |&amp;gt; filter(fn: (r) =&amp;gt; r._measurement == "mem")
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By using this simple model it becomes easy for new functions to be added to the language (both built-in and by the user), that are really just a combination of existing functions. For example, the &lt;code class="language-markup"&gt;top&lt;/code&gt; operation is a combination of the sort and limit operations. As such the &lt;code class="language-markup"&gt;top&lt;/code&gt; function can be implemented using this small Flux code snippet:&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-markup"&gt;top = (n, cols=["_value"], table=&amp;lt;-) =&amp;gt;
    table
        |&amp;gt; sort(cols:cols, desc:true)
        |&amp;gt; limit(n:n)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The top function is defined as having three arguments &lt;code class="language-markup"&gt;n&lt;/code&gt;, &lt;code class="language-markup"&gt;cols&lt;/code&gt;, and &lt;code class="language-markup"&gt;table&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code class="language-markup"&gt;n&lt;/code&gt; argument specifies how many records the result should contain.&lt;/p&gt;

&lt;p&gt;The &lt;code class="language-markup"&gt;cols&lt;/code&gt; argument specifies the list of columns on which to sort the table—it has a default of &lt;code class="language-markup"&gt;["_value"]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code class="language-markup"&gt;table&lt;/code&gt; argument is the source table on which to apply the operation. The table’s default value is the special &lt;code class="language-markup"&gt;&amp;lt;-&lt;/code&gt; syntax, meaning that it comes from the left hand result of the pipe forward &lt;code class="language-markup"&gt;|&amp;gt;&lt;/code&gt; operator.&lt;/p&gt;

&lt;p&gt;The function body simply chains the sort and limit functions off the table with the provided arguments.&lt;/p&gt;

&lt;p&gt;Many of the new functions in this release have been implemented using a similar strategy. If you want to learn more about these more advanced features check out the Flux &lt;a href="https://github.com/influxdata/flux/blob/master/README.md"&gt;README&lt;/a&gt; as it details what is going on here. Also, some of you may be concerned that implementing &lt;code class="language-markup"&gt;top&lt;/code&gt; as a sort and limit operation is expensive and slow. You are right, but do not worry as the query planner is able to find these kinds of patterns and rewrite them with a specialized implementation that is efficient.&lt;/p&gt;

&lt;p&gt;I’d like to highlight one other new function in this release, the &lt;code class="language-markup"&gt;percentile&lt;/code&gt; function. It has long been a &lt;a href="https://github.com/influxdata/influxdb/issues/513"&gt;requested feature&lt;/a&gt; to be able to compute percentiles more efficiently using an approximation method instead of computing exact values.&lt;/p&gt;

&lt;p&gt;The Flux percentile function by default will return a &lt;a href="https://github.com/tdunning/t-digest"&gt;t-digest&lt;/a&gt; approximation unless explicitly asked to compute the exact percentile. The t-digest is an efficient and accurate method for approximating percentiles. Using Flux, the default will be to compute results efficiently by returning good approximations and returning exact results when specifically requested.&lt;/p&gt;

&lt;p&gt;This has been a busy release with lots of great additions and development – check out the complete &lt;a href="https://github.com/influxdata/flux" target="_blank" rel="noopener"&gt;CHANGELOG&lt;/a&gt; for all the details. Thanks to all who contributed valuable input throughout the design process this week. We are excited to hear your feedback on the &lt;a href="https://github.com/influxdata/flux" target="_blank" rel="noopener"&gt;Github project&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Tue, 27 Feb 2018 11:31:35 -0700</pubDate>
      <link>https://www.influxdata.com/blog/announcing-ifql-v0-0-5-with-12-new-functions/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/announcing-ifql-v0-0-5-with-12-new-functions/</guid>
      <category>Product</category>
      <category>Developer</category>
      <author>Nathaniel Cook (InfluxData)</author>
    </item>
    <item>
      <title>Announcing Flux (formerly IFQL) v0.0.4</title>
      <description>&lt;p&gt;We recently released v0.0.4 of IFQL - Influx Query Language [now called Flux]. With the holidays at the end of the year, we were a little slow getting this release out. Going forward, we expect to release every two weeks. This release has some exciting developments, focused almost entirely in new features for the Flux language itself. Here is a quick list of highlights:&lt;/p&gt;
&lt;ul&gt;
 	&lt;li&gt;Support for defining/calling functions within Flux&lt;/li&gt;
 	&lt;li&gt;Several new built-in functions: map, shift, integral, derivative and difference&lt;/li&gt;
 	&lt;li&gt;Support for multiple values, with the covariance function being the first function to use multiple values&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Adding support for functions into the language enables users to create small reusable components in their queries, building up libraries over time of useful snippets. Functions are also used when logic needs to be applied to the records of the data. Functions replace the previous expressions with a clear well-scoped function to evaluate. We hope you find them to be a clear and powerful tool. A Flux function follows this syntax:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-markup"&gt;(parameter list) =&amp;gt; &amp;lt;function body&amp;gt;&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Example function which adds two values:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-markup"&gt;// define the function add
add = (a,b) =&amp;gt; a + b
// call the add function
add(a:1, b:5) // 6&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here is an example of functions in action:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-markup"&gt;// serviceData gets the field from the requests measurement for a given service.
serviceData = (service,field) =&amp;gt;
    from(db:"myapp")
        // Use an anonymous function as the filter predicate, where "r" is the record.
        .filter(fn: (r) =&amp;gt; r._measurement == "requests" and r._service == service and r._field == field)
// We want the last hour of data
start = -1h
// Get the requests for the "cart" service
reqs = serviceData(service:"cart", field:"requests").range(start:start)
// Get the errors for the "cart" service
errs = serviceData(service:"cart", field:"errors").range(start:start)
// Compute the correlation between the reqs and errs for the "cart" service
pearsonr(x:reqs, y:errs, on:["region"])&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above script will compute the pearson correlation coefficient between errors and requests of the cart service for the past hour. Interestingly the &lt;code&gt;pearsonr&lt;/code&gt; function is defined using native Flux functions and is built into the language. Here is a look at the definition of &lt;code&gt;pearsonr&lt;/code&gt; as it appears in the source.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-markup"&gt;// Covariance computes the covariance between x and y.
covariance = (x,y,on,pearsonr=false) =&amp;gt;
    join(
        tables:{x:x, y:y},
        on:on,
        fn: (t) =&amp;gt; ({x:t.x._value, y:t.y._value}),
    )
    .covariance(pearsonr:pearsonr)


// Pearsonr computes the Pearson R correlation coefficient of x and y.
pearsonr = (x,y,on) =&amp;gt; covariance(x:x, y:y, on:on, pearsonr:true)&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;pearsonr&lt;/code&gt; function is really just the &lt;code&gt;covariance&lt;/code&gt; function with the &lt;code&gt;pearsonr&lt;/code&gt; argument set to &lt;code&gt;true&lt;/code&gt;. The &lt;code&gt;covariance&lt;/code&gt; function in turn is a &lt;code&gt;join&lt;/code&gt; operation which joins the x and y tables before passing the data to the &lt;code&gt;covariance&lt;/code&gt; method which computes the actual covariance between the multiple values on the joined table. Over time, more functions will be added to the language, and we hope that these built-in functions can be a good source of examples for new users.&lt;/p&gt;

&lt;p&gt;We are excited about the power that functions and multiple value support will bring to Flux. Have any feedback or want to see support for a certain function? Open an issue or pull request on the Flux &lt;a href="https://github.com/influxdata/flux" target="_blank" rel="noopener"&gt;repo&lt;/a&gt;. For a full list of changes in v0.0.4, see the &lt;a href="https://github.com/influxdata/flux" target="_blank" rel="noopener"&gt;CHANGELOG&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Mon, 22 Jan 2018 09:00:41 -0700</pubDate>
      <link>https://www.influxdata.com/blog/announcing-ifql-v0-0-4/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/announcing-ifql-v0-0-4/</guid>
      <category>Product</category>
      <category>Use Cases</category>
      <category>Developer</category>
      <author>Nathaniel Cook (InfluxData)</author>
    </item>
    <item>
      <title>Announcing Flux (formerly IFQL) v0.0.3</title>
      <description>&lt;p&gt;The Flux (formerly IFQL) team releases a new version every two weeks. We want to get our changes into the hands of our community quickly so we can hear of your experiences early. Please submit issues and PRs on the &lt;a href="https://github.com/influxdata/flux"&gt;repo&lt;/a&gt;. Check out the &lt;a href="https://w2.influxdata.com/blog/announcing-ifql-a-new-query-language-and-engine-for-influxdb/"&gt;Flux release announcement&lt;/a&gt; for details on the vision behind Flux .&lt;/p&gt;

&lt;p&gt;These last two weeks we have focused on performance and resource management (i.e. managing CPU and memory resources so that a single query cannot overwhelm the Flux process).&lt;/p&gt;

&lt;h2&gt;Benchmarking&lt;/h2&gt;

&lt;p&gt;We have put together benchmarks comparing Flux to InfluxQL. These benchmarks have been put in place early so that we can ensure going forward in continuing to maintain strong performance. Here are some initial charts showing where Flux is compared to equivalent InfluxQL queries.&lt;/p&gt;

&lt;p&gt;Five representative queries have been run on both systems&lt;sup&gt;1&lt;/sup&gt;. To see details of the benchmarks, check out the PR.&lt;/p&gt;

&lt;p&gt;Here are the five queries:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Query #1&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-markup"&gt;IFQL - from(db:"db").range(start:2017-11-01T00:00:00Z, stop:2017-11-02T00:00:00Z).filter(exp:{"_measurement" == "m0" and "_field" == "v0" and $ &amp;gt; 0}).sum()
InfluxQL - SELECT sum(v0) FROM m0 WHERE time &amp;gt;= 2017-11-01T00:00:00Z AND time &amp;lt; 2017-11-02T00:00:00Z AND v0 &amp;gt; 0 GROUP BY *&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Query #2&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-markup"&gt;IFQL - from(db:"db").range(start:2017-11-01T00:00:00Z, stop:2017-11-05T00:00:00Z).filter(exp:{"_measurement" == "m0" and "_field" == "v0" and $ &amp;gt; 0}).sum()
InfluxQL - SELECT sum(v0) FROM m0 WHERE time &amp;gt;= 2017-11-01T00:00:00Z AND time &amp;lt; 2017-11-05T00:00:00Z AND v0 &amp;gt; 0 GROUP BY *&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Query #3&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-markup"&gt;IFQL - from(db:"db").range(start:2017-11-01T00:00:00Z, stop:2017-11-05T00:00:00Z).filter(exp:{"_measurement" == "m0" and "_field" == "v0" and $ &amp;gt; 0}).group(by:["tag0"]).sum()
InfluxQL - SELECT sum(v0) FROM m0 WHERE time &amp;gt;= 2017-11-01T00:00:00Z AND time &amp;lt; 2017-11-05T00:00:00Z AND v0 &amp;gt; 0 GROUP BY tag0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Query #4&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-markup"&gt;IFQL - from(db:"db").range(start:2017-11-01T00:00:00Z, stop:2017-11-13T00:00:00Z).filter(exp:{"_measurement" == "m0" and "_field" == "v0" and $ &amp;gt; 0}).sum()
InfluxQL - SELECT sum(v0) FROM m0 WHERE time &amp;gt;= 2017-11-01T00:00:00Z AND time &amp;lt; 2017-11-13T00:00:00Z AND v0 &amp;gt; 0 GROUP BY *&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Query #5&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-markup"&gt;IFQL - from(db:"db").range(start:2017-11-01T00:00:00Z, stop:2017-11-13T00:00:00Z).filter(exp:{"_measurement" == "m0" and "_field" == "v0" and $ &amp;gt; 0}).group(by:["tag0"]).sum()
InfluxQL - SELECT sum(v0) FROM m0 WHERE time &amp;gt;= 2017-11-01T00:00:00Z AND time &amp;lt; 2017-11-13T00:00:00Z AND v0 &amp;gt; 0 GROUP BY tag0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First, let’s look at execution time as that is most important when considering the performance of a query engine.&lt;/p&gt;

&lt;p&gt;&lt;img class="alignnone size-full wp-image-210240" src="/images/legacy-uploads/query-execution-time.png" alt="" width="920" height="545" /&gt;&lt;/p&gt;

&lt;p&gt;For most queries, Flux is already faster than InfluxQL. Note Query #4 did not complete using InfluxQL and so has no time. We have an &lt;a href="https://github.com/influxdata/flux/issues" target="_blank" rel="noopener"&gt;issue&lt;/a&gt; open already that should improve Query #5.&lt;/p&gt;

&lt;p&gt;Next examining the heap usage of the processes, we can see that Flux is significantly more efficient in its usage.&lt;/p&gt;

&lt;p&gt;&lt;img class="alignnone size-full wp-image-210241" src="/images/legacy-uploads/max-heap.png" alt="" width="902" height="541" /&gt;&lt;/p&gt;

&lt;p&gt;The heap usage of both ifql processes barely registers in comparison to the heap usage of InfluxQL. Note, there are two ifql processes, ifqld which can be any number of sidecar processes, and influxd running with the new IFQL API enabled.&lt;/p&gt;

&lt;h2&gt;Resource Management&lt;/h2&gt;

&lt;p&gt;With version v0.0.3, it is now possible to limit the resources a query consumes. Our goal is to ensure that primarily a really hungry query can’t crash the process and secondarily the hungry query will fairly share resources with other concurrent queries according to its priority.&lt;/p&gt;

&lt;p&gt;Now with these limits in place, a bad query that tries to consume too much memory is killed and an appropriate error is returned, instead of allowing the query to crash the process.&lt;/p&gt;

&lt;p&gt;We also ran tests comparing v0.0.2 with v0.0.3. The test submitted more queries than the processes had resources. We then compared the execution times of the queries and could see that v0.0.3 reduced the overall execution time by 15%. This is accomplished by queuing and scheduling the work instead of letting all the queries concurrently fight over resources. The long tail latencies increase in v0.0.3 because of the queueing, but we have a plan to solve that issue later.&lt;/p&gt;

&lt;p&gt;Overall v0.0.3 is a solid iterative release, and we will see you again in two weeks with another release. For a complete list of all changes see the CHANGELOG.&lt;/p&gt;

&lt;h2&gt;Footnotes:&lt;/h2&gt;

&lt;p&gt;[1] Note that InfluxDB master now has a Prometheus “/metrics” endpoint we used to collect these stats. We also used a new tool &lt;a href="https://github.com/influxdata/ingen"&gt;ingen&lt;/a&gt; to create the test datasets.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;
</description>
      <pubDate>Wed, 13 Dec 2017 06:05:36 -0700</pubDate>
      <link>https://www.influxdata.com/blog/announcing-ifql-v0-0-3/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/announcing-ifql-v0-0-3/</guid>
      <category>Product</category>
      <category>Use Cases</category>
      <category>Developer</category>
      <author>Nathaniel Cook (InfluxData)</author>
    </item>
    <item>
      <title>Announcing Kapacitor 1.0 - A Data Processing Engine for InfluxDB</title>
      <description>&lt;p&gt;&lt;span style="font-weight: 400;"&gt;Kapacitor 1.0 GA is &lt;/span&gt;&lt;a href="https://w2.influxdata.com/downloads/"&gt;&lt;span style="font-weight: 400;"&gt;here&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt;. Kapacitor is the brains of the TICK stack. You can leverage Kapacitor to process your data for various business needs and use it to find changes or anomalies within your time series data. We have come a long way since the 0.13.1 release of Kapacitor back in mid May 2016. Since then, we’ve added &lt;/span&gt;&lt;a href="https://github.com/influxdata/kapacitor/blob/master/CHANGELOG.md"&gt;&lt;span style="font-weight: 400;"&gt;33 new features and 42 bug fixes&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt;. We had many PRs from the community, from simple bug fixes to major features. Thanks to everyone for helping improve Kapacitor!&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;&lt;b&gt;What's new?&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span style="font-weight: 400;"&gt;Of the new features in 1.0 there are eight we want to highlight, three of which are community contributions…&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
 	&lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;&lt;strong&gt;HTTP based subscriptions:&lt;/strong&gt; Goodbye to the complexity of managing a unique UDP port per database, HTTP subscription are here and provide a simpler, more reliable transport from InfluxDB to Kapacitor.&lt;/span&gt;&lt;/li&gt;
 	&lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;&lt;strong&gt;Template Tasks:&lt;/strong&gt; You can now define templates so that multiple tasks that share common behavior can easily be managed together.&lt;/span&gt;&lt;/li&gt;
 	&lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;&lt;a href="https://docs.influxdata.com/influxdb/v1.0/query_language/functions/#holt-winters"&gt;Holt-Winters Forecasting&lt;/a&gt;:&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; Start using Kapacitor for more complex anomaly detection tasks, Holt-Winters is the first of many powerful algorithms to be added to the TICK stack.&lt;/span&gt;&lt;/li&gt;
 	&lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;&lt;strong&gt;Alert Reset Expressions:&lt;/strong&gt; Noise from alerts is a plague. Thanks to &lt;/span&gt;&lt;a href="https://github.com/minhdanh?tab=activity"&gt;&lt;span style="font-weight: 400;"&gt;@minhdanh&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt;, you can now define reset expressions for your alert levels to reduce alert noise.&lt;/span&gt;&lt;/li&gt;
 	&lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;&lt;strong&gt;Group By Fields:&lt;/strong&gt; Convert any field into a tag so that you can use it to group your data streams.&lt;/span&gt;&lt;/li&gt;
 	&lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;&lt;strong&gt;Telegram Alerting:&lt;/strong&gt; You can now send messages to Telegram thanks to &lt;/span&gt;&lt;a href="https://github.com/burdandrei?tab=activity"&gt;&lt;span style="font-weight: 400;"&gt;@burdandrei&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt;.&lt;/span&gt;&lt;/li&gt;
 	&lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;&lt;strong&gt;Better and Faster Lambda Expressions:&lt;/strong&gt; &lt;/span&gt;&lt;a href="https://github.com/yosiat"&gt;&lt;span style="font-weight: 400;"&gt;@yosiat&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt; greatly improved the performance of lambda expressions and added support for conditional logic.&lt;/span&gt;&lt;/li&gt;
 	&lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;&lt;strong&gt;Live Replays:&lt;/strong&gt; Replay data directly from InfluxDB without going through any intermediate steps.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!--more--&gt;
&lt;h2&gt;&lt;b&gt;Beyond 1.0&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span style="font-weight: 400;"&gt;On the roadmap are improvements to alert management, UDF snapshots and more powerful algorithms. We plan to add API endpoints where you can query the state of alerts. Snapshots are going to be revamped so that your UDFs can easily save their state and even restore from a previous version. This will make saving your trained models a simple managed process within Kapacitor. For more details on what we are planning check out the planned &lt;/span&gt;&lt;a href="https://github.com/influxdata/kapacitor/milestones"&gt;&lt;span style="font-weight: 400;"&gt;milestones&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;&lt;b&gt;What's next&lt;/b&gt;&lt;/h2&gt;
&lt;ul&gt;
 	&lt;li style="font-weight: 400;"&gt;&lt;b&gt;Download:&lt;/b&gt;&lt;span style="font-weight: 400;"&gt; 1.0 GA &lt;/span&gt;&lt;a href="https://w2.influxdata.com/downloads/"&gt;&lt;span style="font-weight: 400;"&gt;downloads&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt; for the TICK-stack are live on our "downloads" page&lt;/span&gt;&lt;/li&gt;
 	&lt;li style="font-weight: 400;"&gt;&lt;b&gt;Deploy on the Cloud: &lt;/b&gt;&lt;span style="font-weight: 400;"&gt;Get started with a FREE trial of &lt;/span&gt;&lt;a href="https://cloud.influxdata.com/"&gt;&lt;span style="font-weight: 400;"&gt;InfluxDB Cloud&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt; featuring fully-managed clusters, Kapacitor and Grafana.&lt;/span&gt;&lt;/li&gt;
 	&lt;li style="font-weight: 400;"&gt;&lt;b&gt;Deploy on Your Servers: &lt;/b&gt;&lt;span style="font-weight: 400;"&gt;Want to run InfluxDB clusters on your servers? Try a FREE 14-day trial of &lt;/span&gt;&lt;a href="https://portal.influxdata.com/"&gt;&lt;span style="font-weight: 400;"&gt;InfluxDB Enterprise&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt; featuring an intuitive UI for deploying, monitoring and rebalancing clusters, plus managing backups and restores. &lt;/span&gt;&lt;/li&gt;
 	&lt;li style="font-weight: 400;"&gt;&lt;b&gt;Tell Your Story:&lt;/b&gt; &lt;a href="https://w2.influxdata.com/testimonials/"&gt;&lt;span style="font-weight: 400;"&gt;Over 100 companies&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt; have shared their story on how InfluxDB is helping them succeed. Submit your testimonial and get a limited edition InfluxDB hoodie as a thank you.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
      <pubDate>Thu, 08 Sep 2016 03:15:47 -0700</pubDate>
      <link>https://www.influxdata.com/blog/announcing-kapacitor-1-0-a-data-processing-engine-for-influxdb/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/announcing-kapacitor-1-0-a-data-processing-engine-for-influxdb/</guid>
      <category>Use Cases</category>
      <category>Product</category>
      <author>Nathaniel Cook (InfluxData)</author>
    </item>
    <item>
      <title>Combining Kapacitor and Continuous Queries</title>
      <description>&lt;p&gt;&lt;a href="https://w2.influxdata.com/time-series-platform/kapacitor/"&gt;Kapacitor&lt;/a&gt; can be used to do the same work as Continuous Queries in InfluxDB. Today we are going to explore reasons to use one over the other, Kapacitor vs Continuous Queries, and the basics of using Kapacitor for CQ type workloads.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What’s Kapacitor? It’s the “K” in the TICK stack. Kapacitor is InfluxDB’s native data processing engine. It can process both stream and batch data from InfluxDB. Kapacitor lets you plug in your own custom logic or user defined functions to process alerts with dynamic thresholds, match metrics for patterns or compute statistical anomalies.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="an-example"&gt;An Example&lt;/h2&gt;
&lt;p&gt;First, lets take a simple CQ and rewrite it as a Kapacitor TICKscript.&lt;/p&gt;

&lt;p&gt;Here is a CQ that computes the mean of the &lt;code&gt;cpu.usage_idle&lt;/code&gt; every 5m and stores it in the new measurement &lt;code&gt;mean_cpu_idle&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-markup"&gt;CREATE CONTINUOUS QUERY cpu_idle_mean ON telegraf BEGIN SELECT mean("usage_idle") as usage_idle INTO mean_cpu_idle FROM cpu GROUP BY time(5m),* END&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To do the same with Kapacitor here is a streaming TICKscript.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-markup"&gt;stream
    |from()
        .database('telegraf')
        .measurement('cpu')
        .groupBy(*)
    |window()
        .period(5m)
        .every(5m)
        .align()
    |mean('usage_idle')
        .as('usage_idle')
    |influxDBOut()
        .database('telegratelegraff')
        .retentionPolicy('default')
        .measurement('mean_cpu_idle')
        .precision('s')&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The same thing can also be done as a batch task in Kapacitor.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-markup"&gt;batch
    |query('SELECT mean(usage_idle) as usage_idle FROM "telegraf"."default".cpu')
        .period(5m)
        .every(5m)
        .groupBy(*)
    |influxDBOut()
        .database('telegraf')
        .retentionPolicy('default')
        .measurement('mean_cpu_idle')
        .precision('s')&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All three of these methods will produce the same results.&lt;/p&gt;
&lt;h2&gt;&lt;!--more--&gt;Questions&lt;/h2&gt;
&lt;p&gt;At this point there are a few questions we should answer:&lt;/p&gt;
&lt;ul&gt;
 	&lt;li&gt;When should we use Kapacitor instead of CQs?&lt;/li&gt;
 	&lt;li&gt;When should we use stream tasks vs batch tasks in Kapacitor?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="when-should-we-use-kapacitor-instead-of-cqs"&gt;When should we use Kapacitor instead of CQs?&lt;/h2&gt;
&lt;p&gt;There are a few reasons to use Kapacitor instead of CQs.&lt;/p&gt;
&lt;ul&gt;
 	&lt;li&gt;You are performing a significant number of CQs and want to isolate the work load. By using Kapacitor to perform the aggregations InfluxDB's performance profile can remain more stable and isolated from Kapacitor's.&lt;/li&gt;
 	&lt;li&gt;You need to do more than just perform a query, for example maybe you only want to store only outliers from an aggregation instead of all of them. Kapacitor can do significantly more with the data than CQs so you have more flexibility in transforming your data.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are a few use cases where using CQs almost always makes sense.&lt;/p&gt;
&lt;ul&gt;
 	&lt;li&gt;Performing downsampling for retention policies. This is what CQs are designed for and do well. No need to add another moving piece (i.e. Kapacitor) to your infrastructure if you do not need it. Keep it simple.&lt;/li&gt;
 	&lt;li&gt;You only have a handful of CQs, again keep it simple, do not add more moving parts to your setup unless you need it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="when-should-we-use-stream-tasks-vs-batch-tasks-in-kapacitor"&gt;When should we use stream tasks vs batch tasks in Kapacitor?&lt;/h2&gt;
&lt;p&gt;Basically the answer boils down to two things, the available RAM and time period being used.&lt;/p&gt;

&lt;p&gt;A stream task will have to keep all data in RAM for the specified period. If this period is too long for the available RAM then you will first need to store the data in InfluxDB and then query using a batch task. A stream task does have one slight advantage in that since its watching the stream of data it understands time by the timestamps on the data. As such there are no race conditions for whether a given point will make it into a window or not. If you are using a batch task it is still possible for a point to arrive late and be missed in a window.&lt;/p&gt;
&lt;h2 id="wmd-preview-section-43" class="wmd-preview-section preview-content"&gt;Another example: Create a continuous query to down sample across retention policies&lt;/h2&gt;
&lt;pre&gt;&lt;code class="language-markup"&gt;CREATE CONTINUOUS QUERY cpu_idle_median ON telegraf BEGIN SELECT median("usage_idle") as usage_idle INTO "telegraf"."sampled_5m"."median_cpu_idle" FROM "telegraf"."default"."cpu" GROUP BY time(5m),* END&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The stream TICKscript:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-markup"&gt;stream
    |from()
        .database('telegraf')
        .retentionPolicy('default')
        .measurement('cpu')
        .groupBy(*)
    |window()
        .period(5m)
        .every(5m)
        .align()
    |median('usage_idle')
        .as('usage_idle')
    |influxDBOut()
        .database('telegraf')
        .retentionPolicy('sampled_5m')
        .measurement('median_cpu_idle')
        .precision('s')&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the batch TICKscript:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-markup"&gt;batch
    |query('SELECT median(usage_idle) as usage_idle FROM "telegraf"."default"."cpu"')
        .period(5m)
        .every(5m)
        .groupBy(*)
    |influxDBOut()
        .database('telegraf')
        .retentionPolicy('sampled_5m')
        .measurement('median_cpu_idle')
        .precision('s')&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="summary"&gt;Summary&lt;/h2&gt;
&lt;p&gt;Kapacitor is a powerful tool, if you need more power use it. If not keep using CQs until you do. For more information and help writing TICKscripts from InfluxQL queries take a looks at these &lt;a href="https://docs.influxdata.com/kapacitor/latest/nodes/influx_q_l_node/"&gt;docs&lt;/a&gt; on the InfluxQL node in Kapacitor. Every function available in the InfluxDB query language is available in Kapacitor, so you can convert any query into a Kapacitor TICKscript.&lt;/p&gt;
&lt;h2&gt;What's next&lt;/h2&gt;
&lt;ul&gt;
 	&lt;li&gt;&lt;a href="https://w2.influxdata.com/downloads/#influxdb" target="_blank" rel="noopener"&gt;Download&lt;/a&gt; of the TICK stack!&lt;/li&gt;
 	&lt;li&gt;Need help migrating from 0.8x or 0.9x to 0.11? We are here to help! Drop us a line at &lt;a href="https://w2.influxdata.com/contact-us/contact-sales/" target="_blank" rel="noopener"&gt;contact@influxdata.com&lt;/a&gt; to get your migration project started.&lt;/li&gt;
 	&lt;li&gt;Looking to level up your InfluxDB knowledge? Check out our FREE and economically priced &lt;a href="https://w2.influxdata.com/virtual-training-courses/" target="_blank" rel="noopener"&gt;virtual&lt;/a&gt; and &lt;a href="https://w2.influxdata.com/public-training-events/" target="_blank" rel="noopener"&gt;public&lt;/a&gt; trainings.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt; &lt;/p&gt;
</description>
      <pubDate>Tue, 10 May 2016 06:00:56 -0700</pubDate>
      <link>https://www.influxdata.com/blog/combining-kapacitor-and-continous-queries/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/combining-kapacitor-and-continous-queries/</guid>
      <category>Product</category>
      <author>Nathaniel Cook (InfluxData)</author>
    </item>
    <item>
      <title>Announcing Kapacitor 0.11 RC with Big Performance Gains and Simplified API</title>
      <description>&lt;p&gt;We are excited to announce that &lt;a href="/downloads/"&gt;Kapacitor v0.11 RC&lt;/a&gt; is here with big changes. Kapacitor is significantly more performant, exposes internal performance metrics, and has a simplified API for working with functions from InfluxQL.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;What's Kapacitor?&lt;/strong&gt;
&lt;strong&gt; Kapacitor is InfluxDB's native data processing engine. It can process both stream and batch data from InfluxDB. Kapacitor lets you plug in your own custom logic or user defined functions to process alerts with dynamic thresholds, match metrics for patterns or compute statistical anomalies.&lt;/strong&gt;&lt;/blockquote&gt;
&lt;p&gt;Much of the effort that went into this release was on improving the performance of Kapacitor and providing users the needed tools to right-size their Kapacitor instance. Kapacitor is now up to 4x faster in some cases. A user can now also get stats about how fast their task is running and which steps are slowest. With this data now readily available, a user can now decide how large to make a Kapacitor instance, eliminating any guesswork.&lt;/p&gt;

&lt;p&gt;In order to make Kapacitor easier to use we have changed the way TICKscripts use functions from InfluxQL. Now you can write:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-markup"&gt;`stream.from().measurement(...)
.window().period(1m).every(1m)
.count('value')`&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;…directly instead of having to use the mapReduce function. The old syntax will continue to work throughout this release, but will be dropped in version 0.12.&lt;/p&gt;

&lt;p&gt;Kapacitor can also communicate with multiple InfluxDB clusters. Update the configuration with multiple InfluxDB sections and specify which cluster to use in the TICKscript. With this simple addition, Kapacitor can now act as a Continuous Query engine between different InfluxDB clusters.&lt;/p&gt;

&lt;h2&gt;What's next&lt;/h2&gt;

&lt;ul&gt;
 	&lt;li&gt;Get started with Kapacitor &lt;a href="https://docs.influxdata.com/kapacitor/v0.10/" target="_blank" rel="noopener"&gt;here&lt;/a&gt; and check out the official release notes &lt;a href="https://github.com/influxdata/kapacitor/blob/master/CHANGELOG.md" target="_blank" rel="noopener"&gt;here&lt;/a&gt;.&lt;/li&gt;
 	&lt;li&gt;Looking to level up your InfluxDB knowledge? Check out our economically priced &lt;a href="/university/" target="_blank" rel="noopener"&gt;virtual trainings&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</description>
      <pubDate>Tue, 15 Mar 2016 13:36:41 -0700</pubDate>
      <link>https://www.influxdata.com/blog/announcing-kapacitor-0-11-rc-with-big-performance-gains-and-simplified-api/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/announcing-kapacitor-0-11-rc-with-big-performance-gains-and-simplified-api/</guid>
      <category>Product</category>
      <author>Nathaniel Cook (InfluxData)</author>
    </item>
    <item>
      <title>Announcing Kapacitor v0.10: Support for Custom Functions, More Integrations and a Dead Man's Switch</title>
      <description>&lt;p&gt;&lt;span style="font-weight: 400;"&gt;Since the &lt;/span&gt;&lt;a href="https://www.influxdata.com/blog/announcing-kapacitor-an-open-source-streaming-and-batch-time-series-processor/"&gt;&lt;span style="font-weight: 400;"&gt;initial release&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt; of Kapacitor v0.10 in December of last year there have been a few common themes among the community on what features they’d most like to see…&lt;/span&gt;&lt;/p&gt;

&lt;h2&gt;Custom User Functions &amp;amp; Anomaly Detection&lt;/h2&gt;

&lt;p&gt;This release gives users the ability to write custom functions in any programming language. This is done via a Protocol Buffer RPC system with Kapacitor managing the running process. If your language supports Protobuf serialization, you’ll be able to write custom monitoring, alerting, and processing code that can be injected into your TICKScripts.&lt;/p&gt;

&lt;p&gt;&lt;span style="font-weight: 400;"&gt;The big news is that you can now do more advanced anomaly detection with Kapacitor through these User Defined Functions (UDFs). It is now possible to integrate any new or existing algorithm with Kapacitor via UDFs. Check out this &lt;/span&gt;&lt;a href="https://docs.influxdata.com/kapacitor/v0.10/examples/anomaly_detection"&gt;&lt;span style="font-weight: 400;"&gt;guide&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt; to get started integrating your favorite anomaly detection algorithm with Kapacitor.&lt;/span&gt;&lt;/p&gt;

&lt;div style="padding:56.25% 0 0 0;position:relative; margin: 30px 0;"&gt;&lt;iframe src="https://player.vimeo.com/video/153160237?badge=0&amp;amp;autopause=0&amp;amp;quality_selector=1&amp;amp;player_id=0&amp;amp;app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" style="position:absolute;top:0;left:0;width:100%;height:100%;" title="How to Create User Defined Functions in Kapacitor for InfluxDB"&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;script src="https://player.vimeo.com/api/player.js"&gt;&lt;/script&gt;

&lt;h2&gt;Integrations&lt;/h2&gt;

&lt;p&gt;&lt;span style="font-weight: 400;"&gt;Secondly, we have had lots of attention on alerting integrations. Thanks to the community Kapacitor can now send alerts to &lt;/span&gt;&lt;a href="https://www.hipchat.com/"&gt;&lt;span style="font-weight: 400;"&gt;HipChat&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt;, &lt;/span&gt;&lt;a href="https://www.opsgenie.com/"&gt;&lt;span style="font-weight: 400;"&gt;OpsGenie&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt;, &lt;/span&gt;&lt;a href="http://alerta.readthedocs.org/en/latest/"&gt;&lt;span style="font-weight: 400;"&gt;Alerta&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt; and &lt;/span&gt;&lt;a href="https://sensu.io/" target="_blank" rel="noopener"&gt;&lt;span style="font-weight: 400;"&gt;Sensu&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt; in addition to previous integrations with &lt;/span&gt;&lt;a href="https://www.pagerduty.com/"&gt;&lt;span style="font-weight: 400;"&gt;PagerDuty&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt;, &lt;/span&gt;&lt;a href="https://slack.com/"&gt;&lt;span style="font-weight: 400;"&gt;Slack&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt; and &lt;/span&gt;&lt;a href="https://victorops.com/"&gt;&lt;span style="font-weight: 400;"&gt;VictorOps&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt;. If you want to integrate with yet another alerting system check out these &lt;/span&gt;&lt;a href="https://github.com/influxdata/kapacitor/pulls?utf8=%E2%9C%93&amp;amp;q=is%3Apr+139+125+160"&gt;&lt;span style="font-weight: 400;"&gt;PRs&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt; as they layout how easy it is.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="font-weight: 400;"&gt;In addition there have been a dozen bug fixes and another dozen new features, most around improving the alerting experience within Kapacitor. Check out the &lt;/span&gt;&lt;a href="https://github.com/influxdata/kapacitor"&gt;&lt;span style="font-weight: 400;"&gt;release notes&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt; for a complete list of features since the last major release.&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;Dead Man's Switch&lt;span style="font-weight: 400;"&gt;
&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span style="font-weight: 400;"&gt;Lastly, people naturally wanted to know if their task stopped receiving data. We have built in a &lt;/span&gt;&lt;a href="https://en.wikipedia.org/wiki/Dead_man%27s_switch"&gt;&lt;span style="font-weight: 400;"&gt;dead man’s switch&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt;, that can be configured by individual task or globally for all tasks, that will trigger an alert if a task doesn’t receive data for a configurable duration. See this &lt;/span&gt;&lt;a href="https://github.com/influxdata/kapacitor/pull/149"&gt;&lt;span style="font-weight: 400;"&gt;PR&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt; for details.&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;Where is Kapacitor going from here?&lt;span style="font-weight: 400;"&gt;
&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span style="font-weight: 400;"&gt;For the next release we are focusing on two areas. First, more integrations for UDFs, we want to make it easy to plugin your algorithms in whatever language you are using. Second, we are focusing on stability and performance. Kapacitor is a young project but we already like the foundation it has built and are ready to take it to the next level. We will be designing a set of benchmarks and failure tests suites for Kapacitor to ensure ongoing stability and performance.&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;
&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="font-weight: 400;"&gt;We want to be able to make strong statements about how Kapacitor behaves under real load, &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;and to be able to definitively answer questions around instance sizing and resource consumption.&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;What's next?&lt;/h2&gt;
&lt;ul&gt;
 	&lt;li style="font-weight: 400;"&gt;&lt;a href="https://docs.influxdata.com/kapacitor/v0.10/introduction/getting_started/"&gt;&lt;span style="font-weight: 400;"&gt;Download the code and get started&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
 	&lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Visit the &lt;/span&gt;&lt;a href="https://github.com/influxdata/kapacitor"&gt;&lt;span style="font-weight: 400;"&gt;Kapacitor project on GitHub&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt; to report a bug, make a feature request or better yet contribute some code!&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
      <pubDate>Thu, 28 Jan 2016 11:00:55 -0700</pubDate>
      <link>https://www.influxdata.com/blog/announcing-kapacitor-v0-10-udfs/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/announcing-kapacitor-v0-10-udfs/</guid>
      <category>Product</category>
      <author>Nathaniel Cook (InfluxData)</author>
    </item>
  </channel>
</rss>
