GithubHelp home page GithubHelp logo

metrico / fluxpipe Goto Github PK

View Code? Open in Web Editor NEW
55.0 7.0 3.0 16.53 MB

TLDR: Flux for InfluxDB 3.0. Stand-alone, Serverless Flux API/Pipeline for querying, analyzing and interacting with remote data.

Home Page: https://fluxpipe.fly.dev

License: MIT License

Go 38.94% FLUX 55.94% Shell 3.13% Dockerfile 2.00%
flux influx go influxdb clickhouse fluxlang serverless qryn analytics query-language fluxlib flightsql influxdb-client influxdb3 iox

fluxpipe's Introduction

Build-n-Release

FluxPipe is an experimental stand-alone Flux API for serverless workers and embedded datasources
Execute your Flux scripts locally, in serverless functions or anywhere else - decoupled from the data and database.

Fluxpipe runs at 141,6Km/h* and is compatible with InfluxDB 3.0 / IOx, ClickHouse, Grafana and beyond!


InfluxDB Flux is a lightweight scripting language for querying databases and working with data. 1
Need a Flux introduction? Check out the official page, documentation or "3 Minutes to Flux" guide.

Demo

Try our serverless demo or launch your own instance to instantly fall in love with flux


Instructions

Download a binary release, docker or build from source

๐Ÿ“ฆ Download Binary

curl -fsSL github.com/metrico/fluxpipe/releases/latest/download/fluxpipe-server -O \
&& chmod +x fluxpipe-server
๐Ÿ”Œ Start Server w/ Options
./fluxpipe-server -port 8086

Run with -h for a full list of parameters

๐Ÿ‹ Using Docker

docker pull ghcr.io/metrico/fluxpipe:latest
docker run -ti --rm -p 8086:8086 ghcr.io/metrico/fluxpipe:latest

๐Ÿ› Usage

๐Ÿ’ก Check out the scripts folder for working examples

Playground

Fluxpipe embeds a playground interface to instantly execute queries (borrowed from ClickHouse 2)


HTTP API

Fluxpipe serves a simple REST API loosely compatible with existing flux integrations and clients

Grafana Flux 1

Fluxpipe is compatible with the native Grafana InfluxDB/Flux datasource (url + organization fields are required!)


โญ FlightSQL
SQL

You can query InfluxDB 3.0 IOx with raw SQL using the native sql.from handler

import "sql"

sql.from(
    driverName: "influxdb-iox",
    dataSourceName: "iox://iox-server:443/qryn_logs",
    query: "SELECT level, sender, body FROM logs WHERE body LIKE '%DELETE%' limit 10",
)

image

Flux IOx

You can query InfluxDB 3.0 IOx with Flux using the iox.from handler

import "contrib/qxip/iox"
iox.from(
     bucket: "test",
     host: "eu-central-1-1.aws.cloud2.influxdata.com:443",
     token: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
     limit: "10",
     columns: "time, level, sender",
     table: "logs",
     start: -100d,
)
                    _time:time            level:string           sender:string
------------------------------  ----------------------  ----------------------
2023-08-31T00:00:00.091362490Z                    info                 logtest
2023-08-31T00:00:00.091380034Z                    info                 logtest
2023-08-31T00:00:00.091381374Z                    info                 logtest
2023-08-31T00:00:00.091382470Z                    info                 logtest
2023-08-31T00:00:00.091383354Z                    info                 logtest
...

You write data back to InfluxDB 3.0 IOx using the to and wideTo functions

import "contrib/qxip/iox"
import "influxdata/influxdb"
iox.from(
     bucket: "qxip",
     host: "eu-central-1-1.aws.cloud2.influxdata.com:443",
     token: "",
     limit: "10",
     table: "machine_data",
     start: -2d,
 )
 |> range(start: -2d)
 |> aggregateWindow(every: 5s, fn: mean, column: "load", createEmpty: false)
 |> set(key: "_measurement", value: "downsampled")
 |> wideTo(
     bucket: "qxip",
     host: "https://eu-central-1-1.aws.cloud2.influxdata.com",
     token: "",
     orgID: "6a841c0c08328fb1"
    )

โญ ClickHouse SQL
import "contrib/qxip/clickhouse"

clickhouse.query(
  url: "https://[email protected]",
  query: "SELECT database, total_rows FROM tables WHERE total_rows > 0"
)
|> rename(columns: {database: "_value", total_rows: "_data"})
|> keep(columns: ["_value","_data"])

