Skip to content

Commit 9cd89bf

Browse files
authored
Merge pull request #433 from bazsi/add-syslog-ng-visibility-into-perf-stackdumps
Add syslog-ng visibility into perf stackdumps
2 parents 89dd4a1 + 45743a4 commit 9cd89bf

23 files changed

+500
-35
lines changed

cmake/syslog-ng-config.h.in

+1
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,4 @@
106106
#cmakedefine01 SYSLOG_NG_HAVE_SO_MEMINFO
107107
#cmakedefine01 SYSLOG_NG_ENABLE_AFSOCKET_MEMINFO_METRICS
108108
#cmakedefine01 SYSLOG_NG_HAVE_IV_WORK_POOL_SUBMIT_CONTINUATION
109+
#cmakedefine01 SYSLOG_NG_ENABLE_PERF

configure.ac

+18
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,10 @@ AC_ARG_ENABLE(ebpf,
266266
[ --enable-ebpf Enable support for loading of eBPF programs (default: no)]
267267
,,enable_ebpf="no")
268268

269+
AC_ARG_ENABLE(perf,
270+
[ --enable-perf Enable support for the Linux perf tool (default: auto)]
271+
,,enable_perf="auto")
272+
269273
AC_ARG_ENABLE(gcov,
270274
[ --enable-gcov Enable coverage profiling (default: no)]
271275
,,enable_gcov="no")
@@ -466,6 +470,7 @@ dnl Checks for programs.
466470
AC_PROG_CC
467471
AC_PROG_CC_C99
468472
AM_PROG_CC_C_O
473+
AM_PROG_AS
469474
if test "x$ac_cv_prog_cc_c99" = "xno"; then
470475
AC_MSG_ERROR([C99 standard compliant C compiler required. Try GCC 3.x or later.])
471476
fi
@@ -2060,6 +2065,16 @@ if test "x$enable_ebpf" = "xyes"; then
20602065
AC_SUBST(BPF_CC)
20612066
fi
20622067

