Giter Club home page Giter Club logo

facette's Introduction

Facette Travis CI

Facette is a open source web application to display time series data from various sources — such as collectd, Graphite, InfluxDB or KairosDB — on graphs. To learn more on its architecture, read this page.

The source code is available at Github and is licensed under the terms of the BSD license.

Screenshot

Installation

Please see INSTALL.md file for build instructions and installation procedures.

Contribution

We welcome all your contributions. So, don't hesitate to fork the project, make your changes and submit us your pull requests.

However, as Facette is under development and still subject to heavy changes, please open an issue to discuss yours if you think that they will have quite an impact on the code base before starting contributing.

To make the things easier, we will ask for the following:

  • Always use gofmt
  • Keep code lines length under 120 characters
  • Provide (when applicable) unit tests for the new code
  • Make sure to run make test, having the process completing successfully
  • Squash your commits into a single commit

facette's People

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  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  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

facette's Issues

Document the `range` API parameter

The API documentation mentions a range parameter featured in code examples such as:

{
    "graph": "909fe2df-3064-4ee2-5f52-4eca2c953c76",
    "range": "-1d"
}

...but it lacks an actual documentation of the valid value format expected for this parameter.

On-the-fly graph series re-ordering

Some graphs series have plot points with higher values than the other series, thus masking them. It could be helpful to be able to temporarily re-order the series' z-index to make the "smaller" ones more visible.

Set sensible defaults to server "mandatory" settings

Set sensible default values to server configuration settings and drop mandatory settings from documentation:

  • bind: localhost:12003
  • base_dir: /usr/share/facette
  • data_dir: /var/lib/facette
  • providers_dir: /etc/facette/providers

Gracefully handle backend failure

When an error occurs at the backend level — resulting in a 5XX status code for the AJAX queries — the JS frontend "crashes": some UI elements disappear (e.g. graph menu), and don't come back until the whole page is refreshed.

The JS should handle these backend failures more gracefully.

m.

Configuration setting helpers

Implement configuration helper functions to facilitate settings value retrieval in the backend and avoid boilerplate code duplication. The signature of the helper functions would be something like:

config.GetString(config map[string]interface{}, setting string, mandatory bool) (string, err)
config.GetInt(config map[string]interface{}, setting string, mandatory bool) (int, err)
config.GetFloat(config map[string]interface{}, setting string, mandatory bool) (float64, err)
config.GetBool(config map[string]interface{}, setting string, mandatory bool) (bool, err)

This way, the following code:

if _, ok := config["url"]; !ok {
    return nil, fmt.Errorf("missing `url' mandatory connector setting")
}

if configURL, ok = config["url"].(string); !ok {
    return nil, fmt.Errorf("connector setting `url' value should be a string")
}

if _, ok = config["timeout"]; ok {
    if configTimeout, ok = config["timeout"].(float64); !ok {
        return nil, fmt.Errorf("connector setting `timeout' value should be numeric")
    }
}

...would become something like this:

if configURL, err = config.getString(config, "url", true); err != nil {
    return nil, err
}

if configTimeout, err = config.getFloat(config, "timeout", false); err != nil {
    return nil, err
}

Move supported connectors list to `facettectl version`

Move the list of supported connectors list from facettectl support to facettectl version command, and display the Facette and Go compiler versions:

$ facettectl version
Facette version x.y.z
Provider connectors:
   ...
Go version: x.y.z

Prefix API URLs

We should prefix the app API URLs with /api/<API version>/... to allow API changes in the future without breaking legacy clients.

Example:

/api/v1/library/graphs/plots
/api/v1/library/collection

Handle startup errors logging

When the configuration files contain syntax errors, they are not logged in file pointed by the server_log setting.

Add plot points sampling to "graphite" connector

The Graphite REST API does not support downsampling when requesting plot points, and returns all points matching the specifed time interval to the original precision of the whisper databases storing the points. If the whisper precision is high, a large volume of points returned by the back-end can is heavily soliciting the front-end's graphing library and can even freeze the browser.

We have to perform the downsampling manually at the back-end level to avoid overloading the front-end rendering by honoring the sample parameter in the series query.

Back-end crashes if startup is interrupted during provider refresh

The back-end crashes if a shutdown is initiated while a provider is refreshing the catalog:

$ ~/facette/build/facette-linux-amd64/bin/facette -c ~/.facette/etc/facette.json -L info
2014/07/04 08:02:21 INFO: library: refresh started
2014/07/04 08:02:21 INFO: library: refresh completed
2014/07/04 08:02:21 INFO: provider: graphite: received refresh command
2014/07/04 08:02:21 INFO: provider: collectd: received refresh command
2014/07/04 08:02:21 INFO: serveWorker: listening on :9009
^C2014/07/04 08:02:21 NOTICE: server: shutting down server
2014/07/04 08:02:21 INFO: serveWorker: received shutdown command, stopping job
2014/07/04 08:02:21 INFO: serveWorker: server listener closed
panic: runtime error: send on closed channel

