8c8f1e92fcfb8a18421f1871d4d0f51a109035ab
[platform/core/system/dlog.git] / src / shared / metrics.c
1 /* MIT License
2  *
3  * Copyright (c) 2020 Samsung Electronics Co., Ltd
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to deal
7  * in the Software without restriction, including without limitation the rights
8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is furnished to do
10  * so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21  * THE SOFTWARE. */
22
23 #include <metrics.h>
24
25 #include <assert.h>
26 #include <stdlib.h>
27
28 #define INITIAL_CAPACITY 128
29
30 struct metrics {
31         struct metrics_info *inner;
32         int count; // entries in the vector
33         int total; // total logs (entries in vector * entry count)
34         int capacity;
35 };
36
37 struct metrics *metrics_create()
38 {
39         return calloc(1, sizeof(struct metrics));
40 }
41
42 void metrics_destroy(struct metrics *m)
43 {
44         if (!m)
45                 return;
46
47         for (int i = 0; i < m->count; ++i)
48                 free(m->inner[i].tag);
49
50         free(m->inner);
51         free(m);
52 }
53
54 bool metrics_add_log(struct metrics *m, const dlogutil_entry_s *e)
55 {
56         assert(m);
57         assert(e);
58
59         const char *tag;
60         pid_t pid;
61         log_priority prio;
62         if (dlogutil_entry_get_tag(e, &tag))
63                 return false;
64         if (dlogutil_entry_get_pid(e, &pid))
65                 return false;
66         if (dlogutil_entry_get_priority(e, &prio))
67                 return false;
68
69         for (int i = 0; i < m->count; ++i) {
70                 if (pid != m->inner[i].pid || strcmp(tag, m->inner[i].tag) != 0)
71                         continue;
72
73                 assert(prio < DLOG_PRIO_MAX);
74                 m->inner[i].count[prio] += 1;
75                 m->total += 1;
76                 return true;
77         }
78
79         if (m->capacity == 0) {
80                 m->inner = calloc(INITIAL_CAPACITY, sizeof(*m->inner));
81                 if (!m->inner)
82                         return false;
83                 m->capacity = INITIAL_CAPACITY;
84         } else if (m->count == m->capacity) {
85                 typeof(m->inner) tmp = realloc(m->inner, 2 * m->capacity * sizeof *tmp);
86                 if (!tmp)
87                         return false;
88                 m->inner = tmp;
89                 m->capacity *= 2;
90         }
91
92         char *const tag_copy = strdup(tag);
93         if (!tag_copy)
94                 return false;
95         m->inner[m->count].tag = tag_copy;
96         m->inner[m->count].pid = pid;
97         for (int i = 0; i < (int) DLOG_PRIO_MAX; ++i)
98                 m->inner[m->count].count[i] = 0;
99         m->inner[m->count].count[prio] = 1;
100         m->count += 1;
101         m->total += 1;
102         return true;
103 }
104
105 int metrics_get_total(const struct metrics *m)
106 {
107         assert(m);
108
109         return m->total;
110 }
111
112 struct metrics_info *metrics_get_info(const struct metrics *m, int *count)
113 {
114         assert(m);
115         assert(count);
116
117         if (m->count == 0) {
118                 *count = 0;
119                 return NULL;
120         }
121
122         struct metrics_info *ret = calloc(m->count, sizeof(*ret));
123         if (ret == NULL) {
124                 *count = -1;
125                 return NULL;
126         }
127
128         *count = m->count;
129         memcpy(ret, m->inner, m->count * sizeof(*ret));
130         return ret;
131 }
132
133 void metrics_clear(struct metrics *m)
134 {
135         assert(m);
136
137         for (int i = 0; i < m->count; ++i)
138                 free(m->inner[i].tag);
139
140         m->count = 0;
141         m->total = 0;
142 }
143
144 int metrics_sort_by_tag_first(const void *vlhs, const void *vrhs)
145 {
146         const struct metrics_info *lhs = vlhs, *rhs = vrhs;
147         int str_val = strcmp(lhs->tag, rhs->tag);
148
149         if (str_val != 0)
150                 return str_val;
151
152         if (lhs->pid == rhs->pid)
153                 return 0;
154
155         return lhs->pid < rhs->pid ? -1 : 1;
156 }
157
158 int metrics_sort_by_pid_first(const void *vlhs, const void *vrhs)
159 {
160         const struct metrics_info *lhs = vlhs, *rhs = vrhs;
161
162         if (lhs->pid < rhs->pid)
163                 return -1;
164         else if (lhs->pid > rhs->pid)
165                 return 1;
166
167         return strcmp(lhs->tag, rhs->tag);
168 }