Coder Social home page Coder Social logo

hubspot / buckyserver Goto Github PK

View Code? Open in Web Editor NEW
195.0 172.0 33.0 215 KB

Node server that receives metric data over HTTP & forwards to your service of choice

Home Page: http://github.hubspot.com/bucky

License: MIT License

CoffeeScript 99.19% JavaScript 0.81%

buckyserver's Introduction

Bucky Server

Bucky uses a Node server to forward the HTTP requests with your monitoring data to Statsd/Graphite, OpenTSDB, or whatever other service you'd like.

Also see the Bucky Client.

Hosting

Everything you need to run Bucky on Heroku or Nodejitsu is included, just update the config file and push to the service of your choice.

Heroku

heroku create
git push heroku master

Nodejitsu

jitsu deploy

The jitsu application will ask you for a subdomain to run the service on, and will increment the version of the application whenever you deploy.

EC2 / Bare Metal

If you'd rather host Bucky on EC2 directly or on raw hardware, you just need something which will run ./start.js in a reliable way.

You can use environment variables to control runtime options, or put them in your config file in the server section.

You'll need to have nodejs installed. Anything in the 0.8.x series or above should work fine. We recommend using nvm, as it gives you an extra dimension of flexibility, but using your system's package manager should work just as well.

# In the project directory:

npm install
PORT=3333 APP_ROOT=bucky/ ./start.js

The APP_ROOT (or config.server.appRoot) will prefix all endpoints.

Bucky will respond to all requests at /APP_ROOT/v1/health-check, if you need a health check url.

Bucky can be setup to receive data at multiple endpoints, but by default it listens to /APP_ROOT/v1/send on whichever port you specify.

Ubuntu (12.04)

# Install nodejs
# This assumes you're on a 64 bit machine
wget http://nodejs.org/dist/v0.10.19/node-v0.10.19-linux-x64.tar.gz
tar xvf node-v0.10.19-linux-x64.tar.gz 
sudo ln -s `pwd`/node-v0.10.19-linux-x64/bin/{node,npm} /usr/local/bin/

# Grab a Bucky release
# You should use the latest release available at https://github.com/HubSpot/BuckyServer/releases
wget https://github.com/HubSpot/BuckyServer/archive/v0.3.0.tar.gz -O BuckyServer.tar.gz
tar xvf BuckyServer.tar.gz
cd BuckyServer

# Install Bucky
sudo npm install -g

# Make any config changes by editing /usr/local/lib/node_modules/bucky-server/config/default.yaml

# You can start bucky by running bucky-server

# Add the upstart script so Bucky starts on startup and respawns
sudo cp init/bucky-server.conf /etc/init/

# Start Bucky with
sudo start bucky-server

# Log files will appear in /var/log/bucky.log by default

