Merge branch 'collectd-5.7'
[collectd.git] / src / fhcount.c
1 /**
2  *
3  * collectd - src/fhcount.c
4  * Copyright (c) 2015, Jiri Tyr <jiri.tyr at gmail.com>
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  **/
19
20 #include "collectd.h"
21
22 #include "common.h"
23 #include "plugin.h"
24
25 static const char *config_keys[] = {"ValuesAbsolute", "ValuesPercentage"};
26 static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
27
28 static _Bool values_absolute = 1;
29 static _Bool values_percentage = 0;
30
31 static int fhcount_config(const char *key, const char *value) {
32   int ret = -1;
33
34   if (strcasecmp(key, "ValuesAbsolute") == 0) {
35     if (IS_TRUE(value)) {
36       values_absolute = 1;
37     } else {
38       values_absolute = 0;
39     }
40
41     ret = 0;
42   } else if (strcasecmp(key, "ValuesPercentage") == 0) {
43     if (IS_TRUE(value)) {
44       values_percentage = 1;
45     } else {
46       values_percentage = 0;
47     }
48
49     ret = 0;
50   }
51
52   return (ret);
53 }
54
55 static void fhcount_submit(const char *type, const char *type_instance,
56                            gauge_t value) {
57   value_list_t vl = VALUE_LIST_INIT;
58
59   vl.values = &(value_t){.gauge = value};
60   vl.values_len = 1;
61
62   // Compose the metric
63   sstrncpy(vl.plugin, "fhcount", sizeof(vl.plugin));
64   sstrncpy(vl.type, type, sizeof(vl.type));
65   sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance));
66
67   // Dispatch the metric
68   plugin_dispatch_values(&vl);
69 }
70
71 static int fhcount_read(void) {
72   int numfields = 0;
73   int buffer_len = 60;
74   gauge_t used, unused, max;
75   int prc_used, prc_unused;
76   char *fields[3];
77   char buffer[buffer_len];
78   char errbuf[1024];
79   FILE *fp;
80
81   // Open file
82   fp = fopen("/proc/sys/fs/file-nr", "r");
83   if (fp == NULL) {
84     ERROR("fhcount: fopen: %s", sstrerror(errno, errbuf, sizeof(errbuf)));
85     return (EXIT_FAILURE);
86   }
87   if (fgets(buffer, buffer_len, fp) == NULL) {
88     ERROR("fhcount: fgets: %s", sstrerror(errno, errbuf, sizeof(errbuf)));
89     fclose(fp);
90     return (EXIT_FAILURE);
91   }
92   fclose(fp);
93
94   // Tokenize string
95   numfields = strsplit(buffer, fields, STATIC_ARRAY_SIZE(fields));
96
97   if (numfields != 3) {
98     ERROR("fhcount: Line doesn't contain 3 fields");
99     return (EXIT_FAILURE);
100   }
101
102   // Define the values
103   strtogauge(fields[0], &used);
104   strtogauge(fields[1], &unused);
105   strtogauge(fields[2], &max);
106   prc_used = (gauge_t)used / max * 100;
107   prc_unused = (gauge_t)unused / max * 100;
108
109   // Submit values
110   if (values_absolute) {
111     fhcount_submit("file_handles", "used", (gauge_t)used);
112     fhcount_submit("file_handles", "unused", (gauge_t)unused);
113     fhcount_submit("file_handles", "max", (gauge_t)max);
114   }
115   if (values_percentage) {
116     fhcount_submit("percent", "used", (gauge_t)prc_used);
117     fhcount_submit("percent", "unused", (gauge_t)prc_unused);
118   }
119
120   return (0);
121 }
122
123 void module_register(void) {
124   plugin_register_config("fhcount", fhcount_config, config_keys,
125                          config_keys_num);
126   plugin_register_read("fhcount", fhcount_read);
127 }