forked from mhwest13/Memcached-Munin-Plugin
-
Notifications
You must be signed in to change notification settings - Fork 1
/
memcached_multi_
executable file
·1631 lines (1423 loc) · 51.3 KB
/
memcached_multi_
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
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/usr/bin/perl
#
=head1 MEMCACHED MULTI
Memcached Multi - A Plugin to monitor Memcached Servers (Multigraph)
The common difference between this memcached Munin plugin and others that exists, is that
others don't expose slab information from memcached, so you can better tune your memcached
interaction / stability / etc. With this plugin we leverage multigraph capabilities in
Munin to "hide" the slab information underneath of their parent graphs.
=head1 MUNIN NODE CONFIGURATION
The following configuration information can be overridden by placing environment definitions
like shown here, in a file located in /etc/munin/plugin-conf.d
[memcached_multi_*]
env.host 127.0.0.1 *default*
env.port 11211 *default*
env.timescale 3 *default*
env.cmds get set delete incr decr touch *default*
env.leitime -1 *default*
=head2 MUNIN NODE ENVIRONMENT CONFIGURATION EXPLANATION
host = host we are going to monitor, this can be used to specify a unix socket.
port = port we are connecting to, in order to gather stats
timescale = what time frame do we want to format our graphs too
cmds = cmd types to display on cmd graph, remove cmds you don't want displayed from list.
leitime = setting this to 1 will re-enable slab eviction time graphs, see note below.
=head2 BASIC TROUBLESHOOTING
Please make sure you can telnet to your memcache servers and issue the
following commands: stats, stats settings, stats items and stats slabs.
=head2 PLUGIN INFORMATION
Available Graphs contained in this Plugin
bytes => This graphs the current network traffic in and out
commands => I<MULTIGRAPH> This graphs the current commands being issued to the memcache machine.
B<Multigraph breaks this down to per slab.>
conns => This graphs the current, max connections as well as avg conns per sec avg conns per sec
and is derived from total_conns / uptime.
evictions => I<MULTIGRAPH> This graphs the current evictions on the node.
B<Multigraph breaks this down to per slab.>
items => I<MULTIGRAPH> This graphs the current items and total items in the memcached node.
B<Multigraph breaks this down to per slab.>
memory => I<MULTIGRAPH> This graphs the current and max memory allocation.
B<Multigraph breaks this down to per slab.>
unfetched => I<MULTIGRAPH> This graphs the number of items that were never touched by a
get/incr/append/etc before being evicted or expiring from the cache.
B<Multigraph breaks this down to per slab.>
=head1 ADDITIONAL INFORMATION
B<NOTE:> The slab plugin for LEI has been disabled since I believe the counters to be inaccurate,
or perhaps not being updated as often I thought they would be. They can be re-enabled by
setting an environment variable, see munin configuration section at the top.
You will find that some of the graphs have LEI on them. This was done in order to save room
on space for text and stands for B<Last Evicted Item>.
The B<Timescale> variable formats certain graphs based on the following guidelines.
1 => Seconds
2 => Minutes
3 => Hours B<*Default*>
4 => Days
=head1 ACKNOWLEDGEMENTS
Thanks to dormando for putting up with me ;)
=head1 AUTHOR
Matt West < https://github.com/mhwest13/Memcached-Munin-Plugin >
=head1 LICENSE
GPLv2
=head1 MAGIC MARKERS
#%# family=auto
#%# capabilities=autoconf suggest
=cut
use strict;
use warnings;
use IO::Socket;
use Munin::Plugin;
use File::Basename;
if ( basename($0) !~ /(?:([^\/]+)_)?memcached_multi_/ ) {
print
"This script needs to be named (prefix_)?memcached_multi_ to run properly.\n";
exit 1;
}
# tell munin about our multigraph capabilities
need_multigraph();
=head1 Variable Declarations
This section of code is to declare the variables used throughout the plugin
Some of them are imported as environment variables from munin plugin conf.d
file, others are hashes used for storing information that comes from the
stats commands issued to memcached.
=cut
# lets import environment variables for the plugin or use the default
my $host = $ENV{host} || "127.0.0.1";
my $port = $ENV{port} || 11211;
my $connection;
# This gives us the ability to control the timescale our graphs are displaying.
# The default it set to divide by hours, if you want to get seconds set it to 1.
# Options: 1 = seconds, 2 = minutes, 3 = hours, 4 = days
my $timescale = $ENV{timescale} || 3;
# This gives us the ability to turn the Last Evicted Item time slab graph on.
# It was removed because I believe the counter / response to be broken but
# perhaps this was useful to someone.
my $leitime = $ENV{leitime} || -1;
# This gives us the ability to specify which commands we want to display on the
# command graph. Allowing finer control since some environments don't leverage
# every command possible in memcached.
# Options: get set delete incr decr cas touch flush
my $commands = $ENV{cmds} || "get set delete incr decr touch";
# This hash contains the information contained in two memcache commands
# stats and stats settings.
my %stats;
# This gives us eviction rates and other hit stats per slab
# We track this so we can see if something was evicted earlier than necessary
my %items;
# This gives us the memory size and usage per slab
# We track this so we can see what slab is being used the most and has no free chunks
# so we can re-tune memcached to allocate more pages for the specified chunk size
my %chnks;
# Variable for setting up a quick access map for plugin configurations / version adherence
my $globalmap;
=head2 Graph Declarations
This block of code builds up all of the graph info for all root / subgraphs.
%graphs: is a container for all of the graph definition information. In here is where you'll
find the configuration information for munin's graphing procedure.
Format:
$graph{graph_name} => {
config => {
You'll find the main graph config stored here
{ key => value },
{ ... },
},
datasrc => [
Name: name given to data value
Attr: Attribute and value, attribute must be valid plugin argument
{ name => 'Name', info => 'info about graph', ... },
{ ... },
],
}
=cut
my %graphs;
# main graph for memcached item count
$graphs{items} = {
config => {
args => '--base 1000 --lower-limit 0',
vlabel => 'Items in Memcached',
category => 'memcached global items',
title => 'Items',
info => 'Number of items in use by memcached',
},
datasrc => [
{ name => 'curr_items', label => 'Current Items', min => '0' },
{
name => 'total_items',
label => 'New Items',
min => '0',
type => 'DERIVE'
},
],
};
# main graph for memcached memory usage
$graphs{memory} = {
config => {
args => '--base 1024 --lower-limit 0',
vlabel => 'Bytes Used',
category => 'memcached global memory',
title => 'Memory Usage',
info => 'Memory consumption of memcached',
},
datasrc => [
{
name => 'limit_maxbytes',
draw => 'AREA',
label => 'Maximum Bytes Allocated',
min => '0'
},
{
name => 'bytes',
draw => 'AREA',
label => 'Current Bytes Used',
min => '0'
},
],
};
# main graph for memcached network usage
$graphs{bytes} = {
config => {
args => '--base 1000',
vlabel => 'bits in (-) / out (+)',
title => 'Network Traffic',
category => 'memcached',
info => 'Network traffic in (-) / out (+) of the machine',
order => 'bytes_read bytes_written',
},
datasrc => [
{
name => 'bytes_read',
type => 'DERIVE',
label => 'Network Traffic coming in (-)',
graph => 'no',
cdef => 'bytes_read,8,*',
min => '0'
},
{
name => 'bytes_written',
type => 'DERIVE',
label => 'Traffic in (-) / out (+)',
negative => 'bytes_read',
cdef => 'bytes_written,8,*',
min => '0'
},
],
};
# graph for memcached connections
$graphs{conns} = {
config => {
args => '--base 1000 --lower-limit 0',
vlabel => 'Connections per ${graph_period}',
category => 'memcached',
title => 'Connections',
info => 'Number of connections being handled by memcached',
order => 'max_conns curr_conns avg_conns',
},
datasrc => [
{ name => 'curr_conns', label => 'Current Connections', min => '0' },
{ name => 'max_conns', label => 'Max Connections', min => '0' },
{ name => 'avg_conns', label => 'Avg Connections', min => '0' },
],
};
# main graph for memcached commands issued
$graphs{commands} = {
config => {
args => '--base 1000 --lower-limit 0',
vlabel => 'Commands per ${graph_period}',
category => 'memcached global commands',
title => 'Commands',
info => 'Number of commands being handled by memcached',
},
datasrc => [
{
name => 'cmd_get',
type => 'DERIVE',
label => 'Gets',
info => 'Cumulative number of retrieval reqs',
min => '0'
},
{
name => 'cmd_set',
type => 'DERIVE',
label => 'Sets',
info => 'Cumulative number of storage reqs',
min => '0'
},
{
name => 'cmd_flush',
type => 'DERIVE',
label => 'Flushes',
info => 'Cumulative number of flush reqs',
min => '0'
},
{
name => 'cmd_touch',
type => 'DERIVE',
label => 'Touches',
info => 'Cumulative number of touch reqs',
min => '0'
},
{
name => 'get_hits',
type => 'DERIVE',
label => 'Get Hits',
info => 'Number of keys that were requested and found',
min => '0'
},
{
name => 'get_misses',
type => 'DERIVE',
label => 'Get Misses',
info => 'Number of keys there were requested and not found',
min => '0'
},
{
name => 'delete_hits',
type => 'DERIVE',
label => 'Delete Hits',
info =>
'Number of delete requests that resulted in a deletion of a key',
min => '0'
},
{
name => 'delete_misses',
type => 'DERIVE',
label => 'Delete Misses',
info => 'Number of delete requests for missing key',
min => '0'
},
{
name => 'incr_hits',
type => 'DERIVE',
label => 'Increment Hits',
info => 'Number of successful increment requests',
min => '0'
},
{
name => 'incr_misses',
type => 'DERIVE',
label => 'Increment Misses',
info => 'Number of unsuccessful increment requests',
min => '0'
},
{
name => 'decr_hits',
type => 'DERIVE',
label => 'Decrement Hits',
info => 'Number of successful decrement requests',
min => '0'
},
{
name => 'decr_misses',
type => 'DERIVE',
label => 'Decrement Misses',
info => 'Number of unsuccessful decrement requests',
min => '0'
},
{
name => 'cas_misses',
type => 'DERIVE',
label => 'CAS Misses',
info => 'Number of Compare and Swap requests against missing keys',
min => '0'
},
{
name => 'cas_hits',
type => 'DERIVE',
label => 'CAS Hits',
info => 'Number of successful Compare and Swap requests',
min => '0'
},
{
name => 'cas_badval',
type => 'DERIVE',
label => 'CAS Badval',
info => 'Number of unsuccessful Compare and Swap requests',
min => '0'
},
{
name => 'touch_hits',
type => 'DERIVE',
label => 'Touch Hits',
info => 'Number of successfully touched keys',
min => '0'
},
{
name => 'touch_misses',
type => 'DERIVE',
label => 'Touch Misses',
info => 'Number of unsuccessful touch keys',
min => '0'
},
],
};
# main graph for memcached eviction rates
$graphs{evictions} = {
config => {
args => '--base 1000 --lower-limit 0',
vlabel => 'Evictions per ${graph_period}',
category => 'memcached global evictions',
title => 'Evictions',
info => 'Number of evictions per second',
},
datasrc => [
{
name => 'evictions',
type => 'DERIVE',
label => 'Evictions',
info => 'Cumulative Evictions Across All Slabs',
min => '0'
},
{
name => 'evicted_nonzero',
type => 'DERIVE',
label => 'Evictions prior to Expire',
info => 'Cumulative Evictions forced to expire prior to expiration',
min => '0'
},
{
name => 'reclaimed',
type => 'DERIVE',
label => 'Reclaimed Items',
info => 'Cumulative Reclaimed Item Entries Across All Slabs',
min => '0'
},
],
};
# main graph for memcached eviction rates
$graphs{unfetched} = {
config => {
args => '--base 1000 --lower-limit 0',
vlabel => 'Unfetched Items per ${graph_period}',
category => 'memcached global unfetched',
title => 'Unfetched Items',
info =>
'Number of items that were never touched get/incr/append/etc before X occured',
},
datasrc => [
{
name => 'expired_unfetched',
type => 'DERIVE',
label => 'Expired Unfetched',
min => '0',
info =>
'Number of items that expired and never had get/incr/append/etc performed'
},
{
name => 'evicted_unfetched',
type => 'DERIVE',
label => 'Evictioned Unfetched',
min => '0',
info =>
'Number of items that evicted and never had get/incr/append/etc performed'
},
],
};
# subgraph for breaking memory info down by slab ( subgraph of memory )
$graphs{slabchnks} = {
config => {
args => '--base 1000 --lower-limit 0',
vlabel => 'Available Chunks for this Slab',
category => 'memcached slab chunk usage',
title => 'Chunk Usage for Slab: ',
info => 'This graph shows you the chunk usage for this memory slab.',
},
datasrc => [
{
name => 'total_chunks',
label => 'Total Chunks Available',
min => '0'
},
{ name => 'used_chunks', label => 'Total Chunks in Use', min => '0' },
{
name => 'free_chunks',
label => 'Total Chunks Not in Use (Free)',
min => '0'
},
],
};
# subgraph for breaking commands down by slab ( subgraph of commands )
$graphs{slabhits} = {
config => {
args => '--base 1000 --lower-limit 0',
vlabel => 'Hits per Slab per ${graph_period}',
category => 'memcached slab commands',
title => 'Hits for Slab: ',
info =>
'This graph shows you the successful hit rate for this memory slab.',
},
datasrc => [
{
name => 'get_hits',
label => 'Get Requests',
type => 'DERIVE',
min => '0'
},
{
name => 'cmd_set',
label => 'Set Requests',
type => 'DERIVE',
min => '0'
},
{
name => 'delete_hits',
label => 'Delete Requests',
type => 'DERIVE',
min => '0'
},
{
name => 'incr_hits',
label => 'Increment Requests',
type => 'DERIVE',
min => '0'
},
{
name => 'decr_hits',
label => 'Decrement Requests',
type => 'DERIVE',
min => '0'
},
{
name => 'cas_hits',
label => 'Sucessful CAS Requests',
type => 'DERIVE',
min => '0'
},
{
name => 'cas_badval',
label => 'UnSucessful CAS Requests',
type => 'DERIVE',
min => '0'
},
{
name => 'touch_hits',
label => 'Touch Requests',
type => 'DERIVE',
min => '0'
},
],
};
# subgraph for breaking evictions down by slab ( subgraph of evictions )
$graphs{slabevics} = {
config => {
args => '--base 1000 --lower-limit 0',
vlabel => 'Evictions per Slab per ${graph_period}',
category => 'memcached slab evictions',
title => 'Evictions for Slab: ',
info => 'This graph shows you the eviction rate for this memory slab.',
},
datasrc => [
{
name => 'evicted',
label => 'Total Evictions',
type => 'DERIVE',
min => '0',
info => 'Items evicted from memory slab'
},
{
name => 'evicted_nonzero',
type => 'DERIVE',
label => 'Evictions from LRU Prior to Expire',
info => 'Items evicted from memory slab before ttl expiration',
min => '0'
},
{
name => 'reclaimed',
type => 'DERIVE',
label => 'Reclaimed Expired Items',
info =>
'Number of times an item was stored in expired memory slab space',
min => '0'
},
],
};
# subgraph for showing the time between an item was last evicted and requested ( subgraph of evictions )
$graphs{slabevictime} = {
config => {
args => '--base 1000 --lower-limit 0',
vlabel => ' since Request for LEI',
category => 'memcached slab eviction time',
title => 'Eviction Request Time for Slab: ',
info =>
'This graph shows you the time since we requested the last evicted item',
},
datasrc => [
{
name => 'evicted_time',
label => 'Eviction Time (LEI)',
info => 'Time Since Request for Last Evicted Item',
min => '0'
},
],
};
# subgraph for breaking items down by slab ( subgraph of items )
$graphs{slabitems} = {
config => {
args => '--base 1000 --lower-limit 0',
vlabel => 'Items per Slab',
category => 'memcached slab item count',
title => 'Items in Slab: ',
info =>
'This graph shows you the number of items and reclaimed items per slab.',
},
datasrc => [
{
name => 'number',
label => 'Items',
draw => 'AREA',
info => 'This is the amount of items stored in this slab',
min => '0'
},
],
};
# subgraph for showing the age of the eldest item stored in a slab ( subgraph of items )
$graphs{slabitemtime} = {
config => {
args => '--base 1000 --lower-limit 0',
vlabel => ' since item was stored',
category => 'memcached slab item age',
title => 'Age of Eldest Item in Slab: ',
info => 'This graph shows you the time of the eldest item in this slab',
},
datasrc =>
[ { name => 'age', label => 'Eldest Item\'s Age', min => '0' }, ],
};
# main graph for memcached eviction rates
$graphs{slabunfetched} = {
config => {
args => '--base 1000 --lower-limit 0',
vlabel => 'Unfetched Items per ${graph_period}',
category => 'memcached slab unfetched',
title => 'Unfetched Items in Slab: ',
info =>
'Number of items that were never touched get/incr/append/etc before X occured',
},
datasrc => [
{
name => 'expired_unfetched',
type => 'DERIVE',
label => 'Expired Unfetched',
min => '0',
info =>
'Number of items that expired and never had get/incr/append/etc performed'
},
{
name => 'evicted_unfetched',
type => 'DERIVE',
label => 'Evictioned Unfetched',
min => '0',
info =>
'Number of items that evicted and never had get/incr/append/etc performed'
},
],
};
=head1 Munin Checks
These checks look for config / autoconf / suggest params
=head2 Config Check
This block of code looks at the argument that is possibly supplied,
should it be config, it then checks to make sure the plugin
specified exists, assuming it does, it will run the do_config
subroutine for the plugin specified, otherwise it dies complaining
about an unknown plugin.
=cut
if ( defined $ARGV[0] && $ARGV[0] eq 'config' ) {
# Lets get our plugin from the symlink being called up, we'll also verify its a valid
# plugin that we have graph information for
$0 =~ /(?:([^\/]+)_)?memcached_multi_(.+)$/;
my $prefix = $1 ? $1 : '';
my $plugin = $2;
die 'Unknown Plugin Specified: ' . ( $plugin ? $plugin : '' )
unless $graphs{$plugin};
# We need to fetch the stats before we do any config, cause its needed for multigraph
# subgraphs which use slab information for title / info per slab
fetch_stats();
$globalmap = buildglobalmap();
# Now lets go ahead and print out our config.
do_config( $prefix, $plugin );
exit 0;
}
=head2 Autoconf Check
This block of code looks at the argument that is possibly supplied,
should it be autoconf, we will attempt to connect to the memcached
service specified on the host:port, upon successful connection it
prints yes, otherwise it prints no.
=cut
if ( defined $ARGV[0] && $ARGV[0] eq 'autoconf' ) {
# Lets attempt to connect to memcached
my $s = get_conn();
# Lets verify that we did connect to memcached
if ( defined($s) ) {
print "yes\n";
exit 0;
}
else {
print "no (unable to connect to $connection)\n";
exit 0;
}
}
=head2 Suggest Check
This block of code looks at the argument that is possibly supplied,
should it be suggest, we are going to print the possible plugins
which can be specified. Note we only specify the root graphs for the
multigraphs, since the rest of the subgraphs will appear "behind" the
root graphs. It also attempts to connect to the memcached service to
verify it is infact running.
=cut
if ( defined $ARGV[0] && $ARGV[0] eq 'suggest' ) {
# Lets attempt to connect to memcached
my $s = get_conn();
# Lets check that we did connect to memcached
if ( defined($s) ) {
fetch_stats();
my @rootplugins =
( 'bytes', 'conns', 'commands', 'evictions', 'items', 'memory' );
if ( $stats{version} !~ /^1\.4\.[0-7]$/ ) {
push( @rootplugins, 'unfetched' );
}
foreach my $plugin (@rootplugins) {
print "$plugin\n";
}
exit 0;
}
else {
print "no (unable to connect to $connection)\n";
exit 0;
}
}
=head1 Output Subroutines
Output Subroutine calls to output data values
=head2 fetch_output
This subroutine is the main call for printing data for the plugin.
No parameters are taken as this is the default call if no arguments
are supplied from the command line.
=cut
# Well, no arguments were supplied that we know about, so lets print some data
$0 =~ /(?:([^\/]+)_)?memcached_multi_(.+)$/;
my $prefix = $1 ? $1 : '';
my $plugin = $2;
die 'Unknown Plugin Specified: ' . ( $plugin ? $plugin : '' )
unless $graphs{$plugin};
fetch_stats();
$globalmap = buildglobalmap();
fetch_output( $prefix, $plugin );
sub fetch_output {
my ( $prefix, $plugin ) = (@_);
# Now lets go ahead and print out our output.
my @subgraphs;
if ( $plugin eq 'memory' ) {
@subgraphs = ('slabchnks');
foreach my $slabid ( sort { $a <=> $b } keys %chnks ) {
print_submulti_output( $prefix, $slabid, $plugin, @subgraphs );
}
print_subrootmulti_output( $prefix, $plugin );
print_rootmulti_output( $prefix, $plugin );
}
elsif ( $plugin eq 'commands' ) {
@subgraphs = ('slabhits');
foreach my $slabid ( sort { $a <=> $b } keys %chnks ) {
print_submulti_output( $prefix, $slabid, $plugin, @subgraphs );
}
print_subrootmulti_output( $prefix, $plugin );
print_rootmulti_output( $prefix, $plugin );
}
elsif ( $plugin eq 'evictions' ) {
@subgraphs = ('slabevics');
if ( $leitime == 1 ) { push( @subgraphs, 'slabevictime' ); }
foreach my $slabid ( sort { $a <=> $b } keys %items ) {
print_submulti_output( $prefix, $slabid, $plugin, @subgraphs );
}
print_subrootmulti_output( $prefix, $plugin );
print_rootmulti_output( $prefix, $plugin );
}
elsif ( $plugin eq 'items' ) {
@subgraphs = ( 'slabitems', 'slabitemtime' );
foreach my $slabid ( sort { $a <=> $b } keys %items ) {
print_submulti_output( $prefix, $slabid, $plugin, @subgraphs );
}
print_subrootmulti_output( $prefix, $plugin );
print_rootmulti_output( $prefix, $plugin );
}
elsif ( $plugin eq 'unfetched' ) {
@subgraphs = ('slabunfetched');
foreach my $slabid ( sort { $a <=> $b } keys %items ) {
print_submulti_output( $prefix, $slabid, $plugin, @subgraphs );
}
print_subrootmulti_output( $prefix, $plugin );
print_rootmulti_output( $prefix, $plugin );
}
else {
print_root_output($plugin);
}
return;
}
=head2 print_root_output
This subroutine prints out the return values for our non-multigraph root graphs.
It takes one parameter $plugin and returns when completed.
$plugin; graph we are calling up to print data values for
Example: print_root_output($plugin);
=cut
sub print_root_output {
# Lets get our plugin, set our graph reference and print out info for Munin
my ($plugin) = (@_);
my $graph = $graphs{$plugin};
# The conns plugin has some specific needs, looking for plugin type
if ( $plugin ne 'conns' ) {
foreach my $dsrc ( @{ $graph->{datasrc} } ) {
my %datasrc = %$dsrc;
while ( my ( $key, $value ) = each(%datasrc) ) {
next if ( $key ne 'name' );
my $output = $stats{$value};
print "$dsrc->{name}.value $output\n";
}
}
}
else {
my $output;
foreach my $dsrc ( @{ $graph->{datasrc} } ) {
my %datasrc = %$dsrc;
while ( my ( $key, $value ) = each(%datasrc) ) {
if ( $value eq 'max_conns' ) {
$output = $stats{maxconns};
}
elsif ( $value eq 'curr_conns' ) {
$output = $stats{curr_connections};
}
elsif ( $value eq 'avg_conns' ) {
$output = sprintf( "%02d",
$stats{total_connections} / $stats{uptime} );
}
else {
next;
}
print "$dsrc->{name}.value $output\n";
}
}
}
return;
}
=head2 print_rootmulti_output
This subroutine prints out the return values for our multigraph root graphs.
It takes one parameter $plugin and returns when completed.
$plugin; root graph we are calling up to print data values for
Example: print_rootmulti_output($plugin);
=cut
sub print_rootmulti_output {
# Lets get our plugin, set our graph reference and print out info for Munin
my ( $prefix, $plugin ) = (@_);
my $graph = $graphs{$plugin};
if ($prefix) {
print "multigraph $prefix\_memcached_multi_$plugin\n";
}
else {
print "multigraph memcached_multi_$plugin\n";
}
# Lets print our data values with their appropriate name
foreach my $dsrc ( @{ $graph->{datasrc} } ) {
my $output = 0;
my %datasrc = %$dsrc;
while ( my ( $key, $value ) = each(%datasrc) ) {
next if ( $key ne 'name' );
next
if ( ( $plugin eq 'evictions' )
&& ( !exists( $globalmap->{globalevics}->{ $dsrc->{name} } ) )
);
next
if ( ( $plugin eq 'commands' )
&& ( !exists( $globalmap->{globalcmds}->{ $dsrc->{name} } ) ) );
if ( ( $plugin eq 'evictions' ) && ( $value eq 'evicted_nonzero' ) )
{
foreach my $slabid ( sort { $a <=> $b } keys %items ) {
$output += $items{$slabid}->{evicted_nonzero};
}
}
else {
$output = $stats{$value};
}
print "$dsrc->{name}.value $output\n";
}
}
return;
}
=head2 print_subrootmulti_output
This subroutine prints out the return values for our multigraph root graphs, only this set of
data will display on the subpage made by the multigraph capabilities of munin and the plugin.
It takes one parameter $plugin and returns when completed.
$plugin; root graph we are calling up to print data values for
Example: print_rootmulti_output($plugin);
=cut
sub print_subrootmulti_output {
# Lets get our plugin, set our graph reference and print out info for Munin
my ( $prefix, $plugin ) = (@_);
my $graph = $graphs{$plugin};
if ($prefix) {
if ( $plugin eq 'evictions' ) {
print "multigraph $prefix\_memcached_multi_$plugin.global$plugin\n";
}
else {
print "multigraph $prefix\_memcached_multi_$plugin.$plugin\n";
}
}
else {
if ( $plugin eq 'evictions' ) {
print "multigraph memcached_multi_$plugin.global$plugin\n";
}
else {
print "multigraph memcached_multi_$plugin.$plugin\n";
}
}
# Lets print our data values with their appropriate name
foreach my $dsrc ( @{ $graph->{datasrc} } ) {
my $output = 0;
my %datasrc = %$dsrc;
while ( my ( $key, $value ) = each(%datasrc) ) {
next if ( $key ne 'name' );
next
if ( ( $plugin eq 'evictions' )
&& ( !exists( $globalmap->{globalevics}->{ $dsrc->{name} } ) )
);
next
if ( ( $plugin eq 'commands' )
&& ( !exists( $globalmap->{globalcmds}->{ $dsrc->{name} } ) ) );
if ( ( $plugin eq 'evictions' ) && ( $value eq 'evicted_nonzero' ) )
{
foreach my $slabid ( sort { $a <=> $b } keys %items ) {