image

image

โญ LogQL
import "contrib/qxip/logql"

option logql.defaultURL = "http://qryn:3100"
logql.query_range(
     query: "rate({job=\"dummy-server\"}[5m])",
     start: v.timeRangeStart, 
     end: v.timeRangeStop
)
|> map(fn: (r) => ({r with _time: time(v: uint(v: r.timestamp_ns)), _value: float(v: r.value) }))
|> drop(columns: ["timestamp_ns", "value"])
|> sort(columns: ["_time"])
|> group(columns: ["labels"])

image

โญ CURL POST

Usage with curl

curl -XPOST localhost:8086/api/v2/query -sS \
  -H 'Accept:application/csv' \
  -H 'Content-type:application/vnd.flux' \
  -d 'import g "generate" g.from(start: 2022-04-01T00:00:00Z, stop: 2022-04-01T00:03:00Z, count: 3, fn: (n) => n)'

Secrets

Flux builds using EnvironmentSecretService accessing system environment variables from flux scripts.

import "influxdata/influxdb/secrets"
key = secrets.get(key: "ENV_SECRET")

STDIN CMD

Fluxpipe can be used as a command-line tool and stdin pipeline processor

Generate CSV
echo 'import g "generate" g.from(start: 2022-04-01T00:00:00Z, stop: 2022-04-01T00:03:00Z, count: 5, fn: (n) => 1)' \
| ./fluxpipe-server -stdin
Parse CSV
cat scripts/csv.flux | ./fluxpipe-server -stdin
Query SQL
cat scripts/sql.flux | ./fluxpipe-server -stdin

Public Demo

Grafana Datasource

Configure your Grafana instance with our public demo endpoint (limited resources) image

Documentation

Flux(pipe) is built using the InfluxCommunity/flux fork which contains additional features and contributions.
All the standard and additional functions available in Fluxpipe are included in the Flux community documentation


Status

  • Fluxlib
    • parser
    • executor
  • Contribs
    • contrib/qxip/clickhouse
    • contrib/qxip/logql
    • contrib/qxip/hash
    • ENV secrets
  • STDIN pipeline
  • HTTP api
    • plaintext
    • json support
    • web playground

Footnotes

  1. Project is not affiliated or endorsed by Influxdata or Grafana Labs. All rights belong to their respective owners. โ†ฉ โ†ฉ2

  2. Used under Apache2 terms. Project is not affiliated or endorsed by ClickHouse Inc. All rights belong to their respective owners. โ†ฉ

fluxpipe's People

Contributors

adubovikov avatar akvlad avatar dletta avatar lmangani avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

fluxpipe's Issues

Panic Handling

Generic errors are handled correctly, ie:

import "array"
import "runtime"
array.from(rows: [{version: runtime.version() - "string" }])
{"code":"invalid","message":"error @3:29-3:57: string is not Subtractable"}

This is fine.

Library panic events are not correctly returned to the client, ie (float/string panic inside a column):

import "experimental/csv"
csv.from(url: "https://influx-testdata.s3.amazonaws.com/noaa.csv")
 
|> filter(fn: (r) => r._measurement == "average_temperature")
|> map(fn: (r) => ({r with celsius: (( r._value - 32.0) * 5.0 / 9.0)} ))
{"message":"Internal Server Error"}

The actual error is only available in the debug log on the server side:

