]> git.proxmox.com Git - pve-manager.git/blame - PVE/Status/Graphite.pm
update shipped appliance info index
[pve-manager.git] / PVE / Status / Graphite.pm
CommitLineData
eb32152f
DM
1package PVE::Status::Graphite;
2
3use strict;
4use warnings;
fa6f3716 5
228f017e 6use IO::Socket::IP;
8dcf2cac 7use Socket qw(SOL_SOCKET SO_SNDTIMEO SO_RCVTIMEO);
eb32152f 8
228f017e
TL
9use PVE::Status::Plugin;
10use PVE::JSONSchema;
11
eb32152f
DM
12# example config (/etc/pve/status.cfg)
13#graphite:
58541b94 14# server test
567bb543 15# port 2003
2c927f11 16# proto udp
567bb543 17# path proxmox.mycluster
eb32152f
DM
18# disable 0
19#
20
21use base('PVE::Status::Plugin');
22
23sub type {
24 return 'graphite';
25}
26
27sub properties {
28 return {
567bb543 29 path => {
5c90e08a 30 type => 'string', format => 'graphite-path',
567bb543 31 description => "root graphite path (ex: proxmox.mycluster.mykey)",
eb32152f 32 },
2c927f11
MV
33 timeout => {
34 type => 'integer',
87be2c19
TL
35 description => "graphite TCP socket timeout (default=1)",
36 minimum => 0,
37 default => 1,
2c927f11
MV
38 optional => 1
39 },
40 proto => {
41 type => 'string',
42 enum => ['udp', 'tcp'],
87be2c19 43 description => "Protocol to send graphite data. TCP or UDP (default)",
2c927f11
MV
44 optional => 1,
45 },
eb32152f
DM
46 };
47}
48
49sub options {
50 return {
58541b94 51 server => {},
567bb543 52 port => { optional => 1 },
0fc553eb 53 mtu => { optional => 1 },
2c927f11
MV
54 proto => { optional => 1 },
55 timeout => { optional => 1 },
567bb543 56 path => { optional => 1 },
eb32152f 57 disable => { optional => 1 },
5c90e08a 58 };
eb32152f
DM
59}
60
61# Plugin implementation
62sub update_node_status {
87be2c19 63 my ($class, $txn, $node, $data, $ctime) = @_;
567bb543 64
5c77a34f 65 return assemble($class, $txn, $data, $ctime, "nodes.$node");
eb32152f 66
eb32152f
DM
67}
68
69sub update_qemu_status {
87be2c19 70 my ($class, $txn, $vmid, $data, $ctime, $nodename) = @_;
5c77a34f
TL
71
72 return assemble($class, $txn, $data, $ctime, "qemu.$vmid");
eb32152f
DM
73}
74
75sub update_lxc_status {
87be2c19 76 my ($class, $txn, $vmid, $data, $ctime, $nodename) = @_;
eb32152f 77
5c77a34f 78 return assemble($class, $txn, $data, $ctime, "lxc.$vmid");
eb32152f
DM
79}
80
81sub update_storage_status {
87be2c19 82 my ($class, $txn, $nodename, $storeid, $data, $ctime) = @_;
567bb543 83
5c77a34f 84 return assemble($class, $txn, $data, $ctime, "storages.$nodename.$storeid");
567bb543
AD
85}
86
1d5c5ba1
TL
87sub _send_batch_size {
88 my ($class, $cfg) = @_;
89 my $proto = $cfg->{proto} || 'udp';
90 if ($proto eq 'tcp') {
91 return 56000;
92 }
93 return $class->SUPER::_send_batch_size($cfg);
94}
95
68f58b5d
TL
96sub _connect {
97 my ($class, $cfg) = @_;
567bb543 98
68f58b5d
TL
99 my $host = $cfg->{server};
100 my $port = $cfg->{port} || 2003;
101 my $proto = $cfg->{proto} || 'udp';
102 my $timeout = $cfg->{timeout} // 1;
567bb543
AD
103
104 my $carbon_socket = IO::Socket::IP->new(
5c90e08a
DC
105 PeerAddr => $host,
106 PeerPort => $port,
2c927f11
MV
107 Proto => $proto,
108 Timeout => $timeout,
f014da61 109 ) || die "couldn't create carbon socket [$host]:$port - $@\n";
567bb543 110
68f58b5d 111 if ($proto eq 'tcp') {
8dcf2cac
TL
112 # seconds and µs
113 my $timeout_struct = pack( 'l!l!', $timeout, 0);
114 setsockopt($carbon_socket, SOL_SOCKET, SO_SNDTIMEO, $timeout_struct);
115 setsockopt($carbon_socket, SOL_SOCKET, SO_RCVTIMEO, $timeout_struct);
2c927f11 116 }
68f58b5d
TL
117
118 return $carbon_socket;
119}
120
87be2c19 121sub assemble {
5c77a34f 122 my ($class, $txn, $data, $ctime, $object) = @_;
68f58b5d 123
87be2c19
TL
124 my $path = $txn->{cfg}->{path} // 'proxmox';
125 $path .= ".$object";
567bb543 126
108e0c8b
TL
127 # we do not want boolean/state information to export to graphite
128 my $key_blacklist = {
129 'template' => 1,
130 'pid' => 1,
131 'agent' => 1,
132 'serial' => 1,
133 };
134
108e0c8b
TL
135 my $assemble_graphite_data;
136 $assemble_graphite_data = sub {
137 my ($metric, $path) = @_;
138
139 for my $key (sort keys %$metric) {
1e4ae7d4 140 my $value = $metric->{$key};
87be2c19 141 next if !defined($value);
108e0c8b
TL
142
143 $key =~ s/\./-/g;
144 my $metricpath = $path . ".$key";
145
146 if (ref($value) eq 'HASH') {
147 $assemble_graphite_data->($value, $metricpath);
148 } elsif ($value =~ m/^[+-]?[0-9]*\.?[0-9]+$/ && !$key_blacklist->{$key}) {
5c77a34f 149 $class->add_metric_data($txn, "$metricpath $value $ctime\n");
5a5aed73 150 }
5c90e08a 151 }
108e0c8b 152 };
87be2c19 153 $assemble_graphite_data->($data, $path);
db2ce488
TL
154
155 $assemble_graphite_data = undef; # avoid cyclic reference!
567bb543
AD
156}
157
158PVE::JSONSchema::register_format('graphite-path', \&pve_verify_graphite_path);
159sub pve_verify_graphite_path {
160 my ($path, $noerr) = @_;
161
162 my $regex = "([a-zA-Z0-9]([a-zA-Z0-9\-]*[a-zA-Z0-9])?)";
163
164 if ($path !~ /^(${regex}\.)*${regex}$/) {
5c90e08a
DC
165 return undef if $noerr;
166 die "value does not look like a valid graphite path\n";
567bb543
AD
167 }
168
169 return $path;
170}
171
172
eb32152f 1731;