2068+
if test "x$enable_perf" = "xauto"; then
2069+
uname_s=`uname -s`
2070+
uname_m=`uname -m`
2071+
if test "$uname_s" = "Linux" -a "$uname_m" = "x86_64"; then
2072+
enable_perf="yes"
2073+
else
2074+
enable_perf="no"
2075+
fi
2076+
fi
2077+
20632078
dnl ***************************************************************************
20642079
dnl check if we have timezone variable in <time.h>
20652080
dnl ***************************************************************************
@@ -2243,6 +2258,7 @@ AC_DEFINE_UNQUOTED(ENABLE_IPV6, `enable_value $enable_ipv6`, [Enable IPv6 suppor
22432258
AC_DEFINE_UNQUOTED(ENABLE_TCP_WRAPPER, `enable_value $enable_tcp_wrapper`, [Enable TCP wrapper support])
22442259
AC_DEFINE_UNQUOTED(ENABLE_LINUX_CAPS, `enable_value $enable_linux_caps`, [Enable Linux capability management support])
22452260
AC_DEFINE_UNQUOTED(ENABLE_EBPF, `enable_value $enable_ebpf`, [Enable Linux eBPF support])
2261+
AC_DEFINE_UNQUOTED(ENABLE_PERF, `enable_value $enable_perf`, [Enable Linux perf support])
22462262
AC_DEFINE_UNQUOTED(ENABLE_ENV_WRAPPER, `enable_value $enable_env_wrapper`, [Enable environment wrapper support])
22472263
AC_DEFINE_UNQUOTED(ENABLE_SYSTEMD, `enable_value $enable_systemd`, [Enable systemd support])
22482264
AC_DEFINE_UNQUOTED(ENABLE_KAFKA, `enable_value $enable_kafka`, [Enable kafka support])
@@ -2259,6 +2275,7 @@ AM_CONDITIONAL(ENABLE_SUN_STREAMS, [test "$enable_sun_streams" = "yes"])
22592275
AM_CONDITIONAL(ENABLE_DARWIN_OSL, [test "$enable_darwin_osl" = "yes"])
22602276
AM_CONDITIONAL(ENABLE_OPENBSD_SYSTEM_SOURCE, [test "$enable_openbsd_system_source" = "yes"])
22612277
AM_CONDITIONAL(ENABLE_EBPF, [test "$enable_ebpf" = "yes"])
2278+
AM_CONDITIONAL(ENABLE_PERF, [test "$enable_perf" = "yes"])
22622279
AM_CONDITIONAL(ENABLE_PACCT, [test "$enable_pacct" = "yes"])
22632280
AM_CONDITIONAL(ENABLE_MONGODB, [test "$enable_mongodb" = "yes"])
22642281
AM_CONDITIONAL(ENABLE_SMTP, [test "$enable_smtp" = "yes"])
@@ -2414,6 +2431,7 @@ echo " Env wrapper support : ${enable_env_wrapper:=no}"
24142431
echo " systemd support : ${enable_systemd:=no} (unit dir: ${systemdsystemunitdir:=none})"
24152432
echo " systemd-journal support : ${with_systemd_journal:=no}"
24162433
echo " JSON support : $with_jsonc"
2434+
echo " perf support : ${enable_perf:=no}"
24172435
echo " Build options:"
24182436
echo " Generate manual pages : ${enable_manpages:=no}"
24192437
echo " Install manual pages : ${enable_manpages_install:=no}"

lib/Makefile.am

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ include lib/logthrsource/Makefile.am
2929
include lib/logthrdest/Makefile.am
3030
include lib/signal-slot-connector/Makefile.am
3131
include lib/multi-line/Makefile.am
32+
include lib/perf/Makefile.am
3233
include lib/adt/Makefile.am
3334

3435
LSNG_RELEASE = $(shell echo @PACKAGE_VERSION@ | cut -d. -f1,2)
@@ -309,6 +310,7 @@ lib_libsyslog_ng_la_SOURCES = \
309310
$(logthrsource_sources) \
310311
$(logthrdest_sources) \
311312
$(signal_slot_connector_sources) \
313+
$(perf_sources) \
312314
$(adt_sources)
313315

314316
lib_libsyslog_ng_la_CFLAGS = \

lib/afinter.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ static gboolean
414414
afinter_sd_pre_config_init(LogPipe *s)
415415
{
416416
main_loop_worker_allocate_thread_space(1);
417-
return TRUE;
417+
return log_pipe_pre_config_init_method(s);
418418
}
419419

420420
static gboolean
@@ -459,7 +459,10 @@ afinter_sd_post_config_init(LogPipe *s)
459459
{
460460
AFInterSourceDriver *self = (AFInterSourceDriver *) s;
461461

462-
return afinter_source_start_thread(self->source);
462+
if (!afinter_source_start_thread(self->source))
463+
return FALSE;
464+
465+
return log_pipe_post_config_init_method(s);
463466
}
464467

465468
static gboolean

lib/cfg-lexer.c

+2
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ cfg_lexer_init_include_level_buffer(CfgLexer *self, CfgIncludeLevel *level,
393393
level->buffer.content = lexer_buffer;
394394
level->buffer.content_length = lexer_buffer_len;
395395
level->buffer.original_content = g_strdup(lexer_buffer);
396+
level->buffer.original_lines = NULL;
396397
}
397398

398399
gboolean
@@ -458,6 +459,7 @@ cfg_lexer_include_level_clear(CfgLexer *self, CfgIncludeLevel *level)
458459
{
459460
g_free(level->buffer.content);
460461
g_free(level->buffer.original_content);
462+
g_strfreev(level->buffer.original_lines);
461463
}
462464
memset(level, 0, sizeof(*level));
463465
}

lib/cfg-lexer.h

+1
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ struct _CfgIncludeLevel
160160
{
161161
/* the lexer mutates content, so save it for error reporting */
162162
gchar *original_content;
163+
gchar **original_lines;
163164
/* buffer for the lexer */
164165
gchar *content;
165166
gsize content_length;

lib/cfg-source.c

+22-7
Original file line numberDiff line numberDiff line change
@@ -226,9 +226,13 @@ _extract_source_from_file_location(GString *result, const gchar *filename, const
226226
}
227227

228228
static gboolean
229-
_extract_source_from_buffer_location(GString *result, const gchar *buffer_content, const CFG_LTYPE *yylloc)
229+
_extract_source_from_buffer_location(GString *result, CfgIncludeLevel *level, const CFG_LTYPE *yylloc)
230230
{
231-
gchar **lines = g_strsplit(buffer_content, "\n", yylloc->last_line + 1);
231+
const gchar *buffer_content = level->buffer.original_content;
232+
gchar **lines = level->buffer.original_lines;
233+
234+
if (!lines)
235+
lines = level->buffer.original_lines = g_strsplit(buffer_content, "\n", 0);
232236
gint num_lines = g_strv_length(lines);
233237

234238
if (num_lines <= yylloc->first_line)
@@ -244,10 +248,18 @@ _extract_source_from_buffer_location(GString *result, const gchar *buffer_conten
244248

245249
if (lineno == yylloc->first_line)
246250
{
251+
gint token_start = MIN(linelen, yylloc->first_column - 1);
252+
247253
if (yylloc->first_line == yylloc->last_line)
248-
g_string_append_len(result, &line[MIN(linelen, yylloc->first_column-1)], yylloc->last_column - yylloc->first_column);
254+
{
255+
/* both last_column & first_column are 1 based, they cancel that out */
256+
gint token_len = yylloc->last_column - yylloc->first_column;
257+
if (token_start + token_len > linelen)
258+
token_len = linelen - token_start;
259+
g_string_append_len(result, &line[token_start], token_len);
260+
}
249261
else
250-
g_string_append(result, &line[MIN(linelen, yylloc->first_column-1)]);
262+
g_string_append(result, &line[token_start]);
251263
}
252264
else if (lineno < yylloc->last_line)
253265
{
@@ -256,13 +268,16 @@ _extract_source_from_buffer_location(GString *result, const gchar *buffer_conten
256268
}
257269
else if (lineno == yylloc->last_line)
258270
{
271+
/* last_column is 1 based */
272+
gint token_len = yylloc->last_column - 1;
273+
if (token_len > linelen)
274+
token_len = linelen;
259275
g_string_append_c(result, ' ');
260-
g_string_append_len(result, line, yylloc->last_column);
276+
g_string_append_len(result, line, token_len);
261277
}
262278
}
263279

264280
exit:
265-
g_strfreev(lines);
266281
return TRUE;
267282
}
268283

@@ -279,7 +294,7 @@ cfg_source_extract_source_text(CfgLexer *lexer, const CFG_LTYPE *yylloc, GString
279294
CFG_LTYPE buf_lloc = *yylloc;
280295
cfg_lexer_undo_set_file_location(lexer, &buf_lloc);
281296

282-
return _extract_source_from_buffer_location(result, level->buffer.original_content, &buf_lloc);
297+
return _extract_source_from_buffer_location(result, level, &buf_lloc);
283298
}
284299
else
285300
g_assert_not_reached();

lib/filterx/filterx-expr.c

+25-4
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@
2828
#include "mainloop.h"
2929
#include "stats/stats-registry.h"
3030
#include "stats/stats-cluster-single.h"
31+
#include "perf/perf.h"
32+
33+
static inline gboolean
34+
_extract_source_text(void)
35+
{
36+
return debug_flag || perf_is_enabled();
37+
}
3138

3239
void
3340
filterx_expr_set_location_with_text(FilterXExpr *self, CFG_LTYPE *lloc, const gchar *text)
@@ -36,8 +43,11 @@ filterx_expr_set_location_with_text(FilterXExpr *self, CFG_LTYPE *lloc, const gc
3643
self->lloc = g_new0(CFG_LTYPE, 1);
3744
*self->lloc = *lloc;
3845

39-
if (debug_flag && text)
40-
self->expr_text = g_strdup(text);
46+
if (_extract_source_text() && text && text != self->expr_text)
47+
{
48+
g_free(self->expr_text);
49+
self->expr_text = g_strdup(text);
50+
}
4151
}
4252

4353
void
@@ -46,8 +56,9 @@ filterx_expr_set_location(FilterXExpr *self, CfgLexer *lexer, CFG_LTYPE *lloc)
4656
if (!self->lloc)
4757
self->lloc = g_new0(CFG_LTYPE, 1);
4858
*self->lloc = *lloc;
49-
if (debug_flag)
59+
if (_extract_source_text())
5060
{
61+
g_free(self->expr_text);
5162
GString *res = g_string_sized_new(0);
5263
cfg_source_extract_source_text(lexer, lloc, res);
5364
self->expr_text = g_string_free(res, FALSE);
@@ -110,7 +121,7 @@ _init_sc_key_name(FilterXExpr *self, gchar *buf, gsize buf_len)
110121
gboolean
111122
filterx_expr_init_method(FilterXExpr *self, GlobalConfig *cfg)
112123
{
113-
gchar buf[64];
124+
gchar buf[256];
114125

115126
_init_sc_key_name(self, buf, sizeof(buf));
116127
stats_lock();
@@ -123,6 +134,16 @@ filterx_expr_init_method(FilterXExpr *self, GlobalConfig *cfg)
123134
stats_cluster_single_key_set(&sc_key, buf, labels, labels_len);
124135
stats_register_counter(STATS_LEVEL3, &sc_key, SC_TYPE_SINGLE_VALUE, &self->eval_count);
125136
stats_unlock();
137+
138+
if (perf_is_enabled())
139+
{
140+
if (self->expr_text)
141+
g_snprintf(buf, sizeof(buf), "filterx::%s", self->expr_text);
142+
else
143+
g_snprintf(buf, sizeof(buf), "filterx::@%s", self->type);
144+
self->eval = perf_generate_trampoline(self->eval, buf);
145+
}
146+
126147
return TRUE;
127148
}
128149

lib/filterx/filterx-grammar.ym

+4-4
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ _assign_location(FilterXExpr *expr, CfgLexer *lexer, CFG_LTYPE *lloc)
147147
%type <node> comparison_operator
148148
%type <node> arithmetic_operator
149149
%type <node> expr_generator
150-
%type <node> expr_generator_unchecked
150+
%type <node> __expr_generator
151151
%type <node> expr_plus_generator
152152
%type <node> generator_function_call
153153
%type <node> function_call
@@ -469,13 +469,13 @@ expr_value
469469
;
470470

471471
expr_generator
472-
: expr_generator_unchecked {
473-
$$ = $1;
472+
: __expr_generator {
474473
CHECK_ERROR($1, @1, "error initializing generator expression");
474+
$$ = _assign_location($1, lexer, &@1);
475475
}
476476
;
477477

478-
expr_generator_unchecked
478+
__expr_generator
479479
: dict_generator
480480
| list_generator
481481
| generator_function_call

lib/gprocess.c

+15-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "messages.h"
2828
#include "reloc.h"
2929
#include "console.h"
30+
#include "perf/perf.h"
3031

3132
#include <sys/types.h>
3233
#include <sys/stat.h>
@@ -126,6 +127,7 @@ static struct
126127
const gchar *cwd;
127128
const gchar *caps;
128129
gboolean enable_caps;
130+
gboolean enable_perf;
129131
gint argc;
130132
gchar **argv;
131133
gchar *argv_start;
@@ -719,6 +721,16 @@ g_process_enable_core(void)
719721
}
720722
}
721723

724+
static void
725+
g_process_enable_perf(void)
726+
{
727+
if (process_opts.enable_perf || perf_autodetect())
728+
{
729+
if (!perf_enable())
730+
console_printf("Error enabling Linux perf profiling support, maybe not compiled in using --enable-perf?");
731+
}
732+
}
733+
722734
/**
723735
* g_process_format_pidfile_name:
724736
* @buf: buffer to store the pidfile name
@@ -1425,6 +1437,7 @@ g_process_start(void)
14251437
}
14261438
g_process_enable_core();
14271439
g_process_change_dir();
1440+
g_process_enable_perf();
14281441
}
14291442

14301443

@@ -1554,7 +1567,8 @@ static GOptionEntry g_process_option_entries[] =
15541567
{ "no-caps", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, g_process_process_no_caps, "Disable managing Linux capabilities", NULL },
15551568
{ "pidfile", 'p', 0, G_OPTION_ARG_STRING, &process_opts.pidfile, "Set path to pid file", "<pidfile>" },
15561569
{ "enable-core", 0, 0, G_OPTION_ARG_NONE, &process_opts.core, "Enable dumping core files", NULL },
1557-
{ "fd-limit", 0, 0, G_OPTION_ARG_INT, &process_opts.fd_limit_min, "The minimum required number of fds", NULL },
1570+
{ "fd-limit", 0, 0, G_OPTION_ARG_INT, &process_opts.fd_limit_min, "The minimum required number of fds", NULL },
1571+
{ "perf-profiling", 0, 0, G_OPTION_ARG_NONE, &process_opts.enable_perf, "Enable Linux perf based profiling", NULL },
15581572
{ NULL, 0, 0, 0, NULL, NULL, NULL },
15591573
};
15601574

lib/logpipe.c

+21-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "logpipe.h"
2626
#include "cfg-tree.h"
2727
#include "cfg-walker.h"
28+
#include "perf/perf.h"
2829

2930
gboolean (*pipe_single_step_hook)(LogPipe *pipe, LogMessage *msg, const LogPathOptions *path_options);
3031

@@ -146,6 +147,24 @@ log_pipe_clone_method(LogPipe *dst, const LogPipe *src)
146147
log_pipe_set_options(dst, &src->options);
147148
}
148149

150+
gboolean
151+
log_pipe_pre_config_init_method(LogPipe *self)
152+
{
153+
return TRUE;
154+
}
155+
156+
gboolean
157+
log_pipe_post_config_init_method(LogPipe *self)
158+
{
159+
if ((self->flags & PIF_CONFIG_RELATED) && perf_is_enabled())
160+
{
161+
gchar buf[256];
162+
163+
self->queue = perf_generate_trampoline(self->queue, log_expr_node_format_location(self->expr_node, buf, sizeof(buf)));
164+
}
165+
return TRUE;
166+
}
167+
149168
void
150169
log_pipe_init_instance(LogPipe *self, GlobalConfig *cfg)
151170
{
@@ -154,7 +173,8 @@ log_pipe_init_instance(LogPipe *self, GlobalConfig *cfg)
154173
self->pipe_next = NULL;
155174
self->persist_name = NULL;
156175
self->plugin_name = NULL;
157-
176+
self->pre_config_init = log_pipe_pre_config_init_method;
177+
self->post_config_init = log_pipe_post_config_init_method;
158178
self->queue = log_pipe_forward_msg;
159179
self->free_fn = log_pipe_free_method;
160180
self->arcs = _arcs;

lib/logpipe.h

+2
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,8 @@ extern gboolean (*pipe_single_step_hook)(LogPipe *pipe, LogMessage *msg, const L
349349
LogPipe *log_pipe_ref(LogPipe *self);
350350
gboolean log_pipe_unref(LogPipe *self);
351351
LogPipe *log_pipe_new(GlobalConfig *cfg);
352+
gboolean log_pipe_pre_config_init_method(LogPipe *self);
353+
gboolean log_pipe_post_config_init_method(LogPipe *self);
352354
void log_pipe_init_instance(LogPipe *self, GlobalConfig *cfg);
353355
void log_pipe_clone_method(LogPipe *dst, const LogPipe *src);
354356
void log_pipe_forward_notify(LogPipe *self, gint notify_code, gpointer user_data);

0 commit comments

Comments
 (0)