goroutine 30 [running]:
runtime.panic(0x7c4be0, 0xc333be)
    /usr/lib/go/src/pkg/runtime/panic.c:279 +0xf5
github.com/facette/facette/pkg/connector.func·005(0xc20811b240, 0x3e, 0x7fb9a7289b48, 0xc208186cd0, 0x0, 0x0, 0x0, 0x0)
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/connector/rrd.go:321 +0x94c
github.com/facette/facette/pkg/utils.func·002(0xc20811b240, 0x3e, 0x7fb9a7289b48, 0xc208186cd0, 0x0, 0x0, 0x0, 0x0)
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/utils/os.go:27 +0x26f
path/filepath.walk(0xc20811b240, 0x3e, 0x7fb9a7289b48, 0xc208186cd0, 0x7fb9a70f4ce0, 0x0, 0x0)
    /usr/lib/go/src/pkg/path/filepath/path.go:343 +0x8c
path/filepath.walk(0xc2081388a0, 0x2a, 0x7fb9a7289b48, 0xc208186c80, 0x7fb9a70f4ce0, 0x0, 0x0)
    /usr/lib/go/src/pkg/path/filepath/path.go:368 +0x4f5
path/filepath.walk(0xc208138cc0, 0x23, 0x7fb9a7289b48, 0xc208130870, 0x7fb9a70f4ce0, 0x0, 0x0)
    /usr/lib/go/src/pkg/path/filepath/path.go:368 +0x4f5
path/filepath.walk(0xc20803ec40, 0x15, 0x7fb9a7289b48, 0xc208130820, 0x7fb9a70f4ce0, 0x0, 0x0)
    /usr/lib/go/src/pkg/path/filepath/path.go:368 +0x4f5
path/filepath.Walk(0xc20803ec40, 0x15, 0x7fb9a70f4ce0, 0x0, 0x0)
    /usr/lib/go/src/pkg/path/filepath/path.go:390 +0xe5
github.com/facette/facette/pkg/utils.walkDir(0xc20803ec40, 0x15, 0x80adf0, 0x0, 0x7fb9a70f4e50, 0x0, 0x0)
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/utils/os.go:29 +0xcb
github.com/facette/facette/pkg/utils.WalkDir(0xc20803ec40, 0x15, 0x7fb9a70f4e50, 0x0, 0x0)
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/utils/os.go:34 +0x61
github.com/facette/facette/pkg/connector.(*RRDConnector).Refresh(0xc2080ca2c0, 0xc208023822, 0x8, 0xc2080043c0, 0x0, 0x0)
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/connector/rrd.go:328 +0x2da
github.com/facette/facette/pkg/server.workerProviderRun(0xc20800fae0, 0xc2080ac9d0, 0x1, 0x1)
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/server/worker_provider.go:127 +0x589
created by github.com/facette/facette/pkg/worker.func·001
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/worker/worker.go:59 +0x11f

goroutine 16 [semacquire]:
sync.runtime_Semacquire(0xc2080019e0)
    /usr/lib/go/src/pkg/runtime/sema.goc:199 +0x30
sync.(*WaitGroup).Wait(0xc20803e8a0)
    /usr/lib/go/src/pkg/sync/waitgroup.go:129 +0x14b
github.com/facette/facette/pkg/server.(*Server).Run(0xc20804e080, 0x0, 0x0)
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/server/server.go:156 +0xb29
main.main()
    /home/marc/facette/cmd/facette/facette.go:79 +0x343

goroutine 19 [finalizer wait]:
runtime.park(0x415580, 0xc4bcb8, 0xc381c9)
    /usr/lib/go/src/pkg/runtime/proc.c:1369 +0x89
runtime.parkunlock(0xc4bcb8, 0xc381c9)
    /usr/lib/go/src/pkg/runtime/proc.c:1385 +0x3b
runfinq()
    /usr/lib/go/src/pkg/runtime/mgc0.c:2644 +0xcf
runtime.goexit()
    /usr/lib/go/src/pkg/runtime/proc.c:1445

goroutine 17 [syscall]:
runtime.goexit()
    /usr/lib/go/src/pkg/runtime/proc.c:1445

goroutine 20 [syscall]:
os/signal.loop()
    /usr/lib/go/src/pkg/os/signal/signal_unix.go:21 +0x1e
created by os/signal.init·1
    /usr/lib/go/src/pkg/os/signal/signal_unix.go:27 +0x32

goroutine 21 [semacquire]:
sync.runtime_Semacquire(0xc2080019e4)
    /usr/lib/go/src/pkg/runtime/sema.goc:199 +0x30
