Make compatible with kibana core

This commit is contained in:
Rashid Khan 2016-08-12 14:14:04 -07:00
parent 3a7ce2fc85
commit efec20e1cd
14 changed files with 48 additions and 5861 deletions

View file

@ -1,18 +0,0 @@
## How do I contribute code?
Welp, its going to be up to you to figure this one out, but you're going to have to get a dev environment going. Jump on IRC and we can help you with this! You'll find most functionality is related to functions and data sources, and adding those is pretty self explanitory.
## Cutting a release
I'm going to assume if you're reading this part, then you work at Elastic. Good for you. You will need:
1. gulp
1. `~/.aws-config.json`
**Tip for Kibana 5.0+ releases**: You'll need to add the Kibana version you're targeting to `package.json` in the `kibanas` array. The build system will take care of assembling a working package for each version of Kibana, including naming the files correctly and updating each archive's `package.json` to match.
If you've sorted out that complex web of dependencies go ahead and run the following.
```
gulp release
```
You're done. Champagne?

View file

@ -1,323 +0,0 @@
## Timelion function reference
This document is auto generated from the timelion code. Do not submit pulls against this document. You want to submit a pull against something in the `series_functions/` directory.
### Data sources
Data sources can start a chain, they don't need to be attached to anything, but they still need to start with a `.` (dot). Data retreived from a data source can be passed into the chainable functions in the next section.
#### .graphite()
Pull data from graphite. Configure your graphite server in Kibana's Advanced Settings
Argument | Accepts | Description
--- | --- | ---
metric | *string* | Graphite metric to pull, eg _test-data.users.*.data
offset | *string* | Offset the series retrieval by a date expression. Eg -1M to make events from one month ago appear as if they are happening now
fit | *string* | Algorithm to use for fitting series to the target time span and interval. Available: average, carry, nearest, none, scale,
#### .quandl()
Pull data from quandl.com using the quandl code. Set "timelion:quandl.key" to your free API key in Kibana's Advanced Settings.
The API has a really low rate limit without a key
Argument | Accepts | Description
--- | --- | ---
code | *string* | The quandl code to plot. You can find these on quandl.com.
position | *number* | Some quandl sources return multiple series, which one should I use? 1 based index.
offset | *string* | Offset the series retrieval by a date expression. Eg -1M to make events from one month ago appear as if they are happening now
fit | *string* | Algorithm to use for fitting series to the target time span and interval. Available: average, carry, nearest, none, scale,
#### .static()
Draws a single value across the chart
Argument | Accepts | Description
--- | --- | ---
value | *number/string* | The single value to to display, you can also pass several values and I will interpolate them evenly across your time range.
label | *string* | A quick way to set the label for the series. You could also use the .label() function
offset | *string* | Offset the series retrieval by a date expression. Eg -1M to make events from one month ago appear as if they are happening now
fit | *string* | Algorithm to use for fitting series to the target time span and interval. Available: average, carry, nearest, none, scale,
#### .worldbank_indicators()
Pull data from http://data.worldbank.org/ using the country name and indicator. The worldbank provides mostly yearly data, and often has no data for the current year. Try offset=-1y if you get no data for recent time ranges.
Argument | Accepts | Description
--- | --- | ---
country | *string* | Worldbank country identifier. Usually the country's 2 letter code
indicator | *string* | The indicator code to use. You'll have to look this up on data.worldbank.org. Often pretty obtuse. Eg SP.POP.TOTL is population
offset | *string* | Offset the series retrieval by a date expression. Eg -1M to make events from one month ago appear as if they are happening now
fit | *string* | Algorithm to use for fitting series to the target time span and interval. Available: average, carry, nearest, none, scale,
#### .worldbank()
Pull data from http://data.worldbank.org/ using path to series. The worldbank provides mostly yearly data, and often has no data for the current year. Try offset=-1y if you get no data for recent time ranges.
Argument | Accepts | Description
--- | --- | ---
code | *string* | Worldbank API path. This is usually everything after the domain, before the querystring. Eg: /en/countries/ind;chn/indicators/DPANUSSPF.
offset | *string* | Offset the series retrieval by a date expression. Eg -1M to make events from one month ago appear as if they are happening now
fit | *string* | Algorithm to use for fitting series to the target time span and interval. Available: average, carry, nearest, none, scale,
#### .es()
Pull data from an elasticsearch instance
Argument | Accepts | Description
--- | --- | ---
q | *string* | Query in lucene query string syntax
metric | *string* | An elasticsearch single value metric agg, eg avg, sum, min, max or cardinality, followed by a field. Eg "sum:bytes", or just "count"
split | *string* | An elasticsearch field to split the series on and a limit. Eg, "hostname:10" to get the top 10 hostnames
index | *string* | Index to query, wildcards accepted
timefield | *string* | Field of type "date" to use for x-axis
kibana | *boolean* | Respect filters on Kibana dashboards. Only has an effect when using on Kibana dashboards
interval | *string* | **DO NOT USE THIS**. Its fun for debugging fit functions, but you really should use the interval picker
offset | *string* | Offset the series retrieval by a date expression. Eg -1M to make events from one month ago appear as if they are happening now
fit | *string* | Algorithm to use for fitting series to the target time span and interval. Available: average, carry, nearest, none, scale,
### Chainable functions
Chainable functions can not start a chain. Somewhere before them must be a data source function. Chainable functions modify the data output directly from a data source, or from another chainable function that has a data source somewhere before it.
#### .abs()
Return the absolute value of each value in the series list
*This function does not accept any arguments.*
#### .bars()
Show the seriesList as bars
Argument | Accepts | Description
--- | --- | ---
width | *number* | Width of bars in pixels
stack | *boolean* | Should bars be stacked, true by default
#### .color()
Change the color of the series
Argument | Accepts | Description
--- | --- | ---
color | *string* | Color of series, as hex, eg #c6c6c6 is a lovely light grey. If you specify multiple colors, and have multiple series, you will get a gradient, eg "#00B1CC:#00FF94:#FF3A39:#CC1A6F"
#### .condition()
Compares each point to a number, or the same point in another series using an operator, then sets its valueto the result if the condition proves true, with an optional else.
Argument | Accepts | Description
--- | --- | ---
operator | *string* | Operator to use for comparison, valid operators are eq (equal), ne (not equal), lt (less than), lte (less than equal), gt (greater than), gte (greater than equal)
if | *number/seriesList* | The value to which the point will be compared. If you pass a seriesList here the first series will be used
then | *number/seriesList* | The value the point will be set to if the comparison is true. If you pass a seriesList here the first series will be used
else | *number/seriesList* | The value the point will be set to if the comparison is false. If you pass a seriesList here the first series will be used
#### .cusum()
Return the cumulative sum of a series, starting at a base.
Argument | Accepts | Description
--- | --- | ---
base | *number* | Number to start at. Basically just adds this to the beginning of the series
#### .derivative()
Plot the change in values over time.
*This function does not accept any arguments.*
#### .divide()
Divides the values of one or more series in a seriesList to each position, in each series, of the input seriesList
Argument | Accepts | Description
--- | --- | ---
divisor | *seriesList/number* | Number or series to divide by. If passing a seriesList it must contain exactly 1 series.
#### .first()
This is an internal function that simply returns the input seriesList. Don't use this
*This function does not accept any arguments.*
#### .fit()
Fills null values using a defined fit function
Argument | Accepts | Description
--- | --- | ---
mode | *string* | The algorithm to use for fitting the series to the target. One of: average, carry, nearest, none, scale,
#### .hide()
Hide the series by default
Argument | Accepts | Description
--- | --- | ---
hide | *boolean* | Hide or unhide the series
#### .label()
Change the label of the series. Use %s reference the existing label
Argument | Accepts | Description
--- | --- | ---
label | *string* | Legend value for series. You can use $1, $2, etc, in the string to match up with the regex capture groups
regex | *string* | A regex with capture group support
#### .legend()
Set the position and style of the legend on the plot
Argument | Accepts | Description
--- | --- | ---
position | *string/boolean* | Corner to place the legend in: nw, ne, se, or sw. You can also pass false to disable the legend
columns | *number* | Number of columns to divide the legend into
#### .lines()
Show the seriesList as lines
Argument | Accepts | Description
--- | --- | ---
width | *number* | Line thickness
fill | *number* | Number between 0 and 10. Use for making area charts
stack | *boolean* | Stack lines, often misleading. At least use some fill if you use this.
show | *number/boolean* | Show or hide lines
steps | *number/boolean* | Show line as step, eg, do not interpolate between points
#### .max()
Maximum values of one or more series in a seriesList to each position, in each series, of the input seriesList
Argument | Accepts | Description
--- | --- | ---
value | *seriesList/number* | Sets the point to whichever is higher, the existing value, or the one passed. If passing a seriesList it must contain exactly 1 series.
#### .min()
Minimum values of one or more series in a seriesList to each position, in each series, of the input seriesList
Argument | Accepts | Description
--- | --- | ---
value | *seriesList/number* | Sets the point to whichever is lower, the existing value, or the one passed. If passing a seriesList it must contain exactly 1 series.
#### .movingaverage()
Calculate the moving average over a given window. Nice for smoothing noisey series
Argument | Accepts | Description
--- | --- | ---
window | *number* | Number of points to average over
position | *string* | Position of the averaged points relative to the result time. Options are left, right, and center (default).
#### .movingstd()
Calculate the moving standard deviation over a given window. Uses naive two-pass algorithm. Rounding errors may become more noticeable with very long series, or series with very large numbers.
Argument | Accepts | Description
--- | --- | ---
window | *number* | Number of points to compute the standard deviation over
#### .multiply()
Multiply the values of one or more series in a seriesList to each position, in each series, of the input seriesList
Argument | Accepts | Description
--- | --- | ---
multiplier | *seriesList/number* | Number or series by which to multiply. If passing a seriesList it must contain exactly 1 series.
#### .points()
Show the series as points
Argument | Accepts | Description
--- | --- | ---
radius | *number* | Size of points
weight | *number* | Thickness of line around point
fill | *number* | Number between 0 and 10 representing opacity of fill
fillColor | *string* | Color with which to fill point
symbol | *string* | cross, circle, triangle, square or diamond
show | *boolean* | Show points or not
#### .precision()
number of digits to round the decimal portion of the value to
Argument | Accepts | Description
--- | --- | ---
precision | *number* | Number of digits to round each value to
#### .props()
Use at your own risk, sets arbitrary properties on the series. For example .props(label=bears!)
Argument | Accepts | Description
--- | --- | ---
global | *boolean* | Set props on the seriesList vs on each series
#### .range()
Changes the max and min of a series while keeping the same shape
Argument | Accepts | Description
--- | --- | ---
min | *number* | New minimum value
max | *number* | New maximum value
#### .scale_interval()
Changes scales a value (usually a sum or a count) to a new interval. For example, as a per-second rate
Argument | Accepts | Description
--- | --- | ---
interval | *string* | The new interval in date math notation, eg 1s for 1 second. 1m, 5m, 1M, 1w, 1y, etc.
#### .subtract()
Subtract the values of one or more series in a seriesList to each position, in each series, of the input seriesList
Argument | Accepts | Description
--- | --- | ---
term | *seriesList/number* | Number or series to subtract from input. If passing a seriesList it must contain exactly 1 series.
#### .sum()
Adds the values of one or more series in a seriesList to each position, in each series, of the input seriesList
Argument | Accepts | Description
--- | --- | ---
term | *seriesList/number* | Number or series to sum with the input series. If passing a seriesList it must contain exactly 1 series.
#### .title()
Adds a title to the top of the plot. If called on more than 1 seriesList the last call will be used.
Argument | Accepts | Description
--- | --- | ---
title | *string* | Title for the plot.
#### .trim()
Set N buckets at the start or end of a series to null to fit the "partial bucket issue"
Argument | Accepts | Description
--- | --- | ---
start | *number* | Buckets to trim from the beginning of the series. Default: 1
end | *number* | Buckets to trim from the end of the series. Default: 1
#### .yaxis()
Configures a variety of y-axis options, the most important likely being the ability to add an Nth (eg 2nd) y-axis
Argument | Accepts | Description
--- | --- | ---
yaxis | *number* | The numbered y-axis to plot this series on, eg .yaxis(2) for a 2nd y-axis.
min | *number* | Min value
max | *number* | Max value
position | *string* | left or right
label | *string* | Label for axis
color | *string* | Color of axis label
#### .holt()
Sample the beginning of a series and use it to forecast what should happen
via several optional parameters. In general, like everything, this is crappy at predicting the
future. You're much better off using it to predict what should be happening right now, for the
purpose of anomaly detection. Note that nulls will be filled with forecasted values. Deal with it.
Argument | Accepts | Description
--- | --- | ---
alpha | *number* |
Smoothing weight from 0 to 1.
Increasing alpha will make the new series more closely follow the original.
Lowering it will make the series smoother
beta | *number* |
Trending weight from 0 to 1.
Increasing beta will make rising/falling lines continue to rise/fall longer.
Lowering it will make the function learn the new trend faster
gamma | *number* |
Seasonal weight from 0 to 1. Does your data look like a wave?
Increasing this will give recent seasons more importance, thus changing the wave form faster.
Lowering it will reduce the importance of new seasons, making history more important.
season | *string* | How long is the season, eg, 1w if you pattern repeats weekly. (Only useful with gamma)
sample | *number* |
The number of seasons to sample before starting to "predict" in a seasonal series.
(Only useful with gamma, Default: all)
#### .trend()
Draws a trend line using a specified regression algorithm
Argument | Accepts | Description
--- | --- | ---
mode | *string* | The algorithm to use for generating the trend line. One of: linear, log
start | *number* | Where to start calculating from the beginning or end. For example -10 would start calculating 10 points from the end, +15 would start 15 points from the beginning. Default: 0
end | *number* | Where to stop calculating from the beginning or end. For example -10 would stop calculating 10 points from the end, +15 would stop 15 points from the beginning. Default: 0

