summaryrefslogtreecommitdiffstats
path: root/collectors/charts.d.plugin/apache/apache.chart.sh
blob: 7d09ee67670a7ba6ba45e7eda6a8a4c34250fb7e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# shellcheck shell=bash
# no need for shebang - this file is loaded from charts.d.plugin
# SPDX-License-Identifier: GPL-3.0-or-later

# netdata
# real-time performance and health monitoring, done right!
# (C) 2016 Costa Tsaousis <costa@tsaousis.gr>
#

# the URL to download apache status info
apache_url="http://127.0.0.1:80/server-status?auto"
apache_curl_opts=

# _update_every is a special variable - it holds the number of seconds
# between the calls of the _update() function
apache_update_every=

apache_priority=60000

# convert apache floating point values
# to integer using this multiplier
# this only affects precision - the values
# will be in the proper units
apache_decimal_detail=1000000

declare -a apache_response=()
apache_accesses=0
apache_kbytes=0
apache_reqpersec=0
apache_bytespersec=0
apache_bytesperreq=0
apache_busyworkers=0
apache_idleworkers=0
apache_connstotal=0
apache_connsasyncwriting=0
apache_connsasynckeepalive=0
apache_connsasyncclosing=0

apache_keys_detected=0
apache_has_conns=0
apache_key_accesses=
apache_key_kbytes=
apache_key_reqpersec=
apache_key_bytespersec=
apache_key_bytesperreq=
apache_key_busyworkers=
apache_key_idleworkers=
apache_key_scoreboard=
apache_key_connstotal=
apache_key_connsasyncwriting=
apache_key_connsasynckeepalive=
apache_key_connsasyncclosing=
apache_detect() {
	local i=0
	for x in "${@}"; do
		case "${x}" in
		'Total Accesses') apache_key_accesses=$((i + 1)) ;;
		'Total kBytes') apache_key_kbytes=$((i + 1)) ;;
		'ReqPerSec') apache_key_reqpersec=$((i + 1)) ;;
		'BytesPerSec') apache_key_bytespersec=$((i + 1)) ;;
		'BytesPerReq') apache_key_bytesperreq=$((i + 1)) ;;
		'BusyWorkers') apache_key_busyworkers=$((i + 1)) ;;
		'IdleWorkers') apache_key_idleworkers=$((i + 1)) ;;
		'ConnsTotal') apache_key_connstotal=$((i + 1)) ;;
		'ConnsAsyncWriting') apache_key_connsasyncwriting=$((i + 1)) ;;
		'ConnsAsyncKeepAlive') apache_key_connsasynckeepalive=$((i + 1)) ;;
		'ConnsAsyncClosing') apache_key_connsasyncclosing=$((i + 1)) ;;
		'Scoreboard') apache_key_scoreboard=$((i)) ;;
		esac

		i=$((i + 1))
	done

	# we will not check of the Conns*
	# keys, since these are apache 2.4 specific
	[ -z "${apache_key_accesses}" ] && error "missing 'Total Accesses' from apache server: ${*}" && return 1
	[ -z "${apache_key_kbytes}" ] && error "missing 'Total kBytes' from apache server: ${*}" && return 1
	[ -z "${apache_key_reqpersec}" ] && error "missing 'ReqPerSec' from apache server: ${*}" && return 1
	[ -z "${apache_key_bytespersec}" ] && error "missing 'BytesPerSec' from apache server: ${*}" && return 1
	[ -z "${apache_key_bytesperreq}" ] && error "missing 'BytesPerReq' from apache server: ${*}" && return 1
	[ -z "${apache_key_busyworkers}" ] && error "missing 'BusyWorkers' from apache server: ${*}" && return 1
	[ -z "${apache_key_idleworkers}" ] && error "missing 'IdleWorkers' from apache server: ${*}" && return 1
	[ -z "${apache_key_scoreboard}" ] && error "missing 'Scoreboard' from apache server: ${*}" && return 1

	if [ ! -z "${apache_key_connstotal}" ] &&
		[ ! -z "${apache_key_connsasyncwriting}" ] &&
		[ ! -z "${apache_key_connsasynckeepalive}" ] &&
		[ ! -z "${apache_key_connsasyncclosing}" ]; then
		apache_has_conns=1
	else
		apache_has_conns=0
	fi

	return 0
}