sync.(*WaitGroup).Wait(0xc20803f880)
    /usr/lib/go/src/pkg/sync/waitgroup.go:129 +0x14b
github.com/facette/facette/pkg/server.(*Server).stopProviderWorkers(0xc20804e080)
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/server/worker_provider.go:59 +0x133
github.com/facette/facette/pkg/server.(*Server).Stop(0xc20804e080)
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/server/server.go:177 +0x1fb
main.func·002()
    /home/marc/facette/cmd/facette/facette.go:72 +0x16e
created by main.main
    /home/marc/facette/cmd/facette/facette.go:76 +0x32d

goroutine 22 [chan receive]:
github.com/facette/facette/pkg/worker.func·001(0xc20800f2c0)
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/worker/worker.go:54 +0x5f
created by github.com/facette/facette/pkg/worker.NewWorker
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/worker/worker.go:61 +0x135

goroutine 24 [runnable]:
github.com/facette/facette/pkg/provider.func·001(0xc2080043c0, 0xc2080040c0, 0xc20804e600, 0xe, 0x10)
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/provider/filter.go:50 +0x61
created by github.com/facette/facette/pkg/provider.newFilterChain
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/provider/filter.go:112 +0x4f0

goroutine 25 [runnable]:
github.com/facette/facette/pkg/provider.func·001(0xc208004e40, 0xc2080040c0, 0xc2080ac950, 0x2, 0x2)
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/provider/filter.go:50 +0x61
created by github.com/facette/facette/pkg/provider.newFilterChain
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/provider/filter.go:112 +0x4f0

goroutine 26 [runnable]:
github.com/facette/facette/pkg/worker.func·001(0xc20800fae0)
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/worker/worker.go:54 +0x5f
created by github.com/facette/facette/pkg/worker.NewWorker
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/worker/worker.go:61 +0x135

goroutine 27 [select]:
github.com/facette/facette/pkg/server.workerCatalogRun(0xc20800f2c0, 0xc208000f00, 0x1, 0x1)
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/server/worker_catalog.go:39 +0x26a
created by github.com/facette/facette/pkg/worker.func·001
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/worker/worker.go:59 +0x11f

goroutine 29 [chan receive]:
github.com/facette/facette/pkg/worker.func·001(0xc20800fb30)
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/worker/worker.go:54 +0x5f
created by github.com/facette/facette/pkg/worker.NewWorker
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/worker/worker.go:61 +0x135

goroutine 33 [select]:
net/http.(*persistConn).roundTrip(0xc208064a50, 0xc2080ad6a0, 0x0, 0x0, 0x0)
    /usr/lib/go/src/pkg/net/http/transport.go:1015 +0x6db
net/http.(*Transport).RoundTrip(0xc20804e580, 0xc208027ee0, 0xd, 0x0, 0x0)
    /usr/lib/go/src/pkg/net/http/transport.go:208 +0x49a
net/http.send(0xc208027ee0, 0x7fb9a72898f0, 0xc20804e580, 0xc2080294b4, 0x0, 0x0)
    /usr/lib/go/src/pkg/net/http/client.go:195 +0x43d
net/http.(*Client).send(0xc208138a20, 0xc208027ee0, 0x36, 0x0, 0x0)
    /usr/lib/go/src/pkg/net/http/client.go:118 +0x15b
net/http.(*Client).doFollowingRedirects(0xc208138a20, 0xc208027ee0, 0x8e7330, 0x0, 0x0, 0x0)
    /usr/lib/go/src/pkg/net/http/client.go:343 +0x97f
net/http.(*Client).Do(0xc208138a20, 0xc208027ee0, 0x10, 0x0, 0x0)
    /usr/lib/go/src/pkg/net/http/client.go:150 +0xa3
github.com/facette/facette/pkg/connector.(*GraphiteConnector).Refresh(0xc20803f8e0, 0xc208023dc2, 0x8, 0xc208004e40, 0x0, 0x0)
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/connector/graphite.go:156 +0x40e
github.com/facette/facette/pkg/server.workerProviderRun(0xc20800fb30, 0xc2080aca60, 0x1, 0x1)
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/server/worker_provider.go:127 +0x589
created by github.com/facette/facette/pkg/worker.func·001
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/worker/worker.go:59 +0x11f

goroutine 47 [IO wait]:
net.runtime_pollWait(0x7fb9a728b208, 0x72, 0x0)
    /usr/lib/go/src/pkg/runtime/netpoll.goc:146 +0x66
net.(*pollDesc).Wait(0xc208028060, 0x72, 0x0, 0x0)
    /usr/lib/go/src/pkg/net/fd_poll_runtime.go:84 +0x46
net.(*pollDesc).WaitRead(0xc208028060, 0x0, 0x0)
    /usr/lib/go/src/pkg/net/fd_poll_runtime.go:89 +0x42
