From 881058b60d9ea678dc2ddedfc2c9b0d24426b603 Mon Sep 17 00:00:00 2001 From: Antoine Toulme Date: Sat, 27 Jan 2024 00:16:57 -0800 Subject: [PATCH] Add puppet support for Node.js auto-instrumentation on Linux --- deployments/puppet/CHANGELOG.md | 7 +++++ deployments/puppet/README.md | 2 ++ deployments/puppet/manifests/init.pp | 29 +++++++++++++++++++ ...-splunk-otel-auto-instrumentation.conf.erb | 5 ++++ deployments/puppet/templates/node.conf.erb | 13 +++++++++ .../tests/deployments/puppet/puppet_test.py | 19 ++++++++++++ 6 files changed, 75 insertions(+) create mode 100644 deployments/puppet/templates/node.conf.erb diff --git a/deployments/puppet/CHANGELOG.md b/deployments/puppet/CHANGELOG.md index 86e793058e..35525a733a 100644 --- a/deployments/puppet/CHANGELOG.md +++ b/deployments/puppet/CHANGELOG.md @@ -4,6 +4,13 @@ - On Windows the `SPLUNK_*` environment variables were moved from the machine scope to the collector service scope. It is possible that some instrumentations are relying on the machine-wide environment variables set by the installation. ([#3930](https://github.com/signalfx/splunk-otel-collector/pull/3930)) +- Initial support for [Splunk OpenTelemetry for Node.js](https://github.com/signalfx/splunk-otel-js) Auto + Instrumentation on Linux: + - The Node.js SDK is installed and activated by default if the `with_auto_instrumentation` option is set to `true` + and `npm` is found on the node with the `bash -c 'command -v npm'` shell command. + - Set the `with_auto_instrumentation_sdks` option to only `['java']` to skip Node.js auto instrumentation. + - Use the `auto_instrumentation_npm_path` option to specify a custom path for `npm`. + - **Note:** This cookbook does not manage the installation/configuration of Node.js, `npm`, or Node.js applications. ## puppet-v0.12.0 diff --git a/deployments/puppet/README.md b/deployments/puppet/README.md index 1356fa1449..201a3d0e2d 100644 --- a/deployments/puppet/README.md +++ b/deployments/puppet/README.md @@ -90,6 +90,8 @@ configuration changes in order for auto instrumentation to take effect. | Name | Description | Default value | |:------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------| | `with_auto_instrumentation` | **Linux only**: Whether to install/manage [Splunk OpenTelemetry Auto Instrumentation for Java](https://github.com/signalfx/splunk-otel-collector/tree/main/instrumentation). When set to `true`, the `splunk-otel-auto-instrumentation` deb/rpm package will be downloaded and installed from the Collector repository. | `false` | +| `with_auto_instrumentation_sdks` | **Linux only**: Which SDKs to install. Defaults to ['java','nodejs'] | +| `auto_instrumentation_npm_path` | **Linux only**: The path to the `npm` executable used for installation of the splunk-otel-js Node.js package. Defaults to `npm` | | `auto_instrumentation_version` | **Linux only**: Version of the `splunk-otel-auto-instrumentation` package to install, e.g. `0.50.0`. The minimum supported version is `0.48.0`. | `latest` | | `auto_instrumentation_systemd` | **Linux only**: By default, the `/etc/ld.so.preload` file on the node will be configured for the `/usr/lib/splunk-instrumentation/libsplunk.so` [shared object library](https://github.com/signalfx/splunk-otel-collector/tree/main/instrumentation) provided by the `splunk-otel-auto-instrumentation` package to activate and configure auto instrumentation system-wide for all supported applications. Alternatively, set this option to `true` to activate and configure auto instrumentation ***only*** for supported applications running as `systemd` services. If this option is set to `true`, `/usr/lib/splunk-instrumentation/libsplunk.so` will not be added to `/etc/ld.so.preload`. Instead, the `/usr/lib/systemd/system.conf.d/00-splunk-otel-auto-instrumentation.conf` `systemd` drop-in file will be created and configured for environment variables based on the default and specified options. | `false` | | `auto_instrumentation_ld_so_preload` | **Linux only**: Configure this variable to include additional library paths, e.g. `/path/to/my.library.so`, to `/etc/ld.so.preload`. | None | diff --git a/deployments/puppet/manifests/init.pp b/deployments/puppet/manifests/init.pp index 64bce1d660..c8e20edbb5 100644 --- a/deployments/puppet/manifests/init.pp +++ b/deployments/puppet/manifests/init.pp @@ -46,6 +46,8 @@ $auto_instrumentation_enable_profiler_memory = false, # linux only $auto_instrumentation_enable_metrics = false, # linux only $auto_instrumentation_otlp_endpoint = 'http://127.0.0.1:4317', # linux only + $with_auto_instrumentation_sdks = ['java', 'nodejs'], # linux only + $auto_instrumentation_npm_path = 'npm', # linux only $collector_additional_env_vars = {} ) inherits splunk_otel_collector::params { @@ -368,6 +370,7 @@ $libsplunk_path = '/usr/lib/splunk-instrumentation/libsplunk.so' $instrumentation_config_path = '/usr/lib/splunk-instrumentation/instrumentation.conf' $zeroconfig_java_config_path = '/etc/splunk/zeroconfig/java.conf' + $zeroconfig_node_config_path = '/etc/splunk/zeroconfig/node.conf' $zeroconfig_systemd_config_path = '/usr/lib/systemd/system.conf.d/00-splunk-otel-auto-instrumentation.conf' if $::osfamily == 'debian' { @@ -409,6 +412,32 @@ ensure => file, content => template('splunk_otel_collector/java.conf.erb'), require => Package[$auto_instrumentation_package_name], + onlyif => 'java' in $with_auto_instrumentation_sdks + } + $splunk_otel_js_path = '/usr/lib/splunk-instrumentation/splunk-otel-js.tgz' + $splunk_otel_js_prefix = '/usr/lib/splunk-instrumentation/splunk-otel-js' + + exec { 'Check npm is present': + command => "bash -c 'command -v ${$auto_instrumentation_npm_path}'", + provider => shell, + onlyif => 'nodejs' in $with_auto_instrumentation_sdks + } + + file { "${$splunk_otel_js_prefix}/node_modules": + ensure => 'directory', + onlyif => 'nodejs' in $with_auto_instrumentation_sdks, + } + exec { 'Install splunk-otel-js': + command => "${$auto_instrumentation_npm_path} install ${$splunk_otel_js_path}", + provider => shell, + onlyif => 'nodejs' in $with_auto_instrumentation_sdks, + cwd => $splunk_otel_js_prefix, + } + file { $zeroconfig_node_config_path: + ensure => file, + content => template('splunk_otel_collector/node.conf.erb'), + require => Package[$auto_instrumentation_package_name], + onlyif => 'nodejs' in $with_auto_instrumentation_sdks, } } else { file { $instrumentation_config_path: diff --git a/deployments/puppet/templates/00-splunk-otel-auto-instrumentation.conf.erb b/deployments/puppet/templates/00-splunk-otel-auto-instrumentation.conf.erb index ab30019876..e3e5309ff0 100644 --- a/deployments/puppet/templates/00-splunk-otel-auto-instrumentation.conf.erb +++ b/deployments/puppet/templates/00-splunk-otel-auto-instrumentation.conf.erb @@ -1,5 +1,10 @@ [Manager] +<% if @with_auto_instrumentation_sdks.include?('java') -%> DefaultEnvironment="JAVA_TOOL_OPTIONS=-javaagent:<%= @auto_instrumentation_java_agent_jar %>" +<% end -%> +<% if @with_auto_instrumentation_sdks.include?('nodejs') -%> +DefaultEnvironment="NODE_OPTIONS=-r /usr/lib/splunk-instrumentation/splunk-otel-js/node_modules/@splunk/otel/instrument" +<% end -%> <% if defined?(@auto_instrumentation_resource_attributes) && @auto_instrumentation_resource_attributes != "" -%> DefaultEnvironment="OTEL_RESOURCE_ATTRIBUTES=splunk.zc.method=splunk-otel-auto-instrumentation-<%= @auto_instrumentation_version %>-systemd,<%= @auto_instrumentation_resource_attributes %>" <% else -%> diff --git a/deployments/puppet/templates/node.conf.erb b/deployments/puppet/templates/node.conf.erb new file mode 100644 index 0000000000..b5a01591ea --- /dev/null +++ b/deployments/puppet/templates/node.conf.erb @@ -0,0 +1,13 @@ +NODE_OPTIONS=-r /usr/lib/splunk-instrumentation/splunk-otel-js/node_modules/@splunk/otel/instrument +<% if defined?(@auto_instrumentation_resource_attributes) && @auto_instrumentation_resource_attributes != "" -%> +OTEL_RESOURCE_ATTRIBUTES=splunk.zc.method=splunk-otel-auto-instrumentation-<%= @auto_instrumentation_version %>,<%= @auto_instrumentation_resource_attributes %> +<% else -%> +OTEL_RESOURCE_ATTRIBUTES=splunk.zc.method=splunk-otel-auto-instrumentation-<%= @auto_instrumentation_version %> +<% end -%> +<% if defined?(@auto_instrumentation_service_name) && @auto_instrumentation_service_name != "" -%> +OTEL_SERVICE_NAME=<%= @auto_instrumentation_service_name %> +<% end -%> +SPLUNK_PROFILER_ENABLED=<%= @auto_instrumentation_enable_profiler.to_s.downcase %> +SPLUNK_PROFILER_MEMORY_ENABLED=<%= @auto_instrumentation_enable_profiler_memory.to_s.downcase %> +SPLUNK_METRICS_ENABLED=<%= @auto_instrumentation_enable_metrics.to_s.downcase %> +OTEL_EXPORTER_OTLP_ENDPOINT=<%= @auto_instrumentation_otlp_endpoint %> diff --git a/internal/buildscripts/packaging/tests/deployments/puppet/puppet_test.py b/internal/buildscripts/packaging/tests/deployments/puppet/puppet_test.py index 8b82ca3052..85b3ae03b3 100644 --- a/internal/buildscripts/packaging/tests/deployments/puppet/puppet_test.py +++ b/internal/buildscripts/packaging/tests/deployments/puppet/puppet_test.py @@ -55,6 +55,7 @@ INSTRUMENTATION_CONFIG_PATH = "/usr/lib/splunk-instrumentation/instrumentation.conf" SYSTEMD_CONFIG_PATH = "/usr/lib/systemd/system.conf.d/00-splunk-otel-auto-instrumentation.conf" JAVA_CONFIG_PATH = "/etc/splunk/zeroconfig/java.conf" +NODE_CONFIG_PATH = "/etc/splunk/zeroconfig/node.conf" def run_puppet_apply(container, config): @@ -245,6 +246,15 @@ def test_puppet_with_default_instrumentation(distro, puppet_release, version, wi verify_config_file(container, config_path, "SPLUNK_PROFILER_MEMORY_ENABLED", "false") verify_config_file(container, config_path, "SPLUNK_METRICS_ENABLED", "false") verify_config_file(container, config_path, "OTEL_EXPORTER_OTLP_ENDPOINT", r"http://127.0.0.1:4317") + + config_path = SYSTEMD_CONFIG_PATH if with_systemd == "true" else NODE_CONFIG_PATH + verify_config_file(container, config_path, "NODE_OPTIONS", "-r /usr/lib/splunk-instrumentation/splunk-otel-js/node_modules/@splunk/otel/instrument") + verify_config_file(container, config_path, "OTEL_RESOURCE_ATTRIBUTES", resource_attributes) + verify_config_file(container, config_path, "OTEL_SERVICE_NAME", ".*", exists=False) + verify_config_file(container, config_path, "SPLUNK_PROFILER_ENABLED", "false") + verify_config_file(container, config_path, "SPLUNK_PROFILER_MEMORY_ENABLED", "false") + verify_config_file(container, config_path, "SPLUNK_METRICS_ENABLED", "false") + verify_config_file(container, config_path, "OTEL_EXPORTER_OTLP_ENDPOINT", r"http://127.0.0.1:4317") else: config_path = INSTRUMENTATION_CONFIG_PATH verify_package_version(container, "splunk-otel-auto-instrumentation", version) @@ -322,6 +332,15 @@ def test_puppet_with_custom_instrumentation(distro, puppet_release, version, wit verify_config_file(container, config_path, "SPLUNK_PROFILER_MEMORY_ENABLED", "true") verify_config_file(container, config_path, "SPLUNK_METRICS_ENABLED", "true") verify_config_file(container, config_path, "OTEL_EXPORTER_OTLP_ENDPOINT", r"http://0.0.0.0:4317") + + config_path = SYSTEMD_CONFIG_PATH if with_systemd == "true" else NODE_CONFIG_PATH + verify_config_file(container, config_path, "NODE_OPTIONS", "-r /usr/lib/splunk-instrumentation/splunk-otel-js/node_modules/@splunk/otel/instrument") + verify_config_file(container, config_path, "OTEL_RESOURCE_ATTRIBUTES", resource_attributes) + verify_config_file(container, config_path, "OTEL_SERVICE_NAME", "test") + verify_config_file(container, config_path, "SPLUNK_PROFILER_ENABLED", "true") + verify_config_file(container, config_path, "SPLUNK_PROFILER_MEMORY_ENABLED", "true") + verify_config_file(container, config_path, "SPLUNK_METRICS_ENABLED", "true") + verify_config_file(container, config_path, "OTEL_EXPORTER_OTLP_ENDPOINT", r"http://0.0.0.0:4317") else: config_path = INSTRUMENTATION_CONFIG_PATH verify_package_version(container, "splunk-otel-auto-instrumentation", version)