// SPDX-License-Identifier: GPL-3.0-or-later
// only for PACKAGE_VERSION
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#define XXH_INLINE_ALL
#include "../xxhash.h"
#define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h>
#define MAX_OUTPUT_KEYS 1024
#define OVECCOUNT (MAX_OUTPUT_KEYS * 3) // should be a multiple of 3
#define MAX_LINE_LENGTH (1024 * 1024)
#define MAX_KEY_DUPS (MAX_OUTPUT_KEYS / 2)
#define MAX_INJECTIONS (MAX_OUTPUT_KEYS / 2)
#define MAX_REWRITES (MAX_OUTPUT_KEYS / 2)
#define MAX_KEY_DUPS_KEYS 20
#define MAX_KEY_LEN 64 // according to systemd-journald
#define MAX_VALUE_LEN (48 * 1024) // according to systemd-journald
void display_help(const char *name) {
printf("\n");
printf("Netdata log2journal " PACKAGE_VERSION "\n");
printf("\n");
printf("Convert structured log input to systemd Journal Export Format.\n");
printf("\n");
printf("Using PCRE2 patterns, extract the fields from structured logs on the standard\n");
printf("input, and generate output according to systemd Journal Export Format.\n");
printf("\n");
printf("Usage: %s [OPTIONS] PATTERN\n", name);
printf("\n");
printf("Options:\n");
printf("\n");
printf(" --filename-key=KEY\n");
printf(" Add a field with KEY as the key and the current filename as value.\n");
printf(" Automatically detects filenames when piped after 'tail -F',\n");
printf(" and tail matches multiple filenames.\n");
printf(" To inject the filename when tailing a single file, use --inject.\n");
printf("\n");
printf(" --unmatched-key=KEY\n");
printf(" Include unmatched log entries in the output with KEY as the field name.\n");
printf(" Use this to include unmatched entries to the output stream.\n");
printf(" Usually it should be set to --unmatched-key=MESSAGE so that the\n");
printf(" unmatched entry will appear as the log message in the journals.\n");
printf(" Use --inject-unmatched to inject additional fields to unmatched lines.\n");
printf("\n");
printf(" --duplicate=TARGET=KEY1[,KEY2[,KEY3[,...]]\n");
printf(" Create a new key called TARGET, duplicating the values of the keys\n");
printf(" given. Useful for further processing. When multiple keys are given,\n");
printf(" their values are separated by comma.\n");
printf(" Up to %d duplications can be given on the command line, and up to\n", MAX_KEY_DUPS);
printf(" %d keys per duplication command are allowed.\n", MAX_KEY_DUPS_KEYS);
printf("\n");
printf(" --inject=LINE\n");
printf(" Inject constant fields to the output (both matched and unmatched logs).\n");
printf(" --inject entries are added to unmatched lines too, when their key is\n");
printf(" not used in --inject-unmatched (--inject-unmatched override --inject).\n");
printf(" Up to %d fields can be injected.\n", MAX_INJECTIONS);
printf("\n");
printf(" --inject-unmatched=LINE\n");
printf(" Inject lines into the output for each unmatched log entry.\n");
printf(" Usually, --inject-unmatched=PRIORITY=3 is needed to mark the unmatched\n");
printf(" lines as errors, so that they can easily be spotted in the journals.\n");
printf(" Up to %d such lines can be injected.\n", MAX_INJECTIONS);
printf("\n");
printf(" --rewrite=KEY=/SearchPattern/ReplacePattern\n");
printf(" Apply a rewrite rule to the values of a specific key.\n");
printf(" The first character after KEY= is the separator, which should also\n");
printf(" be used between the search pattern and the replacement pattern.\n");
printf(" The search pattern is a PCRE2 regular expression, and the replacement\n");
printf(" pattern supports literals and named capture groups from the search pattern.\n");
printf(" Example:\n");
printf(" --rewrite=DATE=/^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})$/\n");
printf(" ${day}/${month}/${year}\n");
printf(" This will rewrite dates in the format YYYY-MM-DD to DD/MM/YYYY.\n");
printf("\n");
printf(" Only one rewrite rule is applied per key; the sequence of rewrites stops\n");
printf(" for the key once a rule matches it. This allows providing a sequence of\n");
printf(" independent rewriting rules for the same key, matching the different values\n");
printf(" the key may get, and also provide a catch-all rewrite rule at the end of the\n");
printf(" sequence for setting the key value if no other rule matched it.\n");
printf("\n");
printf(" The combination of duplicating keys with the values of multiple other keys\n");
printf(" combined with multiple rewrite rules, allows creating complex rules for\n");
printf(" rewriting key values.\n");
printf("\n");
printf(" Up to %d rewriting rules are allowed.\n", MAX_REWRITES);
printf("\n");
printf(<