You can run bucky on a specific port (make sure to open that port in your security group if you're using EC2), or you can use a reverse proxy like Nginx or HAProxy to serve it on the same domain and port as your website, it's up to you.

Configuring

If you're not already running a stats collection service, you should take a look at our help doc.

Most people will only need to specify the config they're interested in and start up the server.

If you need more customization, you can write a module:

Modules

There are a few of types of modules:

  • Logger - Use to have Bucky log to something other than the console
  • Config - Use to have Bucky pull config from somewhere other than the default file
  • App - Use to do things when Bucky loads and/or on requests. Auth, monitoring initialization, etc.
  • Collectors - Use to send Bucky data to new and exciting places.

We can only have one logger and one config, but you can specify as many app and collector modules as you like.

All modules follow the same basic sketch. You export a method which is called when Bucky starts up. That method is provided with as much of {app, config, logger} as we have loaded so far, and is expected to call a callback when it's ready for the loading to continue.

Logger

Used to log output. Defaults to a wrapper around console.log/console.error.

Should export a function which will be called when the server is started:

module.exports = ({logger}, next) ->
  # logger is the previous logger (just the console)

  next myNewLogger

This function should call the callback with a logger object which implements log and error:

module.exports = ({logger}, next) ->
  myNewLogger = {
    log: ->
      console.log "Bucky message:", arguments...
    error: ->
      console.error "Bucky error:", arguments...
  }

  next myNewLogger

Config

By default config comes from the config files loaded using the node config module.

If specified, this module will replace that config. Please note that the list of modules comes from the config module, so the list of modules must always be specified there. All other config options can be moved to your config solution of choice using this extension point.

At HubSpot, we're believers in config which can be changed without restarting services. For this reason, the config api is a bit more complex than you might expect. A wrapper is provided in lib/configWrapper.coffee for you to use should you wish to use a simpler solution.

module.exports = ({config, logger}, next) ->
  # config is the old config which was being used
  # before this module was loaded

  # logger.log and logger.error should be used rather than
  # console

  next myConfigObject

A config value will be retrieved from the config object the callback is called with like this:

  config.get('some.config').get()

  config.get('some.config').on 'change', ->
    # The config changed!

You are free to implement the on method as a dud if live reloading doesn't make sense using your config system. Take a look at lib/configWrapper.coffee for an example of how a basic object can be converted (and feel free to use it).

App

App modules get loaded once, and can optionally provide a function to be ran with each request.

Simple app modules are a good place to put any server config, initialization code, etc.

We use app modules to make little tweaks to how express works and enable monitoring.

App modules are called at initialize-time with a hash including a reference to the express app:

module.exports = ({app, logger, config}, next) ->

If your app module calls the callback with a function, that function will be executed on all requests to /v1/send, which is the default endpoint.

If the callback is called with a hash, it is expected to be a mapping between endpoints and handler functions.

module.exports = ({app, logger, config}, next) ->
  next
    send: (req, res, _next) ->
      # Standard express request handling stuff in here

    someOtherEndpoint: (req, res, _next) ->
       # Will get requests which are sent to /v1/someOtherEndpoint

These functions work like middleware, they are called sequentially. You can use them to implement things like auth if you need it.

Collectors

It's not a standard type of module (the core of Bucky has no idea about it), but the default collectors app module looks to a fourth type of module to know where to send data.

Statsd and OpenTSDB collectors are included.

Collectors should export a function which is called on initialize, and call the callback with a hash mapping endpoints to handlers.

module.exports = ({app, logger, config}, next) ->
  next
    send: (data) ->
      # This collector will receive any requests to /v1/send (the default endpoint)

      logger.log "We got some data!"

Format

If you are interested in writing new clients, the format of metric data is the same as is used by statsd:

<metric name>:<metric value>|<unit>[@<sample rate>]

For example:

my.awesome.metric:35|ms
some.other.metric:3|[email protected]

All requests are sent with content-type text/plain.

buckyserver's People

Contributors

gaurim17 avatar gward avatar jsmike avatar soloman1124 avatar zackbloom 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  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  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

buckyserver's Issues

Support Node cluster

Currently, Bucky Server only supports single process.
It should support Node cluster to have better performance on multiple core server.

Support whitelisting of keys

BuckyServer currently provides no way to limit the number/volume of keys, enabling anyone on the internet to spam new keys which can make a mess of a statsd/Graphite server.

Optionally whitelisting keys via the config file looks like it would be a pretty straightforward way to fix this.

Lynx send overload UDP packets

UDP package length is 1472 bytes.
This happened when using send API to send a batch of large metrics.

This should be fixed on Lynx side, but their repository might be inactive.
Is it ok if we change the package to other lynx repository:

'lynx': 'vinhlh/lynx'

Config for appRoot and port is never read from config/default.yml

First of all: kudos to Bucky, I really like the library and the documentation makes it relatively easy to get started. With BuckyServer version 0.2.0 though I noticed a problem with the processing of the config file under config/default.yml: in the function loadApp a config object is passed by as second argument for usage with the load() call. The problem is that the APP_ROOT and the port are also read from this config object, which is wrong - instead they should be read from the config object defined in line 6, which unfortunately has the same name. The result of this is that setting the app root and/or the port in config.yml won't affect Bucky in any way!

Prefix at the server config level

While I can gather metrics automatically by adding data-bucky-page data-bucky-requests to my bucky script include, I cannot specify a prefix there (other than by overloading the page name). Ideally I'd want both a static prefix & the name of the page.

Could I set a prefix at the buckyserver config level (something like 'bucky' for instance)?

Compatibility with Hosted Graphite

Great project! I'd like to get this working with HostedGraphite.com
Looks like i need to prefix the metrics with my API Key. Where in the code would you recommend doing this?

multi-metric packets

We currently push a lot of things to statds with multi-metric packets

some.metric.total:33|c\nsome.metric.other.total:2|c\nsome.metric.more.total:77|c\nsome.metric.summore.total:77|c

I have confirmed with tcpdump that multi-metric submissions are not making it through to statsd but single metrics are. Is there any formatting or way to get multi-metric submission through the BuckyServer app and forwarded on to statds?

Communication error between Bucky and statsd

I had previously set up Bucky Server and had everything configured correctly with Graphite and statsd, but had to rebuild the server (Ubuntu 15.10). Since the rebuild, I'm having trouble connecting Bucky and statsd. When refreshing a basic test page with the Bucky client, the server receives the call and tries to send info to statsd, but statsd reports that the messages are bad. The following are logged by Bucky and statsd for a single refresh of the test page. Carbon and statsd are both registering with Graphite and I can register with statsd from bash, so it appears to just be the communication between Bucky and statsd. Any ideas as to what might be happening?

----- logged by Bucky Server:
Server listening on port 5000 in production mode
Collecting index.navigationStart, index.unloadEventStart, index.unloadEventEnd, index.redirectStart, index.redirectEnd, index.fetchStart, index.domainLookupStart, index.domainLookupEnd, index.connectStart, index.connectEnd, index.secureConnectionStart, index.requestStart, index.responseStart, index.responseEnd, index.domLoading, index.domInteractive, index.domContentLoadedEventStart, index.domContentLoadedEventEnd, index.domComplete, index.loadEventStart, index.loadEventEnd for 67.233.128.8
{ [Error: connect ECONNREFUSED]
code: 'ECONNREFUSED',
errno: 'ECONNREFUSED',
syscall: 'connect' } 'on socket'

----- logged by statsd:
20 Apr 17:21:55 - [54308] reading config file: /opt/statsd/localConfig.js
20 Apr 17:21:55 - server is up
20 Apr 17:22:45 - DEBUG: Bad line: -1461172959833,ms in msg "index.redirectStart:-1461172959833|ms"
20 Apr 17:22:45 - DEBUG: Bad line: -1461172959833,ms in msg "index.redirectEnd:-1461172959833|ms"
20 Apr 17:22:45 - DEBUG: Bad line: -1461172959833,ms in msg "index.secureConnectionStart:-1461172959833|ms"

ParsingErrorBuckyServer

Hello,
I am running a CentOS 7 . When trying to run bucky-server i have the following error

/usr/lib/node_modules/bucky-server/node_modules/config/lib/config.js:949
    throw new Error("Cannot parse config file: '" + fullFilename + "': " + e3)
          ^
Error: Cannot parse config file: '/usr/lib/node_modules/bucky-server/config/default.yaml': SyntaxError: invalid indentation, got 2.5 instead of 2
    at Config._parseFile (/usr/lib/node_modules/bucky-server/node_modules/config/lib/config.js:949:11)
    at /usr/lib/node_modules/bucky-server/node_modules/config/lib/config.js:718:25
    at Array.forEach (native)
    at /usr/lib/node_modules/bucky-server/node_modules/config/lib/config.js:714:14
    at Array.forEach (native)
    at Config._loadFileConfigs (/usr/lib/node_modules/bucky-server/node_modules/config/lib/config.js:713:13)
    at new Config (/usr/lib/node_modules/bucky-server/node_modules/config/lib/config.js:118:5)
    at Object.<anonymous> (/usr/lib/node_modules/bucky-server/node_modules/config/lib/config.js:1402:64)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (/usr/lib/node_modules/bucky-server/node_modules/coffee-script/lib/coffee-script/coffee-script.js:211:36)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object.<anonymous> (/usr/lib/node_modules/bucky-server/server.coffee:13:12)
    at Object.<anonymous> (/usr/lib/node_modules/bucky-server/server.coffee:159:4)
    at Module._compile (module.js:456:26)
    at Object.loadFile (/usr/lib/node_modules/bucky-server/node_modules/coffee-script/lib/coffee-script/coffee-script.js:182:19)
    at Module.load (/usr/lib/node_modules/bucky-server/node_modules/coffee-script/lib/coffee-script/coffee-script.js:211:36)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object.<anonymous> (/usr/lib/node_modules/bucky-server/start.js:4:1)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:935:3

Is it something wrong on my side?

CORS issues and 204 response codes from server

I'm having issues with CORS when using my Bucky Server.

Chrome throws a CORS error when the requests are made, but the Bucky console logger shows that the request metrics were indeed posted.

Collecting index.domContentLoadedEventStart, index.domInteractive, index.domLoading, index.responseEnd, index.responseStart, index.requestStart, index.connectEnd, index.connectStart, index.domainLookupEnd, index.domainLookupStart, index.fetchStart, index.unloadEventEnd, index.unloadEventStart, index.navigationStart for 199.180.243.147

Out of curiosity, I decided to use a Chrome plugin called POSTMAN to manually post to the Bucky Server. The server only responds with 204 responses, and never contains any of the CORS response headers that are supposed to be set. So it seems as though something isn't functioning correctly. Requests to the health check route work fine.

Thanks in advance.
-P

Dockerise Bucky Server

Example

FROM node

# a hack to fix: EXDEV: cross-device link not permitted, rename
RUN cd $(npm root -g)/npm \
&& npm install fs-extra \
&& sed -i -e s/graceful-fs/fs-extra/ -e s/fs.rename/fs.move/ ./lib/utils/rename.js

RUN mkdir -p /opt/app
ADD . /opt/app
WORKDIR /opt/app

RUN npm install

CMD ["node", "start.js"]

EXPOSE 5999

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.