5 | Build-Depends: debhelper (>= 5), python-support
6 | Standards-Version: 3.7.2
7 |
8 | Package: ganglia-logtailer
9 | Architecture: any
10 | Depends: ${shlibs:Depends}, ${misc:Depends}, python (>= 2.4), logtail, ganglia-monitor | ganglia
11 | Description: framework to crunch data from logfiles and send using gmetric
12 | Many metrics associated with ganglia and gmetric plugins are rather easy to
13 | collect; you poll the relevant application for a value and report it. Examples
14 | are asking MySQL for the number of questions and calculating queries per
15 | second, or asking iostat for the percentage disk I/O currently being used.
16 | However, there are a large number of applications out there that don't support
17 | being queried for interesting data, but do provide a log file which, when
18 | properly parsed, yields the interesting data we desire. An example of the
19 | latter category is Apache, which does not furnish any interface for measuring
20 | queries per second, yet has a log file allowing you to count how many queries
21 | come in over a specific time period.
22 | .
23 | ganglia-logtailer is designed to make it easy to parse any log file, pull out
24 | the information you desire, and plug it into ganglia to make pretty graphs.
25 |
--------------------------------------------------------------------------------
/gmetric-java/doc/overview-frame.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Overview
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
25 |
26 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/ganglia-go/gmetric/example_test.go:
--------------------------------------------------------------------------------
1 | package gmetric_test
2 |
3 | import (
4 | "fmt"
5 | "net"
6 | "os"
7 | "time"
8 |
9 | "github.com/ganglia/ganglia_contrib/ganglia-go/gmetric"
10 | )
11 |
12 | func Example() {
13 | // A Client can connect to multiple addresses.
14 | client := &gmetric.Client{
15 | Addr: []net.Addr{
16 | &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 8649},
17 | },
18 | }
19 |
20 | // You only need to Open the connections once on application startup.
21 | if err := client.Open(); err != nil {
22 | fmt.Println(err)
23 | os.Exit(1)
24 | }
25 |
26 | // Defines the Metric.
27 | metric := &gmetric.Metric{
28 | Name: "web_requests",
29 | Title: "Number of Web Requests",
30 | Host: "web0.app.com",
31 | ValueType: gmetric.ValueUint32,
32 | Units: "count",
33 | Slope: gmetric.SlopeBoth,
34 | TickInterval: 20 * time.Second,
35 | Lifetime: 24 * time.Hour,
36 | }
37 |
38 | // Meta packets only need to be sent every `send_metadata_interval` as
39 | // configured in gmond.conf.
40 | if err := client.WriteMeta(metric); err != nil {
41 | fmt.Println(err)
42 | os.Exit(1)
43 | }
44 |
45 | if err := client.WriteValue(metric, 1); err != nil {
46 | fmt.Println(err)
47 | os.Exit(1)
48 | }
49 |
50 | // Close the connections before terminating your application.
51 | if err := client.Close(); err != nil {
52 | fmt.Println(err)
53 | os.Exit(1)
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/gmetric-java/doc/info/ganglia/metric/type/package-frame.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | info.ganglia.metric.type
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | info.ganglia.metric.type
20 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/commandline-eventlogger/ganglialog.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | import sys
4 | import syslog
5 | import os
6 | import urllib
7 | import urllib2
8 | import base64
9 |
10 | ########################################################################
11 | # Make sure you change base Ganglia URL
12 | ########################################################################
13 | ganglia_events_url = "<%= @ganglia_base_url %>/api/events.php"
14 |
15 | # Optionally set user name and password
16 | #username = "<%= @username %>"
17 | #password = "<%= @password %>"
18 |
19 | if (len(sys.argv) == 1):
20 | print "\nPlease supply a log message. It can be any number of arguments. Exiting....\n"
21 | exit(1)
22 |
23 | for index in range(1,len(sys.argv)):
24 | print sys.argv[index]
25 |
26 | # Log to syslog
27 | syslog.syslog(" ".join(sys.argv))
28 |
29 | # Remove first argument and join the list of arguments so it can be sent
30 | summary = " ".join(sys.argv[1:])
31 |
32 | # Get hostname
33 | uname=os.uname()
34 | hostname=uname[1]
35 |
36 | params = urllib.urlencode({'action': 'add', 'start_time': 'now',
37 | 'host_regex': hostname, 'summary': summary})
38 |
39 | request = urllib2.Request(ganglia_events_url+ "?%s" % params)
40 |
41 | if 'username' in locals():
42 | base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '')
43 | request.add_header("Authorization", "Basic %s" % base64string)
44 |
45 | f = urllib2.urlopen(request)
46 |
47 | print f.read()
--------------------------------------------------------------------------------
/gmetric-java/doc/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Generated Documentation (Untitled)
8 |
9 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | Frame Alert
30 |
31 |
32 | This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client.
33 |
34 | Link toNon-frame version.
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/gmetric-java/doc/info/ganglia/metric/package-frame.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | info.ganglia.metric
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | info.ganglia.metric
20 |
31 |
32 |
33 |
34 |
35 |
36 | Classes
37 |
38 |
39 | GMetric
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/gmetric-java/src/java/info/ganglia/metric/Incrementable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is the MIT License
3 | * http://www.opensource.org/licenses/mit-license.php
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in
13 | * all copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | * THE SOFTWARE.
22 | *
23 | */
24 | package info.ganglia.metric;
25 |
26 | /**
27 | * Interface for all Metrics which need to increment their value by one
28 | *
29 | * @author Chris Bowling
30 | */
31 | public interface Incrementable {
32 |
33 | /**
34 | * Increments the GMetric value by one
35 | */
36 | public void incrementValue();
37 | }
38 |
--------------------------------------------------------------------------------
/gmetric-java/doc/allclasses-noframe.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | All Classes
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | All Classes
19 |
20 |
21 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/gmetric-java/src/java/info/ganglia/metric/Metricable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is the MIT License
3 | * http://www.opensource.org/licenses/mit-license.php
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in
13 | * all copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | * THE SOFTWARE.
22 | *
23 | */
24 | package info.ganglia.metric;
25 |
26 | /**
27 | * Interface for all Metrics
28 | *
29 | * @author Chris Bowling
30 | */
31 | public interface Metricable {
32 |
33 | /**
34 | * Fetches current GMetric value
35 | * @return
36 | */
37 | public byte[] getValueData();
38 | /**
39 | * Fetches GMetric metadata
40 | * @return
41 | */
42 | public byte[] getMetaData();
43 | /**
44 | * Clears GMetric value
45 | */
46 | public void clearValue();
47 | /**
48 | * @return the additive
49 | */
50 | public boolean isAdditive();
51 | }
52 |
--------------------------------------------------------------------------------
/pmond/pmond/metric.py:
--------------------------------------------------------------------------------
1 | # This is the MIT License
2 | # http://www.opensource.org/licenses/mit-license.php
3 | #
4 | # Copyright (c) 2007,2008 Nick Galbreath
5 | #
6 | # Permission is hereby granted, free of charge, to any person obtaining a copy
7 | # of this software and associated documentation files (the "Software"), to deal
8 | # in the Software without restriction, including without limitation the rights
9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | # copies of the Software, and to permit persons to whom the Software is
11 | # furnished to do so, subject to the following conditions:
12 | #
13 | # The above copyright notice and this permission notice shall be included in
14 | # all copies or substantial portions of the Software.
15 | #
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | # THE SOFTWARE.
23 | #
24 |
25 | import traceback
26 | import sys
27 |
28 | class metric(object):
29 | def __init__(self):
30 | self.tree = None
31 |
32 | def addMetric(self, values):
33 | self.tree.addMetric(values)
34 |
35 | def register(self, s, tree):
36 | if self.tree is None:
37 | self.tree = tree
38 |
39 | self.gather(tree)
40 | s.enter(self.interval(), 1, self.register, [s, tree])
41 |
42 | def startup(self):
43 | pass
44 |
45 | def interval(self):
46 | return 15
47 |
48 | def gather(self):
49 | pass
50 |
51 | def shutdown(self):
52 | pass
53 |
54 |
--------------------------------------------------------------------------------
/gmetric-java/doc/allclasses-frame.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | All Classes
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | All Classes
19 |
20 |
21 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/ganglia-logtailer/debian/BUGS:
--------------------------------------------------------------------------------
1 | Known Bugs
2 |
3 | ** first run can be too expensive **
4 |
5 | The logtail upon which ganglia-logtailer relies reads in the entire file if no
6 | statefile exists. This occurs when you run ganglia-logtailer for the first
7 | time. ganglia-logtailer pipes all that data to /dev/null, but it still reads
8 | through the entire file. This can take quite a while on big log files (~30m on
9 | an 8GB log file). If you drop ganglia-logtailer into cron on a system with a
10 | large log file, it is easy to cause it to launch a second copy before the first
11 | has completed. This increases load, which decreases the probability either
12 | will finish, causing a cascading failure. After 150 copies of
13 | ganglia-logtailer are launched or so, the machine dies.
14 |
15 | There are two solutions to this problem, and both should be implemented.
16 |
17 | 1) patch logtail to accept a -s or --skip option, that merely skips to the end
18 | of the file and writes out a statefile instead of reading through the entire
19 | file. Update ganglia-logtailer to use this flag when it detects that it's the
20 | first run.
21 |
22 | 2) make ganglia-logtailer create a lockfile when it starts (including the
23 | module and logfile names in the lockfile to allow multiple simultaneous
24 | instances to run on different data) and immediately bail if it detects a lock
25 | file. (detecting a stale lockfile would be nice too.) This would allow the
26 | first instance to read all the way through a large log file, and then it would
27 | simply pick up where it left off the next time. The second benefit of this
28 | solution is that if you have misaligned the frequency of the cronjob launching
29 | ganglia-logtailer with the amount of time it takes to crunch your log file,
30 | this change will protect your system (though the stat collection will likely be
31 | impaired beyond usefulness, it is less likely to take down your machine).
32 |
33 |
34 |
--------------------------------------------------------------------------------
/docker/gmetad-gangliaweb/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM debian:jessie
2 |
3 | MAINTAINER Vladimir Vuksan
4 |
5 | COPY config /config
6 |
7 | RUN apt-get update
8 | RUN apt-get upgrade -y
9 |
10 | # Install Apache
11 | RUN DEBIAN_FRONTEND=noninteractive apt-get install -y apache2
12 |
13 | # Install php
14 | RUN DEBIAN_FRONTEND=noninteractive apt-get install -y php5 libapache2-mod-php5 php5-mcrypt php5-mysql
15 |
16 | # Install mod_wsgi
17 | RUN DEBIAN_FRONTEND=noninteractive apt-get install -y libapache2-mod-wsgi
18 |
19 | # Enable apache mods.
20 | RUN a2enmod php5
21 | RUN a2enmod rewrite
22 | RUN a2enmod headers
23 |
24 | # Manually set up the apache environment variables
25 | ENV APACHE_RUN_USER www-data
26 | ENV APACHE_RUN_GROUP www-data
27 | ENV APACHE_LOG_DIR /var/log/apache2
28 | ENV APACHE_LOCK_DIR /var/lock/apache2
29 | ENV APACHE_PID_FILE /var/run/apache2.pid
30 |
31 | # Install gmetad and ganglia-web
32 | RUN DEBIAN_FRONTEND=noninteractive apt-get install -y gmetad rrdcached rrdtool ganglia-webfrontend
33 |
34 | # Enable ganglia-webui
35 | RUN ln -s /etc/ganglia-webfrontend/apache.conf /etc/apache2/sites-enabled/002-ganglia.conf
36 |
37 | # Install Graphite pieces
38 | RUN DEBIAN_FRONTEND=noninteractive apt-get install -y python-rrdtool graphite-web
39 |
40 | RUN rm -f /etc/apache2/sites-enabled/000-default.conf
41 | RUN ln -s /config/graphite_apache.conf /etc/apache2/sites-enabled/000-default.conf
42 |
43 | RUN /bin/sh /config/graphite_install.sh
44 |
45 | # Make ganglia and rrdcached talk
46 | RUN sed -i '/#OPTS=""/c\OPTS=" -t 60 -w 300 -z 300 -F -s ganglia -m 664 -l 127.0.0.1:9998 -s ganglia -m 777 -P FLUSH,STATS,HELP -l unix:/tmp/rrdcached.limited.sock -b /var/lib/ganglia/rrds -B -p /var/lib/ganglia/rrdcached.pid"' /etc/default/rrdcached
47 |
48 | ENV RRDCACHED_ADDRESS 127.0.0.1:9998
49 |
50 | # Adjust permissions
51 | RUN touch /var/lib/ganglia-web/conf/events.json
52 | RUN chown ganglia:ganglia /var/lib/ganglia-web/conf/events.json
53 |
54 | EXPOSE 80
55 |
56 | CMD /etc/init.d/rrdcached start & /etc/init.d/gmetad start & /usr/sbin/apache2ctl -D FOREGROUND
57 |
--------------------------------------------------------------------------------
/ganglia-logtailer/ganglia-logtailer.spec:
--------------------------------------------------------------------------------
1 | Name: ganglia-logtailer
2 | Version: 1.2
3 | Release: 1%{?dist}
4 | Summary: Framework to crunch data from logfiles and send using gmetric.
5 |
6 |
7 | Group: Applications/Internet
8 | License: GPL2+
9 | URL: http://bitbucket.org/maplebed/ganglia-logtailer/overview/
10 | Source0: %{name}.tar.gz
11 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
12 |
13 | BuildRequires: python-devel
14 | Requires: ganglia-gmond
15 |
16 | %description
17 | ganglia-logtailer is a Many metrics associated with ganglia and gmetric
18 | plugins are rather easy to collect; you poll the relevant application for a
19 | value and report it. Examples are asking MySQL for the number of questions and
20 | calculating queries per second, or asking iostat for the percentage disk I/O
21 | currently being used. However, there are a large number of applications out
22 | there that don't support being queried for interesting data, but do provide a
23 | log file which, when properly parsed, yields the interesting data we desire.
24 | An example of the latter category is Apache, which does not furnish any
25 | interface for measuring queries per second, yet has a log file allowing you to
26 | count how many queries come in over a specific time period.
27 |
28 | ganglia-logtailer is designed to make it easy to parse any log file, pull out
29 | the information you desire, and plug it into ganglia to make pretty graphs.
30 |
31 | %prep
32 | %setup -q -n %{name}
33 |
34 |
35 | %install
36 | rm -rf $RPM_BUILD_ROOT
37 | make install DESTDIR=$RPM_BUILD_ROOT
38 | install -d -m 755 $RPM_BUILD_ROOT/var/lib/ganglia-logtailer
39 | install -d -m 755 $RPM_BUILD_ROOT/var/log/ganglia-logtailer
40 |
41 |
42 | %clean
43 | rm -rf $RPM_BUILD_ROOT
44 |
45 |
46 | %files
47 | %defattr(-,root,root,-)
48 | %{_sbindir}/ganglia-logtailer
49 | %{_datadir}/%{name}
50 | %dir %{_localstatedir}/lib/%{name}
51 | %dir %{_localstatedir}/log/%{name}
52 | %doc debian/README debian/BUGS debian/copyright
53 |
54 |
55 |
56 | %changelog
57 | * Wed Mar 20 2010 Paul Nasrat - 1.2-1
58 | - Initial version
59 |
--------------------------------------------------------------------------------
/gmond-debug/lib/gmond-debug/local_gmond_handler.rb:
--------------------------------------------------------------------------------
1 | require 'uuid'
2 | require 'gmond-debug/gmondpacket'
3 | require 'json'
4 |
5 | Thread.abort_on_exception = true
6 |
7 | # Passing params to an EM Connection
8 | # http://stackoverflow.com/questions/3985092/one-question-with-eventmachine
9 |
10 | class LocalGmondHandler < EM::Connection
11 | attr_accessor :zmq_push_socket
12 | attr_accessor :verbose
13 |
14 | def receive_data packet
15 |
16 | @metadata=Hash.new if @metadata.nil?
17 |
18 | gmonpacket=GmonPacket.new(packet)
19 | if gmonpacket.meta?
20 | # Extract the metadata from the packet
21 | meta=gmonpacket.parse_metadata
22 | # Add it to the global metadata of this connection
23 | @metadata[meta['name']]=meta
24 | elsif gmonpacket.data?
25 | data=gmonpacket.parse_data(@metadata)
26 |
27 | # Check if it was a valid data request
28 | unless data.nil?
29 | # We currently assume this goes fast
30 | # send Topic, Body
31 | # Using the correct helper methods - https://github.com/andrewvc/em-zeromq/blob/master/lib/em-zeromq/connection.rb
32 |
33 | message=Hash.new
34 | message['id'] = UUID.new.generate
35 | message['timestamp'] = Time.now.to_i
36 | message['context'] = "METRIC"
37 | message['source'] = "GMOND"
38 | message['payload'] = data
39 | %w{dmax tmax slope type units}.each do |info|
40 | message['payload'][info] = @metadata[data['name']][info]
41 | end
42 | # message['payload']['meta'] = @metadata[data['name']]
43 |
44 | puts message.to_json
45 | # zmq_push_socket.send_msg('gmond', message.to_json)
46 | end
47 | else
48 | # Skipping unknown packet types
49 | end
50 |
51 |
52 | # If not, we might need to defer the block
53 | # # http://www.igvita.com/2008/05/27/ruby-eventmachine-the-speed-demon/
54 | # # Callback block to execute once the parsing is finished
55 | # operation = proc do
56 | # end
57 | #
58 | # callback = proc do |res|
59 | # end
60 | # # Let the thread pool (20 Ruby Threads handle request)
61 | # EM.defer(operation,callback)
62 |
63 | end
64 |
65 | end
66 |
--------------------------------------------------------------------------------
/ganglia-logtailer/debian/rules:
--------------------------------------------------------------------------------
1 | #!/usr/bin/make -f
2 | # -*- makefile -*-
3 | # Sample debian/rules that uses debhelper.
4 | # This file was originally written by Joey Hess and Craig Small.
5 | # As a special exception, when this file is copied by dh-make into a
6 | # dh-make output file, you may use that output file without restriction.
7 | # This special exception was added by Craig Small in version 0.37 of dh-make.
8 |
9 | # Uncomment this to turn on verbose mode.
10 | #export DH_VERBOSE=1
11 |
12 |
13 |
14 |
15 |
16 | configure: configure-stamp
17 | configure-stamp:
18 | dh_testdir
19 | # Add here commands to configure the package.
20 |
21 | touch configure-stamp
22 |
23 |
24 | build: build-stamp
25 |
26 | build-stamp: configure-stamp
27 | dh_testdir
28 |
29 | # Add here commands to compile the package.
30 | $(MAKE)
31 | #docbook-to-man debian/ganglia-logtailer.sgml > ganglia-logtailer.1
32 |
33 | touch $@
34 |
35 | clean:
36 | dh_testdir
37 | dh_testroot
38 | rm -f build-stamp configure-stamp
39 |
40 | # Add here commands to clean up after the build process.
41 | $(MAKE) clean
42 |
43 | dh_clean
44 |
45 | install: build
46 | dh_testdir
47 | dh_testroot
48 | #dh_prep
49 | dh_installdirs
50 |
51 | # Add here commands to install the package into debian/ganglia-logtailer.
52 | $(MAKE) DESTDIR=$(CURDIR)/debian/ganglia-logtailer install
53 |
54 |
55 | # Build architecture-independent files here.
56 | binary-indep: install
57 | # We have nothing to do by default.
58 |
59 | # Build architecture-dependent files here.
60 | binary-arch: install
61 | dh_testdir
62 | dh_testroot
63 | dh_installchangelogs
64 | dh_installdocs
65 | dh_installexamples
66 | # dh_install
67 | # dh_installmenu
68 | # dh_installdebconf
69 | # dh_installlogrotate
70 | # dh_installemacsen
71 | # dh_installpam
72 | # dh_installmime
73 | dh_pysupport
74 | # dh_installinit
75 | # dh_installcron
76 | # dh_installinfo
77 | dh_installman
78 | dh_link
79 | dh_strip
80 | dh_compress
81 | dh_fixperms
82 | # dh_perl
83 | # dh_makeshlibs
84 | dh_installdeb
85 | dh_shlibdeps
86 | dh_gencontrol
87 | dh_md5sums
88 | dh_builddeb
89 |
90 | binary: binary-indep binary-arch
91 | .PHONY: build clean binary-indep binary-arch binary install configure
92 |
--------------------------------------------------------------------------------
/gang2graph/gang2graph.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env perl
2 | # Drew Stephens
3 | # Copyright 2011, Clearspring, Inc.
4 | #
5 | # This is free software; you can redistribute it and/or modify it under
6 | # the same terms as the Perl 5 programming language system itself.
7 | use warnings;
8 | use strict;
9 | use v5.10;
10 | package App::Gang2Graph;
11 |
12 | use Getopt::Long;
13 | use IO::Socket::INET;
14 | use XML::SAX::ParserFactory;
15 |
16 | use Ganglia::GraphiteSender;
17 |
18 | my $gangliaHost = 'localhost';
19 | my $gangliaPort = 8651;
20 | my $graphiteHost = 'localhost';
21 | my $graphitePort = 2023;
22 |
23 | # Set of hostname regexes that will be sent from Ganglia to Graphite
24 | my $include_hosts = ['.'];
25 | #$include_hosts = ['apw', 'apb', 'aab2[0-9a-d]', 'localhost'];
26 |
27 | # Set of hostname regexes that will be excluded from sending
28 | my $exclude_hosts = [];
29 | #my $exclude_hosts = ['apw00', 'apw01', 'apw02'];
30 |
31 | my $xml = getXMLFromSocket();
32 |
33 | # Socket for sending to Graphite
34 | my $graphiteSocket = IO::Socket::INET->new(
35 | PeerHost => $graphiteHost,
36 | PeerPort => $graphitePort,
37 | ) or die"Couldn't connect to " . $graphiteHost . ':' . $graphitePort . " - $!\n";
38 |
39 | my $parser = XML::SAX::ParserFactory->parser(
40 | Handler => Ganglia::GraphiteSender->new(
41 | socket => $graphiteSocket,
42 | include_hosts => $include_hosts,
43 | exclude_hosts => $exclude_hosts,
44 | ),
45 | );
46 | $parser->parse_string($xml);
47 | $graphiteSocket->close();
48 |
49 | sub getXMLFromSocket {
50 | my $socket = IO::Socket::INET->new(
51 | PeerHost => $gangliaHost,
52 | PeerPort => $gangliaPort,
53 | ) or die "Couldn't connect to " . $gangliaHost . ':' . $gangliaPort . " - $!\n";
54 |
55 | my $xml = '';
56 | my $part = '';
57 | my $recvSize = 1024;
58 | $socket->recv($part, $recvSize);
59 |
60 | # Accumulate the XML file from the socket
61 | my $chunk = 0;
62 | while ($part ne '' && $chunk < 1_000_000) {
63 | $xml .= $part;
64 | $socket->recv($part, $recvSize);
65 | $chunk++
66 | }
67 |
68 | return $xml;
69 | }
70 |
71 | 1;
72 |
--------------------------------------------------------------------------------
/ganglia-go/gmetric/gmc/gmc.go:
--------------------------------------------------------------------------------
1 | // Package gmc is a light weight clone of the gmetric CLI. It only provides a
2 | // subset of the functionality provided by the official cli.
3 | package main
4 |
5 | import (
6 | "flag"
7 | "fmt"
8 | "os"
9 | "strings"
10 | "time"
11 |
12 | "github.com/ganglia/ganglia_contrib/ganglia-go/gmetric"
13 | )
14 |
15 | func main() {
16 | hostname, _ := os.Hostname()
17 | client := gmetric.ClientFromFlag("ganglia")
18 | value := flag.String("value", "", "Value of the metric")
19 | groups := flag.String("group", "", "Group(s) of the metric (comma-separated)")
20 | metric := &gmetric.Metric{}
21 | flag.StringVar(&metric.Name, "name", "", "Name of the metric")
22 | flag.StringVar(&metric.Title, "title", "", "Title of the metric")
23 | flag.StringVar(&metric.Host, "host", hostname, "Hostname")
24 | flag.StringVar((*string)(&metric.ValueType), "type", "", "Either string|int8|uint8|int16|uint16|int32|uint32|float|double")
25 | flag.StringVar(&metric.Units, "units", "", "Unit of measure for the value e.g. Kilobytes, Celcius")
26 | flag.StringVar((*string)(&metric.Slope), "slope", "both", "Either zero|positive|negative|both")
27 | flag.DurationVar(&metric.TickInterval, "tmax", 60*time.Second, "The maximum time between gmetric calls")
28 | flag.DurationVar(&metric.Lifetime, "dmax", 0, "The lifetime in seconds of this metric")
29 | flag.StringVar(&metric.Description, "desc", "", "Description of the metric")
30 | flag.StringVar(&metric.Spoof, "spoof", "", "IP address and name of host/device (colon separated) we are spoofing")
31 | flag.Parse()
32 |
33 | if metric.Name == "" || metric.ValueType == "" || *value == "" {
34 | fmt.Fprintln(os.Stderr, "name, type and value are required")
35 | flag.Usage()
36 | os.Exit(2)
37 | }
38 |
39 | if *groups != "" {
40 | metric.Groups = strings.Split(*groups, ",")
41 | }
42 |
43 | if err := client.Open(); err != nil {
44 | fmt.Fprintln(os.Stderr, err)
45 | os.Exit(2)
46 | }
47 |
48 | if err := client.WriteMeta(metric); err != nil {
49 | fmt.Fprintln(os.Stderr, err)
50 | os.Exit(2)
51 | }
52 |
53 | if err := client.WriteValue(metric, *value); err != nil {
54 | fmt.Fprintln(os.Stderr, err)
55 | os.Exit(2)
56 | }
57 |
58 | if err := client.Close(); err != nil {
59 | fmt.Fprintln(os.Stderr, err)
60 | os.Exit(2)
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/ganglia-go/gmon/gmon.go:
--------------------------------------------------------------------------------
1 | // Package gmon provides read access to the gmon data.
2 | package gmon
3 |
4 | import (
5 | "bufio"
6 | "encoding/xml"
7 | "io"
8 | "net"
9 |
10 | "code.google.com/p/go-charset/charset"
11 | _ "code.google.com/p/go-charset/data"
12 | )
13 |
14 | type ExtraElement struct {
15 | Name string `xml:"NAME,attr"`
16 | Val string `xml:"VAL,attr"`
17 | }
18 |
19 | type ExtraData struct {
20 | ExtraElements []ExtraElement `xml:"EXTRA_ELEMENT"`
21 | }
22 |
23 | type Metric struct {
24 | Name string `xml:"NAME,attr"`
25 | Value string `xml:"VAL,attr"`
26 | Unit string `xml:"UNITS,attr"`
27 | Slope string `xml:"SLOPE,attr"`
28 | Tn int `xml:"TN,attr"`
29 | Tmax int `xml:"TMAX,attr"`
30 | Dmax int `xml:"DMAX,attr"`
31 | ExtraData ExtraData `xml:"EXTRA_DATA"`
32 | }
33 |
34 | type Host struct {
35 | Name string `xml:"NAME,attr"`
36 | Ip string `xml:"IP,attr"`
37 | Tags string `xml:"TAGS,attr"`
38 | Reported int `xml:"REPORTED,attr"`
39 | Tn int `xml:"TN,attr"`
40 | Tmax int `xml:"TMAX,attr"`
41 | Dmax int `xml:"DMAX,attr"`
42 | Location string `xml:"LOCATION,attr"`
43 | GmondStarted int `xml:"GMOND_STARTED,attr"`
44 | Metrics []Metric `xml:"METRIC"`
45 | }
46 |
47 | type Cluster struct {
48 | Name string `xml:"NAME,attr"`
49 | Owner string `xml:"OWNER,attr"`
50 | LatLong string `xml:"LATLONG,attr"`
51 | Url string `xml:"URL,attr"`
52 | Localtime int `xml:"LOCALTIME,attr"`
53 | Hosts []Host `xml:"HOST"`
54 | }
55 |
56 | type Ganglia struct {
57 | XMLNAME xml.Name `xml:"GANGLIA_XML"`
58 | Clusters []Cluster `xml:"CLUSTER"`
59 | }
60 |
61 | // Read the gmond XML output.
62 | func Read(r io.Reader) (*Ganglia, error) {
63 | ganglia := Ganglia{}
64 | decoder := xml.NewDecoder(r)
65 | decoder.CharsetReader = charset.NewReader
66 | if err := decoder.Decode(&ganglia); err != nil {
67 | return nil, err
68 | }
69 | return &ganglia, nil
70 | }
71 |
72 | // Connect to the given network/address and read from it.
73 | func RemoteRead(network, addr string) (*Ganglia, error) {
74 | c, err := net.Dial(network, addr)
75 | if err != nil {
76 | return nil, err
77 | }
78 | defer c.Close()
79 | return Read(bufio.NewReader(c))
80 | }
81 |
--------------------------------------------------------------------------------
/graphite_integration/ganglia_graphite.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/ruby -d
2 |
3 | #################################################################################
4 | # Parse Ganglia XML stream and send metrics to Graphite
5 | # License: Same as Ganglia
6 | # Author: Vladimir Vuksan
7 | # Modified from script written by: Kostas Georgiou
8 | #################################################################################
9 | require "rexml/document"
10 | require 'socket'
11 |
12 | # Adjust to the appropriate values
13 | ganglia_hostname = 'localhost'
14 | ganglia_port = 8651
15 | graphite_host = 'localhost'
16 | graphite_port = 2003
17 | Debug = false
18 |
19 | begin
20 | # Open up a socket to gmond
21 | file = TCPSocket.open(ganglia_hostname, ganglia_port)
22 | # Open up a socke to graphite
23 | graphite = TCPSocket.open(graphite_host, graphite_port)
24 | # We need current time stamp in UNIX time
25 | now = Time.now.to_i
26 | # Parse the XML we got from gmond
27 | doc = REXML::Document.new file
28 | #doc.write( $stdout, 0 )
29 |
30 | grid=nil
31 | doc.elements.each("GANGLIA_XML/GRID") { |element|
32 | grid=element.attributes["NAME"]
33 | }
34 | puts "GRID: #{grid}\n" if Debug
35 |
36 | cluster=nil
37 | doc.elements.each("GANGLIA_XML/GRID/CLUSTER") { |element|
38 | cluster=element.attributes["NAME"]
39 | puts "CLUSTER: #{cluster}\n" if Debug
40 |
41 | doc.elements.each("GANGLIA_XML/GRID[@NAME='#{grid}']/CLUSTER[@NAME='#{cluster}']/HOST") { |host|
42 | metric_prefix=host.attributes["NAME"].gsub(".", "_")
43 | host.elements.each("METRIC") { |metric|
44 | # Set metric prefix to the host name. Graphite uses dots to separate subtrees
45 | # therefore we have to change dots in hostnames to _
46 | # Do substitution of whitespace after XML parsing to avoid problems with
47 | # pre-exiting whitespace in GRID / CLUSTER names in XML.
48 | grid.gsub!(/\W/, "_")
49 | cluster.gsub!(/\W/, "_")
50 | if metric.attributes["TYPE"] != "string"
51 | graphite.puts "#{grid}.#{cluster}.#{metric_prefix}.#{metric.attributes["NAME"]} #{metric.attributes["VAL"]} #{now}\n" if !Debug
52 | puts "#{grid}.#{cluster}.#{metric_prefix}.#{metric.attributes["NAME"]} #{metric.attributes["VAL"]} #{now}\n" if Debug
53 | end
54 | }
55 | }
56 | }
57 |
58 | graphite.close()
59 | file.close()
60 | rescue
61 | end
62 |
--------------------------------------------------------------------------------
/pmond/pmond/gparse.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | # This is the MIT License
4 | # http://www.opensource.org/licenses/mit-license.php
5 | #
6 | # Copyright (c) 2009 Nick Galbreath
7 | #
8 | # Permission is hereby granted, free of charge, to any person obtaining a copy
9 | # of this software and associated documentation files (the "Software"), to deal
10 | # in the Software without restriction, including without limitation the rights
11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | # copies of the Software, and to permit persons to whom the Software is
13 | # furnished to do so, subject to the following conditions:
14 | #
15 | # The above copyright notice and this permission notice shall be included in
16 | # all copies or substantial portions of the Software.
17 | #
18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | # THE SOFTWARE.
25 | #
26 |
27 | import socket
28 | from lxml import etree
29 |
30 | def parse(s):
31 | hosts = {}
32 | root = etree.XML(s)
33 | # newer versions could do:
34 | #for host in root.iter('HOST'):
35 | for host in root.findall('HOST'):
36 | name = host.get('NAME')
37 | hosts[name] = {}
38 | metrics = hosts[name]
39 | # new versions of lxml could do
40 | #for m in host.iter('METRIC'):
41 | for m in host.findall('METRIC'):
42 | metrics[m.get('NAME')] = m.attrib.get("VAL")
43 | return hosts
44 |
45 | def read(host, port):
46 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
47 | s.connect((host, port))
48 | data = ""
49 | while True:
50 | bytes = s.recv(4096)
51 | if len(bytes) == 0:
52 | break;
53 | data += bytes
54 | s.close()
55 | return data
56 |
57 | if __name__ == '__main__':
58 |
59 | s = read('localhost', 8649)
60 | hosts = parse(s)
61 | for h in hosts:
62 | print h
63 | keys = sorted(hosts[h])
64 | for k in keys:
65 | print " %s = %s" % (k,hosts[h][k])
66 |
67 |
68 |
--------------------------------------------------------------------------------
/ganglia-logtailer/src/ganglia_logtailer_helper.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """class for ganglia metric objects to be passed around"""
3 | import re
4 |
5 | class GangliaMetricObject(object):
6 | def __init__(self, name, value, units='', type='float', tmax=60, dmax=0):
7 | self.name = name
8 | self.value = value
9 | self.units = units
10 | self.type = type
11 | self.tmax = tmax
12 | self.dmax = dmax
13 | def set_value(self, value):
14 | self.value = value
15 | def dump_dict(self):
16 | """serialize this object to a dictionary"""
17 | return self.__dict__
18 | def set_from_dict(self, hashed_object):
19 | """recreate object from dict"""
20 | self.name = hashed_object["name"]
21 | self.value = hashed_object["value"]
22 | self.units = hashed_object["units"]
23 | self.type = hashed_object["type"]
24 | self.tmax = hashed_object["tmax"]
25 | self.dmax = hashed_object["dmax"]
26 | def sanitize_metric_name(self):
27 | """sanitize metric names by translating all non alphanumerics to underscore"""
28 | self.name = re.sub("[^A-Za-z0-9._-]", "_", self.name)
29 | def __eq__(self, other):
30 | """A ganglia metric object is equivalent if the name is the same."""
31 | return self.name == other.name
32 |
33 | class LogtailerParsingException(Exception):
34 | """Raise this exception if the parse_line function wants to
35 | throw a 'recoverable' exception - i.e. you want parsing
36 | to continue but want to skip this line and log a failure."""
37 | pass
38 |
39 | class LogtailerStateException(Exception):
40 | """Raise this exception if the get_state function has failed. Metrics from
41 | this run will not be submitted (since the function did not properly
42 | return), but reset_state() should have been called so that the metrics
43 | are valid next time."""
44 | pass
45 |
46 | class SavedMetricsException(Exception):
47 | """Raise this exception if there's a problem recovering the saved metric
48 | list from the statedir. This will always happen on the first run, and
49 | should be ignored. On subsequent runs, it probably means a config
50 | problem where the statedir can't be written or something."""
51 | pass
52 |
53 | class LockingError(Exception):
54 | """ Exception raised for errors creating or destroying lockfiles. """
55 |
56 | def __init__(self, message):
57 | self.message = message
58 |
59 |
60 |
--------------------------------------------------------------------------------
/ganglia-go/gmetric/panicky_writer_test.go:
--------------------------------------------------------------------------------
1 | package gmetric
2 |
3 | import (
4 | "errors"
5 | "testing"
6 | "time"
7 | )
8 |
9 | var errFixed = errors.New("fixed error")
10 |
11 | type errWriter int
12 |
13 | func (e errWriter) Write(b []byte) (int, error) {
14 | return 0, errFixed
15 | }
16 |
17 | var panicFixed = "foo42"
18 |
19 | type panicWriter int
20 |
21 | func (e panicWriter) Write(b []byte) (int, error) {
22 | panic(panicFixed)
23 | }
24 |
25 | func TestWriteMetaWriterError(t *testing.T) {
26 | t.Parallel()
27 | c := &Client{}
28 | m := &Metric{
29 | Name: "write_meta_panic_metric",
30 | Host: "localhost",
31 | ValueType: ValueUint32,
32 | Units: "count",
33 | Slope: SlopeBoth,
34 | TickInterval: 20 * time.Second,
35 | Lifetime: 24 * time.Hour,
36 | }
37 | if err := m.writeMeta(c, errWriter(0)); err != errFixed {
38 | t.Fatalf("was expecting errFixed but got %s", err)
39 | }
40 | }
41 |
42 | func TestWriteValueWriterError(t *testing.T) {
43 | t.Parallel()
44 | c := &Client{}
45 | m := &Metric{
46 | Name: "string_metric",
47 | Host: "localhost",
48 | ValueType: ValueString,
49 | Units: "count",
50 | Slope: SlopeBoth,
51 | TickInterval: 20 * time.Second,
52 | Lifetime: 24 * time.Hour,
53 | }
54 | if err := m.writeValue(c, errWriter(0), "val"); err != errFixed {
55 | t.Fatalf("was expecting errFixed but got %s", err)
56 | }
57 | }
58 |
59 | func TestWriteMetaWriterPanic(t *testing.T) {
60 | t.Parallel()
61 | c := &Client{}
62 | defer func() {
63 | if r := recover(); r != panicFixed {
64 | t.Fatalf("was expecting panicFixed but got %s", r)
65 | }
66 | }()
67 | m := &Metric{
68 | Name: "write_meta_panic_metric",
69 | Host: "localhost",
70 | ValueType: ValueUint32,
71 | Units: "count",
72 | Slope: SlopeBoth,
73 | TickInterval: 20 * time.Second,
74 | Lifetime: 24 * time.Hour,
75 | }
76 | if err := m.writeMeta(c, panicWriter(0)); err != errFixed {
77 | t.Fatalf("was expecting errFixed but got %s", err)
78 | }
79 | }
80 |
81 | func TestWriteValueWriterPanic(t *testing.T) {
82 | t.Parallel()
83 | c := &Client{}
84 | defer func() {
85 | if r := recover(); r != panicFixed {
86 | t.Fatalf("was expecting panicFixed but got %s", r)
87 | }
88 | }()
89 | m := &Metric{
90 | Name: "string_metric",
91 | Host: "localhost",
92 | ValueType: ValueString,
93 | Units: "count",
94 | Slope: SlopeBoth,
95 | TickInterval: 20 * time.Second,
96 | Lifetime: 24 * time.Hour,
97 | }
98 | if err := m.writeValue(c, panicWriter(0), "val"); err != errFixed {
99 | t.Fatalf("was expecting errFixed but got %s", err)
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/gmond-debug/lib/gmond-debug/remote_gmond_handler.rb:
--------------------------------------------------------------------------------
1 | require 'uuid'
2 | require 'nokogiri'
3 | require 'json'
4 | # Maybe use defer, as this might take awhile
5 | # http://eventmachine.rubyforge.org/EventMachine.html#M000486
6 | # http://www.igvita.com/2008/05/27/ruby-eventmachine-the-speed-demon/
7 | # Separate thread
8 | class PostCallbacks < Nokogiri::XML::SAX::Document
9 |
10 | attr_reader :metrics
11 | attr_reader :host
12 | attr_reader :base_timestamp
13 |
14 | def initialize(socket)
15 | @socket=socket
16 | @metrics=Array.new
17 | @host=:unknown
18 | end
19 |
20 | def start_element(element,attributes)
21 | if element == "METRIC"
22 | @metrics << metric_to_message(attributes)
23 | end
24 |
25 | #
26 | if element == "CLUSTER"
27 | attributes.each do |attribute|
28 | if attribute[0] == "LOCALTIME"
29 | @base_timestamp=attribute[1]
30 |
31 | end
32 | end
33 | end
34 |
35 | # Extract the hostname
36 | # #
38 | if element == "HOST"
39 | attributes.each do |attribute|
40 | if attribute[0] == "NAME"
41 | @host=attribute[1]
42 | end
43 | end
44 | end
45 | end
46 |
47 | def metric_to_message(attributes)
48 | message=Hash.new
49 | attributes.each do |attribute|
50 | name=attribute[0]
51 | value=attribute[1]
52 | message[name.downcase]=value
53 | end
54 | message['hostname']=@host
55 | return message
56 | end
57 |
58 | def end_document
59 | # At the end of the document send all metrics
60 | @metrics.each do |metric|
61 | message=Hash.new
62 | message['id']=UUID.new.generate
63 |
64 | # Correct the timestamp based on the time last seen
65 | message['timestamp']=@base_timestamp.to_i-message['tn'].to_i
66 | message['payload']=metric
67 | message['payload'].delete('source')
68 | message['context']="METRIC"
69 | message['source']="GMOND"
70 |
71 | # May have to decide on TMAX and DMAX not to send the metric any more
72 | # http://monami.sourceforge.net/tutorial/ar01s06.html
73 | @socket.send_msg('gmond', message.to_json)
74 | end
75 | end
76 |
77 | end
78 |
79 | class RemoteGmondHandler < EM::Connection
80 | attr_accessor :zmq_push_socket
81 | attr_accessor :verbose
82 |
83 | def receive_data data
84 | begin
85 | parser = Nokogiri::XML::SAX::Parser.new(PostCallbacks.new(zmq_push_socket))
86 | parser.parse(data)
87 | rescue ::Exception => ex
88 | puts "Error parsing XML: #{ex}"
89 | end
90 | end
91 |
92 | def unbind
93 | #puts "closing connection"
94 | end
95 | end
96 |
--------------------------------------------------------------------------------
/gmond-debug/lib/gmond-debug/gmondpacket2.rb:
--------------------------------------------------------------------------------
1 | class GmonPacket2
2 |
3 | def initialize(packet)
4 | @unpacked=packet
5 | @result=Hash.new
6 | packet_type=unpack_int
7 | @result['gmetadata_full']=packet_type
8 | case packet_type[0]
9 | when 128 then unpack_meta
10 | when 132 then unpack_heartbeat
11 | when 134,133 then unpack_data
12 | end
13 | end
14 |
15 | def unpack_meta
16 | puts "got meta package"
17 | # This parse is only working correctly with gmetadata_full=128
18 | @result['hostname']=unpack_string
19 | @result['metricname']=unpack_string
20 | @result['spoof']=unpack_int
21 | @result['metrictype']=unpack_string
22 | @result['metricname2']=unpack_string
23 | @result['metricunits']=unpack_string
24 | @result['slope']=unpack_int
25 | @result['tmax']=unpack_int
26 | @result['dmax']=unpack_int
27 | nrelements=unpack_int
28 | @result['nrelements']=nrelements
29 | unless nrelements.nil?
30 | for i in 1..nrelements[0]
31 | name=unpack_string
32 | @result[name]=unpack_string
33 | end
34 | end
35 | end
36 |
37 | def unpack_data
38 | puts "got data package"
39 | unpack_data_blob
40 | end
41 |
42 | def unpack_data_blob
43 | @result['hostname']=unpack_string
44 | @result['metricname']=unpack_string
45 | @result['spoof']=unpack_int
46 | format=unpack_string
47 | @result['format']=format
48 |
49 | # Quick hack here
50 | # Needs real XDR parsing here
51 | # http://ruby-xdr.rubyforge.org/git?p=ruby-xdr.git;a=blob;f=lib/xdr.rb;h=b41177f32ae72f30d31122e5d801e4828a614c79;hb=HEAD
52 | @result['value']=unpack_float if format.include?("f")
53 | @result['value']=unpack_int if format.include?("u")
54 | @result['value']=unpack_string if format.include?("s")
55 | end
56 |
57 | def unpack_heartbeat
58 | puts "got heartbeat"
59 | unpack_data_blob
60 | end
61 |
62 |
63 | def unpack_int
64 | unless @unpacked.nil?
65 | value=@unpacked[0..3].unpack('N')
66 | shift_unpacked(4)
67 | return value
68 | else
69 | return nil
70 | end
71 | end
72 |
73 | def unpack_float
74 | unless @unpacked.nil?
75 | value=@unpacked[0..3].unpack('g')
76 | shift_unpacked(4)
77 | return value
78 | else
79 | return nil
80 | end
81 | end
82 |
83 | def unpack_string
84 | unless @unpacked.nil?
85 | size=@unpacked[0..3].unpack('N').to_s.to_i
86 | shift_unpacked(4)
87 | value=@unpacked[0..size-1]
88 | #The packets are padded
89 | shift_unpacked(size+((4-size) % 4))
90 | return value
91 | else
92 | return nil
93 | end
94 | end
95 |
96 | def shift_unpacked(count)
97 | @unpacked=@unpacked[count..@unpacked.length]
98 | end
99 |
100 | def to_hash
101 | return @result
102 | end
103 |
104 | end
105 |
--------------------------------------------------------------------------------
/docker/README.md:
--------------------------------------------------------------------------------
1 | Included in the two directories are Dockerfiles to install Ganglia using Docker.
2 |
3 | # Requirements
4 |
5 | You need to have a current version of Docker installed.
6 |
7 | # Build images
8 |
9 | First we'll build the gmetad-ganglia web container. This will run Gmetad and the Web interface
10 |
11 |
12 | sudo docker build -t gmetad-gangliaweb gmetad-gangliaweb/.
13 |
14 |
15 | Secondly we'll build the gmond-aggregator container which will kick off a single gmond aggregator
16 |
17 |
18 | sudo docker build -t gmond-aggregator gmond-aggregator/.
19 |
20 |
21 | # Create configuration files and directories
22 |
23 | We are going to create gmetad configuration file and RRD storage outside of the container
24 | and just mount it inside the gmetad container. This is so we can persist it easily
25 |
26 | For example we'll need to do something like this
27 |
28 | ```
29 | sudo mkdir -p /var/lib/ganglia/rrds /etc/ganglia /etc/ganglia-webfrontend
30 | sudo chown -R 999:999 /var/lib/ganglia
31 | sudo sh -c "cat > /etc/ganglia/gmetad.conf < /etc/ganglia-webfrontend/conf.php <
50 | sudo docker run -d -p 8649:8649/udp --name gmond1 gmond-aggregator web-cluster
51 |
52 |
53 | will start gmond aggregator on port 8649 for web-cluster. Please note we named the container gmond1
54 | so we can easily refer to it later. To invoke further ones you will need to change the
55 | bind port on the left e.g. to invoke second aggregator type
56 |
57 |
58 | sudo docker run -d -p 12001:8649/udp --name gmond2 gmond-aggregator db-cluster
59 |
60 |
61 | Secondly we start up gmetad-gangliaweb container
62 |
63 |
64 | sudo docker run -d --name gmetad1 \
65 | -v /etc/ganglia/gmetad.conf:/etc/ganglia/gmetad.conf \
66 | -v /var/lib/ganglia:/var/lib/ganglia \
67 | --link gmond1:gmond1 \
68 | --link gmond2:gmond2 \
69 | -p 0.0.0.0:80:80 gmetad-gangliaweb
70 |
71 |
72 | # Explanation
73 |
74 | What will happen here is following
75 |
76 | - Gmond aggregator will be started on port 8649. It will expose UDP port 8649 on the host hosting the containers. That host is going to be called gmond1. Same story with
77 | - When we launch gmetad-gangliaweb container it will mount /var/lib/ganglia and /etc/ganglia/gmetad.conf from the docker host inside the container
78 | - In addition gmond1 container will be linked with the gmetad1 container so gmetad1 can access it
79 | - Using --link will assure that /etc/hosts file in gmetad1 container is updated with the internal IP for gmond1
80 | - Ganglia Web will be available on http://localhost/ganglia
81 |
--------------------------------------------------------------------------------
/gmetric-java/src/java/info/ganglia/metric/type/GMetricString.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is the MIT License
3 | * http://www.opensource.org/licenses/mit-license.php
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in
13 | * all copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | * THE SOFTWARE.
22 | *
23 | */
24 | package info.ganglia.metric.type;
25 |
26 | import info.ganglia.metric.GMetric;
27 | import info.ganglia.metric.Metricable;
28 |
29 | import java.io.IOException;
30 |
31 |
32 | /**
33 | * String implementation of GMetric
34 | *
35 | * @author Chris Bowling
36 | */
37 | public class GMetricString extends GMetric implements Metricable {
38 | private String valueString = "";
39 |
40 | /**
41 | * Constructor calls super
42 | * @param host
43 | * The hostname of the client server
44 | * @param name
45 | * The name of the metric (e.g. "CPU Usage"). Shows on graph
46 | * @param type
47 | * The type of the value. See GMetric constants.
48 | * @param units
49 | * The units used to measure the metric. Shows on graph
50 | * @param slope
51 | * See GMetric constants.
52 | * @param additive
53 | * If false the GMetric values are reset to 0 after update. If true the GMetric values are additive.
54 | * @throws IOException
55 | */
56 | public GMetricString(String host, String name, String type, String units, int slope, boolean additive) {
57 | super(host, name, type, units, slope, additive);
58 | }
59 |
60 | /**
61 | * Sets current GMetric value to value argument
62 | * @param value set GMetric to new value
63 | */
64 | public void setValue(String value) {
65 | if (null != value) {
66 | valueString = value;
67 | }
68 | }
69 |
70 | /* (non-Javadoc)
71 | * @see info.ganglia.metric.Metricable#clearValue()
72 | */
73 | public void clearValue() {
74 | valueString = "";
75 | }
76 |
77 | /* (non-Javadoc)
78 | * @see info.ganglia.metric.Metricable#getValueData()
79 | */
80 | public byte[] getValueData() {
81 | byte[] valueBytes = null;
82 | valueBytes = writeValue(valueString);
83 | return valueBytes;
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/gmetad_health_checker/gmetadXmlChecker.py:
--------------------------------------------------------------------------------
1 | #!/usr/local/bin/python
2 |
3 | import socket, os, sys, logging
4 | from optparse import OptionParser
5 |
6 | usage = 'usage: %prog [options] arg1 arg2'
7 | parser = OptionParser(usage="%prog [-r] [-q] [-h]", version="%prog 1.0")
8 | parser.add_option("-v", "--verbose",
9 | action="store_true", dest="verbose", default=False,
10 | help="make lots of noise [default]")
11 | parser.add_option("-q", "--quiet",
12 | action="store_false", dest="verbose", default=True,
13 | help="be vewwy quiet (I'm hunting wabbits)")
14 | parser.add_option("-r", "--restart",
15 | action="store_true", dest="restart", default=False,
16 | help="Should I actually restart gmetad")
17 | (options, args) = parser.parse_args()
18 |
19 | LOG_FILENAME = '/var/logs/gmetad.log'
20 | logging.basicConfig(filename=LOG_FILENAME, level=logging.NOTSET)
21 |
22 | def restartGmetad():
23 | cmd = 'service gmetad restart'
24 | pipe = os.popen(cmd)
25 | results = [l for l in pipe.readlines() if l.find('OK') != -1]
26 | if results:
27 | return True
28 | else:
29 | return False
30 |
31 | def gmetadXmlChecker(port):
32 | try:
33 | client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
34 | client_socket.connect(("localhost", port))
35 | data = client_socket.recv(512)
36 | if len(data) < 512:
37 | logging.critical('We didn\'t recieve any output from gmetad running on port: %d' % port)
38 | if options.verbose:
39 | print "We didn\'t recieve any output from gmetad running in port: %d" % port
40 | client_socket.close()
41 | return False
42 | else:
43 | #print "RECIEVED:" , data
44 | client_socket.close()
45 | return True
46 | except Exception as e:
47 | logging.critical('Gmetad does not seem to be running on this port')
48 | if options.verbose:
49 | print "Cannot connect to host"
50 | return False
51 |
52 |
53 | def main():
54 | try:
55 | gmetad_confs = os.listdir('/etc/gmetad')
56 | except:
57 | logging.critical('Directory does not exist')
58 | if options.verbose:
59 | print 'Directory does not exist'
60 | exit()
61 | xml_ports = []
62 | for conf in gmetad_confs:
63 | for line in open('/etc/gmetad/' + conf):
64 | if 'xml_port' in line:
65 | xml_ports.append(int(line.split(' ')[1].rstrip('\n')))
66 |
67 | for port in xml_ports:
68 | if gmetadXmlChecker(port) == True:
69 | logging.info('gmetad on port: %d is running correctly, exiting' % port)
70 | if options.verbose:
71 | print "gmetad on port: %d is running correctly, exiting" % port
72 | else:
73 | logging.critical('gmetad on port: %d is not responding, restarting' % port)
74 | if options.verbose:
75 | print "gmetad on port: %d is not responding, restarting" % port
76 | if options.restart:
77 | restartGmetad()
78 | exit()
79 |
80 | if __name__ == '__main__':
81 | main()
82 |
--------------------------------------------------------------------------------
/graphite_integration/ganglia_graphite_2.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/ruby -d
2 |
3 | #################################################################################
4 | # Parse Ganglia XML stream and send metrics to Graphite
5 | # License: Same as Ganglia
6 | # Author: Gilles Devaux
7 | # Modified from script written by: Vladimir Vuksan
8 | # at https://github.com/ganglia/ganglia_contrib/blob/master/graphite_integration/ganglia_graphite.rb
9 | #
10 | # WARNING: Don't be surprised Carbon does not understand COUNTER type. You have to apply a derivative function in the UI.
11 | #
12 | #################################################################################
13 | require "rubygems"
14 | require "nokogiri"
15 | require 'socket'
16 |
17 | # Adjust to the appropriate values
18 | ganglia_hostname = 'localhost'
19 | ganglia_port = 8651
20 | graphite_host = 'localhost'
21 | graphite_port = 2003
22 | debug = false
23 |
24 | begin
25 | # Open up a socket to gmond
26 | file = TCPSocket.open(ganglia_hostname, ganglia_port)
27 | # Open up a socke to graphite
28 | graphite = TCPSocket.open(graphite_host, graphite_port)
29 | # We need current time stamp in UNIX time
30 | now = Time.now.to_i
31 | # Parse the XML we got from gmond
32 | doc = Nokogiri::XML file
33 | #doc.write( $stdout, 0 )
34 |
35 | #only one grid for now?
36 |
37 | # Set metric prefix to the host name. Graphite uses dots to separate subtrees
38 | # therefore we have to change dots in hostnames to _
39 | # Do substitution of whitespace after XML parsing to avoid problems with
40 | # pre-exiting whitespace in GRID / CLUSTER names in XML.
41 |
42 | grid = doc.at('GANGLIA_XML/GRID')
43 | grid_name = grid['NAME'].gsub(/\W/, "_")
44 | puts "GRID: #{grid['NAME']}" if debug
45 |
46 | grid.css('CLUSTER').each do |cluster|
47 | cluster_name=cluster["NAME"].gsub(/\W/, "_")
48 | puts "CLUSTER: #{cluster_name}" if debug
49 |
50 | cluster.css("HOST").each do |host|
51 |
52 | metric_prefix=host["NAME"].gsub(".", "_")
53 | puts "PREFIX: #{metric_prefix}" if debug
54 |
55 | host.css("METRIC").each do |metric|
56 | metric_name = metric["NAME"]
57 | puts "METRIC: #{metric_name}" if debug
58 |
59 | if metric["TYPE"] != "string"
60 |
61 | group = metric.at("EXTRA_DATA/EXTRA_ELEMENT[@NAME=GROUP]")
62 | if group
63 | group_name = group['VAL'].gsub(/\W/, "_")
64 | else
65 | #Trick for gmetric < 3.2 (do not have --group option)
66 | #Name your metric group_metric_name
67 | split = metric_name.split('_')
68 | if split.count == 1
69 | group_name = 'nogroup'
70 | else
71 | group_name = split[0]
72 | metric_name = split[1..-1].join('_')
73 | end
74 | end
75 |
76 | puts "GROUP: #{group_name}" if debug
77 |
78 | cmd = "#{grid_name}.#{cluster_name}.#{metric_prefix}.#{group_name}.#{metric_name} #{metric["VAL"]} #{now}\n"
79 | debug ? puts(cmd) : graphite.puts(cmd)
80 | end
81 | end
82 | end
83 |
84 | end
85 |
86 | graphite.close()
87 | file.close()
88 | rescue
89 | # ignored
90 | end
91 |
--------------------------------------------------------------------------------
/varnish_web/default.vcl:
--------------------------------------------------------------------------------
1 | # Specify a backend e.g. your Apache server running Ganglia
2 | backend default {
3 | .host = "127.0.0.1";
4 | .port = "8080";
5 | .first_byte_timeout = 60s;
6 | }
7 |
8 | sub vcl_recv {
9 | # We are exposing Ganglia via varnish as /ganglia3/. So we need to rewrite
10 | # the URL we send to the backend since Ganglia lives under /ganglia2
11 | if (req.url ~ "^/ganglia3") {
12 | set req.url = regsub(req.url, "^/ganglia3", "/ganglia2");
13 | }
14 | return (lookup);
15 | }
16 |
17 | sub vcl_fetch {
18 |
19 | # Front page can be cached for 20 minutes. Cluster list shouldn't
20 | # change that often
21 | if (req.url ~ "^/(ganglia2/)?$" ) {
22 | set beresp.ttl = 1200s;
23 | unset beresp.http.Cache-Control;
24 | unset beresp.http.Expires;
25 | unset beresp.http.Pragma;
26 | unset beresp.http.Set-Cookie;
27 | }
28 |
29 | # Cache CSS and JS for a day
30 | if (req.url ~ "^/(ganglia2/)?(css|js)" || req.url ~ "^/naglite3(.*)\.(css|js)$" ) {
31 | set beresp.ttl = 86400s;
32 | unset beresp.http.Expires;
33 | unset beresp.http.Pragma;
34 | unset beresp.http.Set-Cookie;
35 | set beresp.http.Cache-Control = "public, max-age=86400";
36 | }
37 |
38 | # By default cache all graphs for 30 seconds however tell the browser to cache it for 15 seconds
39 | if (req.url ~ "/(ganglia2/)?graph.php") {
40 | set beresp.ttl = 15s;
41 | set beresp.http.Cache-Control = "public, max-age=15";
42 | unset beresp.http.Pragma;
43 | unset beresp.http.Expires;
44 | unset beresp.http.Set-Cookie;
45 | }
46 |
47 | # Yearly graphs show day averages so no need to regenerate that all the time
48 | # Cache for a day. Monthly graphs cache for 2 hours and daily graphs for 5 minutes
49 | if (req.url ~ "/(ganglia2/)?graph.php\?(.*)r=year") {
50 | set beresp.ttl = 86400s;
51 | set beresp.http.Cache-Control = "public, max-age=86400s";
52 | } else if ( req.url ~ "/(ganglia2/)?graph.php\?(.*)r=month") {
53 | set beresp.ttl = 7200s;
54 | set beresp.http.Cache-Control = "public, max-age=7200s";
55 | } else if ( req.url ~ "/(ganglia2/)?graph.php\?(.*)r=day") {
56 | set beresp.ttl = 300s;
57 | set beresp.http.Cache-Control = "public, max-age=300s";
58 | } else if ( req.url ~ "/(ganglia2/)?graph.php\?(.*)r=4hr") {
59 | set beresp.ttl = 60s;
60 | set beresp.http.Cache-Control = "public, max-age=60s";
61 | } else if ( req.url ~ "^/(ganglia2/)?\?.*vn=(.*)&" ) {
62 | set beresp.ttl = 300s;
63 | set beresp.http.Cache-Control = "public, max-age=300s";
64 | } else if ( req.url ~ "^/(ganglia2/)?autorotation.php" ) {
65 | set beresp.ttl = 900s;
66 | set beresp.http.Cache-Control = "public, max-age=300s";
67 | }
68 |
69 | # Graph All periods can be cached for a long time
70 | if (req.url ~ "/(ganglia2/)?graph_all_periods.php") {
71 | set beresp.ttl = 86400s;
72 | set beresp.http.Cache-Control = "public, max-age=600";
73 | unset beresp.http.Pragma;
74 | unset beresp.http.Expires;
75 | unset beresp.http.Set-Cookie;
76 | }
77 |
78 | return (deliver);
79 | }
80 |
81 | sub vcl_deliver {
82 | if (obj.hits > 0) {
83 | set resp.http.X-Cache = "HIT";
84 | set resp.http.X-Cache-Hits = obj.hits;
85 | } else {
86 | set resp.http.X-Cache = "MISS";
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/gmetric-java/src/java/info/ganglia/GConnector.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is the MIT License
3 | * http://www.opensource.org/licenses/mit-license.php
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in
13 | * all copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | * THE SOFTWARE.
22 | *
23 | */
24 | package info.ganglia;
25 |
26 | import java.io.IOException;
27 | import java.net.DatagramPacket;
28 | import java.net.InetAddress;
29 | import java.net.MulticastSocket;
30 |
31 | /**
32 | * Connects and sends packets to Ganglia via a multicast socket connection. If the multicast group is passed in as a constructor argument it will use that address.
33 | * Otherwise it will use the multicast group specified by the system env variable "ganglia.host"
34 | *
35 | * @author Chris Bowling
36 | */
37 | public class GConnector {
38 |
39 | private final static int DEFAULT_PORT = 8649;
40 | private final InetAddress inetAddress;
41 | private final MulticastSocket socket;
42 |
43 | /**
44 | * Constructor uses multicastAddress specified in the System environment variable "ganglia.host" for its connection to ganglia.
45 | * @throws IOException
46 | */
47 | public GConnector() throws IOException {
48 | // read system env setting for Ganglia server address
49 | final String gangliaHostAddress = System.getProperty("ganglia.host");
50 | this.inetAddress = InetAddress.getByName(gangliaHostAddress);
51 |
52 | // create multicast socket, join group, and send meta data packet
53 | socket = new MulticastSocket(DEFAULT_PORT);
54 | }
55 |
56 | /**
57 | * Constructor uses multicastAddress argument for its connection to Ganglia.
58 | * @param multicastAddress address to send metadata and value data packets to
59 | * @throws IOException
60 | */
61 | public GConnector(String multicastAddress) throws IOException {
62 | this.inetAddress = InetAddress.getByName(multicastAddress);
63 | // create multicast socket, join group, and send meta data packet
64 | socket = new MulticastSocket(DEFAULT_PORT);
65 | }
66 |
67 | /**
68 | * Creates a DatagramPacket using the byte[] argument and sends the packet to Ganglia.
69 | * @param buf data formatted for Ganglia to be sent
70 | * @param length byte[] length
71 | */
72 | public void sendPacket(byte[] buf, int length) {
73 | try {
74 | final DatagramPacket packet = new DatagramPacket(buf, length, inetAddress, DEFAULT_PORT);
75 | socket.send(packet);
76 | } catch (IOException ioe) {
77 | ioe.printStackTrace();
78 | }
79 | }
80 | }
--------------------------------------------------------------------------------
/ganglia-logtailer/src/tailnostate.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Tail a file, reopening it if it gets rotated"""
3 |
4 | import time, os, sys, glob
5 |
6 |
7 | class Tail(object):
8 | def __init__(self, filename, start_pos=0):
9 | self.fp = file(filename)
10 | self.filename = filename
11 |
12 | if start_pos < 0:
13 | self.fp.seek(-start_pos-1, 2)
14 | self.pos = self.fp.tell()
15 | else:
16 | self.fp.seek(start_pos)
17 | self.pos = start_pos
18 |
19 | def __iter__(self):
20 | """Return next line. This function will sleep until there *is* a
21 | next line. Works over log rotation."""
22 | counter = 0
23 | while True:
24 | line = self.next()
25 | if line is None:
26 | counter += 1
27 | if counter >= 5:
28 | counter = 0
29 | self.check_inode()
30 | time.sleep(1.0)
31 | else:
32 | yield line
33 |
34 | def check_inode(self):
35 | """check to see if the filename we expect to tail has the same
36 | inode as our currently open file. This catches log rotation"""
37 | inode = os.stat(self.filename).st_ino
38 | old_inode = os.fstat(self.fp.fileno()).st_ino
39 | if inode != old_inode:
40 | self.fp = file(self.filename)
41 | self.pos = 0
42 |
43 | def next(self):
44 | """Return the next line from the file. Returns None if there are not
45 | currently any lines available, at which point you should sleep before
46 | calling again. Does *not* handle log rotation. If you use next(), you
47 | must also use check_inode to handle log rotation"""
48 | where = self.fp.tell()
49 | line = self.fp.readline()
50 | if line and line[-1] == '\n':
51 | self.pos += len(line)
52 | return line
53 | else:
54 | self.fp.seek(where)
55 | return None
56 |
57 | def close(self):
58 | self.fp.close()
59 |
60 |
61 |
62 | class LogTail(Tail):
63 | def __init__(self, filename):
64 | self.base_filename = filename
65 | super(LogTail, self).__init__(filename, -1)
66 |
67 | def get_file(self, inode, next=False):
68 | files = glob.glob('%s*' % self.base_filename)
69 | files = [(os.stat(f).st_mtime, f) for f in files]
70 | # Sort by modification time
71 | files.sort()
72 |
73 | flag = False
74 | for mtime, f in files:
75 | if flag:
76 | return f
77 | if os.stat(f).st_ino == inode:
78 | if next:
79 | flag = True
80 | else:
81 | return f
82 | else:
83 | return self.base_filename
84 |
85 | def reset(self):
86 | self.fp = file(self.filename)
87 | self.pos = 0
88 |
89 | def advance(self):
90 | self.filename = self.get_file(os.fstat(self.fp.fileno()).st_ino, True)
91 | self.reset()
92 |
93 | def check_inode(self):
94 | if self.filename != self.base_filename or os.stat(self.filename).st_ino != os.fstat(self.fp.fileno()).st_ino:
95 | self.advance()
96 |
97 |
98 | def main():
99 | import sys
100 |
101 | t = Tail(sys.argv[1], -1)
102 | for line in t:
103 | print line
104 |
105 |
106 | if __name__ == '__main__':
107 | main()
108 |
109 |
110 |
--------------------------------------------------------------------------------
/pmond/pmond/daemon.py:
--------------------------------------------------------------------------------
1 | #
2 | # This is the MIT License
3 | # http://www.opensource.org/licenses/mit-license.php
4 | #
5 | # Copyright (c) 2007,2008 Nick Galbreath
6 | #
7 | # Permission is hereby granted, free of charge, to any person obtaining a copy
8 | # of this software and associated documentation files (the "Software"), to deal
9 | # in the Software without restriction, including without limitation the rights
10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | # copies of the Software, and to permit persons to whom the Software is
12 | # furnished to do so, subject to the following conditions:
13 | #
14 | # The above copyright notice and this permission notice shall be included in
15 | # all copies or substantial portions of the Software.
16 | #
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | # THE SOFTWARE.
24 | #
25 |
26 | import os
27 | import sys
28 |
29 | #http://www.noah.org/wiki/Daemonize_Python
30 | def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
31 |
32 | # Do first fork.
33 | try:
34 | pid = os.fork()
35 | if pid > 0:
36 | sys.exit(0) # Exit first parent.
37 | except OSError, e:
38 | sys.stderr.write ("fork #1 failed: (%d) %s\n" % (e.errno, e.strerror) )
39 | sys.exit(1)
40 |
41 | # Decouple from parent environment.
42 | os.chdir("/")
43 | os.umask(0)
44 | os.setsid()
45 |
46 | # Do second fork.
47 | try:
48 | pid = os.fork()
49 | if pid > 0:
50 | sys.exit(0) # Exit second parent.
51 | except OSError, e:
52 | sys.stderr.write ("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror) )
53 | sys.exit(1)
54 |
55 | # Now I am a daemon!
56 |
57 | # Redirect standard file descriptors.
58 | si = open(stdin, 'r')
59 | so = open(stdout, 'a+')
60 | se = open(stderr, 'a+', 0)
61 | os.dup2(si.fileno(), sys.stdin.fileno())
62 | os.dup2(so.fileno(), sys.stdout.fileno())
63 | os.dup2(se.fileno(), sys.stderr.fileno())
64 |
65 |
66 | def drop_privileges(uid_name='nobody', gid_name='nogroup'):
67 | import pwd, grp
68 |
69 | starting_uid = os.getuid()
70 | starting_gid = os.getgid()
71 |
72 | starting_uid_name = pwd.getpwuid(starting_uid)[0]
73 |
74 | if os.getuid() != 0:
75 | # We're not root so, like, whatever dude
76 | return
77 |
78 | if starting_uid == 0:
79 |
80 | # Get the uid/gid from the name
81 | running_uid = pwd.getpwnam(uid_name)[2]
82 | #running_gid = grp.getgrnam(gid_name)[2]
83 |
84 | # Try setting the new uid/gid
85 | #os.setgid(running_gid)
86 | os.setuid(running_uid)
87 |
88 | new_umask = 077
89 | old_umask = os.umask(new_umask)
90 | sys.stderr.write('drop_privileges: Old umask: %s, new umask: %s\n' % \
91 | (oct(old_umask), oct(new_umask)))
92 |
93 | final_uid = os.getuid()
94 | final_gid = os.getgid()
95 | sys.stderr.write('drop_privileges: running as %s/%s\n' % \
96 | (pwd.getpwuid(final_uid)[0],
97 | grp.getgrgid(final_gid)[0]))
98 |
99 |
--------------------------------------------------------------------------------
/gmetric-java/src/java/info/ganglia/metric/type/GMetricInteger.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is the MIT License
3 | * http://www.opensource.org/licenses/mit-license.php
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in
13 | * all copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | * THE SOFTWARE.
22 | *
23 | */
24 | package info.ganglia.metric.type;
25 |
26 | import info.ganglia.metric.GMetric;
27 | import info.ganglia.metric.Incrementable;
28 | import info.ganglia.metric.Metricable;
29 |
30 | import java.io.IOException;
31 | import java.util.concurrent.atomic.AtomicInteger;
32 |
33 |
34 | /**
35 | * Integer implementation of GMetric using AtomicInteger
36 | *
37 | * @author Chris Bowling
38 | */
39 | public class GMetricInteger extends GMetric implements Metricable, Incrementable {
40 | private AtomicInteger valueInt = new AtomicInteger(0);
41 |
42 | /**
43 | * Contstructor calls super
44 | * @param host
45 | * The hostname of the client server
46 | * @param name
47 | * The name of the metric (e.g. "CPU Usage"). Shows on graph
48 | * @param type
49 | * The type of the value. See GMetric constants.
50 | * @param units
51 | * The units used to measure the metric. Shows on graph
52 | * @param slope
53 | * See GMetric constants.
54 | * @param additive
55 | * If false the GMetric values are reset to 0 after update. If true the GMetric values are additive.
56 | * @throws IOException
57 | */
58 | public GMetricInteger(String host, String name, String type, String units, int slope, boolean additive) {
59 | super(host, name, type, units, slope, additive);
60 | }
61 |
62 | /* (non-Javadoc)
63 | * @see info.ganglia.metric.Incrementable#incrementValue()
64 | */
65 | public void incrementValue() {
66 | valueInt.getAndIncrement();
67 | }
68 |
69 | /**
70 | * Increments current GMetric value by value argument
71 | * @param value increment GMetric value by value argument
72 | */
73 | public void incrementValue(int value) {
74 | valueInt.addAndGet(value);
75 | }
76 |
77 | /**
78 | * Sets current GMetric value to value argument
79 | * @param value set GMetric to new value
80 | */
81 | public void setValue(int value) {
82 | valueInt.set(value);
83 | }
84 |
85 | /* (non-Javadoc)
86 | * @see info.ganglia.metric.Metricable#clearValue()
87 | */
88 | public void clearValue() {
89 | valueInt.set(0);
90 | }
91 |
92 | /* (non-Javadoc)
93 | * @see info.ganglia.metric.Metricable#getValueData()
94 | */
95 | public byte[] getValueData() {
96 | byte[] valueBytes = null;
97 | valueBytes = writeValue(valueInt.toString());
98 | return valueBytes;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/gmond-debug/bin/gmond-debug:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | require 'pp'
4 | require File.expand_path("../../lib/gmond-debug.rb", __FILE__)
5 |
6 | defaults= { :port => 1234,
7 | :host => "127.0.0.1",
8 | :gmond_host => "127.0.0.1",
9 | :gmond_port => 8649,
10 | :gmond_interval => 0 ,
11 | :zmq_host => "127.0.0.1",
12 | :zmq_port => 7777,
13 | :verbose => false,
14 | :test_zmq => false
15 | }
16 |
17 | # Set defaults
18 | runner= Dante::Runner.new('gmond-zmq',defaults)
19 |
20 | # Set description in the help
21 | runner.description = "A gmond UDP receiver that pushes things to a 0mq Pub/Sub"
22 |
23 | # Set custom options
24 | runner.with_options do |opts|
25 |
26 | # Gmond options
27 | opts.on("--gmond-host [HOST]", String, "hostname/ip address of the gmond to poll") do |gmondhost|
28 | options[:gmond_host] = gmondhost
29 | end
30 | opts.on("--gmond-port [PORT]", Integer, "tcp port of the gmond to poll") do |gmonport|
31 | options[:gmond_port] = gmondport
32 | end
33 | opts.on("--gmond-interval [seconds]", Integer, "interval to poll the gmond, 0 = disable") do |gmondinterval|
34 | options[:gmond_interval] = gmondinterval
35 | end
36 |
37 | # Zmq options
38 | opts.on("--zmq-port [PORT]", Integer, "tcp port of the zmq publisher, 7777 default") do |zmqport|
39 | options[:zmq_port] = zmqport
40 | end
41 | opts.on("--zmq-host [HOST]", String, "hostname/ip address of the zmq publisher") do |zmqhost|
42 | options[:zmq_host] = zmqhost
43 | end
44 |
45 | opts.on("-v","--verbose", "more verbose output") do |verbose|
46 | options[:verbose] = verbose
47 | end
48 |
49 | opts.on("-t","--test-zmq", "Starts a test zmq subscriber") do |test_zmq|
50 | options[:test_zmq] = test_zmq
51 | end
52 |
53 | end
54 |
55 | # Main execution loop
56 | runner.execute do |opts|
57 |
58 | puts "With the following options:"
59 | pp opts
60 |
61 | # Overriding the trap from dante
62 | trap("INT") {
63 | puts "Cleanly stopping event machine"
64 | EM.stop()
65 | }
66 |
67 | # opts: host, pid_path, port, daemonize, user, group
68 | begin
69 | EventMachine::run {
70 |
71 | # Process our settings
72 | host,port = opts[:host],opts[:port]
73 | gmond_host,gmond_port = opts[:gmond_host],opts[:gmond_port]
74 | gmond_interval = opts[:gmond_interval]
75 | #zmq_host,zmq_port = opts[:zmq_host],opts[:zmq_port]
76 | verbose=opts[:verbose]
77 | #test_zmq=opts[:test_zmq]
78 |
79 | # Start our ZMQ Publisher
80 | #zmq_ctx = EM::ZeroMQ::Context.new(1)
81 | #zmq_push_socket = zmq_ctx.bind( ZMQ::PUB, "tcp://#{zmq_host}:#{zmq_port}")
82 |
83 | # Start our own Gmond UDP listener
84 | EventMachine::open_datagram_socket(host,port,LocalGmondHandler) do |conn|
85 | #conn.zmq_push_socket = zmq_push_socket
86 | conn.verbose = verbose
87 | end
88 |
89 | # Start poller for another gmond instance
90 | # -> if an interval > 0
91 | if gmond_interval > 0
92 | EventMachine::add_periodic_timer( gmond_interval ) {
93 | EventMachine::connect gmond_host, gmond_port, RemoteGmondHandler do |conn|
94 | #conn.zmq_push_socket = zmq_push_socket
95 | conn.verbose = verbose
96 | end
97 | }
98 | end
99 |
100 | # Start a keep alive output
101 | if verbose
102 | EventMachine::add_periodic_timer( 5 ) {
103 | $stderr.write "*"
104 | }
105 | end
106 |
107 | puts "Now accepting gmond udp connections on address #{host}, port #{port}..."
108 | }
109 | rescue Interrupt
110 | # We never get here
111 | puts "Performing a clean shutdown"
112 | end
113 |
114 | end
115 |
--------------------------------------------------------------------------------
/gmetric-java/src/java/info/ganglia/metric/type/GMetricFloat.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is the MIT License
3 | * http://www.opensource.org/licenses/mit-license.php
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in
13 | * all copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | * THE SOFTWARE.
22 | *
23 | */
24 | package info.ganglia.metric.type;
25 |
26 | import info.ganglia.metric.GMetric;
27 | import info.ganglia.metric.Incrementable;
28 | import info.ganglia.metric.Metricable;
29 |
30 | import java.io.IOException;
31 |
32 |
33 | /**
34 | * Float implementation of GMetric. Uses method synchronization for thread safety.
35 | * Performance loss from using this synchronization method is acknowledged and using the methods described in java.util.concurrent.atomic could improve this if necessary.
36 | *
37 | * @author Chris Bowling
38 | */
39 | public class GMetricFloat extends GMetric implements Metricable, Incrementable {
40 | private float valueFloat = 0;
41 |
42 | /**
43 | *
44 | * @param host
45 | * The hostname of the client server
46 | * @param name
47 | * The name of the metric (e.g. "CPU Usage"). Shows on graph
48 | * @param type
49 | * The type of the value. See GMetric constants.
50 | * @param units
51 | * The units used to measure the metric. Shows on graph
52 | * @param slope
53 | * See GMetric constants.
54 | * @param additive
55 | * If false the GMetric values are reset to 0 after update. If true the GMetric values are additive.
56 | * @throws IOException
57 | */
58 | public GMetricFloat(String host, String name, String type, String units, int slope, boolean additive) {
59 | super(host, name, type, units, slope, additive);
60 | }
61 |
62 | /* (non-Javadoc)
63 | * @see info.ganglia.metric.Incrementable#incrementValue()
64 | */
65 | public synchronized void incrementValue() {
66 | valueFloat++;
67 | }
68 |
69 | /**
70 | * Increments current GMetric value by value argument
71 | * @param value increment GMetric value by value argument
72 | */
73 | public synchronized void incrementValue(float value) {
74 | valueFloat += value;
75 | }
76 |
77 | /**
78 | * Sets current GMetric value to value argument
79 | * @param value set GMetric to new value
80 | */
81 | public synchronized void setValue(float value) {
82 | valueFloat = value;
83 | }
84 |
85 | /* (non-Javadoc)
86 | * @see info.ganglia.metric.Metricable#clearValue()
87 | */
88 | public synchronized void clearValue() {
89 | valueFloat = 0;
90 | }
91 |
92 | /* (non-Javadoc)
93 | * @see info.ganglia.metric.Metricable#getValueData()
94 | */
95 | public byte[] getValueData() {
96 | byte[] valueBytes = null;
97 | valueBytes = writeValue(Float.toString(valueFloat));
98 | return valueBytes;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/gmetric-java/src/java/info/ganglia/metric/type/GMetricDouble.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is the MIT License
3 | * http://www.opensource.org/licenses/mit-license.php
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in
13 | * all copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | * THE SOFTWARE.
22 | *
23 | */
24 | package info.ganglia.metric.type;
25 |
26 | import info.ganglia.metric.GMetric;
27 | import info.ganglia.metric.Incrementable;
28 | import info.ganglia.metric.Metricable;
29 |
30 | import java.io.IOException;
31 |
32 |
33 | /**
34 | * Double implementation of GMetric. Uses method synchronization for thread safety.
35 | * Performance loss from using this synchronization method is acknowledged and using the methods described in java.util.concurrent.atomic could improve this if necessary.
36 | *
37 | * @author Chris Bowling
38 | */
39 | public class GMetricDouble extends GMetric implements Metricable, Incrementable {
40 | private double valueDouble = 0;
41 |
42 | /**
43 | *
44 | * @param host
45 | * The hostname of the client server
46 | * @param name
47 | * The name of the metric (e.g. "CPU Usage"). Shows on graph
48 | * @param type
49 | * The type of the value. See GMetric constants.
50 | * @param units
51 | * The units used to measure the metric. Shows on graph
52 | * @param slope
53 | * See GMetric constants.
54 | * @param additive
55 | * If false the GMetric values are reset to 0 after update. If true the GMetric values are additive.
56 | * @throws IOException
57 | */
58 | public GMetricDouble(String host, String name, String type, String units, int slope, boolean additive) {
59 | super(host, name, type, units, slope, additive);
60 | }
61 |
62 | /* (non-Javadoc)
63 | * @see info.ganglia.metric.Incrementable#incrementValue()
64 | */
65 | public synchronized void incrementValue() {
66 | valueDouble++;
67 | }
68 |
69 | /**
70 | * Increments current GMetric value by value argument
71 | * @param value increment GMetric value by value argument
72 | */
73 | public synchronized void incrementValue(double value) {
74 | valueDouble += value;
75 | }
76 |
77 | /**
78 | * Sets current GMetric value to value argument
79 | * @param value set GMetric to new value
80 | */
81 | public synchronized void setValue(double value) {
82 | valueDouble = value;
83 | }
84 |
85 | /* (non-Javadoc)
86 | * @see info.ganglia.metric.Metricable#clearValue()
87 | */
88 | public synchronized void clearValue() {
89 | valueDouble = 0;
90 | }
91 |
92 | /* (non-Javadoc)
93 | * @see info.ganglia.metric.Metricable#getValueData()
94 | */
95 | public byte[] getValueData() {
96 | byte[] valueBytes = null;
97 | valueBytes = writeValue(Double.toString(valueDouble));
98 | return valueBytes;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/gmond-debug/lib/gmond-debug/gmondpacket.rb:
--------------------------------------------------------------------------------
1 | # Inspiration
2 | # https://github.com/fastly/ganglia/blob/master/lib/gm_protocol.x
3 | # https://github.com/igrigorik/gmetric/blob/master/lib/gmetric.rb
4 | # https://github.com/ganglia/monitor-core/blob/master/gmond/gmond.c#L1211
5 | # https://github.com/ganglia/ganglia_contrib/blob/master/gmetric-python/gmetric.py#L107
6 | # https://gist.github.com/1377993
7 | # http://rubyforge.org/projects/ruby-xdr/
8 |
9 | require 'gmond-debug/xdr'
10 | class GmonPacket
11 |
12 | def initialize(packet)
13 | @xdr=XDR::Reader.new(StringIO.new(packet))
14 |
15 | # Read packet type
16 | type=@xdr.uint32
17 | case type
18 | when 128
19 | @type=:meta
20 | when 132
21 | @type=:heartbeat
22 | when 133..134
23 | @type=:data
24 | when 135
25 | @type=:gexec
26 | else
27 | @type=:unknown
28 | end
29 | end
30 |
31 | def heartbeat?
32 | @type == :hearbeat
33 | end
34 |
35 | def data?
36 | @type == :data
37 | end
38 |
39 | def meta?
40 | @type == :meta
41 | end
42 |
43 | # Parsing a metadata packet : type 128
44 | def parse_metadata
45 | meta=Hash.new
46 | meta['hostname']=@xdr.string
47 | meta['name']=@xdr.string
48 | meta['spoof']=@xdr.uint32
49 | meta['type']=@xdr.string
50 | meta['name2']=@xdr.string
51 | meta['units']=@xdr.string
52 | slope=@xdr.uint32
53 |
54 | case slope
55 | when 0
56 | meta['slope']= 'zero'
57 | when 1
58 | meta['slope']= 'positive'
59 | when 2
60 | meta['slope']= 'negative'
61 | when 3
62 | meta['slope']= 'both'
63 | when 4
64 | meta['slope']= 'unspecified'
65 | end
66 |
67 | meta['tmax']=@xdr.uint32
68 | meta['dmax']=@xdr.uint32
69 | nrelements=@xdr.uint32
70 | meta['nrelements']=nrelements
71 | unless nrelements.nil?
72 | extra={}
73 | for i in 1..nrelements
74 | name=@xdr.string
75 | extra[name]=@xdr.string
76 | end
77 | meta['extra']=extra
78 | end
79 | return meta
80 | end
81 |
82 | # Parsing a data packet : type 133..135
83 | # Requires metadata to be available for correct parsing of the value
84 | def parse_data(metadata)
85 | data=Hash.new
86 | data['hostname']=@xdr.string
87 |
88 | metricname=@xdr.string
89 | data['name']=metricname
90 |
91 | data['spoof']=@xdr.uint32
92 | data['format']=@xdr.string
93 |
94 | metrictype=name_to_type(metricname,metadata)
95 |
96 | if metrictype.nil?
97 | # Probably we got a data packet before a metadata packet
98 | puts "Received datapacket without metadata packet hostname=" + data['hostname'] + " metric=" + data['name'] + " format=" + data['format']
99 | return nil
100 | end
101 |
102 | data['val']=parse_value(metrictype)
103 |
104 | # If we received a packet, last update was 0 time ago
105 | data['tn']=0
106 | return data
107 | end
108 |
109 | # Parsing a specific value of type
110 | # https://github.com/ganglia/monitor-core/blob/master/gmond/gmond.c#L1527
111 | def parse_value(type)
112 | value=:unknown
113 | case type
114 | when "int16":
115 | value=@xdr.int16
116 | when "uint16":
117 | value=@xdr.uint16
118 | when "uint32":
119 | value=@xdr.uint32
120 | when "int32":
121 | value=@xdr.int32
122 | when "float":
123 | value=@xdr.float32
124 | when "double":
125 | value=@xdr.float64
126 | when "string":
127 | value=@xdr.string
128 | else
129 | puts "Received unknown type #{type}"
130 | end
131 | return value
132 | end
133 |
134 | # Does lookup of metricname in metadata table to find the correct type
135 | def name_to_type(name,metadata)
136 | # Lookup this metric metadata
137 | meta=metadata[name]
138 | return nil if meta.nil?
139 |
140 | return meta['type']
141 | end
142 |
143 | end
144 |
--------------------------------------------------------------------------------
/ganglia-logtailer/debian/changelog:
--------------------------------------------------------------------------------
1 | ganglia-logtailer (1.9) stable; urgency=low
2 |
3 | * switching from os.system() with string interpolation to subprocess.call
4 | to protect the call out from bad metric names (eg special characters)
5 | * sanitizing the metric name before submission by stripping out all
6 | non-alphanumerics except hyphen, period, and underscore
7 |
8 | -- Ben Hartshorne Mon, 7 Apr 2014 17:48:00 -0700
9 |
10 | ganglia-logtailer (1.8) stable; urgency=low
11 |
12 | * adding missing as zero flag to squash bug where rare data flatlines the graphs
13 |
14 | -- Ben Hartshorne Fri, 4 Apr 2014 16:24:00 -0700
15 |
16 | ganglia-logtailer (1.7) stable; urgency=low
17 |
18 | * changed default logging level from INFO to ERROR. INFO was too verbose
19 |
20 | -- Ben Hartshorne Mon, 31 Oct 2011 16:27:34 -0700
21 |
22 | ganglia-logtailer (1.6) stable; urgency=low
23 |
24 | * added tmax and dmax as arguments to the GangliaMetricObject so that
25 | modules that need a different time period from every minute may tell
26 | gmetric to keep the metric around for longer.
27 |
28 | -- Ben Hartshorne Mon, 31 Oct 2011 16:15:12 -0700
29 |
30 | ganglia-logtailer (1.5) stable; urgency=low
31 |
32 | *submit patch from kazu@lindenlab.com. Add tomcatlogtailer, and import
33 | floor from math for ganglia-logtailer.
34 |
35 | -- Ben O'Connor Wed, 4 May 2011 16:21:15 -0700
36 |
37 | ganglia-logtailer (1.4) stable; urgency=low
38 |
39 | * changing query name in the Slapd module, normalizing to qps instead of
40 | total # queries
41 | * fixing a bug in ganglia-logtailer where the lack of a state file causes an
42 | sys.exit() to get caught by an exception handler and improperly reported
43 |
44 | -- Ben Hartshorne Wed, 13 Jan 2010 13:15:52 -0800
45 |
46 | ganglia-logtailer (1.3-4) stable; urgency=low
47 |
48 | * Added JavaGCLogtailer module for processing Java GC logs
49 |
50 | -- Vladimir Vuksan Tue, 19 Jan 2010 11:09:00 -0500
51 |
52 | ganglia-logtailer (1.3-3) stable; urgency=low
53 |
54 | * caught error in the ApacheVHostLogtailer module - the class was
55 | incorrectly named. Changed the name from WebApacheLogtailer to
56 | ApacheVHostLogtailer.
57 |
58 | -- Ben Hartshorne Fri, 4 Dec 2009 16:22:56 -0800
59 |
60 | ganglia-logtailer (1.3-2) stable; urgency=low
61 |
62 | * Added VarnishLogtailer script to parse out Varnish HTTP accelerator
63 | logs
64 | * Modified Makefile to add *.py from the modules directory
65 |
66 | -- Vladimir Vuksan Tue, 17 Nov 2009 17:50:00 -0500
67 |
68 | ganglia-logtailer (1.3-1) stable; urgency=low
69 |
70 | * Updated Makefile to actually install the two newer modules,
71 | ApacheVhostLogtailer and SlapdLogtailer
72 |
73 | -- Ben Hartshorne Thu, 5 Nov 2009 08:50:34 -0800
74 |
75 | ganglia-logtailer (1.2-1) stable; urgency=low
76 |
77 | * Changed the install target from /usr/bin to /usr/sbin, to match the
78 | filesystem heirarchy standard.
79 | *
80 |
81 | -- Ben Hartshorne Fri, 30 Oct 2009 06:44:09 -0700
82 |
83 | * Added the slapd logtailer module
84 |
85 | -- Jessica Yamasaki Thu, 29 Oct 2009 09:41:24 -0700
86 |
87 | ganglia-logtailer (1.1-2) stable; urgency=low
88 |
89 | * added comment to ganglia-logtailer where logic to include a lockfile would
90 | live.
91 |
92 | -- Ben Hartshorne Wed, 28 Oct 2009 06:42:56 -0700
93 |
94 | ganglia-logtailer (1.1-1) stable; urgency=low
95 |
96 | * Added BUGS file documenting a bug in logtail that can affect ganglia-
97 | logtailer.
98 | * Added VHostApacheLogtailer to crunch apache logs and return per-vhost
99 | metrics.
100 | * Removed creation of /usr/local/share/ganglia-logtailer by debian package.
101 | * Added "make deb" target.
102 |
103 | -- Lex Linden Fri, 23 Oct 2009 14:16:33 -0400
104 |
105 | ganglia-logtailer (1.0-1) stable; urgency=low
106 |
107 | * Initial release
108 |
109 | -- Lex Linden Wed, 21 Oct 2009 15:02:51 -0400
110 |
--------------------------------------------------------------------------------
/gang2graph/Ganglia/GraphiteSender.pm:
--------------------------------------------------------------------------------
1 | # Drew Stephens
2 | # Copyright 2011, Clearspring, Inc.
3 | #
4 | # This is free software; you can redistribute it and/or modify it under
5 | # the same terms as the Perl 5 programming language system itself.
6 | use warnings;
7 | use strict;
8 | use v5.10;
9 | package Ganglia::GraphiteSender;
10 |
11 | use base qw(XML::SAX::ExpatXS);
12 | our @ISA = ('XML::SAX::ExpatXS');
13 |
14 | use Carp qw/croak/;
15 | use IO::Socket::INET;
16 |
17 | my $debug = 0;
18 |
19 | sub new {
20 | my $class = shift;
21 | my %params = @_;
22 |
23 | my $self = {
24 | grid => '',
25 | cluster => '',
26 | host => '',
27 | metric => {
28 | name => '',
29 | val => '',
30 | },
31 |
32 | skipHost => 0,
33 |
34 | now => time,
35 | socket => $params{socket},
36 | include_hosts => defined $params{include_hosts} ? $params{include_hosts} : '.',
37 | exclude_hosts => defined $params{exclude_hosts} ? $params{exclude_hosts} : '',
38 | metrics => 0,
39 | };
40 |
41 | bless $self, $class;
42 | return $self;
43 | }
44 |
45 | sub start_element {
46 | my ($self, $data) = @_;
47 |
48 | # Move along if we're skipping this host
49 | return if ($self->{skipHost} == 1);
50 |
51 | if ($data->{LocalName} eq 'METRIC') {
52 | $self->_handleMetric($data);
53 | } elsif ($data->{LocalName} eq 'HOST') {
54 | # Skip hosts that aren't in the includeHosts list
55 | unless (grep {$data->{Attributes}->{'{}NAME'}->{Value} =~ /$_/} @{$self->{include_hosts}}) {
56 | $self->{skipHost} = 1;
57 | return;
58 | }
59 | # Skip hosts that are in the excludeHosts list
60 | if (grep {$data->{Attributes}->{'{}NAME'}->{Value} =~ /$_/} @{$self->{exclude_hosts}}) {
61 | $self->{skipHost} = 1;
62 | return;
63 | }
64 |
65 | $self->_handleHost($data);
66 | } elsif ($data->{LocalName} eq 'GRID') {
67 | $self->_handleGrid($data);
68 | } elsif ($data->{LocalName} eq 'CLUSTER') {
69 | $self->_handleCluster($data);
70 | }
71 | }
72 |
73 | sub end_element {
74 | my ($self, $data) = @_;
75 |
76 | if ($data->{LocalName} eq 'METRIC') {
77 | } elsif ($data->{LocalName} eq 'HOST') {
78 | # Reset the skipHost flag
79 | $self->{skipHost} = 0 if ($data->{LocalName} eq 'HOST');
80 | } elsif ($data->{LocalName} eq 'GRID') {
81 | print "Ending grid " . $self->{grid} . "\n" if ($debug);
82 | } elsif ($data->{LocalName} eq 'CLUSTER') {
83 | print " Ending cluster " . $self->{cluster} . "\n" if ($debug);
84 | }
85 | }
86 |
87 | sub end_document {
88 | my ($self, $data) = @_;
89 | $self->{socket}->close();
90 | print "Processed " . $self->{metrics} . " metrics\n" if ($debug);
91 | }
92 |
93 | sub _handleGrid {
94 | my ($self, $data) = @_;
95 | $self->{grid} = $data->{Attributes}->{'{}NAME'}->{Value};
96 | $self->{grid} =~ s/ /_/g;
97 | print "Starting grid " . $self->{grid} . "\n" if ($debug);
98 | }
99 |
100 | sub _handleCluster {
101 | my ($self, $data) = @_;
102 | $self->{cluster} = $data->{Attributes}->{'{}NAME'}->{Value};
103 | $self->{cluster} =~ s/ /_/g;
104 | print " Starting cluster " . $self->{cluster} . "\n" if ($debug);
105 | }
106 |
107 | sub _handleHost {
108 | my ($self, $data) = @_;
109 | $self->{host} = $data->{Attributes}->{'{}NAME'}->{Value};
110 | $self->{host} =~ s/ /_/g;
111 | print " Host " . $self->{host} . "\n" if ($debug);
112 | }
113 |
114 | sub _handleMetric {
115 | my ($self, $data) = @_;
116 | my $name = $data->{Attributes}->{'{}NAME'}->{Value};
117 | my $val = $data->{Attributes}->{'{}VAL'}->{Value};
118 |
119 | # Graphite doesn't do non-numeric things
120 | if ($val !~ /^[0-9.]*$/) {
121 | return;
122 | }
123 |
124 | my $graphiteString = $self->{grid} . '.' . $self->{cluster} . '.' .
125 | $self->{host} . '.' . "$name $val " . $self->{now} . "\n";
126 | my $socket = $self->{socket};
127 | print $socket $graphiteString;
128 | print " $graphiteString" if ($debug > 1);
129 |
130 | $self->{metrics}++;
131 | }
132 |
133 | 1;
134 |
--------------------------------------------------------------------------------
/ganglia-go/gmondtest/gmondtest.go:
--------------------------------------------------------------------------------
1 | // Package gmondtest provides test helpers for gmond.
2 | package gmondtest
3 |
4 | import (
5 | "fmt"
6 | "io/ioutil"
7 | "net"
8 | "os"
9 | "os/exec"
10 | "testing"
11 | "text/template"
12 | "time"
13 |
14 | "github.com/daaku/go.freeport"
15 | "github.com/daaku/go.subset"
16 | "github.com/davecgh/go-spew/spew"
17 |
18 | "github.com/ganglia/ganglia_contrib/ganglia-go/gmetric"
19 | "github.com/ganglia/ganglia_contrib/ganglia-go/gmon"
20 | )
21 |
22 | const localhostIP = "127.0.0.1"
23 |
24 | var configTemplate, configTemplateErr = template.New("config").Parse(`
25 | globals {
26 | daemonize = no
27 | setuid = false
28 | debug_level = 0
29 | max_udp_msg_len = 1472
30 | mute = no
31 | deaf = no
32 | allow_extra_data = yes
33 | host_dmax = 864000
34 | }
35 |
36 | cluster {
37 | name = "gmetric_test"
38 | owner = "gmetric_test"
39 | latlong = "gmetric_test"
40 | url = "gmetric_test"
41 | }
42 |
43 | host {
44 | location = "gmetric_test"
45 | }
46 |
47 | udp_recv_channel {
48 | port = {{.Port}}
49 | family = inet4
50 | }
51 |
52 | udp_recv_channel {
53 | port = {{.Port}}
54 | family = inet6
55 | }
56 |
57 | tcp_accept_channel {
58 | port = {{.Port}}
59 | }
60 | `)
61 |
62 | func init() {
63 | if configTemplateErr != nil {
64 | panic(configTemplateErr)
65 | }
66 | }
67 |
68 | // The Harness provides an unique instance of gmond suitable for use in
69 | // testing. Use NewHarness to create a Harness and start the gmond server, and
70 | // ensure you 'defer h.Stop()' to shutdown the gmond server once the test has
71 | // finished.
72 | type Harness struct {
73 | Client *gmetric.Client
74 | t *testing.T
75 | port int
76 | configPath string
77 | cmd *exec.Cmd
78 | }
79 |
80 | func (h *Harness) start() {
81 | var err error
82 | if h.port == 0 {
83 | if h.port, err = freeport.Get(); err != nil {
84 | h.t.Fatal(err)
85 | }
86 | }
87 |
88 | cf, err := ioutil.TempFile("", "gmetric_test_gmond_conf")
89 | if err != nil {
90 | h.t.Fatal(err)
91 | }
92 | h.configPath = cf.Name()
93 |
94 | td := struct{ Port int }{Port: h.port}
95 | if err := configTemplate.Execute(cf, td); err != nil {
96 | h.t.Fatal(err)
97 | }
98 |
99 | if err := cf.Close(); err != nil {
100 | h.t.Fatal(err)
101 | }
102 |
103 | h.cmd = exec.Command("gmond", "--conf", h.configPath)
104 | h.cmd.Stderr = os.Stderr
105 | h.cmd.Stdout = os.Stdout
106 | if err := h.cmd.Start(); err != nil {
107 | h.t.Fatal(err)
108 | }
109 |
110 | // Wait until TCP socket is active to ensure we don't progress until the
111 | // server is ready to accept.
112 | for {
113 | if c, err := net.Dial("tcp", fmt.Sprintf("%s:%d", localhostIP, h.port)); err == nil {
114 | c.Close()
115 | break
116 | }
117 | }
118 |
119 | h.Client = &gmetric.Client{
120 | Addr: []net.Addr{
121 | &net.UDPAddr{IP: net.ParseIP(localhostIP), Port: h.port},
122 | },
123 | }
124 |
125 | if err := h.Client.Open(); err != nil {
126 | h.t.Fatal(err)
127 | }
128 | }
129 |
130 | // Stop the associated gmond server.
131 | func (h *Harness) Stop() {
132 | if err := h.Client.Close(); err != nil {
133 | h.t.Fatal(err)
134 | }
135 |
136 | if err := h.cmd.Process.Kill(); err != nil {
137 | h.t.Fatal(err)
138 | }
139 |
140 | if err := os.Remove(h.configPath); err != nil {
141 | h.t.Fatal(err)
142 | }
143 | }
144 |
145 | // Returns the current state of the associated gmond instance.
146 | func (h *Harness) State() *gmon.Ganglia {
147 | addr := fmt.Sprintf("%s:%d", localhostIP, h.port)
148 | ganglia, err := gmon.RemoteRead("tcp", addr)
149 | if err != nil {
150 | h.t.Fatal(err)
151 | }
152 | return ganglia
153 | }
154 |
155 | // Check if associated gmond instance contains the given metric.
156 | func (h *Harness) ContainsMetric(m *gmon.Metric) {
157 | deadline := time.Now().Add(5 * time.Second)
158 | for {
159 | g := h.State()
160 | for _, cluster := range g.Clusters {
161 | for _, host := range cluster.Hosts {
162 | for _, metric := range host.Metrics {
163 | if subset.Check(m, &metric) {
164 | return
165 | }
166 | }
167 | }
168 | }
169 |
170 | if time.Now().After(deadline) {
171 | h.t.Fatalf("did not find metric\n%s\n--in--\n%s", spew.Sdump(m), spew.Sdump(g))
172 | }
173 | }
174 | }
175 |
176 | // Create a new Harness. It will start the server and initialize the container
177 | // Client.
178 | func NewHarness(t *testing.T) *Harness {
179 | h := &Harness{t: t}
180 | h.start()
181 | return h
182 | }
183 |
--------------------------------------------------------------------------------
/pmond/pmond/gweb.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | #
4 | # SUPER LOW LEVEL WEBSERVER
5 | # Sorta like CGI if anyone remembers that
6 | #
7 | #
8 | from wsgiref.simple_server import make_server
9 | from wsgiref.util import FileWrapper
10 | from wsgiref.util import shift_path_info
11 | import cgi
12 | import mimetypes
13 | import os.path
14 | import glob
15 | import os.path
16 | import gparse
17 | import ggraph
18 |
19 | static_root = '.'
20 | rrd_root = '/tmp'
21 | img_root = '/tmp'
22 |
23 | def sendfile(fname, start_response):
24 | status = "200 OK"
25 | mtype = 'text/plain'
26 | try:
27 | f = open(fname, 'r'); data = f.read(); f.close()
28 | m = mimetypes.guess_type(fname)
29 | if m[0] is not None: mtype = m[0]
30 | except IOError,e:
31 | data = str(e) + '\n'
32 | status = "404 Not Found"
33 | start_response(status, [('Content-Type', mtype)])
34 | return [ data ]
35 |
36 | def static(environ, start_response):
37 | # shift PATH_INFO /static/foo ----> /foo
38 | # then skip first '/'
39 | # and merge with static_root
40 | shift_path_info(environ)
41 | filename = os.path.abspath(os.path.join(static_root,
42 | environ['PATH_INFO'][1:]))
43 | return sendfile(fname, start_response)
44 |
45 | def overview(environ, start_response):
46 | qs = cgi.parse_qs(environ['QUERY_STRING'])
47 | host = qs['host'][0]
48 | duration = qs['duration'][0]
49 | width = qs['width'][0]
50 | status = '200 OK'
51 | headers = [('Content-type', 'text/html')]
52 | start_response(status, headers)
53 | html = ["%s " % host]
54 | for metric in ('cpu', 'memory', 'load', 'network'):
55 | html.append(' ' % (host, metric, duration, width))
56 | html.append("")
57 | return html
58 |
59 | def hostlist(environ, start_response):
60 | # just get everyfile underneath 'rrd_root' and see
61 | # if they are a directorya
62 | hosts = []
63 | files = glob.glob(rrd_root + '/*')
64 | for f in files:
65 | if os.path.isdir(f):
66 | hosts.append(os.path.basename(f))
67 | status = '200 OK'
68 | headers = [('Content-type', 'text/html')]
69 | start_response(status, headers)
70 | html = ["HOSTS "]
71 | for h in hosts:
72 | html.append('%s \n' % (h,h))
73 | html.append(""" """)
74 | return html
75 |
76 | def rrd(environ, start_response):
77 | shift_path_info(environ)
78 | filename = os.path.abspath(os.path.join(static_root,
79 | environ['PATH_INFO'][1:]))
80 | qs = cgi.parse_qs(environ['QUERY_STRING'])
81 | host = qs['host'][0]
82 | metric = qs['metric'][0]
83 | duration = qs['duration'][0]
84 |
85 | # optional
86 | width = 400
87 | if 'width' in qs:
88 | width = int(qs['width'][0])
89 |
90 | fname = ggraph.make_graph(rrd_root, img_root, host, metric, duration, width)
91 |
92 | return sendfile(fname, start_response)
93 |
94 | # just for debugging
95 | def echo(environ, start_response):
96 | status = '200 OK'
97 | headers = [('Content-type', 'text/plain')]
98 | start_response(status, headers)
99 | text = []
100 | keys = sorted(environ.keys())
101 | for k in keys:
102 | text.append("%s = %s\n" % (k,environ[k]))
103 | return text
104 |
105 | def dispatch(environ, start_response):
106 | path = environ['PATH_INFO']
107 | if path == '/':
108 | return hostlist(environ, start_response)
109 | if path == '/overview':
110 | return overview(environ, start_response)
111 | if path == '/echo':
112 | return echo(environ, start_response)
113 | if path == '/rrd':
114 | return rrd(environ, start_response)
115 |
116 | # remap common webby things into the static directory
117 | if path == '/favicon.txt' or path == '/robots.txt':
118 | path = '/static' + path
119 | environ['PATH_INFO'] = path
120 | if path.startswith('/static'):
121 | return static(environ, start_response)
122 |
123 | # nothing matched, do 404
124 | status = "404 Not Found"
125 | start_response(status, [('Content-Type', 'text/plain')])
126 | return [ "%s not found" % path ]
127 |
128 |
129 | if __name__ == '__main__':
130 | httpd = make_server('', 8000, dispatch)
131 | print "Serving on port 8000..."
132 |
133 | # Serve until process is killed
134 | httpd.serve_forever()
135 |
--------------------------------------------------------------------------------
/ganglia-alert/init.d-debian:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 | ### BEGIN INIT INFO
3 | # Provides: ganglia-alert
4 | # Required-Start: $network $named $remote_fs $syslog gmetad
5 | # Required-Stop: $network $named $remote_fs $syslog gmetad
6 | # Default-Start: 2 3 4 5
7 | # Default-Stop: 0 1 6
8 | # Short-Description: ganglia-alert
9 | # Description: Sends alerts using metrics from ganglia
10 | ### END INIT INFO
11 |
12 | # Author: Giovanni Toraldo
13 |
14 | # Do NOT "set -e"
15 |
16 | PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
17 | DESC="ganglia-alert"
18 | NAME=ganglia-alert
19 | DAEMON=/usr/bin/$NAME
20 | DAEMON_ARGS="-d"
21 | PIDFILE=/var/run/$NAME.pid
22 | SCRIPTNAME=/etc/init.d/$NAME
23 |
24 | # Exit if the package is not installed
25 | [ -x "$DAEMON" ] || exit 0
26 |
27 | # Read configuration variable file if it is present
28 | [ -r /etc/default/$NAME ] && . /etc/default/$NAME
29 |
30 | # Load the VERBOSE setting and other rcS variables
31 | . /lib/init/vars.sh
32 |
33 | # Define LSB log_* functions.
34 | # Depend on lsb-base (>= 3.2-14) to ensure that this file is present
35 | # and status_of_proc is working.
36 | . /lib/lsb/init-functions
37 |
38 | #
39 | # Function that starts the daemon/service
40 | #
41 | do_start()
42 | {
43 | # Return
44 | # 0 if daemon has been started
45 | # 1 if daemon was already running
46 | # 2 if daemon could not be started
47 | start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
48 | || return 1
49 | start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
50 | $DAEMON_ARGS \
51 | || return 2
52 | # Add code here, if necessary, that waits for the process to be ready
53 | # to handle requests from services started subsequently which depend
54 | # on this one. As a last resort, sleep for some time.
55 | }
56 |
57 | #
58 | # Function that stops the daemon/service
59 | #
60 | do_stop()
61 | {
62 | # Return
63 | # 0 if daemon has been stopped
64 | # 1 if daemon was already stopped
65 | # 2 if daemon could not be stopped
66 | # other if a failure occurred
67 | start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
68 | RETVAL="$?"
69 | [ "$RETVAL" = 2 ] && return 2
70 | # Wait for children to finish too if this is a daemon that forks
71 | # and if the daemon is only ever run from this initscript.
72 | # If the above conditions are not satisfied then add some other code
73 | # that waits for the process to drop all resources that could be
74 | # needed by services started subsequently. A last resort is to
75 | # sleep for some time.
76 | start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
77 | [ "$?" = 2 ] && return 2
78 | # Many daemons don't delete their pidfiles when they exit.
79 | rm -f $PIDFILE
80 | return "$RETVAL"
81 | }
82 |
83 | #
84 | # Function that sends a SIGHUP to the daemon/service
85 | #
86 | do_reload() {
87 | #
88 | # If the daemon can reload its configuration without
89 | # restarting (for example, when it is sent a SIGHUP),
90 | # then implement that here.
91 | #
92 | start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
93 | return 0
94 | }
95 |
96 | case "$1" in
97 | start)
98 | [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
99 | do_start
100 | case "$?" in
101 | 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
102 | 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
103 | esac
104 | ;;
105 | stop)
106 | [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
107 | do_stop
108 | case "$?" in
109 | 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
110 | 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
111 | esac
112 | ;;
113 | status)
114 | status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
115 | ;;
116 | #reload|force-reload)
117 | #
118 | # If do_reload() is not implemented then leave this commented out
119 | # and leave 'force-reload' as an alias for 'restart'.
120 | #
121 | #log_daemon_msg "Reloading $DESC" "$NAME"
122 | #do_reload
123 | #log_end_msg $?
124 | #;;
125 | restart|force-reload)
126 | #
127 | # If the "reload" option is implemented then remove the
128 | # 'force-reload' alias
129 | #
130 | log_daemon_msg "Restarting $DESC" "$NAME"
131 | do_stop
132 | case "$?" in
133 | 0|1)
134 | do_start
135 | case "$?" in
136 | 0) log_end_msg 0 ;;
137 | 1) log_end_msg 1 ;; # Old process is still running
138 | *) log_end_msg 1 ;; # Failed to start
139 | esac
140 | ;;
141 | *)
142 | # Failed to stop
143 | log_end_msg 1
144 | ;;
145 | esac
146 | ;;
147 | *)
148 | #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
149 | echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
150 | exit 3
151 | ;;
152 | esac
153 |
154 | :
155 |
--------------------------------------------------------------------------------
/gmond-debug/README.md:
--------------------------------------------------------------------------------
1 | GMOND-DEBUG
2 | ===========
3 |
4 | BUILDING
5 | --------
6 |
7 | ```
8 | . source.env
9 | for i in gems/cache/*.gem; do gem install $i; done
10 | ```
11 |
12 | RUNNING
13 | -------
14 |
15 | ```
16 | . source.env
17 | ./bin/gmond-debug
18 | ```
19 |
20 |
21 | OLD DOCUMENTATION
22 | -----------------
23 |
24 | ### What is this project about:
25 |
26 | There is not one monitoring project to rule them all:
27 |
28 | Ganglia, Graphite, Collectd, Opentsdb, ... they all have their specific unique functionality and their associate unique storage.
29 |
30 | Instead of trying to create one central storage, we want to send the different metric information, to each monitoring solution for their optimized function.
31 |
32 | This project's code will:
33 |
34 | - listen into the gmond UDP protocol
35 | - optionally poll existing gmond's and put the message on to a 0mq (pub/sub).
36 |
37 | From there, other subscribers can pull the information into graphite, collectd, opentsdb etc..
38 |
39 | We have deliberately chosen not to go for peer to peer communication, but for a bus/queue oriented system.
40 |
41 | It currently doesn't do more than put things on the queue, the next step is to write subscribers for the other monitoring systems.
42 |
43 | And maybe , just maybe, this will evolve into a swiss-army knife of monitoring/metrics conversion ....
44 |
45 | ### Thanks!
46 |
47 | A big thanks to Vladimir Vuksan (@vvuksan) for helping me out with the original proof of concept!
48 |
49 | ### Requirements:
50 | #### Centos
51 |
52 | # yum install libxml2-devel
53 | # yum install libxslt-devel
54 | # yum install zeromq-devel
55 | # yum install uuid-devel
56 | # yum install json-c-devel
57 |
58 | ### Configuring gmond
59 |
60 | Just add another udp send channel for your existing gmond's
61 |
62 | udp_send_channel {
63 | host = 127.0.0.1
64 | port = 1234
65 | }
66 |
67 | ### Running it:
68 |
69 | gmond-zmq - A gmond UDP receiver that pushes things to a 0mq Pub/Sub
70 |
71 | Usage: gmond-zmq [-p port] [-P file] [-d] [-k]
72 | gmond-zmq --help
73 |
74 | -p, --port PORT Specify port
75 | (default: 1234)
76 | -P, --pid FILE save PID in FILE when using -d option.
77 | (default: /var/run/gmond-zmq.pid)
78 | -d, --daemon Daemonize mode
79 | -k, --kill [PORT] Kill specified running daemons - leave blank to kill all.
80 | -u, --user USER User to run as
81 | -G, --group GROUP Group to run as
82 | --gmond-host [HOST] hostname/ip address of the gmond to poll
83 | --gmond-port [PORT] tcp port of the gmond to poll
84 | --gmond-interval [seconds]
85 | interval to poll the gmond, 0 = disable (default)
86 | --zmq-port [PORT] tcp port of the zmq publisher
87 | --zmq-host [HOST] hostname/ip address of the zmq publisher
88 | -v, --verbose more verbose output
89 | -t, --test-zmq Starts a test zmq subscriber
90 | -?, --help Display this usage information.
91 |
92 | ### Message examples
93 |
94 | {"timestamp":1324639623,"payload":{"name":"machine_type","val":"x86_64","slope":"zero","dmax":"0","tn":"809","units":"","type":"string","tmax":"1200","hostname":"localhost"},"id":"f6412a10-0f86-012f-0bdb-080027701f72","context":"METRIC","source":"GMOND"}
95 | {"timestamp":1324639623,"payload":{"name":"proc_total","val":"105","slope":"both","dmax":"0","tn":"89","units":" ","type":"uint32","tmax":"950","hostname":"localhost"},"id":"f6415250-0f86-012f-0bdc-080027701f72","context":"METRIC","source":"GMOND"}
96 | {"timestamp":1324639623,"payload":{"name":"cpu_num","val":"1","slope":"zero","dmax":"0","tn":"809","units":"CPUs","type":"uint16","tmax":"1200","hostname":"localhost"},"id":"f6417410-0f86-012f-0bdd-080027701f72","context":"METRIC","source":"GMOND"}
97 | {"timestamp":1324639623,"payload":{"name":"cpu_speed","val":"2800","slope":"zero","dmax":"0","tn":"809","units":"MHz","type":"uint32","tmax":"1200","hostname":"localhost"},"id":"f64186c0-0f86-012f-0bdf-080027701f72","context":"METRIC","source":"GMOND"}
98 | {"timestamp":1324639623,"payload":{"name":"pkts_out","val":"3.27","slope":"both","dmax":"0","tn":"49","units":"packets/sec","type":"float","tmax":"300","hostname":"localhost"},"id":"f641aa00-0f86-012f-0be0-080027701f72","context":"METRIC","source":"GMOND"}
99 | {"timestamp":1324639623,"payload":{"name":"swap_free","val":"741752","slope":"both","dmax":"0","tn":"89","units":"KB","type":"float","tmax":"180","hostname":"localhost"},"id":"f641c720-0f86-012f-0be1-080027701f72","context":"METRIC","source":"GMOND"}
100 |
101 | ### Some inspiration:
102 |
103 | - [The Ganglia XDR protocol](https://github.com/fastly/ganglia/blob/master/lib/gm_protocol.x)
104 | - [Gmetric library - ruby lib to send ganglia metrics](https://github.com/igrigorik/gmetric/blob/master/lib/gmetric.rb)
105 | - [Gmond Source code](https://github.com/ganglia/monitor-core/blob/master/gmond/gmond.c#L1211)
106 | - [Gmetric Python code](https://github.com/ganglia/ganglia_contrib/blob/master/gmetric-python/gmetric.py#L107)
107 | - [Vladimir Vuksan sample Python Gmond Listener code](https://gist.github.com/1377993)
108 | - [My initial sample Gmond listener code](https://gist.github.com/1376525)
109 | - [Ruby XDR gem](http://rubyforge.org/projects/ruby-xdr/)
110 |
--------------------------------------------------------------------------------
/gmetric-java/doc/deprecated-list.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Deprecated List
8 |
9 |
10 |
11 |
12 |
13 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | Overview
37 | Package
38 | Class
39 | Use
40 | Tree
41 | Deprecated
42 | Index
43 | Help
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | PREV
55 | NEXT
56 |
57 | FRAMES
58 | NO FRAMES
59 |
66 |
67 | All Classes
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | Deprecated API
81 |
82 |
83 | Contents
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 | Overview
99 | Package
100 | Class
101 | Use
102 | Tree
103 | Deprecated
104 | Index
105 | Help
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | PREV
117 | NEXT
118 |
119 | FRAMES
120 | NO FRAMES
121 |
128 |
129 | All Classes
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
--------------------------------------------------------------------------------
/gmetric-java/doc/info/ganglia/package-use.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Uses of Package info.ganglia
8 |
9 |
10 |
11 |
12 |
13 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | PREV
55 | NEXT
56 |
57 | FRAMES
58 | NO FRAMES
59 |
66 |
67 | All Classes
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | Uses of Package info.ganglia
81 |
82 | No usage of info.ganglia
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 | PREV
115 | NEXT
116 |
117 | FRAMES
118 | NO FRAMES
119 |
126 |
127 | All Classes
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/ganglia-logtailer/README:
--------------------------------------------------------------------------------
1 | Imported from
2 |
3 | https://bitbucket.org/maplebed/ganglia-logtailer
4 |
5 | ##################
6 | ##
7 | ## ganglia-logtailer
8 | ##
9 | ## ganglia-logtailer is a python script that will tail any log file,
10 | ## crunch the data collected, and report summary data to ganglia.
11 | ##
12 | ## This directory contains the script ganglia-logtailer, its required
13 | ## helper classes, and two example classes, one generic and one for
14 | ## parsing Apache logs.
15 | ##
16 | ## Copyright Linden Lab, 2008
17 | ## License to modify and redistribute granted under the GPL v2 or later
18 | ##
19 | ##################
20 |
21 |
22 | 0. Table of Contents
23 | 1. Overview
24 | 2. Installation
25 | 3. License
26 |
27 | 1. Overview
28 |
29 | Many metrics associated with ganglia and gmetric plugins are rather easy to
30 | collect; you poll the relevant application for a value and report it. Examples
31 | are asking MySQL for the number of questions and calculating queries per
32 | second, or asking iostat for the percentage disk I/O currently being used.
33 | However, there are a large number of applications out there that don't support
34 | being queried for interesting data, but do provide a log file which, when
35 | properly parsed, yields the interesting data we desire. An example of the
36 | latter category is Apache, which does not furnish any interface for measuring
37 | queries per second, yet has a log file allowing you to count how many queries
38 | come in over a specific time period.
39 |
40 | ganglia-logtailer is designed to make it easy to parse any log file, pull out
41 | the information you desire, and plug it into ganglia to make pretty graphs.
42 |
43 | ganglia-logtailer is comprised of three parts:
44 | * ganglia-logtailer - the python script doing the real work
45 | * ganglia_logtailer_helper.py and tailnostate.py - supporting python classes
46 | * ApacheLogtailer.py, DummyLogtailer.py, etc. - user modifiable, log-file specific classes
47 |
48 | You must modify DummyLogtailer.py or write new FooLogtailer.py classes for
49 | each of the log files you wish to parse. As every log file has a specific
50 | format, you must write the regular expression to properly pick out interesting
51 | information for your specific application. As each application has different
52 | ways of expressing what might be interesting metrics to graph, you must write
53 | the functions to collect the information present in each line of the log file.
54 |
55 | DummyLogtailer.py is an example file; it does nothing other than count the
56 | number of lines present in the log file and report lines per second. However,
57 | it does have extensive comments explaining the purpose of each of the functions
58 | present in the file. I would recommend reading that file and modifying it to
59 | do more interesting things.
60 |
61 | ApacheLogtailer.py is a fully functional class parsing an Apache log. At
62 | Linden Lab, we use a custom log format (and include the very interesting %D -
63 | time to execute the query in microseconds), so the regular expression included
64 | there will probably have to be changed for your environment.
65 | ApacheLogtailer.py defines and returns the number of Apache requests per
66 | second, also broken out by return code (200, 300, 400, 500), and the average,
67 | maximum, and 90th percentile run time of all queries caught during the sample
68 | period.
69 |
70 | The rest of the *Logtailer.py classes present are customized for different
71 | types of logs (postfix, bind, etc.)
72 |
73 | ganglia-logtailer can be invoked in two different modes, either as a daemon
74 | (which tells it to run as a persistent process) or invoked from cron on a
75 | regular basis. I recommend using daemon mode for testing, but invoking it from
76 | cron every 1-5 minutes for deploy. I make this recommendation because (aside
77 | from minimizing the number of running daemons), there are no start scripts to
78 | invoke daemon mode on system boot, and there is no facility to relaunch the
79 | process if it were to crash or raise an exception.
80 |
81 | ganglia-logtailer will log certain bits of information to
82 | /var/log/ganglia/ganglia_logtailer in case of error. Log level is variable by
83 | modfying ganglia-logtailer and editing the following line:
84 | logger.setLevel(logging.INFO) Look up the 'logging' python module for valid
85 | values. (logging.DEBUG is a good bet)
86 |
87 | 2. Installation
88 |
89 | ganglia-logtailer depends on the 'logtail' package
90 | (http://packages.debian.org/etch/logtail) when run in cron mode.
91 |
92 | i. Copy ganglia-logtailer to /usr/local/bin/ (or wherever you store
93 | unpackaged binaries)
94 | ii. Copy ganglia_logtailer_helper.py and tailnostate.py to
95 | /usr/local/share/ganglia-logtailer (or somewhere in your python search
96 | path)
97 | iii. Copy ApacheLogtailer.py and DummyLogtailer.py to /usr/local/share/ganglia-logtailer
98 | (or somewhere in your python search path)
99 |
100 | Create the directory ganglia-logtailer uses to store state:
101 | /var/lib/ganglia-logtailer/
102 |
103 | Test the installation by invoking ganglia-logtailer with the DummyLogtailer
104 | class on a log file:
105 | # ganglia-logtailer --classname DummyLogtailer --log_file /var/log/daemon.log --mode daemon
106 | wait 30s to 1m, then check and see whether your new metric is present in
107 | ganglia.
108 |
109 | If all goes well, try out one of the real modules:
110 | # ganglia-logtailer --classname PostfixLogtailer --log_file /var/log/mail.log --mode daemon
111 |
112 | If that works as well, deploy! Add the following to
113 | /etc/cron.d/ganglia-logtailer
114 | * * * * * root /usr/local/bin/ganglia-logtailer --classname PostfixLogtailer --log_file /var/log/mail.log --mode cron
115 |
116 | 3. License
117 |
118 | These scripts are all released under the GPL v2 or later. For a full
119 | description of the licence, please visit http://www.gnu.org/licenses/gpl.txt
120 |
121 |
122 |
123 |
--------------------------------------------------------------------------------
/gmetric-java/src/test/info/ganglia/GMetricTest.java:
--------------------------------------------------------------------------------
1 | package info.ganglia;
2 |
3 | import static org.junit.Assert.assertTrue;
4 | import static org.junit.Assert.fail;
5 |
6 | import info.ganglia.GMonitor;
7 | import info.ganglia.metric.GMetric;
8 | import info.ganglia.metric.type.GMetricDouble;
9 | import info.ganglia.metric.type.GMetricFloat;
10 | import info.ganglia.metric.type.GMetricInteger;
11 | import info.ganglia.metric.type.GMetricString;
12 |
13 | import java.io.ByteArrayOutputStream;
14 | import java.io.DataOutputStream;
15 | import java.io.IOException;
16 | import java.net.InetAddress;
17 |
18 | import org.junit.BeforeClass;
19 | import org.junit.Test;
20 |
21 |
22 |
23 | public class GMetricTest {
24 | public final static String MULTICAST_ADDRESS = "239.0.0.0";
25 | private static String host;
26 |
27 | @BeforeClass
28 | public static void oneTimeSetUp() throws Exception {
29 | System.setProperty("ganglia.host", "239.0.0.0");
30 | host = InetAddress.getLocalHost().getHostName();
31 | }
32 |
33 | @Test
34 | @SuppressWarnings("unused")
35 | public void testMetricTypeConstructor() {
36 | try {
37 | GMonitor gmon = new GMonitor(MULTICAST_ADDRESS, 30l);
38 | GMetricInteger testMetric = (GMetricInteger) gmon.createGMetric(host, "Ganglia Test", GMetric.VALUE_TYPE_INT, "count", GMetric.SLOPE_UNSPECIFIED, true);
39 | } catch (IOException e) {
40 | e.printStackTrace();
41 | fail();
42 | }
43 | }
44 | @Test
45 | @SuppressWarnings("unused")
46 | public void testMetricTypeConstructor2() {
47 | try {
48 | GMonitor gmon = new GMonitor(MULTICAST_ADDRESS, 30l);
49 | GMetricString testMetric = (GMetricString) gmon.createGMetric(host, "Ganglia Test", GMetric.VALUE_TYPE_STRING, "count", GMetric.SLOPE_UNSPECIFIED, true);
50 | } catch (IOException e) {
51 | e.printStackTrace();
52 | fail();
53 | }
54 | }
55 | @Test
56 | @SuppressWarnings("unused")
57 | public void testMetricTypeConstructor3() {
58 | try {
59 | GMonitor gmon = new GMonitor(MULTICAST_ADDRESS, 30l);
60 | GMetricFloat testMetric = (GMetricFloat) gmon.createGMetric(host, "Ganglia Test", GMetric.VALUE_TYPE_FLOAT, "count", GMetric.SLOPE_UNSPECIFIED, true);
61 | } catch (IOException e) {
62 | e.printStackTrace();
63 | fail();
64 | }
65 | }
66 | @Test
67 | @SuppressWarnings("unused")
68 | public void testMetricTypeConstructor4() {
69 | try {
70 | GMonitor gmon = new GMonitor(MULTICAST_ADDRESS, 30l);
71 | GMetricDouble testMetric = (GMetricDouble) gmon.createGMetric(host, "Ganglia Test", GMetric.VALUE_TYPE_DOUBLE, "count", GMetric.SLOPE_UNSPECIFIED, true);
72 | } catch (IOException e) {
73 | e.printStackTrace();
74 | fail();
75 | }
76 | }
77 |
78 | @Test
79 | @SuppressWarnings("unused")
80 | public void testMetricTypeConstructor5() {
81 | try {
82 | GMonitor gmon = new GMonitor(MULTICAST_ADDRESS, 30l);
83 | GMetricInteger testMetric = (GMetricInteger) gmon.createGMetric(host, "Ganglia Test", "INVALID_TYPE", "count", GMetric.SLOPE_UNSPECIFIED, true);
84 | } catch (IllegalArgumentException e) {
85 | assertTrue(true);
86 | } catch (Exception e) {
87 | fail();
88 | }
89 | }
90 |
91 | @Test
92 | public void testUpdateInt() {
93 | int value = 10;
94 | try {
95 | GMonitor gmon = new GMonitor(MULTICAST_ADDRESS, 30l);
96 | GMetricInteger testMetric = (GMetricInteger) gmon.createGMetric(host, "Ganglia Test", GMetric.VALUE_TYPE_INT, "count", GMetric.SLOPE_UNSPECIFIED, true);
97 | testMetric.incrementValue(value);
98 | testMetric.incrementValue();
99 | testMetric.setValue(value);
100 | } catch (IOException e) {
101 | e.printStackTrace();
102 | fail();
103 | }
104 | }
105 |
106 | @Test
107 | public void testUpdateDouble() {
108 | double value = 10.50;
109 | try {
110 | GMonitor gmon = new GMonitor(MULTICAST_ADDRESS, 30l);
111 | GMetricDouble testMetric = (GMetricDouble) gmon.createGMetric(host, "Ganglia Test", GMetric.VALUE_TYPE_DOUBLE, "count", GMetric.SLOPE_UNSPECIFIED, true);
112 | testMetric.incrementValue(value);
113 | testMetric.incrementValue();
114 | testMetric.setValue(value);
115 | } catch (IOException e) {
116 | e.printStackTrace();
117 | fail();
118 | }
119 | }
120 |
121 | @Test
122 | public void testUpdateFloat() {
123 | float value = 10.50f;
124 | try {
125 | GMonitor gmon = new GMonitor(MULTICAST_ADDRESS, 30l);
126 | GMetricFloat testMetric = (GMetricFloat) gmon.createGMetric(host, "Ganglia Test", GMetric.VALUE_TYPE_FLOAT, "count", GMetric.SLOPE_UNSPECIFIED, true);
127 | testMetric.incrementValue(value);
128 | testMetric.incrementValue();
129 | testMetric.setValue(value);
130 | } catch (IOException e) {
131 | e.printStackTrace();
132 | fail();
133 | }
134 | }
135 |
136 | @Test
137 | public void testUpdateString() {
138 | String value = "10";
139 | try {
140 | GMonitor gmon = new GMonitor(MULTICAST_ADDRESS, 30l);
141 | GMetricString testMetric = (GMetricString) gmon.createGMetric(host, "Ganglia Test", GMetric.VALUE_TYPE_STRING, "count", GMetric.SLOPE_UNSPECIFIED, true);
142 | testMetric.setValue(value);
143 | testMetric.setValue(null);
144 | } catch (IOException e) {
145 | e.printStackTrace();
146 | fail();
147 | }
148 | }
149 |
150 | @SuppressWarnings("unchecked")
151 | @Test
152 | public void testWriteXDRString() {
153 | try {
154 | GMetric gmetric = new GMetric(host, "Ganglia Test", GMetric.VALUE_TYPE_INT, "count", GMetric.SLOPE_UNSPECIFIED, true);
155 | Class[] inputType = new Class[2];
156 | Object[] input = new Object[2];
157 | inputType[0] = DataOutputStream.class;
158 | inputType[1] = String.class;
159 | input[0] = null;
160 | input[1] = null;
161 | UnitTestHelper.invokeMethod(gmetric, "writeXDRString", inputType, input);
162 | input[0] = new DataOutputStream(new ByteArrayOutputStream());
163 | UnitTestHelper.invokeMethod(gmetric, "writeXDRString", inputType, input);
164 | } catch (Exception e) {
165 | e.printStackTrace();
166 | fail();
167 | }
168 | }
169 | }
--------------------------------------------------------------------------------
/gmetric-java/doc/info/ganglia/metric/type/package-use.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Uses of Package info.ganglia.metric.type
8 |
9 |
10 |
11 |
12 |
13 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | PREV
55 | NEXT
56 |
57 | FRAMES
58 | NO FRAMES
59 |
66 |
67 | All Classes
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | Uses of Package info.ganglia.metric.type
81 |
82 | No usage of info.ganglia.metric.type
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 | PREV
115 | NEXT
116 |
117 | FRAMES
118 | NO FRAMES
119 |
126 |
127 | All Classes
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/gmetric-java/doc/info/ganglia/class-use/GMonitor.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Uses of Class info.ganglia.GMonitor
8 |
9 |
10 |
11 |
12 |
13 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | PREV
55 | NEXT
56 |
57 | FRAMES
58 | NO FRAMES
59 |
66 |
67 | All Classes
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | Uses of Class info.ganglia.GMonitor
81 |
82 | No usage of info.ganglia.GMonitor
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 | PREV
115 | NEXT
116 |
117 | FRAMES
118 | NO FRAMES
119 |
126 |
127 | All Classes
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/gmetric-java/doc/info/ganglia/class-use/GConnector.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Uses of Class info.ganglia.GConnector
8 |
9 |
10 |
11 |
12 |
13 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | PREV
55 | NEXT
56 |
57 | FRAMES
58 | NO FRAMES
59 |
66 |
67 | All Classes
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | Uses of Class info.ganglia.GConnector
81 |
82 | No usage of info.ganglia.GConnector
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 | PREV
115 | NEXT
116 |
117 | FRAMES
118 | NO FRAMES
119 |
126 |
127 | All Classes
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/pmond/pmond/make_graph001.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | PREFIX=/usr/graph001
4 |
5 | BUILD_CONCURRENCY=1
6 |
7 |
8 |
9 |
10 | #-------------------------------------------------
11 | set -e
12 | DOWNLOADS=${PREFIX}/work/tarballs
13 | BUILDS=${PREFIX}/work/builds
14 | RECEIPTS=${PREFIX}/.installed
15 |
16 | # 3 variables inspired by Mozilla's crazy build system
17 | # OS_ARCH e.g.Linux, SunOS, Darwin
18 | # OS_CPUARCH, e.g. i86pc (solaris), x86, x86_64 (linux), i386 (darwin)
19 | # OS_RELEASE, e.g. 2.6.21-2952xen (linux variant), 5.11 (solaris variant)
20 |
21 | OS_ARCH=`uname -s`
22 | OS_CPUARCH=`uname -m`
23 | OS_RELEASE=`uname -r`
24 |
25 | #
26 | # Location of basic files... most of the time this won't need to be changed
27 | #
28 | TAR=tar
29 | MAKE=make
30 | BZCAT=bzcat
31 | GZCAT="gunzip -c"
32 | # some systems don't have sudo and run as root
33 | SUDO=sudo
34 | # something to download files, or curl or wget works
35 | #WGET="curl -A Mozilla -O"
36 | WGET=wget
37 |
38 | # required by 'binutils' -- part of the gnu 'texinfo' package
39 | MAKEINFO=makeinfo
40 |
41 | export PATH=${PREFIX}/bin:${PATH}
42 | export LDFLAGS="-L${PREFIX}/lib"
43 | export CPPFLAGS=-I${PREFIX}/include
44 | export CONFIG_SHELL=/bin/bash
45 | export LD_LIBRARY_PATH=${PREFIX}/lib:${LD_LIBRARY_PATH}
46 | if [ "${OS_ARCH}" = "Darwin" ]; then
47 | export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH
48 | fi
49 |
50 |
51 | function init_directories() {
52 | if [ ! -d $BUILDS ]; then
53 | mkdir -p ${BUILDS}
54 | fi
55 |
56 | if [ ! -d $PREFIX ]; then
57 | ${SUDO} mkdir -p ${PREFIX}
58 | fi
59 |
60 | if [ ! -d $RECEIPTS ]; then
61 | ${SUDO} mkdir -p ${RECEIPTS}
62 | fi
63 |
64 | if [ ! -d $DOWNLOADS ]; then
65 | ${SUDO} mkdir -p ${DOWNLOADS}
66 | fi
67 | }
68 |
69 | function find_receipt()
70 | {
71 | TARFILE=$1
72 | RECEIPT="${RECEIPTS}/${TARFILE}"
73 | if [ -f "${RECEIPT}" ]; then
74 | echo "Found receipt for ${TARFILE}";
75 | export HAS_RECEIPT=1;
76 | else
77 | export HAS_RECEIPT=0;
78 | fi
79 | return 0;
80 | }
81 |
82 | function write_receipt()
83 | {
84 | RECEIPT="${RECEIPTS}/${TARFILE}"
85 | ${SUDO} touch ${RECEIPT}
86 | }
87 |
88 | function unpacktar()
89 | {
90 | # given FULLFILE=/Downloads/gmp-4.2.4.tar.gz, then...
91 | # TARFILE = gmp.4.2.4.tar.gz
92 | # SUFFIX = 'gz'
93 | # TARDIR = gmp-4.2.4
94 |
95 | TARFILE="$1"
96 | TARDIR="$2"
97 | FULLFILE="${DOWNLOADS}/${TARFILE}";
98 | SUFFIX=${TARFILE/*./}
99 | if [ -z "${TARDIR}" ]; then
100 | TARDIR=${TARFILE/%.${SUFFIX}/}
101 | TARDIR=${TARDIR/%.tar/}
102 | fi
103 |
104 | UNPACK=""
105 | case ${SUFFIX} in
106 | ('bz2') { UNPACK="$BZCAT $FULLFILE"; } ;;
107 | ('gz' | 'tgz') { UNPACK="$GZCAT $FULLFILE"; } ;;
108 | ('tar') { UNPACK="cat $FULLFILE"; } ;;
109 | esac
110 | echo "UNPACK=${UNPACK}"
111 | # if not match, then exit
112 | if [ -z "${UNPACK}" ]; then
113 | echo "unknown tar file type: $SUFFIX for $FULLFILE";
114 | exit 1
115 | fi
116 | pushd .
117 |
118 | cd ${BUILDS}
119 | CMD="${UNPACK} | ${TAR} -xf -"
120 | echo "$CMD"
121 | eval $CMD
122 |
123 | cd $TARDIR
124 | CMD="${UNPACK} | tar -xf -"
125 | }
126 |
127 |
128 | function download_file()
129 | {
130 | URL="$1"
131 | TARFILE="`basename $URL`"
132 | # get tarball
133 | if [ ! -f "${DOWNLOADS}/${TARFILE}" ]; then
134 | echo "Downloading ${URL}"
135 | (cd ${DOWNLOADS} && ${WGET} ${URL})
136 | fi
137 | }
138 |
139 | function installgnu()
140 | {
141 | URL="$1"
142 | TARFILE="`basename $URL`"
143 |
144 | # $2 is 'configure args'
145 | CARGV="$2"
146 |
147 | # $3 is configure env, list as "KEY=VAL KEY2=VAL2...."
148 | CENV="$3"
149 |
150 | # sometimes, the directory created by untar is "non-standard"
151 | ALTDIR="$4"
152 |
153 | find_receipt $TARFILE
154 | if [ $HAS_RECEIPT -eq 1 ]; then
155 | return
156 | fi
157 |
158 | download_file $URL
159 | unpacktar $TARFILE $ALTDIR;
160 |
161 | #if [ ! -d objdir ]; then mkdir objdir; fi
162 | #cd objdir
163 |
164 | # the ${CARGV[@]} -- if string, then use it
165 | # if array, do a 'join' on the argument, with ' ' as separator
166 | CMD="${CENV} ./configure --prefix=${PREFIX} ${CARGV[@]}"
167 | echo $CMD
168 | eval $CMD
169 |
170 | ${MAKE} -j ${BUILD_CONCURRENCY}
171 | ${SUDO} ${MAKE} install
172 | write_receipt $TARFILE
173 | popd
174 | }
175 |
176 | function install_python() {
177 | URL="$1"
178 | TARFILE="`basename $URL`"
179 | # $2 is 'configure args'
180 | CARGV="$2"
181 |
182 | find_receipt $TARFILE
183 | if [ $HAS_RECEIPT -eq 1 ]; then
184 | return
185 | fi
186 | download_file ${URL}
187 | unpacktar ${TARFILE}
188 | ${SUDO} python setup.py build ${CARGV}
189 | ${SUDO} python setup.py install
190 | write_receipt ${TARFILE}
191 | popd
192 | }
193 |
194 | #-------------------------------------------------
195 | init_directories
196 |
197 | installgnu http://pkgconfig.freedesktop.org/releases/pkg-config-0.23.tar.gz
198 | export PKG_CONFIG=${PREFIX}/bin/pkg-config
199 |
200 | installgnu http://www.python.org/ftp/python/2.6.1/Python-2.6.1.tar.bz2 '--disable-toolbox-glue'
201 | installgnu ftp://ftp.simplesystems.org/pub/libpng/png/src/libpng-1.2.34.tar.bz2
202 |
203 | installgnu http://savannah.inetbridge.net/freetype/freetype-2.3.8.tar.bz2
204 |
205 | installgnu ftp://xmlsoft.org/libxml2/libxml2-2.7.3.tar.gz
206 | installgnu ftp://xmlsoft.org/libxml2/libxslt-1.1.24.tar.gz
207 |
208 | installgnu http://fontconfig.org/release/fontconfig-2.6.0.tar.gz '--enable-libxml2 --disable-docs'
209 |
210 | installgnu http://www.cairographics.org/releases/pixman-0.13.2.tar.gz
211 | installgnu http://ftp.gnome.org/pub/gnome/sources/glib/2.18/glib-2.18.4.tar.bz2
212 |
213 | #installgnu http://cairographics.org/releases/cairo-1.8.6.tar.gz
214 |
215 |
216 | installgnu http://ftp.gnome.org/pub/GNOME/sources/pango/1.23/pango-1.23.0.tar.bz2
217 |
218 | installgnu ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7-p72.tar.gz
219 |
220 | installgnu http://oss.oetiker.ch/rrdtool/pub/rrdtool-1.3.6.tar.gz
221 |
222 | install_python http://www.cython.org/Cython-0.10.3.tar.gz
223 | install_python http://codespeak.net/lxml/lxml-2.1.5.tgz --with-xslt-config=${PREFIX}/bin/xslt-config
224 |
225 |
--------------------------------------------------------------------------------
/gmetric-java/doc/info/ganglia/package-tree.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | info.ganglia Class Hierarchy
8 |
9 |
10 |
11 |
12 |
13 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | PREV
55 | NEXT
56 |
57 | FRAMES
58 | NO FRAMES
59 |
66 |
67 | All Classes
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | Hierarchy For Package info.ganglia
81 |
82 |
83 |
84 | Package Hierarchies: All Packages
85 |
86 |
87 | Class Hierarchy
88 |
89 |
90 | java.lang.Object
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 | PREV
124 | NEXT
125 |
126 | FRAMES
127 | NO FRAMES
128 |
135 |
136 | All Classes
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
--------------------------------------------------------------------------------
/gmetric-java/doc/overview-summary.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Overview
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | PREV
56 | NEXT
57 |
58 | FRAMES
59 | NO FRAMES
60 |
67 |
68 | All Classes
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | GMetric
82 |
83 |
84 |
85 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 | Overview
118 | Package
119 | Class
120 | Use
121 | Tree
122 | Deprecated
123 | Index
124 | Help
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 | PREV
136 | NEXT
137 |
138 | FRAMES
139 | NO FRAMES
140 |
147 |
148 | All Classes
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
--------------------------------------------------------------------------------