# OpenTelemetry Injector

Copy as Markdown[Open in ChatGPT](https://chatgpt.com/?q=Read%20https%3A%2F%2Fcoralogix.com%2Fdocs%2Fopentelemetry%2Fstandalone-installation%2Fopentelemetry-injector.md%20and%20help%20me%20with%20my%20question%20about%20this%20Coralogix%20documentation%20page.)[Open in Claude](https://claude.ai/new?q=Read%20https%3A%2F%2Fcoralogix.com%2Fdocs%2Fopentelemetry%2Fstandalone-installation%2Fopentelemetry-injector.md%20and%20help%20me%20with%20my%20question%20about%20this%20Coralogix%20documentation%20page.)

Use the [OpenTelemetry Injector](https://github.com/open-telemetry/opentelemetry-injector) to collect telemetry from applications that run directly on a Linux host, without changing application code, build pipelines, or start commands. It automatically loads the matching OpenTelemetry agent when an application starts. Depending on the language agent and its configuration, telemetry can include traces, metrics, and logs.

This page covers hosts managed with system packages: virtual machines, bare metal, and cloud instances. For Kubernetes workloads, use [OpenTelemetry AutoInstrumentation for Kubernetes](https://coralogix.com/docs/opentelemetry/kubernetes-observability/opentelemetry-autoinstrumentation.md) instead.

Note

The OpenTelemetry Injector and its system packages are maintained by the OpenTelemetry community. Test them in a staging environment before rolling them out to production hosts.

## How it works[​](#how-it-works "Direct link to How it works")

Linux's dynamic loader loads shared libraries when a program starts. Preloading tells it to load an additional library before application code runs: `LD_PRELOAD` sets this for selected processes, while `/etc/ld.so.preload` applies it system-wide. The injector uses this mechanism to load `libotelinject.so` and set the environment variables that activate the language agents. See the [Linux dynamic loader documentation](https://man7.org/linux/man-pages/man8/ld.so.8.html).

You start your application as usual. The injector does not choose or launch a language runtime; it sets environment variables that tell the runtime to load its installed, enabled agent. For example, when you run `java -jar myapp.jar`, the injector adds `-javaagent` to `JAVA_TOOL_OPTIONS`. The JVM reads that option and loads the Java agent before your application's `main()` runs. Node.js, Python, and .NET use their own startup settings, listed under [Supported runtimes](#supported-runtimes).

For .NET, the injector also checks the application's target framework and existing OpenTelemetry dependencies before setting the agent's startup variables. See [.NET application is skipped](#net-application-is-skipped) for the checks and configuration file locations.

1. Install the injector and the agents for your application's languages on the host.
2. Restart your applications. Each runtime loads its agent using the settings provided by the injector.
3. The agents send telemetry to the Coralogix OpenTelemetry Collector on the same host. The collector forwards it to your Coralogix account, alongside the host data enabled in your integration.

Set a name, version, and custom attributes for each service to identify its telemetry in Coralogix. See [Per-service settings](#per-service-settings).

## Supported runtimes[​](#supported-runtimes "Direct link to Supported runtimes")

| Runtime | Package                                    | Variable set by the injector                     | Notes                                                                                  |
| ------- | ------------------------------------------ | ------------------------------------------------ | -------------------------------------------------------------------------------------- |
| Java    | `opentelemetry-java-autoinstrumentation`   | `JAVA_TOOL_OPTIONS`                              | Appends `-javaagent` for the OpenTelemetry Java agent                                  |
| Node.js | `opentelemetry-nodejs-autoinstrumentation` | `NODE_OPTIONS`                                   | Appends `--require` for `@opentelemetry/auto-instrumentations-node`                    |
| .NET    | `opentelemetry-dotnet-autoinstrumentation` | `CORECLR_*`, `DOTNET_*`, `OTEL_DOTNET_AUTO_HOME` | .NET 8 and later. Skipped when the application already ships OpenTelemetry packages    |
| Python  | `opentelemetry-python-autoinstrumentation` | `PYTHONPATH`                                     | Python 3.10 and later. See [Python dependency conflicts](#python-dependency-conflicts) |

The injector supports `amd64` and `arm64` hosts with glibc or musl. These are implementations of the C standard library (`libc`), which provides common functions such as memory allocation and file access. The injector detects which implementation the process uses. The system packages in this guide target glibc-based Debian and RHEL families.

## What you need[​](#what-you-need "Direct link to What you need")

* A Linux host running Debian, Ubuntu, RHEL, Fedora, Amazon Linux, or a derivative, with root access
* The Coralogix OpenTelemetry Collector installed on the host with the OTLP receiver enabled. Follow [Standalone complete observability: basic configuration](https://coralogix.com/docs/opentelemetry/standalone-installation/standalone-complete-observability-configuration.md) first. The installer listens on `127.0.0.1:4317` (gRPC) and `127.0.0.1:4318` (HTTP) by default
* Applications that use one of the [supported runtimes](#supported-runtimes): Java, Node.js, .NET, or Python

## Install the injector[​](#install-the-injector "Direct link to Install the injector")

:::warning Security considerations The preload library runs inside each affected process with that process's privileges, including root privileges for processes running as root. A faulty or compromised library can affect application behavior or startup across the host. Install packages only from a source you trust, and restrict write access to `/etc/ld.so.preload`, the injector configuration, and installed injector and agent files to administrators.

The repository commands below bypass repository authentication with `trusted=yes` and RPM package signature checks with `gpgcheck=0`. Review this trust requirement against your organization's software supply-chain policy before deployment. Per-service opt-out settings control instrumentation; they do not prevent the loader from loading the preload library. :::

### 1. Add the OpenTelemetry package repository[​](#1-add-the-opentelemetry-package-repository "Direct link to 1. Add the OpenTelemetry package repository")

On Debian and Ubuntu:

```
echo "deb [trusted=yes] https://open-telemetry.github.io/opentelemetry-packaging/debian stable main" \

  | sudo tee /etc/apt/sources.list.d/opentelemetry.list

sudo apt update
```

On RHEL, Fedora, Amazon Linux, and derivatives:

```
cat <<EOT | sudo tee /etc/yum.repos.d/opentelemetry.repo

[opentelemetry]

name=OpenTelemetry Auto-Instrumentation System Packages

baseurl=https://open-telemetry.github.io/opentelemetry-packaging/rpm/packages

enabled=1

gpgcheck=0

EOT
```

### 2. Install the packages[​](#2-install-the-packages "Direct link to 2. Install the packages")

Install the `opentelemetry` metapackage to get the injector and all language agents:

```
sudo apt install opentelemetry        # Debian, Ubuntu

sudo dnf install opentelemetry        # RHEL, Fedora, Amazon Linux
```

To limit the install to the runtimes you use, install `opentelemetry-injector` plus the language packages you need. For example, for Java only:

```
sudo apt install opentelemetry-injector opentelemetry-java-autoinstrumentation
```

The package post-install step writes the library path to `/etc/ld.so.preload`. Confirm it:

```
cat /etc/ld.so.preload

# /usr/lib/opentelemetry/injector/libotelinject.so
```

### 3. Use the local collector[​](#3-use-the-local-collector "Direct link to 3. Use the local collector")

Complete the [Host OpenTelemetry integration setup](https://coralogix.com/docs/opentelemetry/standalone-installation/standalone-complete-observability-configuration.md#installation) first, including your Send-Your-Data API key, application name, and subsystem name. Deploy the generated collector configuration on the same host as your applications. Its default OTLP receiver accepts logs, metrics, and traces.

With the default agent settings, no exporter configuration is needed. Agents send telemetry to `localhost` on port `4317` (gRPC) or `4318` (HTTP), and the Host integration accepts both. If your applications already override OTLP settings, remove those overrides to use the defaults.

If you need to customize the endpoint or protocol, set the values in `/etc/opentelemetry/injector/default_env.conf`. For example, the following optional configuration explicitly selects the local HTTP receiver:

```
OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4318

OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
```

This file provides shared `OTEL_` settings for all instrumented applications. The example is not required for the default Host integration. When customizing it, match the endpoint and protocol to your collector's receiver configuration, then restart the affected applications.

The collector handles authentication and forwarding to your Coralogix account. Keep the Coralogix API key in the integration's collector setup; agents do not need Coralogix authentication headers for this local endpoint.

Set `OTEL_SERVICE_NAME` separately for each application, for example `checkout`, as shown in [Per-service settings](#per-service-settings). This makes each service identifiable in Coralogix. Use the [agent configuration guides](#related-resources) to enable or customize the signals supported by your language agent.

### 4. Restart the applications[​](#4-restart-the-applications "Direct link to 4. Restart the applications")

The injector only affects processes started after it was installed. Restart each service you want to instrument:

```
sudo systemctl restart <service-name>
```

New processes started from a shell are instrumented automatically.

## Verify the instrumentation[​](#verify-the-instrumentation "Direct link to Verify the instrumentation")

1. Confirm that the injector modified the environment of a running service. For a Java service, the JVM prints the agent flag on startup:

   ```
   journalctl -u <service-name> | grep JAVA_TOOL_OPTIONS

   # Picked up JAVA_TOOL_OPTIONS: -javaagent:/usr/lib/opentelemetry/java/opentelemetry-javaagent.jar
   ```

   For any runtime, start a short-lived process and read its environment. The injector sets the variables with `setenv` after the process starts, so `/proc/<pid>/environ` does not show them.

   ```
   node -e 'console.log(process.env.NODE_OPTIONS)'

   # --require /usr/lib/opentelemetry/nodejs/register.js
   ```

2. Generate traffic to the application.

3. In Coralogix, open **Explore** and select the `spans` dataset. Set the time range to include your test traffic and filter by your service name. Confirm that spans from your application appear. See [Get started with Explore spans](https://coralogix.com/docs/user-guides/data_exploration/spans/explore-spans.md).

## Per-service settings[​](#per-service-settings "Direct link to Per-service settings")

The injector reads a set of `OTEL_INJECTOR_*` variables from the environment of each process. Set them where the service is defined, for example with `Environment=` in a systemd unit. They are not read from `default_env.conf`.

| Variable                                      | Effect                                                                                                                        |
| --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `OTEL_INJECTOR_SERVICE_NAME`                  | Adds `service.name` to `OTEL_RESOURCE_ATTRIBUTES`. Setting `OTEL_SERVICE_NAME` directly works too                             |
| `OTEL_INJECTOR_SERVICE_VERSION`               | Adds `service.version`                                                                                                        |
| `OTEL_INJECTOR_SERVICE_NAMESPACE`             | Adds `service.namespace`, which the Coralogix Collector uses as the application name                                          |
| `OTEL_INJECTOR_RESOURCE_ATTRIBUTES`           | Comma-separated `key=value` pairs added as they are, for example `deployment.environment.name=production`                     |
| `OTEL_INJECTOR_DISABLED=true`                 | Turns the injector off for this process. No environment variable is changed                                                   |
| `OTEL_INJECTOR_AUTO_INSTRUMENTATION_DISABLED` | `*` to skip all agents, or a comma-separated list of `dotnet`, `jvm`, `nodejs`, `python`. Resource attributes are still added |

Example systemd unit for a Node.js service:

```
[Service]

ExecStart=/usr/bin/node /opt/checkout/server.js

Environment=OTEL_SERVICE_NAME=checkout

Environment=OTEL_INJECTOR_SERVICE_VERSION=2.4.1

Environment=OTEL_INJECTOR_RESOURCE_ATTRIBUTES=deployment.environment.name=production
```

To instrument only some programs on a host, set include or exclude patterns in `/etc/opentelemetry/injector/injector.conf` or as environment variables. Patterns are globs matched against the executable path or the command-line arguments:

| Setting                  | Environment variable                   |
| ------------------------ | -------------------------------------- |
| `include_paths`          | `OTEL_INJECTOR_INCLUDE_PATHS`          |
| `exclude_paths`          | `OTEL_INJECTOR_EXCLUDE_PATHS`          |
| `include_with_arguments` | `OTEL_INJECTOR_INCLUDE_WITH_ARGUMENTS` |
| `exclude_with_arguments` | `OTEL_INJECTOR_EXCLUDE_WITH_ARGUMENTS` |

To disable a runtime for the whole host, add `auto_instrumentation_disabled=<runtime>` to `injector.conf`.

## Troubleshooting[​](#troubleshooting "Direct link to Troubleshooting")

### No traces from a service[​](#no-traces-from-a-service "Direct link to No traces from a service")

* Check that the service was restarted after the packages were installed.
* Run the process once with `OTEL_INJECTOR_LOG_LEVEL=debug` to see what the injector decided. Keep the default level (`error`) on the host; at `info` or `debug` every process on the host logs to standard error.
* Check the collector health status with `curl -s http://127.0.0.1:13133`.
* Confirm that the application uses one of the [supported runtimes](#supported-runtimes) and meets its version requirements.

### Python dependency conflicts[​](#python-dependency-conflicts "Direct link to Python dependency conflicts")

The Python agent ships its own pinned dependencies and refuses to activate when the interpreter already has a different version of one of them, to avoid breaking the application. The process then logs:

```
[opentelemetry-python-autoinstrumentation] WARN: cannot auto-instrument Python process: dependency conflicts: {...}
```

This happens on distribution interpreters that carry system packages such as `python3-attr` or `python3-yaml`. Run the application from its own virtual environment created with `python3 -m venv`, which excludes system site packages.

### .NET application is skipped[​](#net-application-is-skipped "Direct link to .NET application is skipped")

Before setting the .NET profiler and startup-hook environment variables, the injector checks two files beside the application:

* `<app-name>.runtimeconfig.json`: Reads the target framework from `runtimeOptions.tfm` and skips injection when it identifies a version older than .NET 8 by default.
* `<app-name>.deps.json`: Checks for `OpenTelemetry*` dependencies and skips injection when they are present, to reduce the risk of double instrumentation.

The .NET SDK generates these files from the project's framework settings and dependencies during the application build. For a standard deployment, [`dotnet publish`](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-publish) includes them in the publish output alongside the application DLL. For example, `Checkout.dll`, `Checkout.runtimeconfig.json`, and `Checkout.deps.json` are deployed together in the application's directory. These are application files, not injector configuration files; you do not need to create them for the injector.

These checks are best-effort: missing, unreadable, or malformed files do not by themselves prevent injection. If neither check causes the injector to skip the application, it sets the startup variables and the .NET runtime loads the agent. See the [upstream injector design](https://github.com/open-telemetry/opentelemetry-injector/blob/main/DESIGN.md#design).

Set `DOTNET_AUTO_INSTRUMENTATION_MINIMUM_DOTNET_MAJOR_VERSION` only if you ship a .NET auto-instrumentation build that supports older runtimes.

## Limitations[​](#limitations "Direct link to Limitations")

* Linux only.
* The system packages are built for Debian and RHEL families on `amd64` and `arm64`. Alpine and other musl-based distributions are not packaged.
* .NET does not support more than one agent. The injector overwrites the .NET profiler variables if they are already set.

## Related resources[​](#related-resources "Direct link to Related resources")

|                          |                                                                                                                                                                                                                                                                                                 |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Coralogix host collector | [Standalone complete observability: basic configuration](https://coralogix.com/docs/opentelemetry/standalone-installation/standalone-complete-observability-configuration.md)                                                                                                                   |
| Kubernetes workloads     | [OpenTelemetry AutoInstrumentation for Kubernetes](https://coralogix.com/docs/opentelemetry/kubernetes-observability/opentelemetry-autoinstrumentation.md)                                                                                                                                      |
| Compiled languages       | [eBPF auto-instrumentation](https://coralogix.com/docs/opentelemetry/instrumentation-options/ebpf-auto-instrumentation/overview.md)                                                                                                                                                             |
| OpenTelemetry Injector   | [GitHub repository](https://github.com/open-telemetry/opentelemetry-injector)                                                                                                                                                                                                                   |
| System packages          | [OpenTelemetry packaging](https://github.com/open-telemetry/opentelemetry-packaging)                                                                                                                                                                                                            |
| Agent configuration      | [Java](https://opentelemetry.io/docs/zero-code/java/agent/configuration/), [Node.js](https://opentelemetry.io/docs/zero-code/js/configuration/), [.NET](https://opentelemetry.io/docs/zero-code/dotnet/configuration/), [Python](https://opentelemetry.io/docs/zero-code/python/configuration/) |
