summaryrefslogtreecommitdiffstats
path: root/collectors/systemd-journal.plugin/systemd-main.c
blob: e9f4ebd4cc0a0233ea4fd7482b91eff84449fcbc (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
// SPDX-License-Identifier: GPL-3.0-or-later

#include "systemd-internals.h"
#include "libnetdata/required_dummies.h"

#define SYSTEMD_JOURNAL_WORKER_THREADS          5

netdata_mutex_t stdout_mutex = NETDATA_MUTEX_INITIALIZER;
static bool plugin_should_exit = false;

static bool journal_data_direcories_exist() {
    struct stat st;
    for (unsigned i = 0; i < MAX_JOURNAL_DIRECTORIES && journal_directories[i].path; i++) {
        if ((stat(string2str(journal_directories[i].path), &st) == 0) && S_ISDIR(st.st_mode))
            return true;
    }
    return false;
}

int main(int argc __maybe_unused, char **argv __maybe_unused) {
    clocks_init();
    netdata_thread_set_tag("SDMAIN");
    nd_log_initialize_for_external_plugins("systemd-journal.plugin");

    netdata_configured_host_prefix = getenv("NETDATA_HOST_PREFIX");
    if(verify_netdata_host_prefix(true) == -1) exit(1);

    // ------------------------------------------------------------------------
    // initialization

    netdata_systemd_journal_message_ids_init();
    journal_init_files_and_directories();

    if (!journal_data_direcories_exist()) {
        nd_log_collector(NDLP_INFO, "unable to locate journal data directories. Exiting...");
        fprintf(stdout, "DISABLE\n");
        fflush(stdout);
        exit(0);
    }

    // ------------------------------------------------------------------------
    // debug

    if(argc == 2 && strcmp(argv[1], "debug") == 0) {
        journal_files_registry_update();

        bool cancelled = false;
        usec_t stop_monotonic_ut = now_monotonic_usec() + 600 * USEC_PER_SEC;
        char buf[] = "systemd-journal after:-8640000 before:0 direction:backward last:200 data_only:false slice:true source:all";
        // char buf[] = "systemd-journal after:1695332964 before:1695937764 direction:backward last:100 slice:true source:all DHKucpqUoe1:PtVoyIuX.MU";
        // char buf[] = "systemd-journal after:1694511062 before:1694514662 anchor:1694514122024403";
        function_systemd_journal("123", buf, &stop_monotonic_ut, &cancelled, NULL, NULL, NULL);
//        function_systemd_units("123", "systemd-units", 600, &cancelled);
        exit(1);
    }
#ifdef ENABLE_SYSTEMD_DBUS
    if(argc == 2 && strcmp(argv[1], "debug-units") == 0) {
        bool cancelled = false;
        usec_t stop_monotonic_ut = now_monotonic_usec() + 600 * USEC_PER_SEC;
        function_systemd_units("123", "systemd-units", &stop_monotonic_ut, &cancelled, NULL, NULL, NULL);
        exit(1);
    }
#endif

    // ------------------------------------------------------------------------
    // watcher thread

    netdata_thread_t watcher_thread;
    netdata_thread_create(&watcher_thread, "SDWATCH",
                          NETDATA_THREAD_OPTION_DONT_LOG, journal_watcher_main, NULL);

    // ------------------------------------------------------------------------
    // the event loop for functions

    struct functions_evloop_globals *wg =
            functions_evloop_init(SYSTEMD_JOURNAL_WORKER_THREADS, "SDJ", &stdout_mutex, &plugin_should_exit);

    functions_evloop_add_function(wg,
                                  SYSTEMD_JOURNAL_FUNCTION_NAME,
                                  function_systemd_journal,
                                  SYSTEMD_JOURNAL_DEFAULT_TIMEOUT,
                                  NULL);

#ifdef ENABLE_SYSTEMD_DBUS
    functions_evloop_add_function(wg,
                                  SYSTEMD_UNITS_FUNCTION_NAME,
                                  function_systemd_units,
                                  SYSTEMD_UNITS_DEFAULT_TIMEOUT,
                                  NULL);
#endif

    systemd_journal_dyncfg_init(wg);

    // ------------------------------------------------------------------------
    // register functions to netdata

    netdata_mutex_lock(&stdout_mutex);

    fprintf(stdout, PLUGINSD_KEYWORD_FUNCTION " GLOBAL \"%s\" %d \"%s\" \"logs\" \"members\" %d\n",
            SYSTEMD_JOURNAL_FUNCTION_NAME, SYSTEMD_JOURNAL_DEFAULT_TIMEOUT, SYSTEMD_JOURNAL_FUNCTION_DESCRIPTION,
            RRDFUNCTIONS_PRIORITY_DEFAULT);

#ifdef ENABLE_SYSTEMD_DBUS
    fprintf(stdout, PLUGINSD_KEYWORD_FUNCTION " GLOBAL \"%s\" %d \"%s\" \"top\" \"members\" %d\n",
            SYSTEMD_UNITS_FUNCTION_NAME, SYSTEMD_UNITS_DEFAULT_TIMEOUT, SYSTEMD_UNITS_FUNCTION_DESCRIPTION,
            RRDFUNCTIONS_PRIORITY_DEFAULT);
#endif

    fflush(stdout);
    netdata_mutex_unlock(&stdout_mutex);

    // ------------------------------------------------------------------------

    usec_t step_ut = 100 * USEC_PER_MS;
    usec_t send_newline_ut = 0;
    usec_t since_last_scan_ut = SYSTEMD_JOURNAL_ALL_FILES_SCAN_EVERY_USEC * 2; // something big to trigger scanning at start
    bool tty = isatty(fileno(stdout)) == 1;

    heartbeat_t hb;
    heartbeat_init(&hb);
    while(!plugin_should_exit) {

        if(since_last_scan_ut > SYSTEMD_JOURNAL_ALL_FILES_SCAN_EVERY_USEC) {
            journal_files_registry_update();
            since_last_scan_ut = 0;
        }

        usec_t dt_ut = heartbeat_next(&hb, step_ut);
        since_last_scan_ut += dt_ut;
        send_newline_ut += dt_ut;

        if(!tty && send_newline_ut > USEC_PER_SEC) {
            send_newline_and_flush();
            send_newline_ut = 0;
        }
    }

    exit(0);
}