]> git.proxmox.com Git - pve-manager.git/blob - PVE/Status/Graphite.pm
status/graphite: just use setsockopt to set timeouts
[pve-manager.git] / PVE / Status / Graphite.pm
1 package PVE::Status::Graphite;
2
3 use strict;
4 use warnings;
5
6 use IO::Socket::IP;
7 use Socket qw(SOL_SOCKET SO_SNDTIMEO SO_RCVTIMEO);
8
9 use PVE::Status::Plugin;
10 use PVE::JSONSchema;
11
12 # example config (/etc/pve/status.cfg)
13 #graphite:
14 # server test
15 # port 2003
16 # proto udp
17 # path proxmox.mycluster
18 # disable 0
19 #
20
21 use base('PVE::Status::Plugin');
22
23 sub type {
24 return 'graphite';
25 }
26
27 sub properties {
28 return {
29 path => {
30 type => 'string', format => 'graphite-path',
31 description => "root graphite path (ex: proxmox.mycluster.mykey)",
32 },
33 timeout => {
34 type => 'integer',
35 description => "graphite tcp socket timeout (default=1)",
36 optional => 1
37 },
38 proto => {
39 type => 'string',
40 enum => ['udp', 'tcp'],
41 description => "send graphite data using tcp or udp (default)",
42 optional => 1,
43 },
44 };
45 }
46
47 sub options {
48 return {
49 server => {},
50 port => { optional => 1 },
51 proto => { optional => 1 },
52 timeout => { optional => 1 },
53 path => { optional => 1 },
54 disable => { optional => 1 },
55 };
56 }
57
58 # we do not want boolean/state information to export to graphite
59 my $key_blacklist = {
60 'template' => 1,
61 'pid' => 1,
62 'agent' => 1,
63 'serial' => 1,
64 };
65
66 # Plugin implementation
67 sub update_node_status {
68 my ($class, $plugin_config, $node, $data, $ctime) = @_;
69
70 write_graphite_hash($plugin_config, $data, $ctime, "nodes.$node");
71
72 }
73
74 sub update_qemu_status {
75 my ($class, $plugin_config, $vmid, $data, $ctime, $nodename) = @_;
76 write_graphite_hash($plugin_config, $data, $ctime, "qemu.$vmid");
77 }
78
79 sub update_lxc_status {
80 my ($class, $plugin_config, $vmid, $data, $ctime, $nodename) = @_;
81
82 write_graphite_hash($plugin_config, $data, $ctime, "lxc.$vmid");
83 }
84
85 sub update_storage_status {
86 my ($class, $plugin_config, $nodename, $storeid, $data, $ctime) = @_;
87
88 write_graphite_hash($plugin_config, $data, $ctime, "storages.$nodename.$storeid");
89 }
90
91 sub write_graphite_hash {
92 my ($plugin_config, $d, $ctime, $object) = @_;
93
94 my $host = $plugin_config->{server};
95 my $port = $plugin_config->{port} || 2003;
96 my $path = $plugin_config->{path} // 'proxmox';
97 my $proto = $plugin_config->{proto} || 'udp';
98 my $timeout = $plugin_config->{timeout} // 1;
99
100 my $carbon_socket = IO::Socket::IP->new(
101 PeerAddr => $host,
102 PeerPort => $port,
103 Proto => $proto,
104 Timeout => $timeout,
105 ) || die "couldn't create carbon socket [$host]:$port - $@\n";
106
107 if ( $proto eq 'tcp' ) {
108 # seconds and µs
109 my $timeout_struct = pack( 'l!l!', $timeout, 0);
110 setsockopt($carbon_socket, SOL_SOCKET, SO_SNDTIMEO, $timeout_struct);
111 setsockopt($carbon_socket, SOL_SOCKET, SO_RCVTIMEO, $timeout_struct);
112 }
113 write_graphite($carbon_socket, $d, $ctime, $path.".$object");
114
115 $carbon_socket->close() if $carbon_socket;
116
117 }
118
119 sub write_graphite {
120 my ($carbon_socket, $d, $ctime, $path) = @_;
121
122 for my $key (keys %$d) {
123
124 my $value = $d->{$key};
125 my $oldpath = $path;
126 $key =~ s/\./-/g;
127 $path .= ".$key";
128
129 if ( defined $value ) {
130 if ( ref $value eq 'HASH' ) {
131 write_graphite($carbon_socket, $value, $ctime, $path);
132 } elsif ($value =~ m/^[+-]?[0-9]*\.?[0-9]+$/ &&
133 !$key_blacklist->{$key}) {
134 $carbon_socket->send( "$path $value $ctime\n" );
135 } else {
136 # do not send blacklisted or non-numeric values
137 }
138 }
139 $path = $oldpath;
140 }
141 }
142
143 PVE::JSONSchema::register_format('graphite-path', \&pve_verify_graphite_path);
144 sub pve_verify_graphite_path {
145 my ($path, $noerr) = @_;
146
147 my $regex = "([a-zA-Z0-9]([a-zA-Z0-9\-]*[a-zA-Z0-9])?)";
148
149 if ($path !~ /^(${regex}\.)*${regex}$/) {
150 return undef if $noerr;
151 die "value does not look like a valid graphite path\n";
152 }
153
154 return $path;
155 }
156
157
158 1;