{"time":"2023-04-13T13:34:33.304082423Z","level":"-","prefix":"echo","file":"recover.go","line":"92","message":"[PANIC RECOVER] runtime error [@5:4-5:62](https://matrix.to/#/@5:4-5:62): filter: type conflict: float != string goroutine 24 [running]:\[ngithub.com/labstack/echo/v4/middleware.RecoverWithConfig.func1.1.1()\n\t/home/runner/go/pkg/mod/github.com/labstack/echo/[email protected]/middleware/recover.go:77](http://ngithub.com/labstack/echo/v4/middleware.RecoverWithConfig.func1.1.1()/n/t/home/runner/go/pkg/mod/github.com/labstack/echo/[email protected]/middleware/recover.go:77) +0x10d\npanic({0x19c7760, 0xc0016e8bc0})\n\t/opt/hostedtoolcache/go/1.18.10/x64/src/runtime/panic.go:838 +0x207\nmain.exec({0xc001690f00, 0x13e})\n\t/home/runner/work/fluXpipe/fluXpipe/fluxpipe-server.go:151 +0x737\nmain.postQuery({0x1ecc518, 0xc00079d7c0})\n\t/home/runner/work/fluXpipe/fluXpipe/fluxpipe-server.go:97 +0x5d3\[ngithub.com/labstack/echo/v4.(*Echo).add.func1({0x1ecc518,](http://ngithub.com/labstack/echo/v4.(*Echo).add.func1(%7B0x1ecc518,) 0xc00079d7c0})\n\t/home/runner/go/pkg/mod/[github.com/labstack/echo/[email protected]/echo.go:536](http://github.com/labstack/echo/[email protected]/echo.go:536) +0x51\[ngithub.com/labstack/echo/v4/middleware.CORSWithConfig.func1.1({0x1ecc518,](http://ngithub.com/labstack/echo/v4/middleware.CORSWithConfig.func1.1(%7B0x1ecc518,) 0xc00079d7c0})\n\t/home/runner/go/pkg/mod/[github.com/labstack/echo/[email protected]/middleware/cors.go:186](http://github.com/labstack/echo/[email protected]/middleware/cors.go:186) +0xe98\[ngithub.com/labstack/echo/v4/middleware.RecoverWithConfig.func1.1({0x1ecc518,](http://ngithub.com/labstack/echo/v4/middleware.RecoverWithConfig.func1.1(%7B0x1ecc518,) 0xc00079d7c0})\n\t/home/runner/go/pkg/mod/[github.com/labstack/echo/[email protected]/middleware/recover.go:98](http://github.com/labstack/echo/[email protected]/middleware/recover.go:98) +0xf8\[ngithub.com/labstack/echo/v4/middleware.LoggerWithConfig.func2.1({0x1ecc518,](http://ngithub.com/labstack/echo/v4/middleware.LoggerWithConfig.func2.1(%7B0x1ecc518,) 0xc00079d7c0})\n\t/home/runner/go/pkg/mod/[github.com/labstack/echo/[email protected]/middleware/logger.go:117](http://github.com/labstack/echo/[email protected]/middleware/logger.go:117) +0xe2\[ngithub.com/labstack/echo/v4.(*Echo).ServeHTTP(0xc000b25200,](http://ngithub.com/labstack/echo/v4.(*Echo).ServeHTTP(0xc000b25200,) {0x1eb9e50?, 0xc0004f4fc0}, 0xc0018a2000)\n\t/home/runner/go/pkg/mod/[github.com/labstack/echo/[email protected]/echo.go:646](http://github.com/labstack/echo/[email protected]/echo.go:646) +0x3bc\nnet/http.serverHandler.ServeHTTP({0x1eb5cc0?}, {0x1eb9e50, 0xc0004f4fc0}, 0xc0018a2000)\n\t/opt/hostedtoolcache/go/1.18.10/x64/src/net/http/server.go:2916 +0x43b\nnet/http.(*conn).serve(0xc00079d720, {0x1ebada0, 0xc001830990})\n\t/opt/hostedtoolcache/go/1.18.10/x64/src/net/http/server.go:1966 +0x5d7\ncreated by net/http.(*Server).Serve\n\t/opt/hostedtoolcache/go/1.18.10/x64/src/net/http/server.go:3071 +0x4db\n\ngoroutine 1 [IO wait]:\ninternal/poll.runtime_pollWait(0x7f2693a80d90, 0x72)\n\t/opt/hostedtoolcache/go/1.18.10/x64/src/runtime/netpoll.go:302 +0x89\ninternal/poll.(*pollDesc).wait(0xc001821b80?, 0xc0000021a0?, 0x0)\n\t/opt/hostedtoolcache/go/1.18.10/x64/src/internal/poll/fd_poll_runtime.go:83 +0x32\ninternal/poll.(*pollDesc).waitRead(...)\n\t/opt/hostedtoolcache/go/1.18.10/x64/src/internal/poll/fd_poll_runtime.go:88\ninternal/poll.(*FD).Accept(0xc001821b80)\n\t/opt/hostedtoolcache/go/1.18.10/x64/src/internal/poll/fd_unix.go:614 +0x22c\nnet.(*netFD).accept(0xc001821b80)\n\t/opt/hostedtoolcache/go/1.18.10/x64/src/net/fd_unix.go:172 +0x35\nnet.(*TCPListener).accept(0xc0016e7968)\n\t/opt/hostedtoolcache/go/1.18.10/x64/src/net/tcpsock_posix.go:139 +0x28\nnet.(*TCPListener).AcceptTCP(0xc0016e7968)\n\t/opt/hostedtoolcache/go/1.18.10/x64/src/net/tcpsock.go:275 +0x3d\[ngithub.com/labstack/echo/v4.tcpKeepAliveListener.Accept({0x44e0c0?})\n\t/home/runner/go/pkg/mod/github.com/labstack/echo/[email protected]/echo.go:955](http://ngithub.com/labstack/echo/v4.tcpKeepAliveListener.Accept(%7B0x44e0c0?})\n\t/home/runner/go/pkg/mod/github.com/labstack/echo/[email protected]/echo.go:955) +0x1d\nnet/http.(*Server).Serve(0xc0004f4c40, {0x1eb90d0, 0xc000010650})\n\t/opt/hostedtoolcache/go/1.18.10/x64/src/net/http/server.go:3039 +0x385\[ngithub.com/labstack/echo/v4.(*Echo).Start(0xc000b25200,](http://ngithub.com/labstack/echo/v4.(*Echo).Start(0xc000b25200,) {0xc0017f5638, 0x5})\n\t/home/runner/go/pkg/mod/[github.com/labstack/echo/[email protected]/echo.go:663](http://github.com/labstack/echo/[email protected]/echo.go:663) +0xc7\nmain.main()\n\t/home/runner/work/fluXpipe/fluXpipe/fluxpipe-server.go:221 +0x85a\n\ngoroutine 7 [select]:\[ngo.opencensus.io/stats/view.(*worker).start(0xc0003c8180)\n\t/home/runner/go/pkg/mod/[email protected]/stats/view/worker.go:276](http://ngo.opencensus.io/stats/view.(*worker).start(0xc0003c8180)/n/t/home/runner/go/pkg/mod/[email protected]/stats/view/worker.go:276) +0xad\ncreated by [go.opencensus.io/stats/view.init.0\n\t/home/runner/go/pkg/mod/[email protected]/stats/view/worker.go:34](http://go.opencensus.io/stats/view.init.0/n/t/home/runner/go/pkg/mod/[email protected]/stats/view/worker.go:34) +0x8d\n\ngoroutine 26 [IO wait]:\ninternal/poll.runtime_pollWait(0x7f2693a80ca0, 0x72)\n\t/opt/hostedtoolcache/go/1.18.10/x64/src/runtime/netpoll.go:302 +0x89\ninternal/poll.(*pollDesc).wait(0xc001821c00?, 0xc001830a91?, 0x0)\n\t/opt/hostedtoolcache/go/1.18.10/x64/src/internal/poll/fd_poll_runtime.go:83 +0x32\ninternal/poll.(*pollDesc).waitRead(...)\n\t/opt/hostedtoolcache/go/1.18.10/x64/src/internal/poll/fd_poll_runtime.go:88\ninternal/poll.(*FD).Read(0xc001821c00, {0xc001830a91, 0x1, 0x1})\n\t/opt/hostedtoolcache/go/1.18.10/x64/src/internal/poll/fd_unix.go:167 +0x25a\nnet.(*netFD).Read(0xc001821c00, {0xc001830a91?, 0xc00182f998?, 0xc0004ca768?})\n\t/opt/hostedtoolcache/go/1.\n"}

or simply

runtime error [@5:4-5:62](https://matrix.to/#/@5:4-5:62): filter: type conflict: float != string

The library panic message (or at least the runtime error string) should be returned to the client.
Since this is not a panic/err of the API handler, the output is uncaught.

Is the to() and wideTo() function supported?

We are currently testing the ability to write data back to InfluxDB.

 import "contrib/qxip/iox"
 import "influxdata/influxdb"
 iox.from(
     bucket: "quix",
     host: "eu-central-1-1.aws.cloud2.influxdata.com:443",
     token: "",
     limit: "10",
     table: "machine_data",
     start: -2d,
 )
 |> range(start: -2d)
 |> aggregateWindow(every: 5s, fn: mean, column: "load", createEmpty: false)
 |> set(key: "_measurement", value: "downsampled")
 |> wideTo(
     bucket: "quix",
     host: "https://eu-central-1-1.aws.cloud2.influxdata.com",
     token: "",
     orgID: "6a841c0c08328fb1"
    )

Is this currently possible? This would be a great feature for task-based downsampling/enrichment.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.