Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
d5196ab3
Commit
d5196ab3
authored
Jun 14, 2018
by
David Kaltschmidt
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
remove internal influx ifql datasource
parent
56628996
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
0 additions
and
862 deletions
+0
-862
pkg/api/frontendsettings.go
+0
-11
pkg/models/datasource.go
+0
-1
public/app/features/plugins/built_in_plugins.ts
+0
-2
public/app/plugins/datasource/influxdb-ifql/README.md
+0
-29
public/app/plugins/datasource/influxdb-ifql/datasource.ts
+0
-256
public/app/plugins/datasource/influxdb-ifql/img/influxdb_logo.svg
+0
-26
public/app/plugins/datasource/influxdb-ifql/metric_find_query.ts
+0
-63
public/app/plugins/datasource/influxdb-ifql/module.ts
+0
-17
public/app/plugins/datasource/influxdb-ifql/partials/annotations.editor.html
+0
-23
public/app/plugins/datasource/influxdb-ifql/partials/config.html
+0
-25
public/app/plugins/datasource/influxdb-ifql/partials/query.editor.html
+0
-33
public/app/plugins/datasource/influxdb-ifql/plugin.json
+0
-25
public/app/plugins/datasource/influxdb-ifql/query_ctrl.ts
+0
-56
public/app/plugins/datasource/influxdb-ifql/response_parser.ts
+0
-129
public/app/plugins/datasource/influxdb-ifql/specs/datasource.jest.ts
+0
-39
public/app/plugins/datasource/influxdb-ifql/specs/metric_find_query.jest.ts
+0
-43
public/app/plugins/datasource/influxdb-ifql/specs/response_parser.jest.ts
+0
-84
public/app/plugins/datasource/influxdb-ifql/specs/sample_response_csv.ts
+0
-0
No files found.
pkg/api/frontendsettings.go
View file @
d5196ab3
...
...
@@ -85,13 +85,6 @@ func getFrontendSettingsMap(c *m.ReqContext) (map[string]interface{}, error) {
dsMap
[
"database"
]
=
ds
.
Database
dsMap
[
"url"
]
=
url
}
if
ds
.
Type
==
m
.
DS_INFLUXDB_IFQL
{
dsMap
[
"username"
]
=
ds
.
User
dsMap
[
"password"
]
=
ds
.
Password
dsMap
[
"database"
]
=
ds
.
Database
dsMap
[
"url"
]
=
url
}
}
if
ds
.
Type
==
m
.
DS_ES
{
...
...
@@ -102,10 +95,6 @@ func getFrontendSettingsMap(c *m.ReqContext) (map[string]interface{}, error) {
dsMap
[
"database"
]
=
ds
.
Database
}
if
ds
.
Type
==
m
.
DS_INFLUXDB_IFQL
{
dsMap
[
"database"
]
=
ds
.
Database
}
if
ds
.
Type
==
m
.
DS_PROMETHEUS
{
// add unproxied server URL for link to Prometheus web UI
dsMap
[
"directUrl"
]
=
ds
.
Url
...
...
pkg/models/datasource.go
View file @
d5196ab3
...
...
@@ -12,7 +12,6 @@ const (
DS_GRAPHITE
=
"graphite"
DS_INFLUXDB
=
"influxdb"
DS_INFLUXDB_08
=
"influxdb_08"
DS_INFLUXDB_IFQL
=
"influxdb-ifql"
DS_ES
=
"elasticsearch"
DS_OPENTSDB
=
"opentsdb"
DS_CLOUDWATCH
=
"cloudwatch"
...
...
public/app/features/plugins/built_in_plugins.ts
View file @
d5196ab3
...
...
@@ -4,7 +4,6 @@ import * as elasticsearchPlugin from 'app/plugins/datasource/elasticsearch/modul
import
*
as
opentsdbPlugin
from
'app/plugins/datasource/opentsdb/module'
;
import
*
as
grafanaPlugin
from
'app/plugins/datasource/grafana/module'
;
import
*
as
influxdbPlugin
from
'app/plugins/datasource/influxdb/module'
;
import
*
as
influxdbIfqlPlugin
from
'app/plugins/datasource/influxdb-ifql/module'
;
import
*
as
mixedPlugin
from
'app/plugins/datasource/mixed/module'
;
import
*
as
mysqlPlugin
from
'app/plugins/datasource/mysql/module'
;
import
*
as
postgresPlugin
from
'app/plugins/datasource/postgres/module'
;
...
...
@@ -31,7 +30,6 @@ const builtInPlugins = {
'app/plugins/datasource/opentsdb/module'
:
opentsdbPlugin
,
'app/plugins/datasource/grafana/module'
:
grafanaPlugin
,
'app/plugins/datasource/influxdb/module'
:
influxdbPlugin
,
'app/plugins/datasource/influxdb-ifql/module'
:
influxdbIfqlPlugin
,
'app/plugins/datasource/mixed/module'
:
mixedPlugin
,
'app/plugins/datasource/mysql/module'
:
mysqlPlugin
,
'app/plugins/datasource/postgres/module'
:
postgresPlugin
,
...
...
public/app/plugins/datasource/influxdb-ifql/README.md
deleted
100644 → 0
View file @
56628996
# InfluxDB (IFQL) Datasource [BETA] - Native Plugin
Grafana ships with
**built in**
support for InfluxDB (>= 1.4.1).
Use this datasource if you want to use IFQL to query your InfluxDB.
Feel free to run this datasource side-by-side with the non-IFQL datasource.
If you point both datasources to the same InfluxDB instance, you can switch query mode by switching the datasources.
Read more about IFQL here:
[
https://github.com/influxdata/ifql
](
https://github.com/influxdata/ifql
)
Read more about InfluxDB here:
[
http://docs.grafana.org/datasources/influxdb/
](
http://docs.grafana.org/datasources/influxdb/
)
## Supported Template Variable Macros:
*
List all measurements for a given database:
`measurements(database)`
*
List all tags for a given database and measurement:
`tags(database, measurement)`
*
List all tag values for a given database, measurement, and tag:
`tag_valuess(database, measurement, tag)`
*
List all field keys for a given database and measurement:
`field_keys(database, measurement)`
## Roadmap
-
Syntax highlighting
-
Tab completion (functions, values)
-
Alerting integration
-
Explore UI integration
public/app/plugins/datasource/influxdb-ifql/datasource.ts
deleted
100644 → 0
View file @
56628996
import
_
from
'lodash'
;
import
*
as
dateMath
from
'app/core/utils/datemath'
;
import
{
getAnnotationsFromResult
,
getTableModelFromResult
,
getTimeSeriesFromResult
,
getValuesFromResult
,
parseResults
,
}
from
'./response_parser'
;
import
expandMacros
from
'./metric_find_query'
;
function
serializeParams
(
params
)
{
if
(
!
params
)
{
return
''
;
}
return
_
.
reduce
(
params
,
(
memo
,
value
,
key
)
=>
{
if
(
value
===
null
||
value
===
undefined
)
{
return
memo
;
}
memo
.
push
(
encodeURIComponent
(
key
)
+
'='
+
encodeURIComponent
(
value
));
return
memo
;
},
[]
).
join
(
'&'
);
}
const
MAX_SERIES
=
20
;
export
default
class
InfluxDatasource
{
type
:
string
;
url
:
string
;
username
:
string
;
password
:
string
;
name
:
string
;
orgName
:
string
;
database
:
any
;
basicAuth
:
any
;
withCredentials
:
any
;
interval
:
any
;
supportAnnotations
:
boolean
;
supportMetrics
:
boolean
;
/** @ngInject */
constructor
(
instanceSettings
,
private
backendSrv
,
private
templateSrv
)
{
this
.
type
=
'influxdb-ifql'
;
this
.
url
=
instanceSettings
.
url
.
trim
();
this
.
username
=
instanceSettings
.
username
;
this
.
password
=
instanceSettings
.
password
;
this
.
name
=
instanceSettings
.
name
;
this
.
orgName
=
instanceSettings
.
orgName
||
'defaultorgname'
;
this
.
database
=
instanceSettings
.
database
;
this
.
basicAuth
=
instanceSettings
.
basicAuth
;
this
.
withCredentials
=
instanceSettings
.
withCredentials
;
this
.
interval
=
(
instanceSettings
.
jsonData
||
{}).
timeInterval
;
this
.
supportAnnotations
=
true
;
this
.
supportMetrics
=
true
;
}
prepareQueryTarget
(
target
,
options
)
{
// Replace grafana variables
const
timeFilter
=
this
.
getTimeFilter
(
options
);
options
.
scopedVars
.
range
=
{
value
:
timeFilter
};
const
interpolated
=
this
.
templateSrv
.
replace
(
target
.
query
,
options
.
scopedVars
);
return
{
...
target
,
query
:
interpolated
,
};
}
query
(
options
)
{
const
queryTargets
=
options
.
targets
.
filter
(
target
=>
target
.
query
)
.
map
(
target
=>
this
.
prepareQueryTarget
(
target
,
options
));
if
(
queryTargets
.
length
===
0
)
{
return
Promise
.
resolve
({
data
:
[]
});
}
const
queries
=
queryTargets
.
map
(
target
=>
{
const
{
query
,
resultFormat
}
=
target
;
if
(
resultFormat
===
'table'
)
{
return
this
.
_seriesQuery
(
query
,
options
)
.
then
(
response
=>
parseResults
(
response
.
data
))
.
then
(
results
=>
results
.
map
(
getTableModelFromResult
));
}
else
{
return
this
.
_seriesQuery
(
query
,
options
)
.
then
(
response
=>
parseResults
(
response
.
data
))
.
then
(
results
=>
results
.
map
(
getTimeSeriesFromResult
));
}
});
return
Promise
.
all
(
queries
).
then
((
series
:
any
)
=>
{
let
seriesList
=
_
.
flattenDeep
(
series
).
slice
(
0
,
MAX_SERIES
);
return
{
data
:
seriesList
};
});
}
annotationQuery
(
options
)
{
if
(
!
options
.
annotation
.
query
)
{
return
Promise
.
reject
({
message
:
'Query missing in annotation definition'
,
});
}
const
{
query
}
=
options
.
annotation
;
const
queryOptions
=
{
scopedVars
:
{},
...
options
,
silent
:
true
,
};
const
target
=
this
.
prepareQueryTarget
({
query
},
queryOptions
);
return
this
.
_seriesQuery
(
target
.
query
,
queryOptions
).
then
(
response
=>
{
const
results
=
parseResults
(
response
.
data
);
if
(
results
.
length
===
0
)
{
throw
{
message
:
'No results in response from InfluxDB'
};
}
const
annotations
=
_
.
flatten
(
results
.
map
(
result
=>
getAnnotationsFromResult
(
result
,
options
.
annotation
)));
return
annotations
;
});
}
metricFindQuery
(
query
:
string
,
options
?:
any
)
{
const
interpreted
=
expandMacros
(
query
);
// Use normal querier in silent mode
const
queryOptions
=
{
rangeRaw
:
{
to
:
'now'
,
from
:
'now - 1h'
},
scopedVars
:
{},
...
options
,
silent
:
true
,
};
const
target
=
this
.
prepareQueryTarget
({
query
:
interpreted
},
queryOptions
);
return
this
.
_seriesQuery
(
target
.
query
,
queryOptions
).
then
(
response
=>
{
const
results
=
parseResults
(
response
.
data
);
const
values
=
_
.
uniq
(
_
.
flatten
(
results
.
map
(
getValuesFromResult
)));
return
values
.
filter
(
value
=>
value
&&
value
[
0
]
!==
'_'
)
// Ignore internal fields
.
map
(
value
=>
({
text
:
value
}));
});
}
_seriesQuery
(
query
:
string
,
options
?:
any
)
{
if
(
!
query
)
{
return
Promise
.
resolve
({
data
:
''
});
}
return
this
.
_influxRequest
(
'POST'
,
'/v1/query'
,
{
q
:
query
},
options
);
}
testDatasource
()
{
const
query
=
`from(db:"
${
this
.
database
}
") |> last()`
;
return
this
.
_influxRequest
(
'POST'
,
'/v1/query'
,
{
q
:
query
})
.
then
(
res
=>
{
if
(
res
&&
res
.
data
&&
res
.
data
.
trim
())
{
return
{
status
:
'success'
,
message
:
'Data source connected and database found.'
};
}
return
{
status
:
'error'
,
message
:
'Data source connected, but has no data. Verify the "Database" field and make sure the database has data.'
,
};
})
.
catch
(
err
=>
{
return
{
status
:
'error'
,
message
:
err
.
message
};
});
}
_influxRequest
(
method
:
string
,
url
:
string
,
data
:
any
,
options
?:
any
)
{
let
params
:
any
=
{
orgName
:
this
.
orgName
,
};
if
(
this
.
username
)
{
params
.
u
=
this
.
username
;
params
.
p
=
this
.
password
;
}
// data sent as GET param
_
.
extend
(
params
,
data
);
data
=
null
;
let
req
:
any
=
{
method
:
method
,
url
:
this
.
url
+
url
,
params
:
params
,
data
:
data
,
precision
:
'ms'
,
inspect
:
{
type
:
this
.
type
},
paramSerializer
:
serializeParams
,
};
req
.
headers
=
req
.
headers
||
{};
if
(
this
.
basicAuth
||
this
.
withCredentials
)
{
req
.
withCredentials
=
true
;
}
if
(
this
.
basicAuth
)
{
req
.
headers
.
Authorization
=
this
.
basicAuth
;
}
return
this
.
backendSrv
.
datasourceRequest
(
req
).
then
(
result
=>
{
return
result
;
},
function
(
err
)
{
if
(
err
.
status
!==
0
||
err
.
status
>=
300
)
{
if
(
err
.
data
&&
err
.
data
.
error
)
{
throw
{
message
:
'InfluxDB Error: '
+
err
.
data
.
error
,
data
:
err
.
data
,
config
:
err
.
config
,
};
}
else
{
throw
{
message
:
'Network Error: '
+
err
.
statusText
+
'('
+
err
.
status
+
')'
,
data
:
err
.
data
,
config
:
err
.
config
,
};
}
}
}
);
}
getTimeFilter
(
options
)
{
const
from
=
this
.
getInfluxTime
(
options
.
rangeRaw
.
from
,
false
);
const
to
=
this
.
getInfluxTime
(
options
.
rangeRaw
.
to
,
true
);
if
(
to
===
'now'
)
{
return
`start:
${
from
}
`
;
}
return
`start:
${
from
}
, stop:
${
to
}
`
;
}
getInfluxTime
(
date
,
roundUp
)
{
if
(
_
.
isString
(
date
))
{
if
(
date
===
'now'
)
{
return
date
;
}
const
parts
=
/^now
\s
*-
\s
*
(\d
+
)([
d|h|m|s
])
$/
.
exec
(
date
);
if
(
parts
)
{
const
amount
=
parseInt
(
parts
[
1
]);
const
unit
=
parts
[
2
];
return
'-'
+
amount
+
unit
;
}
date
=
dateMath
.
parse
(
date
,
roundUp
);
}
return
date
.
toISOString
();
}
}
public/app/plugins/datasource/influxdb-ifql/img/influxdb_logo.svg
deleted
100644 → 0
View file @
56628996
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
version=
"1.1"
id=
"Layer_1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
x=
"0px"
y=
"0px"
viewBox=
"0 0 78.8 79.9"
style=
"enable-background:new 0 0 78.8 79.9;"
xml:space=
"preserve"
>
<style
type=
"text/css"
>
.st0{fill:url(#symbol_1_);}
</style>
<g
id=
"influxdb_logo"
>
<linearGradient
id=
"symbol_1_"
gradientUnits=
"userSpaceOnUse"
x1=
"41.5273"
y1=
"41.85"
x2=
"319.2919"
y2=
"41.85"
gradientTransform=
"matrix(1 0 0 -1 0 81.8)"
>
<stop
offset=
"0"
style=
"stop-color:#4591ED"
/>
<stop
offset=
"1"
style=
"stop-color:#00C9FF"
/>
</linearGradient>
<path
id=
"symbol_2_"
class=
"st0"
d=
"M78.7,48.2L71.1,15c-0.4-1.8-2.1-3.6-3.9-4.1L32.3,0.2c-0.5-0.1-1-0.2-1.5-0.2
c-1.5,0-3.1,0.6-4,1.5l-25,23.2c-1.3,1.2-2.1,3.6-1.7,5.4l8.1,35.5c0.4,1.8,2.1,3.6,3.9,4.1l32.6,10c0.5,0.1,1,0.2,1.5,0.2
c1.5,0,3.1-0.6,4-1.5l26.7-24.8C78.4,52.4,79.1,50,78.7,48.2z M35.9,8l23.9,7.3c0.9,0.3,0.9,0.7,0,0.9l-12.6,2.9
c-1,0.2-2.3-0.2-2.9-0.9l-8.8-9.5C34.8,8.1,35,7.8,35.9,8z M50.8,50.9c0.2,1-0.4,1.5-1.3,1.2l-25.8-7.9c-0.9-0.3-1.1-1.1-0.4-1.7
l19.8-18.4c0.7-0.7,1.5-0.4,1.7,0.5L50.8,50.9z M8.3,27.5L29.3,8c0.7-0.7,1.8-0.6,2.5,0.1l10.5,11.3c0.7,0.7,0.6,1.8-0.1,2.5
l-21,19.5c-0.7,0.7-1.8,0.6-2.5-0.1L8.2,30C7.6,29.3,7.6,28.2,8.3,27.5z M13.4,58.5L7.8,34.2c-0.2-1,0.1-1.1,0.8-0.4l8.8,9.5
c0.7,0.7,1,2.1,0.7,3l-3.8,12.3C14.1,59.4,13.6,59.4,13.4,58.5z M44.1,72.6l-27.3-8.4c-0.9-0.3-1.5-1.3-1.2-2.2l4.5-14.8
c0.3-0.9,1.3-1.5,2.2-1.2l27.3,8.4c0.9,0.3,1.5,1.3,1.2,2.2l-4.5,14.8C46,72.4,45,72.9,44.1,72.6z M68.4,52.7l-18.3,17
c-0.7,0.7-1.1,0.4-0.8-0.5l3.8-12.3c0.3-0.9,1.3-1.9,2.3-2.1L68,51.9C68.9,51.7,69.1,52.1,68.4,52.7z M70.4,49.1l-15.1,3.4
c-1,0.2-1.9-0.4-2.1-1.3l-6.4-27.9c-0.2-1,0.4-1.9,1.3-2.1l15.1-3.4c1-0.2,1.9,0.4,2.1,1.3L71.7,47C71.9,47.9,71.3,48.9,70.4,49.1z
"
/>
</g>
</svg>
public/app/plugins/datasource/influxdb-ifql/metric_find_query.ts
deleted
100644 → 0
View file @
56628996
// MACROS
// List all measurements for a given database: `measurements(database)`
const
MEASUREMENTS_REGEXP
=
/^
\s
*measurements
\((
.+
)\)\s
*$/
;
// List all tags for a given database and measurement: `tags(database, measurement)`
const
TAGS_REGEXP
=
/^
\s
*tags
\((
.+
)\s
*,
\s
*
(
.+
)\)\s
*$/
;
// List all tag values for a given database, measurement, and tag: `tag_valuess(database, measurement, tag)`
const
TAG_VALUES_REGEXP
=
/^
\s
*tag_values
\((
.+
)\s
*,
\s
*
(
.+
)\s
*,
\s
*
(
.+
)\)\s
*$/
;
// List all field keys for a given database and measurement: `field_keys(database, measurement)`
const
FIELD_KEYS_REGEXP
=
/^
\s
*field_keys
\((
.+
)\s
*,
\s
*
(
.+
)\)\s
*$/
;
export
default
function
expandMacros
(
query
)
{
const
measurementsQuery
=
query
.
match
(
MEASUREMENTS_REGEXP
);
if
(
measurementsQuery
)
{
const
database
=
measurementsQuery
[
1
];
return
`from(db:"
${
database
}
")
|> range($range)
|> group(by:["_measurement"])
|> distinct(column:"_measurement")
|> group(none:true)`
;
}
const
tagsQuery
=
query
.
match
(
TAGS_REGEXP
);
if
(
tagsQuery
)
{
const
database
=
tagsQuery
[
1
];
const
measurement
=
tagsQuery
[
2
];
return
`from(db:"
${
database
}
")
|> range($range)
|> filter(fn:(r) => r._measurement == "
${
measurement
}
")
|> keys()`
;
}
const
tagValuesQuery
=
query
.
match
(
TAG_VALUES_REGEXP
);
if
(
tagValuesQuery
)
{
const
database
=
tagValuesQuery
[
1
];
const
measurement
=
tagValuesQuery
[
2
];
const
tag
=
tagValuesQuery
[
3
];
return
`from(db:"
${
database
}
")
|> range($range)
|> filter(fn:(r) => r._measurement == "
${
measurement
}
")
|> group(by:["
${
tag
}
"])
|> distinct(column:"
${
tag
}
")
|> group(none:true)`
;
}
const
fieldKeysQuery
=
query
.
match
(
FIELD_KEYS_REGEXP
);
if
(
fieldKeysQuery
)
{
const
database
=
fieldKeysQuery
[
1
];
const
measurement
=
fieldKeysQuery
[
2
];
return
`from(db:"
${
database
}
")
|> range($range)
|> filter(fn:(r) => r._measurement == "
${
measurement
}
")
|> group(by:["_field"])
|> distinct(column:"_field")
|> group(none:true)`
;
}
// By default return pure query
return
query
;
}
public/app/plugins/datasource/influxdb-ifql/module.ts
deleted
100644 → 0
View file @
56628996
import
InfluxDatasource
from
'./datasource'
;
import
{
InfluxIfqlQueryCtrl
}
from
'./query_ctrl'
;
class
InfluxConfigCtrl
{
static
templateUrl
=
'partials/config.html'
;
}
class
InfluxAnnotationsQueryCtrl
{
static
templateUrl
=
'partials/annotations.editor.html'
;
}
export
{
InfluxDatasource
as
Datasource
,
InfluxIfqlQueryCtrl
as
QueryCtrl
,
InfluxConfigCtrl
as
ConfigCtrl
,
InfluxAnnotationsQueryCtrl
as
AnnotationsQueryCtrl
,
};
public/app/plugins/datasource/influxdb-ifql/partials/annotations.editor.html
deleted
100644 → 0
View file @
56628996
<div
class=
"gf-form-group"
>
<div
class=
"gf-form"
>
<input
type=
"text"
class=
"gf-form-input"
ng-model=
'ctrl.annotation.query'
placeholder=
'from(db:"telegraf") |> range($range)'
></input>
</div>
</div>
<h5
class=
"section-heading"
>
Field mappings
<tip>
If your influxdb query returns more than one field you need to specify the column names below. An annotation event is composed
of a title, tags, and an additional text field.
</tip>
</h5>
<div
class=
"gf-form-group"
>
<div
class=
"gf-form-inline"
>
<div
class=
"gf-form"
>
<span
class=
"gf-form-label width-4"
>
Text
</span>
<input
type=
"text"
class=
"gf-form-input max-width-10"
ng-model=
'ctrl.annotation.textColumn'
placeholder=
""
></input>
</div>
<div
class=
"gf-form"
>
<span
class=
"gf-form-label width-4"
>
Tags
</span>
<input
type=
"text"
class=
"gf-form-input max-width-10"
ng-model=
'ctrl.annotation.tagsColumn'
placeholder=
""
></input>
</div>
</div>
</div>
\ No newline at end of file
public/app/plugins/datasource/influxdb-ifql/partials/config.html
deleted
100644 → 0
View file @
56628996
<datasource-http-settings
current=
"ctrl.current"
no-direct-access=
"true"
suggest-url=
"http://localhost:8093"
>
</datasource-http-settings>
<h3
class=
"page-heading"
>
InfluxDB Details
</h3>
<div
class=
"gf-form-group"
>
<div
class=
"gf-form-inline"
>
<div
class=
"gf-form max-width-30"
>
<span
class=
"gf-form-label width-7"
>
Default Database
</span>
<input
type=
"text"
class=
"gf-form-input"
ng-model=
'ctrl.current.database'
placeholder=
""
required
></input>
</div>
</div>
<div
class=
"gf-form-inline"
>
<div
class=
"gf-form max-width-15"
>
<span
class=
"gf-form-label width-7"
>
User
</span>
<input
type=
"text"
class=
"gf-form-input"
ng-model=
'ctrl.current.user'
placeholder=
""
></input>
</div>
<div
class=
"gf-form max-width-15"
>
<span
class=
"gf-form-label width-7"
>
Password
</span>
<input
type=
"password"
class=
"gf-form-input"
ng-model=
'ctrl.current.password'
placeholder=
""
></input>
</div>
</div>
</div>
\ No newline at end of file
public/app/plugins/datasource/influxdb-ifql/partials/query.editor.html
deleted
100644 → 0
View file @
56628996
<query-editor-row
query-ctrl=
"ctrl"
can-collapse=
"true"
has-text-edit-mode=
"true"
>
<div
class=
"gf-form"
>
<textarea
rows=
"10"
class=
"gf-form-input"
ng-model=
"ctrl.target.query"
spellcheck=
"false"
placeholder=
"IFQL Query"
ng-model-onblur
ng-change=
"ctrl.refresh()"
></textarea>
<!-- Result preview -->
<textarea
rows=
"10"
class=
"gf-form-input"
ng-model=
"ctrl.dataPreview"
readonly
></textarea>
</div>
<div
class=
"gf-form-inline"
>
<div
class=
"gf-form"
>
<label
class=
"gf-form-label query-keyword"
>
FORMAT AS
</label>
<div
class=
"gf-form-select-wrapper"
>
<select
class=
"gf-form-input gf-size-auto"
ng-model=
"ctrl.target.resultFormat"
ng-options=
"f.value as f.text for f in ctrl.resultFormats"
ng-change=
"ctrl.refresh()"
></select>
</div>
</div>
<div
class=
"gf-form"
ng-if=
"ctrl.panelCtrl.loading"
>
<label
class=
"gf-form-label"
>
<i
class=
"fa fa-spinner fa-spin"
></i>
Loading
</label>
</div>
<div
class=
"gf-form"
ng-if=
"!ctrl.panelCtrl.loading"
>
<label
class=
"gf-form-label"
>
Result tables
</label>
<input
type=
"text"
class=
"gf-form-input"
ng-model=
"ctrl.resultTableCount"
disabled=
"disabled"
>
<label
class=
"gf-form-label"
>
Result records
</label>
<input
type=
"text"
class=
"gf-form-input"
ng-model=
"ctrl.resultRecordCount"
disabled=
"disabled"
>
</div>
<div
class=
"gf-form gf-form--grow"
>
<div
class=
"gf-form-label gf-form-label--grow"
></div>
</div>
</div>
</query-editor-row>
\ No newline at end of file
public/app/plugins/datasource/influxdb-ifql/plugin.json
deleted
100644 → 0
View file @
56628996
{
"type"
:
"datasource"
,
"name"
:
"InfluxDB (IFQL) [BETA]"
,
"id"
:
"influxdb-ifql"
,
"defaultMatchFormat"
:
"regex values"
,
"metrics"
:
true
,
"annotations"
:
true
,
"alerting"
:
false
,
"queryOptions"
:
{
"minInterval"
:
true
},
"info"
:
{
"description"
:
"InfluxDB Data Source for IFQL Queries for Grafana"
,
"author"
:
{
"name"
:
"Grafana Project"
,
"url"
:
"https://grafana.com"
},
"logos"
:
{
"small"
:
"img/influxdb_logo.svg"
,
"large"
:
"img/influxdb_logo.svg"
},
"version"
:
"5.1.0"
}
}
\ No newline at end of file
public/app/plugins/datasource/influxdb-ifql/query_ctrl.ts
deleted
100644 → 0
View file @
56628996
import
appEvents
from
'app/core/app_events'
;
import
{
QueryCtrl
}
from
'app/plugins/sdk'
;
function
makeDefaultQuery
(
database
)
{
return
`from(db: "
${
database
}
")
|> range($range)
|> limit(n:1000)
`
;
}
export
class
InfluxIfqlQueryCtrl
extends
QueryCtrl
{
static
templateUrl
=
'partials/query.editor.html'
;
dataPreview
:
string
;
resultRecordCount
:
string
;
resultTableCount
:
string
;
resultFormats
:
any
[];
/** @ngInject **/
constructor
(
$scope
,
$injector
)
{
super
(
$scope
,
$injector
);
this
.
resultRecordCount
=
''
;
this
.
resultTableCount
=
''
;
if
(
this
.
target
.
query
===
undefined
)
{
this
.
target
.
query
=
makeDefaultQuery
(
this
.
datasource
.
database
);
}
this
.
resultFormats
=
[{
text
:
'Time series'
,
value
:
'time_series'
},
{
text
:
'Table'
,
value
:
'table'
}];
appEvents
.
on
(
'ds-request-response'
,
this
.
onResponseReceived
,
$scope
);
this
.
panelCtrl
.
events
.
on
(
'refresh'
,
this
.
onRefresh
,
$scope
);
this
.
panelCtrl
.
events
.
on
(
'data-received'
,
this
.
onDataReceived
,
$scope
);
}
onDataReceived
=
dataList
=>
{
this
.
resultRecordCount
=
dataList
.
reduce
((
count
,
model
)
=>
{
const
records
=
model
.
type
===
'table'
?
model
.
rows
.
length
:
model
.
datapoints
.
length
;
return
count
+
records
;
},
0
);
this
.
resultTableCount
=
dataList
.
length
;
};
onResponseReceived
=
response
=>
{
this
.
dataPreview
=
response
.
data
;
};
onRefresh
=
()
=>
{
this
.
dataPreview
=
''
;
this
.
resultRecordCount
=
''
;
this
.
resultTableCount
=
''
;
};
getCollapsedText
()
{
return
this
.
target
.
query
;
}
}
public/app/plugins/datasource/influxdb-ifql/response_parser.ts
deleted
100644 → 0
View file @
56628996
import
Papa
from
'papaparse'
;
import
flatten
from
'lodash/flatten'
;
import
groupBy
from
'lodash/groupBy'
;
import
TableModel
from
'app/core/table_model'
;
const
filterColumnKeys
=
key
=>
key
&&
key
[
0
]
!==
'_'
&&
key
!==
'result'
&&
key
!==
'table'
;
const
IGNORE_FIELDS_FOR_NAME
=
[
'result'
,
''
,
'table'
];
export
const
getTagsFromRecord
=
record
=>
Object
.
keys
(
record
)
.
filter
(
key
=>
key
[
0
]
!==
'_'
)
.
filter
(
key
=>
IGNORE_FIELDS_FOR_NAME
.
indexOf
(
key
)
===
-
1
)
.
reduce
((
tags
,
key
)
=>
{
tags
[
key
]
=
record
[
key
];
return
tags
;
},
{});
export
const
getNameFromRecord
=
record
=>
{
// Measurement and field
const
metric
=
[
record
.
_measurement
,
record
.
_field
];
// Add tags
const
tags
=
getTagsFromRecord
(
record
);
const
tagValues
=
Object
.
keys
(
tags
).
map
(
key
=>
`
${
key
}
=
${
tags
[
key
]}
`
);
return
[...
metric
,
...
tagValues
].
join
(
' '
);
};
const
parseCSV
=
(
input
:
string
)
=>
Papa
.
parse
(
input
,
{
header
:
true
,
comments
:
'#'
,
}).
data
;
export
const
parseValue
=
(
input
:
string
)
=>
{
const
value
=
parseFloat
(
input
);
return
isNaN
(
value
)
?
null
:
value
;
};
export
const
parseTime
=
(
input
:
string
)
=>
Date
.
parse
(
input
);
export
function
parseResults
(
response
:
string
):
any
[]
{
return
response
.
trim
().
split
(
/
\n\s
*
\s
/
);
}
export
function
getAnnotationsFromResult
(
result
:
string
,
options
:
any
)
{
const
data
=
parseCSV
(
result
);
if
(
data
.
length
===
0
)
{
return
[];
}
const
annotations
=
[];
const
textSelector
=
options
.
textCol
||
'_value'
;
const
tagsSelector
=
options
.
tagsCol
||
''
;
const
tagSelection
=
tagsSelector
.
split
(
','
).
map
(
t
=>
t
.
trim
());
data
.
forEach
(
record
=>
{
// Remove empty values, then split in different tags for comma separated values
const
tags
=
getTagsFromRecord
(
record
);
const
tagValues
=
flatten
(
tagSelection
.
filter
(
tag
=>
tags
[
tag
]).
map
(
tag
=>
tags
[
tag
].
split
(
','
)));
annotations
.
push
({
annotation
:
options
,
time
:
parseTime
(
record
.
_time
),
tags
:
tagValues
,
text
:
record
[
textSelector
],
});
});
return
annotations
;
}
export
function
getTableModelFromResult
(
result
:
string
)
{
const
data
=
parseCSV
(
result
);
const
table
=
new
TableModel
();
if
(
data
.
length
>
0
)
{
// First columns are fixed
const
firstColumns
=
[
{
text
:
'Time'
,
id
:
'_time'
},
{
text
:
'Measurement'
,
id
:
'_measurement'
},
{
text
:
'Field'
,
id
:
'_field'
},
];
// Dynamically add columns for tags
const
firstRecord
=
data
[
0
];
const
tags
=
Object
.
keys
(
firstRecord
)
.
filter
(
filterColumnKeys
)
.
map
(
key
=>
({
id
:
key
,
text
:
key
}));
const
valueColumn
=
{
id
:
'_value'
,
text
:
'Value'
};
const
columns
=
[...
firstColumns
,
...
tags
,
valueColumn
];
columns
.
forEach
(
c
=>
table
.
addColumn
(
c
));
// Add rows
data
.
forEach
(
record
=>
{
const
row
=
columns
.
map
(
c
=>
record
[
c
.
id
]);
table
.
addRow
(
row
);
});
}
return
table
;
}
export
function
getTimeSeriesFromResult
(
result
:
string
)
{
const
data
=
parseCSV
(
result
);
if
(
data
.
length
===
0
)
{
return
[];
}
// Group results by table ID (assume one table per timeseries for now)
const
tables
=
groupBy
(
data
,
'table'
);
const
seriesList
=
Object
.
keys
(
tables
)
.
map
(
id
=>
tables
[
id
])
.
map
(
series
=>
{
const
datapoints
=
series
.
map
(
record
=>
[
parseValue
(
record
.
_value
),
parseTime
(
record
.
_time
)]);
const
alias
=
getNameFromRecord
(
series
[
0
]);
return
{
datapoints
,
target
:
alias
};
});
return
seriesList
;
}
export
function
getValuesFromResult
(
result
:
string
)
{
const
data
=
parseCSV
(
result
);
return
data
.
map
(
record
=>
record
[
'_value'
]);
}
public/app/plugins/datasource/influxdb-ifql/specs/datasource.jest.ts
deleted
100644 → 0
View file @
56628996
import
moment
from
'moment'
;
import
{
TemplateSrv
}
from
'app/features/templating/template_srv'
;
import
Datasource
from
'../datasource'
;
describe
(
'InfluxDB (IFQL)'
,
()
=>
{
const
templateSrv
=
new
TemplateSrv
();
const
ds
=
new
Datasource
({
url
:
''
},
{},
templateSrv
);
const
DEFAULT_OPTIONS
=
{
rangeRaw
:
{
to
:
'now'
,
from
:
'now - 3h'
},
scopedVars
:
{},
targets
:
[],
};
describe
(
'prepareQueryTarget()'
,
()
=>
{
let
target
:
any
;
it
(
'replaces $range variable'
,
()
=>
{
target
=
ds
.
prepareQueryTarget
({
query
:
'from(db: "test") |> range($range)'
},
DEFAULT_OPTIONS
);
expect
(
target
.
query
).
toBe
(
'from(db: "test") |> range(start: -3h)'
);
});
it
(
'replaces $range variable with custom dates'
,
()
=>
{
const
to
=
moment
();
const
from
=
moment
().
subtract
(
1
,
'hours'
);
target
=
ds
.
prepareQueryTarget
(
{
query
:
'from(db: "test") |> range($range)'
},
{
...
DEFAULT_OPTIONS
,
rangeRaw
:
{
to
,
from
},
}
);
const
start
=
from
.
toISOString
();
const
stop
=
to
.
toISOString
();
expect
(
target
.
query
).
toBe
(
`from(db: "test") |> range(start:
${
start
}
, stop:
${
stop
}
)`
);
});
});
});
public/app/plugins/datasource/influxdb-ifql/specs/metric_find_query.jest.ts
deleted
100644 → 0
View file @
56628996
import
expandMacros
from
'../metric_find_query'
;
describe
(
'metric find query'
,
()
=>
{
describe
(
'expandMacros()'
,
()
=>
{
it
(
'returns a non-macro query unadulterated'
,
()
=>
{
const
query
=
'from(db:"telegraf") |> last()'
;
const
result
=
expandMacros
(
query
);
expect
(
result
).
toBe
(
query
);
});
it
(
'returns a measurement query for measurements()'
,
()
=>
{
const
query
=
' measurements(mydb) '
;
const
result
=
expandMacros
(
query
).
replace
(
/
\s
/g
,
''
);
expect
(
result
).
toBe
(
'from(db:"mydb")|>range($range)|>group(by:["_measurement"])|>distinct(column:"_measurement")|>group(none:true)'
);
});
it
(
'returns a tags query for tags()'
,
()
=>
{
const
query
=
' tags(mydb , mymetric) '
;
const
result
=
expandMacros
(
query
).
replace
(
/
\s
/g
,
''
);
expect
(
result
).
toBe
(
'from(db:"mydb")|>range($range)|>filter(fn:(r)=>r._measurement=="mymetric")|>keys()'
);
});
it
(
'returns a tag values query for tag_values()'
,
()
=>
{
const
query
=
' tag_values(mydb , mymetric, mytag) '
;
const
result
=
expandMacros
(
query
).
replace
(
/
\s
/g
,
''
);
expect
(
result
).
toBe
(
'from(db:"mydb")|>range($range)|>filter(fn:(r)=>r._measurement=="mymetric")'
+
'|>group(by:["mytag"])|>distinct(column:"mytag")|>group(none:true)'
);
});
it
(
'returns a field keys query for field_keys()'
,
()
=>
{
const
query
=
' field_keys(mydb , mymetric) '
;
const
result
=
expandMacros
(
query
).
replace
(
/
\s
/g
,
''
);
expect
(
result
).
toBe
(
'from(db:"mydb")|>range($range)|>filter(fn:(r)=>r._measurement=="mymetric")'
+
'|>group(by:["_field"])|>distinct(column:"_field")|>group(none:true)'
);
});
});
});
public/app/plugins/datasource/influxdb-ifql/specs/response_parser.jest.ts
deleted
100644 → 0
View file @
56628996
import
{
getAnnotationsFromResult
,
getNameFromRecord
,
getTableModelFromResult
,
getTimeSeriesFromResult
,
getValuesFromResult
,
parseResults
,
parseValue
,
}
from
'../response_parser'
;
import
response
from
'./sample_response_csv'
;
describe
(
'influxdb ifql response parser'
,
()
=>
{
describe
(
'parseResults()'
,
()
=>
{
it
(
'expects three results'
,
()
=>
{
const
results
=
parseResults
(
response
);
expect
(
results
.
length
).
toBe
(
2
);
});
});
describe
(
'getAnnotationsFromResult()'
,
()
=>
{
it
(
'expects a list of annotations'
,
()
=>
{
const
results
=
parseResults
(
response
);
const
annotations
=
getAnnotationsFromResult
(
results
[
0
],
{
tagsCol
:
'cpu'
});
expect
(
annotations
.
length
).
toBe
(
300
);
expect
(
annotations
[
0
].
tags
.
length
).
toBe
(
1
);
expect
(
annotations
[
0
].
tags
[
0
]).
toBe
(
'cpu-total'
);
expect
(
annotations
[
0
].
text
).
toBe
(
'0'
);
});
});
describe
(
'getTableModelFromResult()'
,
()
=>
{
it
(
'expects a table model'
,
()
=>
{
const
results
=
parseResults
(
response
);
const
table
=
getTableModelFromResult
(
results
[
0
]);
expect
(
table
.
columns
.
length
).
toBe
(
6
);
expect
(
table
.
rows
.
length
).
toBe
(
300
);
});
});
describe
(
'getTimeSeriesFromResult()'
,
()
=>
{
it
(
'expects time series'
,
()
=>
{
const
results
=
parseResults
(
response
);
const
series
=
getTimeSeriesFromResult
(
results
[
0
]);
expect
(
series
.
length
).
toBe
(
50
);
expect
(
series
[
0
].
datapoints
.
length
).
toBe
(
6
);
});
});
describe
(
'getValuesFromResult()'
,
()
=>
{
it
(
'returns all values from the _value field in the response'
,
()
=>
{
const
results
=
parseResults
(
response
);
const
values
=
getValuesFromResult
(
results
[
0
]);
expect
(
values
.
length
).
toBe
(
300
);
});
});
describe
(
'getNameFromRecord()'
,
()
=>
{
it
(
'expects name based on measurements and tags'
,
()
=>
{
const
record
=
{
''
:
''
,
result
:
''
,
table
:
'0'
,
_start
:
'2018-06-02T06:35:25.651942602Z'
,
_stop
:
'2018-06-02T07:35:25.651942602Z'
,
_time
:
'2018-06-02T06:35:31Z'
,
_value
:
'0'
,
_field
:
'usage_guest'
,
_measurement
:
'cpu'
,
cpu
:
'cpu-total'
,
host
:
'kenobi-3.local'
,
};
expect
(
getNameFromRecord
(
record
)).
toBe
(
'cpu usage_guest cpu=cpu-total host=kenobi-3.local'
);
});
});
describe
(
'parseValue()'
,
()
=>
{
it
(
'parses a number'
,
()
=>
{
expect
(
parseValue
(
'42.3'
)).
toBe
(
42.3
);
});
it
(
'parses a non-number to null'
,
()
=>
{
expect
(
parseValue
(
'foo'
)).
toBe
(
null
);
});
});
});
public/app/plugins/datasource/influxdb-ifql/specs/sample_response_csv.ts
deleted
100644 → 0
View file @
56628996
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment