Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for always on profiling to zero config #2538

Merged
merged 5 commits into from
Feb 16, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions instrumentation/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ RUN apt-get update && \
WORKDIR /libsplunk

COPY src /libsplunk/src
COPY testdata/instrumentation.conf /libsplunk/testdata/instrumentation.conf
COPY testdata/instrumentation-svcname.conf /libsplunk/testdata/instrumentation-svcname.conf
COPY testdata/instrumentation-default.conf /libsplunk/testdata/instrumentation-default.conf
COPY testdata/instrumentation-options.conf /libsplunk/testdata/instrumentation-options.conf
COPY install/instrumentation.conf /libsplunk/install/instrumentation.conf
COPY Makefile /libsplunk/Makefile
28 changes: 27 additions & 1 deletion instrumentation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,31 @@ Java instrumentation jar. Typically, it will be set to something like:

to set the deployment environment for the Splunk backend.

### disable_telemetry (optional)

Set this value to `true` to disable the preloader from sending the `splunk.linux-autoinstr.executions` metric to the
local collector. Default: `false`.

### generate_service_name (optional)

Set this value to `false` to prevent the preloader from setting the `OTEL_SERVICE_NAME` environment variable.
Default: `true`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a doc or brief description you could provide of what the false behavior is?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which takes precedence if both generate_service_name is true and service_name is set?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Turns out there really isn't a doc yet that describes in detail what the instrumentation library does, although there is this. But I've added a couple of sentences to explain the implications of the false behavior.

Regarding precedence, generate_service_name=true will cause the .so generate the service name either dynamically or via the service_name override. If it's false, no service name will be set, regardless of the value of the service_name override. I've added an explanation to the readme as well as a test case.


### enable_profiler (optional)