apache_get() {
	local oIFS="${IFS}" ret
	# shellcheck disable=2207
	IFS=$':\n' apache_response=($(run curl -Ss ${apache_curl_opts} "${apache_url}"))
	ret=$?
	IFS="${oIFS}"

	if [ $ret -ne 0 ] || [ "${#apache_response[@]}" -eq 0 ]; then
		return 1
	fi

	# the last line on the apache output is "Scoreboard"
	# we use this label to detect that the output has a new word count
	if [ ${apache_keys_detected} -eq 0 ] || [ "${apache_response[${apache_key_scoreboard}]}" != "Scoreboard" ]; then
		apache_detect "${apache_response[@]}" || return 1
		apache_keys_detected=1
	fi

	apache_accesses="${apache_response[${apache_key_accesses}]}"
	apache_kbytes="${apache_response[${apache_key_kbytes}]}"

	float2int "${apache_response[${apache_key_reqpersec}]}" ${apache_decimal_detail}
	apache_reqpersec=${FLOAT2INT_RESULT}

	float2int "${apache_response[${apache_key_bytespersec}]}" ${apache_decimal_detail}
	apache_bytespersec=${FLOAT2INT_RESULT}

	float2int "${apache_response[${apache_key_bytesperreq}]}" ${apache_decimal_detail}
	apache_bytesperreq=${FLOAT2INT_RESULT}

	apache_busyworkers="${apache_response[${apache_key_busyworkers}]}"
	apache_idleworkers="${apache_response[${apache_key_idleworkers}]}"

	if
		[ -z "${apache_accesses}" ] ||
			[ -z "${apache_kbytes}" ] ||
			[ -z "${apache_reqpersec}" ] ||
			[ -z "${apache_bytespersec}" ] ||
			[ -z "${apache_bytesperreq}" ] ||
			[ -z "${apache_busyworkers}" ]
		[ -z "${apache_idleworkers}" ]
	then
		error "empty values got from apache server: ${apache_response[*]}"
		return 1
	fi

	if [ ${apache_has_conns} -eq 1 ]; then
		apache_connstotal="${apache_response[${apache_key_connstotal}]}"
		apache_connsasyncwriting="${apache_response[${apache_key_connsasyncwriting}]}"
		apache_connsasynckeepalive="${apache_response[${apache_key_connsasynckeepalive}]}"
		apache_connsasyncclosing="${apache_response[${apache_key_connsasyncclosing}]}"
	fi

	return 0
}

# _check is called once, to find out if this chart should be enabled or not
apache_check() {

	apache_get
	# shellcheck disable=2181
	if [ $? -ne 0 ]; then
		# shellcheck disable=2154
		error "cannot find stub_status on URL '${apache_url}'. Please set apache_url='http://apache.server:80/server-status?auto' in $confd/apache.conf"
		return 1
	fi

	# this should return:
	#  - 0 to enable the chart
	#  - 1 to disable the chart

	return 0
}

# _create is called once, to create the charts
apache_create() {
	cat <<EOF
CHART apache_local.bytesperreq '' "apache Lifetime Avg. Response Size" "bytes/request" statistics apache.bytesperreq area $((apache_priority + 8)) $apache_update_every
DIMENSION size '' absolute 1 ${apache_decimal_detail}
CHART apache_local.workers '' "apache Workers" "workers" workers apache.workers stacked $((apache_priority + 5)) $apache_update_every
DIMENSION idle '' absolute 1 1
DIMENSION busy '' absolute 1 1
CHART apache_local.reqpersec '' "apache Lifetime Avg. Requests/s" "requests/s" statistics apache.reqpersec line $((apache_priority + 6)) $apache_update_every
DIMENSION requests '' absolute 1 ${apache_decimal_detail}
CHART apache_local.bytespersec '' "apache Lifetime Avg. Bandwidth/s" "kilobits/s" statistics apache.bytespersec area $((apache_priority + 7)) $apache_update_every
DIMENSION sent '' absolute 8 $((apache_decimal_detail * 1000))
CHART apache_local.requests '' "apache Requests" "requests/s" requests apache.requests line $((apache_priority + 1)) $apache_update_every
DIMENSION requests '' incremental 1 1
CHART apache_local.net '' "apache Bandwidth" "kilobits/s" bandwidth apache.net area $((apache_priority + 3)) $apache_update_every
DIMENSION sent '' incremental 8 1
EOF

	if [ ${apache_has_conns} -eq 1 ]; then
		cat <<EOF2
CHART apache_local.connections '' "apache Connections" "connections" connections apache.connections line $((apache_priority + 2)) $apache_update_every
DIMENSION connections '' absolute 1 1
CHART apache_local.conns_async '' "apache Async Connections" "connections" connections apache.conns_async stacked $((apache_priority + 4)) $apache_update_every
DIMENSION keepalive '' absolute 1 1
DIMENSION closing '' absolute 1 1
DIMENSION writing '' absolute 1 1
EOF2
	fi

	return 0
}

# _update is called continuously, to collect the values
apache_update() {
	# the first argument to this function is the microseconds since last update
	# pass this parameter to the BEGIN statement (see bellow).

	# do all the work to collect / calculate the values
	# for each dimension
	# remember: KEEP IT SIMPLE AND SHORT

	apache_get || return 1

	# write the result of the work.
	cat <<VALUESEOF
BEGIN apache_local.requests $1
SET requests = $((apache_accesses))
END
BEGIN apache_local.net $1
SET sent = $((apache_kbytes))
END
BEGIN apache_local.reqpersec $1
SET requests = $((apache_reqpersec))
END
BEGIN apache_local.bytespersec $1
SET sent = $((apache_bytespersec))
END
BEGIN apache_local.bytesperreq $1
SET size = $((apache_bytesperreq))
END
BEGIN apache_local.workers $1
SET idle = $((apache_idleworkers))
SET busy = $((apache_busyworkers))
END
VALUESEOF

	if [ ${apache_has_conns} -eq 1 ]; then
		cat <<VALUESEOF2
BEGIN apache_local.connections $1
SET connections = $((apache_connstotal))
END
BEGIN apache_local.conns_async $1
SET keepalive = $((apache_connsasynckeepalive))
SET closing = $((apache_connsasyncclosing))
SET writing = $((apache_connsasyncwriting))
END
VALUESEOF2
	fi

	return 0
}