summaryrefslogtreecommitdiffstats
path: root/collectors/systemd-journal.plugin/systemd-internals.h
blob: e1ae44d4f1b05881297913b9c80719f70535d61f (plain)
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
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef NETDATA_COLLECTORS_SYSTEMD_INTERNALS_H
#define NETDATA_COLLECTORS_SYSTEMD_INTERNALS_H

#include "collectors/all.h"
#include "libnetdata/libnetdata.h"

#include <linux/capability.h>
#include <systemd/sd-journal.h>
#include <syslog.h>

#define SYSTEMD_JOURNAL_FUNCTION_DESCRIPTION    "View, search and analyze systemd journal entries."
#define SYSTEMD_JOURNAL_FUNCTION_NAME           "systemd-journal"
#define SYSTEMD_JOURNAL_DEFAULT_TIMEOUT         60
#define SYSTEMD_JOURNAL_ENABLE_ESTIMATIONS_FILE_PERCENTAGE 0.01
#define SYSTEMD_JOURNAL_EXECUTE_WATCHER_PENDING_EVERY_MS 250
#define SYSTEMD_JOURNAL_ALL_FILES_SCAN_EVERY_USEC (5 * 60 * USEC_PER_SEC)

#define SYSTEMD_UNITS_FUNCTION_DESCRIPTION      "View the status of systemd units"
#define SYSTEMD_UNITS_FUNCTION_NAME              "systemd-list-units"
#define SYSTEMD_UNITS_DEFAULT_TIMEOUT            30

extern __thread size_t fstat_thread_calls;
extern __thread size_t fstat_thread_cached_responses;
void fstat_cache_enable_on_thread(void);
void fstat_cache_disable_on_thread(void);

extern netdata_mutex_t stdout_mutex;

typedef enum {
    ND_SD_JOURNAL_NO_FILE_MATCHED,
    ND_SD_JOURNAL_FAILED_TO_OPEN,
    ND_SD_JOURNAL_FAILED_TO_SEEK,
    ND_SD_JOURNAL_TIMED_OUT,
    ND_SD_JOURNAL_OK,
    ND_SD_JOURNAL_NOT_MODIFIED,
    ND_SD_JOURNAL_CANCELLED,
} ND_SD_JOURNAL_STATUS;

typedef enum {
    SDJF_NONE               = 0,
    SDJF_ALL                = (1 << 0),
    SDJF_LOCAL_ALL          = (1 << 1),
    SDJF_REMOTE_ALL         = (1 << 2),
    SDJF_LOCAL_SYSTEM       = (1 << 3),
    SDJF_LOCAL_USER         = (1 << 4),
    SDJF_LOCAL_NAMESPACE    = (1 << 5),
    SDJF_LOCAL_OTHER        = (1 << 6),
} SD_JOURNAL_FILE_SOURCE_TYPE;

struct journal_file {
    const char *filename;
    size_t filename_len;
    STRING *source;
    SD_JOURNAL_FILE_SOURCE_TYPE source_type;
    usec_t file_last_modified_ut;
    usec_t msg_first_ut;
    usec_t msg_last_ut;
    size_t size;
    bool logged_failure;
    bool logged_journalctl_failure;
    usec_t max_journal_vs_realtime_delta_ut;

    usec_t last_scan_monotonic_ut;
    usec_t last_scan_header_vs_last_modified_ut;

    uint64_t first_seqnum;
    uint64_t last_seqnum;
    sd_id128_t first_writer_id;
    sd_id128_t last_writer_id;

    uint64_t messages_in_file;
};

#define SDJF_SOURCE_ALL_NAME "all"
#define SDJF_SOURCE_LOCAL_NAME "all-local-logs"
#define SDJF_SOURCE_LOCAL_SYSTEM_NAME "all-local-system-logs"
#define SDJF_SOURCE_LOCAL_USERS_NAME "all-local-user-logs"
#define SDJF_SOURCE_LOCAL_OTHER_NAME "all-uncategorized"
#define SDJF_SOURCE_NAMESPACES_NAME "all-local-namespaces"
#define SDJF_SOURCE_REMOTES_NAME "all-remote-systems"

#define ND_SD_JOURNAL_OPEN_FLAGS (0)

#define JOURNAL_VS_REALTIME_DELTA_DEFAULT_UT (5 * USEC_PER_SEC) // assume always 5 seconds latency
#define JOURNAL_VS_REALTIME_DELTA_MAX_UT (2 * 60 * USEC_PER_SEC) // up to 2 minutes latency

extern DICTIONARY *journal_files_registry;
extern DICTIONARY *used_hashes_registry;
extern DICTIONARY *function_query_status_dict;
extern DICTIONARY *boot_ids_to_first_ut;

int journal_file_dict_items_backward_compar(const void *a, const void *b);
int journal_file_dict_items_forward_compar(const void *a, const void *b);
void buffer_json_journal_versions(BUFFER *wb);
void available_journal_file_sources_to_json_array(BUFFER *wb);
bool journal_files_completed_once(void);
void journal_files_registry_update(void);
void journal_directory_scan_recursively(DICTIONARY *files, DICTIONARY *dirs, const char *dirname, int depth);

FACET_ROW_SEVERITY syslog_priority_to_facet_severity(FACETS *facets, FACET_ROW *row, void *data);

void netdata_systemd_journal_dynamic_row_id(FACETS *facets, BUFFER *json_array, FACET_ROW_KEY_VALUE *rkv, FACET_ROW *row, void *data);
void netdata_systemd_journal_transform_priority(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
void netdata_systemd_journal_transform_syslog_facility(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
void netdata_systemd_journal_transform_errno(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
void netdata_systemd_journal_transform_boot_id(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
void netdata_systemd_journal_transform_uid(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
void netdata_systemd_journal_transform_gid(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
void netdata_systemd_journal_transform_cap_effective(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
void netdata_systemd_journal_transform_timestamp_usec(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);

usec_t journal_file_update_annotation_boot_id(sd_journal *j, struct journal_file *jf, const char *boot_id);

#define MAX_JOURNAL_DIRECTORIES 100
struct journal_directory {
    char *path;
};
extern struct journal_directory journal_directories[MAX_JOURNAL_DIRECTORIES];

void journal_init_files_and_directories(void);
void journal_init_query_status(void);
void function_systemd_journal(const char *transaction, char *function, int timeout, bool *cancelled);
void journal_file_update_header(const char *filename, struct journal_file *jf);

void netdata_systemd_journal_message_ids_init(void);
void netdata_systemd_journal_transform_message_id(FACETS *facets __maybe_unused, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope __maybe_unused, void *data __maybe_unused);

void *journal_watcher_main(void *arg);

#ifdef ENABLE_SYSTEMD_DBUS
void function_systemd_units(const char *transaction, char *function, int timeout, bool *cancelled);
#endif

static inline void send_newline_and_flush(void) {
    netdata_mutex_lock(&stdout_mutex);
    fprintf(stdout, "\n");
    fflush(stdout);
    netdata_mutex_unlock(&stdout_mutex);
}

static inline bool parse_journal_field(const char *data, size_t data_length, const char **key, size_t *key_length, const char **value, size_t *value_length) {
    const char *k = data;
    const char *equal = strchr(k, '=');
    if(unlikely(!equal))
        return false;

    size_t kl = equal - k;

    const char *v = ++equal;
    size_t vl = data_length - kl - 1;

    *key = k;
    *key_length = kl;
    *value = v;
    *value_length = vl;

    return true;
}

#endif //NETDATA_COLLECTORS_SYSTEMD_INTERNALS_H