Set this value to `true` to pass `-Dsplunk.profiler.enabled=true` to the starting Java executable, which will enable
[AlwaysOn CPU Profiling](https://docs.splunk.com/Observability/apm/profiling/get-data-in-profiling.html). Default: `false`.

### enable_profiler_memory (optional)

Set this value to `true` to pass `-Dsplunk.profiler.memory.enabled=true` to the starting Java executable, which will enable
[AlwaysOn Memory Profiling](https://docs.splunk.com/Observability/apm/profiling/get-data-in-profiling.html). Default: `false`.

### enable_metrics (optional)

Set this value to `true` to pass `-Dsplunk.metrics.enabled=true` to the starting Java executable, which will enable
[exporting metrics](https://github.com/signalfx/splunk-otel-java/blob/main/docs/metrics.md). Default: `false`.

### Syntax

To add a comment or comment out a line, start it with a `#`.
Expand All @@ -79,7 +104,8 @@ This environment variable contains a `-javaagent` flag set to the full path of t

e.g. `JAVA_TOOL_OPTIONS='-javaagent:/usr/lib/splunk-instrumentation/splunk-otel-javaagent.jar'`

This variable is populated by the .so by concatenating the `java_agent_jar` attribute the config to a `-javaagent:` prefix.
This variable is populated by the .so by concatenating the `java_agent_jar` attribute in the config to a `-javaagent:`
prefix, and then appending any additional system properties specified in the configuration file.

#### OTEL_SERVICE_NAME

Expand Down
10 changes: 9 additions & 1 deletion instrumentation/install/instrumentation.conf
Original file line number Diff line number Diff line change
@@ -1,2 +1,10 @@
# service_name=default.service
java_agent_jar=/usr/lib/splunk-instrumentation/splunk-otel-javaagent.jar
#resource_attributes=deployment.environment=my.environment
#service_name=hardcoded.service

# note: any of the the following lines may be uncommented to override defaults
#disable_telemetry=true
#generate_service_name=false
#enable_profiler=true
#enable_profiler_memory=true
#enable_metrics=true
62 changes: 42 additions & 20 deletions instrumentation/src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,28 @@ void read_lines(struct config *cfg, FILE *fp);

void split_on_eq(char *string, struct kv *pair);

void log_config_field(logger log, const char *field, const char *value);

void load_config(logger log, struct config *cfg, char *file_name) {
read_config_file(log, cfg, file_name);
if (cfg->service_name == NULL) {
log_debug(log, "service_name not specified in config");
}
if (cfg->java_agent_jar == NULL) {
log_debug(log, "java_agent_jar not specified in config");
}
if (cfg->resource_attributes == NULL) {
log_debug(log, "resource_attributes not specified in config");
}
if (cfg->disable_telemetry == NULL) {
log_debug(log, "disable_telemetry not specified in config");
}
if (cfg->generate_service_name == NULL) {
log_debug(log, "generate_service_name not specified in config");
log_config_field(log, "service_name", cfg->service_name);
log_config_field(log, "java_agent_jar", cfg->java_agent_jar);
log_config_field(log, "resource_attributes", cfg->resource_attributes);
log_config_field(log, "disable_telemetry", cfg->disable_telemetry);
log_config_field(log, "generate_service_name", cfg->generate_service_name);
log_config_field(log, "enable_profiler", cfg->enable_profiler);
log_config_field(log, "enable_profiler_memory", cfg->enable_profiler_memory);
log_config_field(log, "enable_metrics", cfg->enable_metrics);
}

void log_config_field(logger log, const char *field, const char *value) {
char msg[MAX_LOG_LINE_LEN] = "";
if (value == NULL) {
snprintf(msg, MAX_LOG_LINE_LEN, "config: %s not specified", field);
} else {
snprintf(msg, MAX_LOG_LINE_LEN, "config: %s=%s", field, value);
}
log_debug(log, msg);
}

void read_config_file(logger log, struct config *cfg, char *file_name) {
Expand Down Expand Up @@ -68,6 +73,12 @@ void read_lines(struct config *cfg, FILE *fp) {
cfg->disable_telemetry = strdup(pair.v);
} else if (streq(pair.k, "generate_service_name")) {
cfg->generate_service_name = strdup(pair.v);
} else if (streq(pair.k, "enable_profiler")) {
cfg->enable_profiler = strdup(pair.v);
} else if (streq(pair.k, "enable_profiler_memory")) {
cfg->enable_profiler_memory = strdup(pair.v);
} else if (streq(pair.k, "enable_metrics")) {
cfg->enable_metrics = strdup(pair.v);
}
}
}
Expand All @@ -77,12 +88,14 @@ void split_on_eq(char *string, struct kv *pair) {
pair->v = string;
}

bool str_eq_true(char *v) {
return v != NULL && !streq("false", v) && !streq("FALSE", v) && !streq("0", v);
}

bool str_eq_false(char *v) {
return v != NULL && (streq("false", v) || streq("FALSE", v) || streq("0", v));
bool str_to_bool(char *v, bool defaultVal) {
if (v == NULL) {
return defaultVal;
}
if (streq("false", v) || streq("FALSE", v) || streq("0", v)) {
return false;
}
return true;
}

void free_config(struct config *cfg) {
Expand All @@ -101,4 +114,13 @@ void free_config(struct config *cfg) {
if (cfg->generate_service_name != NULL) {
free(cfg->generate_service_name);
}
if (cfg->enable_profiler != NULL) {
free(cfg->enable_profiler);
}
if (cfg->enable_profiler_memory != NULL) {
free(cfg->enable_profiler_memory);
}
if (cfg->enable_metrics != NULL) {
free(cfg->enable_metrics);
}
}
7 changes: 4 additions & 3 deletions instrumentation/src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ struct config {
char *resource_attributes;
char *disable_telemetry;
char *generate_service_name;
char *enable_profiler;
char *enable_profiler_memory;
char *enable_metrics;
};

void load_config(logger log, struct config *cfg, char *file_name);

bool str_eq_true(char *v);

bool str_eq_false(char *v);
bool str_to_bool(char *v, bool);

void free_config(struct config *cfg);

Expand Down
34 changes: 26 additions & 8 deletions instrumentation/src/splunk.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@
#include <unistd.h>
#include <stdio.h>

#define ENV_VAR_LEN 512
#define MAX_ENV_VAR_LEN 512
pmcollins marked this conversation as resolved.
Show resolved Hide resolved
#define MAX_CONFIG_ATTR_LEN 256
#define MAX_CMDLINE_LEN 16000
#define MAX_ARGS 256

#define JAVA_TOOL_OPTIONS_PREFIX "-javaagent:";

static char *const conf_file = "/usr/lib/splunk-instrumentation/instrumentation.conf";
static char *const prof_enabled_cmdline_switch = " -Dsplunk.profiler.enabled=true";
static char *const prof_memory_enabled_cmdline_switch = " -Dsplunk.profiler.memory.enabled=true";
static char *const metrics_enabled_cmdline_switch = " -Dsplunk.metrics.enabled=true";

extern char *program_invocation_short_name;

Expand Down Expand Up @@ -73,7 +76,11 @@ void auto_instrument(
.java_agent_jar = NULL,
.resource_attributes = NULL,
.service_name = NULL,
.disable_telemetry = NULL
.disable_telemetry = NULL,
.generate_service_name = NULL,
.enable_profiler = NULL,
.enable_profiler_memory = NULL,
.enable_metrics = NULL
};
load_config_func(log, &cfg, conf_file);
if (cfg.java_agent_jar == NULL) {
Expand All @@ -87,22 +94,22 @@ void auto_instrument(
}

char service_name[MAX_CMDLINE_LEN] = "";
if (str_eq_false(cfg.generate_service_name)) {
log_debug(log, "service name generation disabled");
} else {
if (str_to_bool(cfg.generate_service_name, true)) {
get_service_name(log, cr, &cfg, service_name);
if (strlen(service_name) == 0) {
log_info(log, "service name empty, quitting");
return;
}
set_env_var(log, otel_service_name_var, service_name);
} else {
log_debug(log, "service name generation explicitly disabled");
}

set_java_tool_options(log, &cfg);

set_env_var_from_attr(log, "resource_attributes", resource_attributes_var, cfg.resource_attributes);

if (str_eq_true(cfg.disable_telemetry)) {
if (str_to_bool(cfg.disable_telemetry, false)) {
log_info(log, "disabling telemetry as per config");
} else {
send_otlp_metric_func(log, service_name);
Expand Down Expand Up @@ -148,15 +155,26 @@ void set_env_var(logger log, const char *var_name, const char *value) {
}

void set_java_tool_options(logger log, struct config *cfg) {
char java_tool_options[ENV_VAR_LEN] = JAVA_TOOL_OPTIONS_PREFIX;
char java_tool_options[MAX_ENV_VAR_LEN] = JAVA_TOOL_OPTIONS_PREFIX;
char log_line[MAX_LOG_LINE_LEN] = "";
size_t jar_path_len = strlen(cfg->java_agent_jar);
if (jar_path_len > MAX_CONFIG_ATTR_LEN) {
sprintf(log_line, "jar_path too long: got %zu chars, max %d chars", jar_path_len, MAX_CONFIG_ATTR_LEN);
log_warning(log, log_line);
return;
}
strcat(java_tool_options, (*cfg).java_agent_jar);
strncat(java_tool_options, cfg->java_agent_jar, MAX_ENV_VAR_LEN - strlen(java_tool_options) - 1);
rmfitzpatrick marked this conversation as resolved.
Show resolved Hide resolved

if (str_to_bool(cfg->enable_profiler, false)) {
strncat(java_tool_options, prof_enabled_cmdline_switch, MAX_ENV_VAR_LEN - strlen(java_tool_options) - 1);
}
if (str_to_bool(cfg->enable_profiler_memory, false)) {
strncat(java_tool_options, prof_memory_enabled_cmdline_switch, MAX_ENV_VAR_LEN - strlen(java_tool_options) - 1);
}
if (str_to_bool(cfg->enable_metrics, false)) {
strncat(java_tool_options, metrics_enabled_cmdline_switch, MAX_ENV_VAR_LEN - strlen(java_tool_options) - 1);
}

sprintf(log_line, "setting JAVA_TOOL_OPTIONS='%s'", java_tool_options);
log_debug(log, log_line);
setenv(java_tool_options_var, java_tool_options, 0);
Expand Down
Loading