diff options
author | Guillaume Friloux <guillaume.friloux@gmail.com> | 2013-12-26 13:55:38 +0100 |
---|---|---|
committer | Guillaume Friloux <guillaume.friloux@gmail.com> | 2013-12-26 13:55:38 +0100 |
commit | 2b1ec293f4919ddfa13d972b65d506f323e862a1 (patch) | |
tree | fe963c116ed26ca2973116e4eb54e2d1c8799013 | |
parent | 5ef188c4ba84603c808ea1b31c2ae5ef84f5aaf4 (diff) |
Make smman able to parse logs into JSON for ES.
-rw-r--r-- | src/bin/config.c | 2 | ||||
-rw-r--r-- | src/bin/filter.c | 13 | ||||
-rw-r--r-- | src/bin/log.c | 87 | ||||
-rw-r--r-- | src/bin/smman.h | 6 | ||||
-rw-r--r-- | src/bin/utils.c | 42 | ||||
-rw-r--r-- | src/include/Store.h | 21 |
6 files changed, 156 insertions, 15 deletions
diff --git a/src/bin/config.c b/src/bin/config.c index 65b2637..4c29e34 100644 --- a/src/bin/config.c +++ b/src/bin/config.c | |||
@@ -28,6 +28,8 @@ config_done(void *data, | |||
28 | DBG("Server = %s", smman->cfg.server); | 28 | DBG("Server = %s", smman->cfg.server); |
29 | DBG("Host = %s", smman->cfg.host); | 29 | DBG("Host = %s", smman->cfg.host); |
30 | eina_iterator_free(it); | 30 | eina_iterator_free(it); |
31 | |||
32 | smman->store = store_new(smman->cfg.server); | ||
31 | } | 33 | } |
32 | 34 | ||
33 | void | 35 | void |
diff --git a/src/bin/filter.c b/src/bin/filter.c index 274f0cb..fec905e 100644 --- a/src/bin/filter.c +++ b/src/bin/filter.c | |||
@@ -40,10 +40,9 @@ filter_load(void *data, | |||
40 | DBG("smman[%p] rules[%p] rule[%p][%s]", smman, rules, rule, rule->name); | 40 | DBG("smman[%p] rules[%p] rule[%p][%s]", smman, rules, rule, rule->name); |
41 | 41 | ||
42 | DBG("rule : %s\n\tfilename[%s]\n\tsource_host[%s]\n\t" | 42 | DBG("rule : %s\n\tfilename[%s]\n\tsource_host[%s]\n\t" |
43 | "source_path[%s]\n\ttags[%s]\n\ttodel[%s]", | 43 | "source_path[%s]\ntodel[%s]", |
44 | rule->name, rule->spec.filename, rule->spec.source_host, | 44 | rule->name, rule->spec.filename, rule->spec.source_host, |
45 | rule->spec.source_path, rule->spec.tags, | 45 | rule->spec.source_path, (rule->spec.todel) ? "EINA_TRUE" : "EINA_FALSE"); |
46 | (rule->spec.todel) ? "EINA_TRUE" : "EINA_FALSE"); | ||
47 | 46 | ||
48 | /* Loop with globbing to write here! */ | 47 | /* Loop with globbing to write here! */ |
49 | r = glob(rule->spec.filename, GLOB_MARK, 0, &files); | 48 | r = glob(rule->spec.filename, GLOB_MARK, 0, &files); |
@@ -65,6 +64,13 @@ filter_load(void *data, | |||
65 | DBG("No filter found for %s, creating new one", *s); | 64 | DBG("No filter found for %s, creating new one", *s); |
66 | filter = calloc(1, sizeof(Filter)); | 65 | filter = calloc(1, sizeof(Filter)); |
67 | filter->sf = spy_file_new(smman->spy, *s); | 66 | filter->sf = spy_file_new(smman->spy, *s); |
67 | if (!filter->sf) | ||
68 | { | ||
69 | ERR("Failed to put spy on %s", *s); | ||
70 | free(filter); | ||
71 | continue; | ||
72 | } | ||
73 | |||
68 | spy_file_data_set(filter->sf, filter); | 74 | spy_file_data_set(filter->sf, filter); |
69 | filter->filename = strdup(*s); | 75 | filter->filename = strdup(*s); |
70 | filter->rules = eina_hash_string_superfast_new(_filter_rules_free); | 76 | filter->rules = eina_hash_string_superfast_new(_filter_rules_free); |
@@ -76,6 +82,7 @@ filter_load(void *data, | |||
76 | rule, rule->name, filter, filter->filename); | 82 | rule, rule->name, filter, filter->filename); |
77 | eina_hash_add(filter->rules, rule->name, rule); | 83 | eina_hash_add(filter->rules, rule->name, rule); |
78 | } | 84 | } |
85 | globfree(&files); | ||
79 | } | 86 | } |
80 | 87 | ||
81 | void | 88 | void |
diff --git a/src/bin/log.c b/src/bin/log.c index 4ebc053..0ecfe4c 100644 --- a/src/bin/log.c +++ b/src/bin/log.c | |||
@@ -6,10 +6,75 @@ typedef struct _Log | |||
6 | *source_host, | 6 | *source_host, |
7 | *source_path, | 7 | *source_path, |
8 | *message; | 8 | *message; |
9 | Eina_Strbuf *tags; | 9 | Eina_List *tags; |
10 | Eina_Bool todel; | 10 | Eina_Bool todel; |
11 | } Log; | 11 | } Log; |
12 | 12 | ||
13 | void | ||
14 | _log_send(Smman *smman, | ||
15 | Log *log) | ||
16 | { | ||
17 | cJSON *json, | ||
18 | *json_tags; | ||
19 | char *source, | ||
20 | *date, | ||
21 | *tag; | ||
22 | Eina_List *l; | ||
23 | |||
24 | json = cJSON_CreateObject(); | ||
25 | if (!json) | ||
26 | { | ||
27 | ERR("Failed to allocate JSON object"); | ||
28 | return; | ||
29 | } | ||
30 | |||
31 | source = sdupf("file://%s%s", smman->cfg.server, log->source_path); | ||
32 | EINA_SAFETY_ON_NULL_RETURN(source); | ||
33 | |||
34 | date = date_es(); | ||
35 | EINA_SAFETY_ON_NULL_RETURN(date); | ||
36 | |||
37 | |||
38 | cJSON_AddStringToObject(json, "@source", source); | ||
39 | cJSON_AddStringToObject(json, "@type", "syslog"); | ||
40 | |||
41 | json_tags = cJSON_CreateArray(); | ||
42 | cJSON_AddItemToObject(json, "tags", json_tags); | ||
43 | |||
44 | EINA_LIST_FOREACH(log->tags, l, tag) | ||
45 | { | ||
46 | cJSON_AddItemToArray(json_tags, cJSON_CreateString(tag)); | ||
47 | } | ||
48 | |||
49 | cJSON_AddItemToObject(json, "fields", cJSON_CreateObject()); | ||
50 | |||
51 | cJSON_AddStringToObject(json, "@message", log->message); | ||
52 | cJSON_AddStringToObject(json, "@timestamp", date); | ||
53 | cJSON_AddStringToObject(json, "@source_host", log->source_host); | ||
54 | cJSON_AddStringToObject(json, "@source_path", log->source_path); | ||
55 | |||
56 | |||
57 | free(date); | ||
58 | free(source); | ||
59 | DBG("JSON = \n%s", cJSON_Print(json)); | ||
60 | cJSON_Delete(json); | ||
61 | } | ||
62 | |||
63 | void | ||
64 | _log_free(Log *log) | ||
65 | { | ||
66 | char *tag; | ||
67 | |||
68 | eina_stringshare_replace(&log->filename, NULL); | ||
69 | eina_stringshare_replace(&log->source_host, NULL); | ||
70 | eina_stringshare_replace(&log->source_path, NULL); | ||
71 | eina_stringshare_replace(&log->message, NULL); | ||
72 | |||
73 | EINA_LIST_FREE(log->tags, tag) | ||
74 | free(tag); | ||
75 | free(log); | ||
76 | } | ||
77 | |||
13 | Eina_Bool | 78 | Eina_Bool |
14 | _log_line_match(const char *log, Rule *rule) | 79 | _log_line_match(const char *log, Rule *rule) |
15 | { | 80 | { |
@@ -47,6 +112,7 @@ log_line_event(void *data, | |||
47 | Eina_Iterator *it; | 112 | Eina_Iterator *it; |
48 | Eina_Hash_Tuple *t; | 113 | Eina_Hash_Tuple *t; |
49 | Eina_Bool r; | 114 | Eina_Bool r; |
115 | const char *tag; | ||
50 | 116 | ||
51 | DBG("smman[%p] sl[%p][%s] filter[%p][%s]", | 117 | DBG("smman[%p] sl[%p][%s] filter[%p][%s]", |
52 | smman, sl, spy_file_name_get(sf), filter, filter->filename); | 118 | smman, sl, spy_file_name_get(sf), filter, filter->filename); |
@@ -56,13 +122,13 @@ log_line_event(void *data, | |||
56 | eina_stringshare_replace(&log->filename, filter->filename); | 122 | eina_stringshare_replace(&log->filename, filter->filename); |
57 | eina_stringshare_replace(&log->source_host, smman->cfg.host); | 123 | eina_stringshare_replace(&log->source_host, smman->cfg.host); |
58 | eina_stringshare_replace(&log->source_path, filter->filename); | 124 | eina_stringshare_replace(&log->source_path, filter->filename); |
59 | log->tags = eina_strbuf_new(); | ||
60 | 125 | ||
61 | /* Now we apply rules */ | 126 | /* Now we apply rules */ |
62 | it = eina_hash_iterator_tuple_new(filter->rules); | 127 | it = eina_hash_iterator_tuple_new(filter->rules); |
63 | while (eina_iterator_next(it, (void **)&t)) | 128 | while (eina_iterator_next(it, (void **)&t)) |
64 | { | 129 | { |
65 | const char *name; | 130 | const char *name; |
131 | Eina_List *l; | ||
66 | 132 | ||
67 | name = t->key; | 133 | name = t->key; |
68 | rule = t->data; | 134 | rule = t->data; |
@@ -84,12 +150,8 @@ log_line_event(void *data, | |||
84 | if (rule->spec.source_path) | 150 | if (rule->spec.source_path) |
85 | eina_stringshare_replace(&log->source_path, rule->spec.source_path); | 151 | eina_stringshare_replace(&log->source_path, rule->spec.source_path); |
86 | 152 | ||
87 | if (rule->spec.tags) | 153 | EINA_LIST_FOREACH(rule->spec.tags, l, tag) |
88 | { | 154 | log->tags = eina_list_append(log->tags, strdup(tag)); |
89 | if (eina_strbuf_length_get(log->tags)) | ||
90 | eina_strbuf_append(log->tags, ","); | ||
91 | eina_strbuf_append(log->tags, rule->spec.tags); | ||
92 | } | ||
93 | } | 155 | } |
94 | eina_iterator_free(it); | 156 | eina_iterator_free(it); |
95 | 157 | ||
@@ -101,13 +163,14 @@ log_line_event(void *data, | |||
101 | "\tmessage = %s\n" | 163 | "\tmessage = %s\n" |
102 | "\tfilename = %s\n" | 164 | "\tfilename = %s\n" |
103 | "\tsource_host = %s\n" | 165 | "\tsource_host = %s\n" |
104 | "\tsource_path = %s\n" | 166 | "\tsource_path = %s", |
105 | "\ttags = %s\n", | ||
106 | log->message, | 167 | log->message, |
107 | log->filename, | 168 | log->filename, |
108 | log->source_host, | 169 | log->source_host, |
109 | log->source_path, | 170 | log->source_path); |
110 | eina_strbuf_string_get(log->tags)); | 171 | |
172 | _log_send(smman, log); | ||
111 | 173 | ||
174 | _log_free(log); | ||
112 | return EINA_TRUE; | 175 | return EINA_TRUE; |
113 | } | 176 | } |
diff --git a/src/bin/smman.h b/src/bin/smman.h index d75452b..d912ffa 100644 --- a/src/bin/smman.h +++ b/src/bin/smman.h | |||
@@ -9,6 +9,8 @@ | |||
9 | #include <Conf.h> | 9 | #include <Conf.h> |
10 | #include <Rules.h> | 10 | #include <Rules.h> |
11 | #include <Spy.h> | 11 | #include <Spy.h> |
12 | #include <Store.h> | ||
13 | #include <cJSON.h> | ||
12 | 14 | ||
13 | int smman_log_dom_global; | 15 | int smman_log_dom_global; |
14 | 16 | ||
@@ -16,6 +18,7 @@ typedef struct _Smman | |||
16 | { | 18 | { |
17 | Rules *rules; | 19 | Rules *rules; |
18 | Spy *spy; | 20 | Spy *spy; |
21 | Store *store; | ||
19 | Eina_Inlist *filters; | 22 | Eina_Inlist *filters; |
20 | 23 | ||
21 | struct | 24 | struct |
@@ -52,3 +55,6 @@ void filter_load_done(void *data, Rules *rules); | |||
52 | void filter_load_error(void *data, Rules *rules, const char *errstr); | 55 | void filter_load_error(void *data, Rules *rules, const char *errstr); |
53 | 56 | ||
54 | Eina_Bool log_line_event(void *data, int type, void *event); | 57 | Eina_Bool log_line_event(void *data, int type, void *event); |
58 | |||
59 | char * sdupf(const char *s, ...); | ||
60 | char * date_es(void); | ||
diff --git a/src/bin/utils.c b/src/bin/utils.c new file mode 100644 index 0000000..dcdf3a8 --- /dev/null +++ b/src/bin/utils.c | |||
@@ -0,0 +1,42 @@ | |||
1 | #define _GNU_SOURCE | ||
2 | #include <stdio.h> | ||
3 | |||
4 | #include "smman.h" | ||
5 | |||
6 | char * | ||
7 | sdupf(const char *s, ...) | ||
8 | { | ||
9 | va_list args; | ||
10 | int len; | ||
11 | char *str; | ||
12 | |||
13 | va_start(args, s); | ||
14 | len = vasprintf(&str, s, args); | ||
15 | va_end(args); | ||
16 | |||
17 | if (len == -1) | ||
18 | return NULL; | ||
19 | |||
20 | return str; | ||
21 | } | ||
22 | |||
23 | char * | ||
24 | date_es(void) | ||
25 | { | ||
26 | char *s; | ||
27 | time_t temps; | ||
28 | struct tm temp; | ||
29 | |||
30 | temps = time(NULL); | ||
31 | if (!localtime_r(&temps,&temp)) | ||
32 | return NULL; | ||
33 | |||
34 | s = calloc(1, 28); | ||
35 | EINA_SAFETY_ON_NULL_RETURN_VAL(s, NULL); | ||
36 | |||
37 | sprintf(s,"%04d-%02d-%02dT%02d:%02d:%02d.000000Z", | ||
38 | (temp.tm_year)+1900,(temp.tm_mon)+1,temp.tm_mday, | ||
39 | temp.tm_hour,temp.tm_min,temp.tm_sec); | ||
40 | return s; | ||
41 | } | ||
42 | |||
diff --git a/src/include/Store.h b/src/include/Store.h new file mode 100644 index 0000000..3a867b3 --- /dev/null +++ b/src/include/Store.h | |||
@@ -0,0 +1,21 @@ | |||
1 | #ifndef STORE_H | ||
2 | #define STORE_H | ||
3 | #include <Eina.h> | ||
4 | #include <Ecore.h> | ||
5 | #include <Ecore_Con.h> | ||
6 | |||
7 | |||
8 | typedef struct _Store Store; | ||
9 | |||
10 | typedef void (*Store_Done_Cb)(void *data, Store *store, char *answer, size_t len); | ||
11 | typedef void (*Store_Error_Cb)(void *data, Store *store, char *strerr); | ||
12 | |||
13 | int store_init(void); | ||
14 | int store_shutdown(void); | ||
15 | |||
16 | Store * store_new(const char *url); | ||
17 | Eina_Bool store_add(Store *store, const char *buf, size_t len, Store_Done_Cb done_cb, Store_Error_Cb error_cb, const void *data); | ||
18 | |||
19 | void store_data_set(Store *store, const void *data); | ||
20 | void * store_data_get(Store *store); | ||
21 | #endif | ||