Projet

Général

Profil

Paste
Télécharger au format
Statistiques
| Branche: | Révision:

root / plugins / icecast / icecast_ @ 17f78427

Historique | Voir | Annoter | Télécharger (5,65 ko)

1
#!/usr/bin/env python2.5
2
"""
3
Plugin to monitor icecast2 streaming servers.
4

    
5
Author: Markus Lindenberg <markus.lindenberg@gmail.com>
6
COntributors: Julien 'Lta' BALLET <elthariel@gmail.com>
7
Version: 2009111101
8

    
9
This program is free software: you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation, either version 3 of the License, or
12
(at your option) any later version.
13

    
14
This program is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
GNU General Public License for more details.
18

    
19
You should have received a copy of the GNU General Public License
20
along with this program.  If not, see <http://www.gnu.org/licenses/>.
21

    
22
Usage:
23
	- Link or copy to /etc/munin/plugins
24
	- To enable listening duration, traffic and uptime stats,
25
	also link to icecast_duration, icecast_traffic and
26
	icecast_uptime respectively.
27

    
28
Configuration:
29
	- Enter your server, user and pw below
30
	  (The plugin does not need to run on
31
	  the same host as your icecast2 server)
32
	- Optionally provide hosts to exclude.
33
        - Optionally provide sources to exclude.
34

    
35
Possible TODOs:
36
	- use autoconf
37
	- use munin's configuration system
38
	- documentation
39

    
40
"""
41

    
42
# CONFIGURATION
43

    
44
server = "localhost:8000"
45
user = "admin"
46
pw = "yourpassword"
47

    
48
# Exclude these hosts when calculating listening duration / listeners count
49
# (we use this to prevent our aircheck recording system from appearing in the stats)
50
#exclude = ("123.123.123.123",)
51
exclude = ()
52

    
53
# Exclude these sources from calculation. This is useful to excluse special sources like
54
# fallback sources which doesn't expose the same informations and then break this script
55
# Ever add fallback sources to this list
56
#source_exclude = ["/fallback.mp3", "/fallback.ogg"]
57
source_exclude = ("/fallback.mp3", "/fallback.ogg")
58

    
59
# /CONFIGURATION
60

    
61
from sys import argv, exit, stderr
62
import urllib
63
from xml.etree.ElementTree import ElementTree
64
from os.path import basename
65

    
66
class IcecastURLopener(urllib.FancyURLopener):
67
	def prompt_user_passwd(self, host, realm):
68
		return (user, pw)
69

    
70
opener = IcecastURLopener()
71
f = opener.open("http://%s/admin/listmounts" % server)
72

    
73
tree = ElementTree()
74
tree.parse(f)
75
f.close()
76

    
77
sources = []
78
for s in tree.getiterator("source"):
79
	if s.attrib["mount"] not in source_exclude:
80
		sources.append({"mount": s.attrib["mount"],
81
				"listeners": s.find("listeners").text,
82
				"connected": s.find("Connected").text})
83

    
84
plugin_name = basename(argv[0])
85

    
86
try:
87
	if argv[1] == "config":
88
		if plugin_name == "icecast_duration":
89
			print "graph_title Icecast client listening duration"
90
			print "graph_args --base 1000 -l 0"
91
			print "graph_scale no"
92
			print "graph_category streaming"
93
			print "graph_vlabel minutes"
94
			print "avg.label average listening duration"
95
			print "mdn.label median listening duration"
96
		elif plugin_name == "icecast_uptime":
97
			print "graph_title Icecast source uptime"
98
			print "graph_args --base 1000 -l 0"
99
			print "graph_scale no"
100
			print "graph_category streaming"
101
			print "graph_vlabel hours"
102
			for s in sources:
103
				print "%s.label source %s" % (s["mount"].strip("/").replace(".","_").replace("-","_"), s["mount"])
104
		elif plugin_name == "icecast_traffic":
105
			print "graph_title Icecast outgoing traffic"
106
			print "graph_args --base 1024 -l 0"
107
			print "graph_category streaming"
108
			print "graph_vlabel bytes / second"
109
			is_first = True
110
			for s in sources:
111
				sname = s["mount"].strip("/").replace(".","_").replace("-","_")
112
				print "%s.label source %s" % (sname, s["mount"])
113
				print "%s.type DERIVE" % sname
114
				print "%s.min 0" % sname
115
				if is_first:
116
					print "%s.draw AREA" % sname
117
					is_first = False
118
				else:
119
					print "%s.draw STACK" % sname
120
		else:
121
			print "graph_title Icecast listeners count"
122
			print "graph_args --base 1000 -l 0"
123
			print "graph_scale no"
124
			print "graph_category streaming"
125
			print "graph_vlabel listeners"
126
			is_first = True
127
			for s in sources:
128
				sname = s["mount"].strip("/").replace(".","_").replace("-","_")
129
				print "%s.label source %s" % (sname, s["mount"])
130
				if is_first:
131
					print "%s.draw AREA" % sname
132
					is_first = False
133
				else:
134
					print "%s.draw STACK" % sname
135

    
136
		exit(0)
137

    
138
except IndexError:
139
	pass
140

    
141
if plugin_name == "icecast_uptime":
142
	for s in sources:
143
		print "%s.value %s" % (s["mount"].strip("/").replace(".","_").replace("-","_"), int(s["connected"]) / 3600.)
144

    
145
elif plugin_name == "icecast_traffic":
146
	f = opener.open("http://%s/admin/stats.xml" % server)
147
	tree = ElementTree()
148
	tree.parse(f)
149
	f.close()
150
	for s in tree.getiterator("source"):
151
		print "%s.value %s" % (s.attrib["mount"].strip("/").replace(".","_").replace("-","_"), s.find("total_bytes_sent").text)
152

    
153
else:
154
	durations = {}
155
	for s in sources:
156
		durations[s["mount"]] = []
157
		f = opener.open("http://%s/admin/listclients?mount=%s" % (server, s["mount"]))
158
		tree = ElementTree()
159
		tree.parse(f)
160
		f.close()
161
		for l in tree.getiterator("listener"):
162
			if l.find("IP").text not in exclude:
163
				durations[s["mount"]].append(int(l.find("Connected").text))
164

    
165
	if plugin_name == "icecast_duration":
166
		if not durations:
167
			exit(0)
168
		alldurations = reduce(lambda x, y: x+y, durations.values())
169
		alldurations.sort()
170
		print "avg.value %s" % (sum(alldurations) / float(len(alldurations)) / 60.,)
171
		if len(alldurations) % 2:
172
			median = alldurations[len(alldurations) / 2] / 60.
173
		elif len(alldurations):
174
			median = (alldurations[len(alldurations) / 2 - 1] + alldurations[len(alldurations) / 2]) / 2. / 60.
175
		else:
176
			median = 0
177
		print "mdn.value %s" % median
178
	else:
179
		for s in sources:
180
			print "%s.value %s" % (s["mount"].strip("/").replace(".","_").replace("-","_"), len(durations[s["mount"]]))
181