View file

@ -1,7 +0,0 @@
Copyright 20122014 Elasticsearch BV
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

View file

@ -1,45 +0,0 @@
# Timelion
Timelion pronounced time-lion, not time-leon, brings together totally independent data sources into a single interface, driven by a simple, one-line expression language combining data retrieval, time series combination and transformation, plus visualization.
- How many pages does each unique user hit over time?
- Whats the difference between this Friday and last Friday?
- What % of Japans population came to my site today?
- Whats the 10 day moving average of the S&P 500?
- How what is the cumulative sum of all searches made in the last 2 years?
Timelion makes all that possible, and more. Timelion is an Elastic {Re}search project into time series, but its more than just an experiment: Its completely usable. By you. Right now.
### Installation
- Run this, bounce the Kibana server. and refresh your browser: `./bin/kibana plugin -i elastic/timelion`.
- If you're messing around with the 5.0.0 alphas of Kibana, use `./bin/kibana-plugin install timelion`
- **Timelion requires the latest version of Kibana.** Always. What does that mean? I means if a beta version of kibana 9.2.1492 comes out, you'll need to install the latest version of Kibana to install Timelion.
- **You can not install from the archives that github provides**. They are not built versions, they won't work, use the command above.
### Timelion expressions
Every Timelion expression starts with a data source function. For example .elasticsearch(*) (or .es(*) for short). Thats about as simple as it gets right? Count everything in Elasticsearch over time. Easy peasy. As you can see, functions always start with a '.' (dot). What if I want to answer that first question above: “How many pages does each unique user hit over time”. Well, I could plot the two parts together on the same chart, by separating them with a comma. But there's a better way ...
![](https://www.elastic.co/assets/blt6858173f61f41f74/Screen%20Shot%202015-11-12%20at%202.16.23%20PM.png)
We can do more than individual functions, we can chain functions! What I really want is to divide total hits by unique users. WE CAN DO THAT. SCORE. What we're doing here is saying: Get everything, then divide every point in that series, by every point in this cardinality-of-user-field series I'm passing to .divide()
![](https://www.elastic.co/assets/blt7e65751490506e7f/Screen%20Shot%202015-11-12%20at%202.14.56%20PM.png)
We can do that, we can do more: Timelion can reach out to other data sources, using the exact same syntax. For example, the Worldbanks Data API. Series even can be grouped together into lists with parenthesis and a function applied to the grouping. All data sources can receive an offset argument, eg offset=-1M to compare last month as if it was happening now. Timeline can even fit series with dissimilar intervals to a reference, then enabling you to divide you by-the-minute Elasticsearch series with say, yearly Worldbank data.
![](https://www.elastic.co/assets/blt9117e105b1535caf/Screen%20Shot%202015-11-12%20at%202.27.39%20PM.png)
That means we can mix and match these sources, even within the same expression.Thus we can ask crazy questions like “What percentage of the US Gross Domestic Product is my company personally responsible for year-to-date?” Also, if that number is big, how about sharing with your old buddy Rashid? Just kidding. Or am I?
### Funk-shun Al
Theres 25 different functions, from simple arithmetic like addition and division to moving averages, cumulative sums and derivatives. That said, Timelion functions and data sources are totally pluggable and super easy to write. Wed love your help rounding out the offering, so get hacking!
### Go get it
I won't give it all away, theres more to it than just this post. Timelion will launch a tutorial to step you through configuration and some simple starter functions, the rest is up to you to discover.
Installing it is easy, run this, bounce the Kibana server. and refresh your browser: `./bin/kibana plugin -i elastic/timelion`. Or you can try it on Found, the best hosted Elasticsearch in the history of the universe, for free: Found by Elastic
You can also install offline by grabbing [the latest build](https://download.elasticsearch.org/kibana/timelion/timelion-latest.tar.gz) and using the `--url` parameter to point the plugin installer at say, `file:///Users/ItsAYou/timelion-latest.tar.gz`
Now use it. Abuse it.
Once you've installed it, you'll have a new icon in Kibana, which opens the app switcher and allows you to enter other apps
![](https://www.elastic.co/assets/bltb6b576d300d1ae45/Screen%20Shot%202015-11-12%20at%205.33.20%20PM.png)

View file

@ -2,7 +2,6 @@
"name": "timelion",
"version": "0.0.0",
"dependencies": {
"pegjs": "~0.8.0",
"flot": "~0.8.3",
"angular-sortable-view": "~0.0.13"
}

View file

@ -1,40 +0,0 @@
{
"name": "pegjs",
"description": "PEG.js: Parser Generator for JavaScript (Browser version)",
"version": "0.8.0",
"main": [
"./peg-0.8.0.js"
],
"license": "MIT",
"ignore": [],
"keywords": [
"peg",
"pegjs",
"grammar",
"parser",
"generator",
"browser"
],
"authors": [
{
"name": "David Majda",
"email": "david@majda.cz"
}
],
"homepage": "http://pegjs.majda.cz/",
"repository": {
"type": "git",
"url": "git://github.com/dmajda/pegjs.git"
},
"dependencies": {},
"devDependencies": {},
"_release": "0.8.0",
"_resolution": {
"type": "version",
"tag": "0.8.0",
"commit": "9e7f95155675691a4589de4621e1dcaa52a39188"
},
"_source": "git://github.com/pegjs/bower.git",
"_target": "~0.8.0",
"_originalSource": "pegjs"
}

View file

@ -1,22 +0,0 @@
Copyright (c) 2010-2013 David Majda
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View file

@ -1,21 +0,0 @@
PEG.js Bower package
====================
This repository contains the files necessary to make [PEG.js][pegjs]
available in the Browser through [bower][].
Installation
-------------
```
bower install pegjs
```
Need a new version?
--------------------
If you need a new version of this package, please [open an issue][issues].
[pegjs]: http://pegjs.majda.cz/
[bower]: http://bower.io/
[issues]: https://github.com/pegjs/bower/issues

View file

@ -1,29 +0,0 @@
{
"name": "pegjs",
"description": "PEG.js: Parser Generator for JavaScript (Browser version)",
"version": "0.8.0",
"main": ["./peg-0.8.0.js"],
"license": "MIT",
"ignore": [],
"keywords": [
"peg",
"pegjs",
"grammar",
"parser",
"generator",
"browser"
],
"authors": [{
"name": "David Majda",
"email": "david@majda.cz"
}],
"homepage": "http://pegjs.majda.cz/",
"repository": {
"type": "git",
"url": "git://github.com/dmajda/pegjs.git"
},
"dependencies": {
},
"devDependencies": {
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -1,210 +0,0 @@
var gulp = require('gulp');
var _ = require('lodash');
var glob = require('glob');
var yargs = require('yargs').argv;
var aws = require('aws-sdk');
var path = require('path');
var gulpUtil = require('gulp-util');
var mkdirp = require('mkdirp');
var Rsync = require('rsync');
var Promise = require('bluebird');
var eslint = require('gulp-eslint');
var rimraf = require('rimraf');
var zip = require('gulp-zip');
var fs = require('fs');
var child = require('child_process');
var semver = require('semver');
var mocha = require('gulp-mocha');
var pkg = require('./package.json');
var packageName = pkg.name + '-' + pkg.version;
var buildDir = path.resolve(__dirname, 'build/kibana');
var packageRoot = path.resolve(__dirname, 'build');
var targetDir = path.resolve(__dirname, 'target');
var buildTarget = path.resolve(buildDir, pkg.name);
var kibanaPluginDir = path.resolve(__dirname, '../kibana/plugins/' + pkg.name);
var build = [
'package.json',
'index.js',
'node_modules',
'public',
'bower_components',
'vendor_components',
'init.js',
'server',
'timelion.json'
];
var develop = build.concat([
'timelion.private.json'
]);
var exclude = Object.keys(pkg.devDependencies).map(function (name) {
return path.join('node_modules', name);
});
function writeDocs(done) {
require('babel-core/register');
var fs = require('fs');
var helpish = require('./server/lib/functions_md');
fs.writeFile(path.resolve(__dirname, 'FUNCTIONS.md'), helpish, function (err) {
if (err) {
return done(err);
} else {
done();
}
});
}
function syncPluginTo(include, dest, done) {
mkdirp(dest, function (err) {
if (err) return done(err);
Promise.all(include.map(function (name) {
var source = path.resolve(__dirname, name);
try {fs.accessSync(source);} catch (e) {return;};
return new Promise(function (resolve, reject) {
var rsync = new Rsync();
rsync
.source(source)
.destination(dest)
.flags('uav')
.recursive(true)
.set('delete')
.exclude(exclude)
.output(function (data) {
process.stdout.write(data.toString('utf8'));
});
rsync.execute(function (err) {
if (err) {
console.log(err);
return reject(err);
}
resolve();
});
});
}))
.then(function () {
done();
})
.catch(done);
});
}
gulp.task('sync', function (done) {
syncPluginTo(develop, kibanaPluginDir, done);
});
gulp.task('docs', function (done) {
writeDocs(done);
});
gulp.task('version', function (done) {
var newVersion = '0.1.' + (semver.patch(pkg.version) + 1);
child.exec('npm version --no-git-tag-version ' + newVersion, function () {
console.log('Timelion version is ' + newVersion);
done();
});
});
gulp.task('lint', function (done) {
return gulp.src(['server/**/*.js', 'public/**/*.js'])
// eslint() attaches the lint output to the eslint property
// of the file object so it can be used by other modules.
.pipe(eslint())
// eslint.format() outputs the lint results to the console.
// Alternatively use eslint.formatEach() (see Docs).
.pipe(eslint.formatEach())
// To have the process exit with an error code (1) on
// lint error, return the stream and pipe to failOnError last.
.pipe(eslint.failOnError());
});
gulp.task('clean', function (done) {
Promise.each([packageRoot, targetDir], function (dir) {
return new Promise(function (resolve, reject) {
rimraf(dir, function (err) {
if (err) return reject(err);
resolve();
});
});
}).nodeify(done);
});
gulp.task('build', ['clean'], function (done) {
syncPluginTo(build, buildTarget, done);
});
gulp.task('package', ['build'], function (done) {
function writePackages(versions, done) {
if (!versions.length) { done(); return; }
// Write a new version so it works with the Kibana package manager
var editable = _.cloneDeep(pkg);
editable.version = versions.shift();
require('fs').writeFileSync(buildTarget + '/' + 'package.json', JSON.stringify(editable, null, ' '));
var archiveName = editable.name + '-' + editable.version + '.zip';
gulp.src(path.join(packageRoot, '**', '*'))
.pipe(zip(archiveName))
.pipe(gulp.dest(targetDir))
.on('end', function () {
gulpUtil.log('Packaged', archiveName);
writePackages(versions, done);
});
}
// Write one archive for every supported kibana version, plus one with the actual timelion version
writePackages(pkg.kibanas.concat([pkg.version]), done);
});
gulp.task('release', ['package'], function (done) {
function upload(files, done) {
if (!files.length) { done(); return; }
var filename = _.last(files.shift().split('/'));
var s3 = new aws.S3();
var params = {
Bucket: 'download.elasticsearch.org',
Key: 'kibana/timelion/' + filename,
Body: fs.createReadStream(path.join(targetDir, filename))
};
s3.upload(params, function (err, data) {
if (err) return done(err);
gulpUtil.log('Finished', gulpUtil.colors.cyan('uploaded') + ' Available at ' + data.Location);
upload(files, done);
});
}
glob(targetDir + '/*.zip', function (err, files) {
upload(files, done);
});
});
gulp.task('dev', ['sync'], function (done) {
gulp.watch([
'index.js',
'node_modules',
'public/**/*',
'bower_components',
'vendor_components',
'init.js',
'server/**/*',
'timelion.json'
], ['sync', 'lint', 'test']);
});
gulp.task('test', [], function () {
require('babel-core/register');
return gulp.src([
'server/**/__test__/**/*.js'
], { read: false })
.pipe(mocha({ reporter: 'list' }));
});

View file

@ -1,51 +1,5 @@
{
"author": "Rashid Khan <rashid@elastic.co>",
"name": "timelion",
"version": "0.1.412",
"kibanas": [
"5.0.0-alpha4",
"5.0.0-alpha5",
"5.0.0-beta1"
],
"dependencies": {
"body-parser": "^1.12.0",
"boom": "^2.8.0",
"css-loader": "0.17.0",
"glob": "^5.0.13",
"gradient": "^0.2.0",
"gulp-zip": "^3.2.0",
"moment": "^2.10.3",
"node-fetch": "^1.3.2",
"pegjs": "^0.9.0",
"tinygradient": "^0.3.0"
},
"devDependencies": {
"aws-sdk": "^2.2.16",
"babel": "^5.8.38",
"babel-core": "^5.8.38",
"babel-eslint": "^6.0.4",
"bluebird": "^3.0.5",
"chai": "^3.2.0",
"eslint": "^1.9.0",
"eslint-plugin-mocha": "^1.0.0",
"gulp": "^3.9.0",
"gulp-babel": "^6.1.2",
"gulp-babel-istanbul": "^1.2.0",
"gulp-eslint": "^1.0.0",
"gulp-gzip": "^1.2.0",
"gulp-mocha": "^2.2.0",
"gulp-tar": "^1.5.0",
"gulp-util": "^3.0.7",
"lodash": "^3.10.1",
"mkdirp": "^0.5.1",
"mocha": "^2.3.0",
"proxyquire": "^1.7.9",
"rimraf": "^2.4.3",
"rsync": "^0.4.0",
"semver": "^5.1.0",
"yargs": "^3.29.0"
},
"scripts": {
"test": "gulp test",
"start": "gulp dev"
}
"version": "kibana"
}

View file

@ -1,55 +1,54 @@
define(function (require) {
var module = require('ui/modules').get('app/timelion');
var _ = require('lodash');
var moment = require('moment');
import uiModules from 'ui/modules';
import _ from 'lodash';
import moment from 'moment';
const module = uiModules.get('app/timelion');
// Used only by the savedSheets service, usually no reason to change this
module.factory('SavedSheet', function (courier, config) {
// Used only by the savedSheets service, usually no reason to change this
module.factory('SavedSheet', function (courier, config) {
// SavedSheet constructor. Usually you'd interact with an instance of this.
// ID is option, without it one will be generated on save.
_.class(SavedSheet).inherits(courier.SavedObject);
function SavedSheet(id) {
// Gives our SavedSheet the properties of a SavedObject
courier.SavedObject.call(this, {
type: SavedSheet.type,
mapping: SavedSheet.mapping,
// SavedSheet constructor. Usually you'd interact with an instance of this.
// ID is option, without it one will be generated on save.
_.class(SavedSheet).inherits(courier.SavedObject);
function SavedSheet(id) {
// Gives our SavedSheet the properties of a SavedObject
courier.SavedObject.call(this, {
type: SavedSheet.type,
mapping: SavedSheet.mapping,
// if this is null/undefined then the SavedObject will be assigned the defaults
id: id,
// if this is null/undefined then the SavedObject will be assigned the defaults
id: id,
// default values that will get assigned if the doc is new
defaults: {
title: 'New TimeLion Sheet',
hits: 0,
description: '',
timelion_sheet: ['.es(*)'],
timelion_interval: 'auto',
timelion_chart_height: 275,
timelion_columns: config.get('timelion:default_columns') || 2,
timelion_rows: config.get('timelion:default_rows') || 2,
version: 1,
}
});
}
// default values that will get assigned if the doc is new
defaults: {
title: 'New TimeLion Sheet',
hits: 0,
description: '',
timelion_sheet: ['.es(*)'],
timelion_interval: 'auto',
timelion_chart_height: 275,
timelion_columns: config.get('timelion:default_columns') || 2,
timelion_rows: config.get('timelion:default_rows') || 2,
version: 1,
}
});
}
// save these objects with the 'sheet' type
SavedSheet.type = 'timelion-sheet';
// save these objects with the 'sheet' type
SavedSheet.type = 'timelion-sheet';
// if type:sheet has no mapping, we push this mapping into ES
SavedSheet.mapping = {
title: 'string',
hits: 'integer',
description: 'string',
timelion_sheet: 'string',
timelion_interval: 'string',
timelion_other_interval: 'string',
timelion_chart_height: 'integer',
timelion_columns: 'integer',
timelion_rows: 'integer',
version: 'integer'
};
// if type:sheet has no mapping, we push this mapping into ES
SavedSheet.mapping = {
title: 'string',
hits: 'integer',
description: 'string',
timelion_sheet: 'string',
timelion_interval: 'string',
timelion_other_interval: 'string',
timelion_chart_height: 'integer',
timelion_columns: 'integer',
timelion_rows: 'integer',
version: 'integer'
};
return SavedSheet;
});
return SavedSheet;
});