1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3 /* CMetrics
4 * ========
5 * Copyright 2021 Eduardo Silva <eduardo@calyptia.com>
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 #include <cmetrics/cmetrics.h>
21 #include <cmetrics/cmt_log.h>
22 #include <cmetrics/cmt_map.h>
23 #include <cmetrics/cmt_metric.h>
24 #include <cmetrics/cmt_counter.h>
25
cmt_counter_create(struct cmt * cmt,char * ns,char * subsystem,char * name,char * help,int label_count,char ** label_keys)26 struct cmt_counter *cmt_counter_create(struct cmt *cmt,
27 char *ns, char *subsystem,
28 char *name, char *help,
29 int label_count, char **label_keys)
30 {
31 int ret;
32 struct cmt_counter *counter;
33
34 if (!ns) {
35 cmt_log_error(cmt, "null ns not allowed");
36 return NULL;
37 }
38
39 if (!subsystem) {
40 cmt_log_error(cmt, "null subsystem not allowed");
41 return NULL;
42 }
43
44 if (!name || strlen(name) == 0) {
45 cmt_log_error(cmt, "undefined name");
46 return NULL;
47 }
48
49 if (!help || strlen(help) == 0) {
50 cmt_log_error(cmt, "undefined help");
51 return NULL;
52 }
53
54 counter = calloc(1, sizeof(struct cmt_counter));
55 if (!counter) {
56 cmt_errno();
57 return NULL;
58 }
59 mk_list_add(&counter->_head, &cmt->counters);
60
61 ret = cmt_opts_init(&counter->opts, ns, subsystem, name, help);
62 if (ret == -1) {
63 cmt_log_error(cmt, "unable to initialize options for counter");
64 cmt_counter_destroy(counter);
65 return NULL;
66 }
67
68 /* Create the map */
69 counter->map = cmt_map_create(CMT_COUNTER, &counter->opts, label_count, label_keys);
70 if (!counter->map) {
71 cmt_log_error(cmt, "unable to allocate map for counter");
72 cmt_counter_destroy(counter);
73 return NULL;
74 }
75
76 counter->cmt = cmt;
77 return counter;
78 }
79
cmt_counter_allow_reset(struct cmt_counter * counter)80 void cmt_counter_allow_reset(struct cmt_counter *counter)
81 {
82 counter->allow_reset = 1;
83 }
84
cmt_counter_destroy(struct cmt_counter * counter)85 int cmt_counter_destroy(struct cmt_counter *counter)
86 {
87 mk_list_del(&counter->_head);
88 cmt_opts_exit(&counter->opts);
89
90 if (counter->map) {
91 cmt_map_destroy(counter->map);
92 }
93 free(counter);
94 return 0;
95 }
96
cmt_counter_inc(struct cmt_counter * counter,uint64_t timestamp,int labels_count,char ** label_vals)97 int cmt_counter_inc(struct cmt_counter *counter,
98 uint64_t timestamp,
99 int labels_count, char **label_vals)
100 {
101 struct cmt_metric *metric;
102
103 metric = cmt_map_metric_get(&counter->opts,
104 counter->map, labels_count, label_vals,
105 CMT_TRUE);
106 if (!metric) {
107 cmt_log_error(counter->cmt, "unable to retrieve metric: %s for counter %s_%s_%s",
108 counter->map, counter->opts.ns, counter->opts.subsystem,
109 counter->opts.name);
110 return -1;
111 }
112 cmt_metric_inc(metric, timestamp);
113 return 0;
114 }
115
cmt_counter_add(struct cmt_counter * counter,uint64_t timestamp,double val,int labels_count,char ** label_vals)116 int cmt_counter_add(struct cmt_counter *counter, uint64_t timestamp, double val,
117 int labels_count, char **label_vals)
118 {
119 struct cmt_metric *metric;
120
121 metric = cmt_map_metric_get(&counter->opts,
122 counter->map, labels_count, label_vals,
123 CMT_TRUE);
124 if (!metric) {
125 cmt_log_error(counter->cmt, "unable to retrieve metric: %s for counter %s_%s_%s",
126 counter->map, counter->opts.ns, counter->opts.subsystem,
127 counter->opts.name);
128 return -1;
129 }
130 cmt_metric_add(metric, timestamp, val);
131 return 0;
132 }
133
134 /* Set counter value, new value cannot be smaller than current value */
cmt_counter_set(struct cmt_counter * counter,uint64_t timestamp,double val,int labels_count,char ** label_vals)135 int cmt_counter_set(struct cmt_counter *counter, uint64_t timestamp, double val,
136 int labels_count, char **label_vals)
137 {
138 struct cmt_metric *metric;
139
140 metric = cmt_map_metric_get(&counter->opts, counter->map,
141 labels_count, label_vals,
142 CMT_TRUE);
143 if (!metric) {
144 cmt_log_error(counter->cmt, "unable to retrieve metric: %s for counter %s_%s_%s",
145 counter->map, counter->opts.ns, counter->opts.subsystem,
146 counter->opts.name);
147 return -1;
148 }
149
150 if (cmt_metric_get_value(metric) > val && counter->allow_reset == 0) {
151 cmt_log_error(counter->cmt, "attempting to reset unresetable counter: %s_%s_%s",
152 counter->opts.ns, counter->opts.subsystem,
153 counter->opts.name);
154 return -1;
155 }
156 cmt_metric_set(metric, timestamp, val);
157 return 0;
158 }
159
cmt_counter_get_val(struct cmt_counter * counter,int labels_count,char ** label_vals,double * out_val)160 int cmt_counter_get_val(struct cmt_counter *counter,
161 int labels_count, char **label_vals, double *out_val)
162 {
163 int ret;
164 double val = 0;
165
166 ret = cmt_map_metric_get_val(&counter->opts,
167 counter->map, labels_count, label_vals,
168 &val);
169 if (ret == -1) {
170 cmt_log_error(counter->cmt, "unable to retrieve metric: %s for counter %s_%s_%s",
171 counter->map, counter->opts.ns, counter->opts.subsystem,
172 counter->opts.name);
173 return -1;
174 }
175 *out_val = val;
176 return 0;
177 }
178