Skip to content

Commit 36d9252

Browse files
author
Stepan Oksanichenko
authored
Added ability to use unix socket instead http connection (#1)
* Add ability to use unix socket instead http requests to server - Feature: Added parameter `web.socket-path` which sets path to an unix socket file. The program uses http server if the parameter is empty. - Feature: Added parameter `web.socket-permissions` which set file permissions to an unix socket file. Default value is 0640. Signed-off-by: Stepan Oksanichenko <soksanichenko@cloudlinux.com>
1 parent 16ef6de commit 36d9252

3 files changed

Lines changed: 89 additions & 12 deletions

File tree

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ update_fixtures:
105105
test-e2e: build collector/fixtures/sys/.unpacked
106106
@echo ">> running end-to-end tests"
107107
./end-to-end-test.sh
108+
@echo ">> running end-to-end tests with unix socket"
109+
./end-to-end-test.sh -s
108110

109111
.PHONY: skip-test-e2e
110112
skip-test-e2e:

end-to-end-test.sh

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ cd "$(dirname $0)"
5757

5858
port="$((10000 + (RANDOM % 10000)))"
5959
tmpdir=$(mktemp -d /tmp/node_exporter_e2e_test.XXXXXX)
60+
unix_socket="${tmpdir}/node_exporter.socket"
6061

6162
skip_re="^(go_|node_exporter_build_info|node_scrape_collector_duration_seconds|process_|node_textfile_mtime_seconds)"
6263

@@ -67,8 +68,8 @@ case "${arch}" in
6768
*) fixture='collector/fixtures/e2e-output.txt' ;;
6869
esac
6970

70-
keep=0; update=0; verbose=0
71-
while getopts 'hkuv' opt
71+
keep=0; update=0; verbose=0; socket=0;
72+
while getopts 'hkuvs' opt
7273
do
7374
case "$opt" in
7475
k)
@@ -77,6 +78,9 @@ do
7778
u)
7879
update=1
7980
;;
81+
s)
82+
socket=1
83+
;;
8084
v)
8185
verbose=1
8286
set -x
@@ -86,6 +90,7 @@ do
8690
echo " -k: keep temporary files and leave node_exporter running"
8791
echo " -u: update fixture"
8892
echo " -v: verbose output"
93+
echo " -s: use unix socket"
8994
exit 1
9095
;;
9196
esac
@@ -97,6 +102,14 @@ then
97102
exit 1
98103
fi
99104

105+
if [ ${socket} -ne 0 ]; then
106+
touch "${unix_socket}"
107+
connection_params="--web.socket-path=${unix_socket}"
108+
else
109+
connection_params="--web.listen-address=127.0.0.1:${port}"
110+
fi
111+
112+
100113
./node_exporter \
101114
--path.procfs="collector/fixtures/proc" \
102115
--path.sysfs="collector/fixtures/sys" \
@@ -107,7 +120,7 @@ fi
107120
--collector.qdisc.fixtures="collector/fixtures/qdisc/" \
108121
--collector.netclass.ignored-devices="(bond0|dmz|int)" \
109122
--collector.cpu.info \
110-
--web.listen-address "127.0.0.1:${port}" \
123+
${connection_params} \
111124
--log.level="debug" > "${tmpdir}/node_exporter.log" 2>&1 &
112125

113126
echo $! > "${tmpdir}/node_exporter.pid"
@@ -129,11 +142,21 @@ EOF
129142

130143
if [ ${keep} -eq 0 ]
131144
then
132-
kill -9 "$(cat ${tmpdir}/node_exporter.pid)"
145+
kill "$(cat ${tmpdir}/node_exporter.pid)"
133146
# This silences the "Killed" message
134147
set +e
135148
wait "$(cat ${tmpdir}/node_exporter.pid)" > /dev/null 2>&1
149+
rc=0
150+
if [ ${socket} -ne 0 ]; then
151+
if ls -l "${unix_socket}" &> /dev/null; then
152+
echo "Node exporter didn't remove the socket file after it exiting"
153+
rc=1
154+
fi
155+
fi
136156
rm -rf "${tmpdir}"
157+
# We should exit with non-zero code,
158+
# if node exporter didn't remove the socket file.
159+
exit $rc
137160
fi
138161
}
139162

@@ -153,8 +176,13 @@ get() {
153176
}
154177

155178
sleep 1
156-
157-
get "127.0.0.1:${port}/metrics" | grep -E -v "${skip_re}" > "${tmpdir}/e2e-output.txt"
179+
(
180+
if [ ${socket} -ne 0 ]; then
181+
curl -s -X GET --unix-socket "${unix_socket}" ./metrics
182+
else
183+
get "127.0.0.1:${port}/metrics"
184+
fi
185+
) | grep -E -v "${skip_re}" > "${tmpdir}/e2e-output.txt"
158186

159187
diff -u \
160188
"${fixture}" \

node_exporter.go

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,14 @@ package main
1515

1616
import (
1717
"fmt"
18+
"github.com/prometheus/node_exporter/https"
19+
"net"
1820
"net/http"
1921
_ "net/http/pprof"
2022
"os"
23+
"os/signal"
2124
"sort"
25+
"syscall"
2226

2327
"github.com/prometheus/common/promlog"
2428
"github.com/prometheus/common/promlog/flag"
@@ -29,7 +33,6 @@ import (
2933
"github.com/prometheus/client_golang/prometheus/promhttp"
3034
"github.com/prometheus/common/version"
3135
"github.com/prometheus/node_exporter/collector"
32-
"github.com/prometheus/node_exporter/https"
3336
kingpin "gopkg.in/alecthomas/kingpin.v2"
3437
)
3538

@@ -137,7 +140,19 @@ func (h *handler) innerHandler(filters ...string) (http.Handler, error) {
137140
}
138141

139142
func main() {
143+
144+
done := make(chan os.Signal, 1)
145+
signal.Notify(done, syscall.SIGINT, syscall.SIGTERM)
146+
140147
var (
148+
socketPath = kingpin.Flag(
149+
"web.socket-path",
150+
"Path to a unix socket file on which to expose metrics and web interface.",
151+
).String()
152+
socketPermissions = kingpin.Flag(
153+
"web.socket-permissions",
154+
"Permissions of unix socket file.",
155+
).Default("0640").Int32()
141156
listenAddress = kingpin.Flag(
142157
"web.listen-address",
143158
"Address on which to expose metrics and web interface.",
@@ -188,10 +203,42 @@ func main() {
188203
</html>`))
189204
})
190205

191-
level.Info(logger).Log("msg", "Listening on", "address", *listenAddress)
192-
server := &http.Server{Addr: *listenAddress}
193-
if err := https.Listen(server, *configFile, logger); err != nil {
194-
level.Error(logger).Log("err", err)
195-
os.Exit(1)
206+
humanAddress := "address " + *listenAddress
207+
if *socketPath != "" {
208+
humanAddress = "path " + *socketPath
196209
}
210+
var server *http.Server
211+
var serve func() error
212+
level.Info(logger).Log("msg", "Listening on", "address", humanAddress)
213+
server = &http.Server{}
214+
if *socketPath == "" {
215+
server = &http.Server{Addr: *listenAddress}
216+
serve = func() error {
217+
return https.Listen(server, *configFile, logger)
218+
}
219+
} else {
220+
os.Remove(*socketPath)
221+
unixListener, err := net.Listen("unix", *socketPath)
222+
if err != nil {
223+
level.Error(logger).Log("err", err)
224+
os.Exit(1)
225+
}
226+
if err := os.Chmod(*socketPath, os.FileMode(*socketPermissions)); err != nil {
227+
level.Error(logger).Log("err", err)
228+
os.Exit(1)
229+
}
230+
serve = func() error {
231+
return server.Serve(unixListener)
232+
}
233+
}
234+
go func() {
235+
if err := serve(); err != nil {
236+
level.Error(logger).Log("err", err)
237+
os.Exit(1)
238+
}
239+
}()
240+
<-done
241+
level.Info(logger).Log("msg", "Connection closed on", humanAddress)
242+
server.Close()
243+
os.Exit(0)
197244
}

0 commit comments

Comments
 (0)