net.(*netFD).Read(0xc208028000, 0xc208053000, 0x400, 0x400, 0x0, 0x7fb9a7289720, 0xb)
    /usr/lib/go/src/pkg/net/fd_unix.go:232 +0x34c
net.(*conn).Read(0xc208038018, 0xc208053000, 0x400, 0x400, 0x0, 0x0, 0x0)
    /usr/lib/go/src/pkg/net/net.go:122 +0xe7
crypto/tls.(*block).readFromUntil(0xc208087380, 0x7fb9a728b578, 0xc208038018, 0x5, 0x0, 0x0)
    /usr/lib/go/src/pkg/crypto/tls/conn.go:451 +0xd9
crypto/tls.(*Conn).readRecord(0xc20804c580, 0x17, 0x0, 0x0)
    /usr/lib/go/src/pkg/crypto/tls/conn.go:536 +0x1ff
crypto/tls.(*Conn).Read(0xc20804c580, 0xc208127000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
    /usr/lib/go/src/pkg/crypto/tls/conn.go:901 +0x16a
net/http.noteEOFReader.Read(0x7fb9a728fe20, 0xc20804c580, 0xc208064aa8, 0xc208127000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
    /usr/lib/go/src/pkg/net/http/transport.go:1203 +0x72
net/http.(*noteEOFReader).Read(0xc208191600, 0xc208127000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
    <autogenerated>:124 +0xca
bufio.(*Reader).fill(0xc208132cc0)
    /usr/lib/go/src/pkg/bufio/bufio.go:97 +0x1b3
bufio.(*Reader).Peek(0xc208132cc0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0)
    /usr/lib/go/src/pkg/bufio/bufio.go:132 +0x101
net/http.(*persistConn).readLoop(0xc208064a50)
    /usr/lib/go/src/pkg/net/http/transport.go:782 +0x95
created by net/http.(*Transport).dialConn
    /usr/lib/go/src/pkg/net/http/transport.go:600 +0x93f

goroutine 50 [runnable]:
github.com/facette/facette/pkg/server.workerProviderShutdown(0xc20800fae0, 0xc2080019f0, 0x1, 0x1)
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/server/worker_provider.go:86
created by github.com/facette/facette/pkg/worker.func·001
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/worker/worker.go:59 +0x11f

goroutine 51 [runnable]:
github.com/facette/facette/pkg/server.workerProviderShutdown(0xc20800fb30, 0xc2080019f0, 0x1, 0x1)
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/server/worker_provider.go:86
created by github.com/facette/facette/pkg/worker.func·001
    /home/marc/facette/tmp/src/github.com/facette/facette/pkg/worker/worker.go:59 +0x11f

goroutine 48 [select]:
net/http.(*persistConn).writeLoop(0xc208064a50)
    /usr/lib/go/src/pkg/net/http/transport.go:885 +0x38f
created by net/http.(*Transport).dialConn
    /usr/lib/go/src/pkg/net/http/transport.go:601 +0x957

UI tooltips

Add help "tooltips" to the UI (dismiss after first display?).

Unable to reset series' color to default

"Reset to default" action series color doesn't' work: it clears the previous color on the dot near the serie's name, but once you leave the page it falls back to its previously defined color.

m.

"Togglable" graphs in collections

It would be nice to be able to temporarily "toggle" a graph visibility within a collection, for instance with a checkbox in the "Graphs List" in the "Edit Collection" of the administration panel.

When queried, the back-end would return only graphs that are "visible"/"enabled" in a graph definition.

Get back to the collections list in the navigation bar

In the UI when the collections list is displayed in the left navigation bar, once the user has selected a collection the graphs list is displayed instead there is no way to get back to the global collections list except using the "back" button of the browser.

It could be nicer to have some kind of "Back to collections" link topping a collection's graphs list, of even display the collections/graphs as an expandable/collapsable tree in the like of Graphite's web UI.

Add meta keywords to documentation

To help referencing the documentation website, add keywords <meta> HTML tags to the Hugo HTML templates and write keywords to each page's front matter.

Update search

Make search look for single graphs or graphs in collections.

Unprivileged users cannot use facettectl if logging to /var/log/*

As an unprivileged user, I cannot use the facettectl utility since it logs into a log file for which I don't have the write permissions:

marc@edea:~/facette/build$ facette/bin/facette useradd
2014/05/10 19:18:16 ERROR: unable to open `/var/log/facette/server.log' log file
Error: open /var/log/facette/server.log: permission denied

I don't think facettectl should use the Go log package to output messages, but rather use fmt to write to stdout/stderr.

Handle software version

We need to add the current version number into Facette.

Then:

  • Add a -V flag to facette binary
  • Add the major version to Facette's User-Agent (could help for debugging purpose, maybe add a flag to prevent its disclosure on production environment?)

This could be useful to automatically handle future data structure changes while upgrading.

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.