# Exporters

> Process and export your telemetry data

---

LLMS index: [llms.txt](/llms.txt)

---

Send telemetry to the [OpenTelemetry Collector](/docs/collector/) to make sure
it's exported correctly. Using the Collector in production environments is a
best practice. To visualize your telemetry, export it to a backend such as
[Jaeger](https://jaegertracing.io/), [Zipkin](https://zipkin.io/),
[Prometheus](https://prometheus.io/), or a
[vendor-specific](/ecosystem/vendors/) backend.



## Available exporters

The registry contains a [list of exporters for JavaScript][reg].





Among exporters, [OpenTelemetry Protocol (OTLP)][OTLP] exporters are designed
with the OpenTelemetry data model in mind, emitting OTel data without any loss
of information. Furthermore, many tools that operate on telemetry data support
OTLP (such as [Prometheus][], [Jaeger][], and most [vendors][]), providing you
with a high degree of flexibility when you need it. To learn more about OTLP,
see [OTLP Specification][OTLP].

[Jaeger]: /blog/2022/jaeger-native-otlp/
[OTLP]: /docs/specs/otlp/
[Prometheus]:
  https://prometheus.io/docs/prometheus/2.55/feature_flags/#otlp-receiver
[reg]: </ecosystem/registry/?component=exporter&language=js>
[vendors]: /ecosystem/vendors/



This page covers the main OpenTelemetry JavaScript exporters and how to set
them up.





> [!NOTE]
>
> If you use [zero-code instrumentation](</docs/zero-code/js>),
> you can learn how to set up exporters by following the
> [Configuration Guide](</docs/zero-code/js/configuration/>).





## OTLP

### Collector Setup

> [!NOTE]
>
> If you have a OTLP collector or backend already set up, you can skip this
> section and [setup the OTLP exporter dependencies](#otlp-dependencies) for
> your application.

To try out and verify your OTLP exporters, you can run the collector in a docker
container that writes telemetry directly to the console.

In an empty directory, create a file called `collector-config.yaml` with the
following content:

```yaml
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318
exporters:
  debug:
    verbosity: detailed
service:
  pipelines:
    traces:
      receivers: [otlp]
      exporters: [debug]
    metrics:
      receivers: [otlp]
      exporters: [debug]
    logs:
      receivers: [otlp]
      exporters: [debug]
```

Now run the collector in a docker container:

```shell
docker run -p 4317:4317 -p 4318:4318 --rm -v $(pwd)/collector-config.yaml:/etc/otelcol/config.yaml otel/opentelemetry-collector
```

This collector is now able to accept telemetry via OTLP. Later you may want to
[configure the collector](/docs/collector/configuration) to send your telemetry
to your observability backend.


{{__hugo_ctx/}}


## Dependencies {#otlp-dependencies}

If you want to send telemetry data to an OTLP endpoint (like the
[OpenTelemetry Collector](#collector-setup), [Jaeger](#jaeger) or
[Prometheus](#prometheus)), you can choose between three different protocols to
transport your data:

- [HTTP/protobuf](https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-proto)
- [HTTP/JSON](https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-http)
- [gRPC](https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-grpc)

Start by installing the respective exporter packages as a dependency for your
project:

    <ul class="nav nav-tabs" id="tabs-1" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-01-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-01-00" role="tab"
          data-td-tp-persist="http/proto" aria-controls="tabs-01-00" aria-selected="true">
        HTTP/Proto
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-01-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-01-01" role="tab"
          data-td-tp-persist="http/json" aria-controls="tabs-01-01" aria-selected="false">
        HTTP/JSON
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-01-02-tab" data-bs-toggle="tab" data-bs-target="#tabs-01-02" role="tab"
          data-td-tp-persist="grpc" aria-controls="tabs-01-02" aria-selected="false">
        gRPC
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-1-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-01-00" role="tabpanel" aria-labelled-by="tabs-01-00-tab" tabindex="1">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">npm install --save @opentelemetry/exporter-trace-otlp-proto <span class="se">\
</span></span></span><span class="line"><span class="cl">  @opentelemetry/exporter-metrics-otlp-proto
</span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-01-01" role="tabpanel" aria-labelled-by="tabs-01-01-tab" tabindex="1">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">npm install --save @opentelemetry/exporter-trace-otlp-http <span class="se">\
</span></span></span><span class="line"><span class="cl">  @opentelemetry/exporter-metrics-otlp-http
</span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-01-02" role="tabpanel" aria-labelled-by="tabs-01-02-tab" tabindex="1">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">npm install --save @opentelemetry/exporter-trace-otlp-grpc <span class="se">\
</span></span></span><span class="line"><span class="cl">  @opentelemetry/exporter-metrics-otlp-grpc
</span></span></code></pre></div>
    </div>
</div>


## Usage with Node.js

Next, configure the exporter to point at an OTLP endpoint. For example you can
update the file `instrumentation.ts` (or `instrumentation.js` if you use
JavaScript) from the
[Getting Started](/docs/languages/js/getting-started/nodejs/) like the following
to export traces and metrics via OTLP (`http/protobuf`) :

   <ul class="nav nav-tabs" id="tabs-2" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-02-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-02-00" role="tab"
          data-td-tp-persist="typescript" aria-controls="tabs-02-00" aria-selected="true">
        TypeScript
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-02-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-02-01" role="tab"
          data-td-tp-persist="javascript" aria-controls="tabs-02-01" aria-selected="false">
        JavaScript
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-2-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-02-00" role="tabpanel" aria-labelled-by="tabs-02-00-tab" tabindex="2">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="cm">/*instrumentation.ts*/</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="o">*</span> <span class="kr">as</span> <span class="nx">opentelemetry</span> <span class="kr">from</span> <span class="s1">&#39;@opentelemetry/sdk-node&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">getNodeAutoInstrumentations</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@opentelemetry/auto-instrumentations-node&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">OTLPTraceExporter</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@opentelemetry/exporter-trace-otlp-proto&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">OTLPMetricExporter</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@opentelemetry/exporter-metrics-otlp-proto&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">PeriodicExportingMetricReader</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@opentelemetry/sdk-metrics&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">sdk</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">opentelemetry</span><span class="p">.</span><span class="nx">NodeSDK</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">traceExporter</span>: <span class="kt">new</span> <span class="nx">OTLPTraceExporter</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// optional - default url is http://localhost:4318/v1/traces
</span></span></span><span class="line"><span class="cl">    <span class="nx">url</span><span class="o">:</span> <span class="s1">&#39;&lt;your-otlp-endpoint&gt;/v1/traces&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// optional - collection of custom headers to be sent with each request, empty by default
</span></span></span><span class="line"><span class="cl">    <span class="nx">headers</span><span class="o">:</span> <span class="p">{},</span>
</span></span><span class="line"><span class="cl">  <span class="p">}),</span>
</span></span><span class="line"><span class="cl">  <span class="nx">metricReader</span>: <span class="kt">new</span> <span class="nx">PeriodicExportingMetricReader</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">    <span class="nx">exporter</span>: <span class="kt">new</span> <span class="nx">OTLPMetricExporter</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">      <span class="nx">url</span><span class="o">:</span> <span class="s1">&#39;&lt;your-otlp-endpoint&gt;/v1/metrics&#39;</span><span class="p">,</span> <span class="c1">// url is optional and can be omitted - default is http://localhost:4318/v1/metrics
</span></span></span><span class="line"><span class="cl">      <span class="nx">headers</span><span class="o">:</span> <span class="p">{},</span> <span class="c1">// an optional object containing custom headers to be sent with each request
</span></span></span><span class="line"><span class="cl">    <span class="p">}),</span>
</span></span><span class="line"><span class="cl">  <span class="p">}),</span>
</span></span><span class="line"><span class="cl">  <span class="nx">instrumentations</span><span class="o">:</span> <span class="p">[</span><span class="nx">getNodeAutoInstrumentations</span><span class="p">()],</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="nx">sdk</span><span class="p">.</span><span class="nx">start</span><span class="p">();</span>
</span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-02-01" role="tabpanel" aria-labelled-by="tabs-02-01-tab" tabindex="2">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="cm">/*instrumentation.js*/</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">opentelemetry</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;@opentelemetry/sdk-node&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">getNodeAutoInstrumentations</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;@opentelemetry/auto-instrumentations-node&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">OTLPTraceExporter</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;@opentelemetry/exporter-trace-otlp-proto&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">OTLPMetricExporter</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;@opentelemetry/exporter-metrics-otlp-proto&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">PeriodicExportingMetricReader</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;@opentelemetry/sdk-metrics&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">sdk</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">opentelemetry</span><span class="p">.</span><span class="nx">NodeSDK</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">traceExporter</span><span class="o">:</span> <span class="k">new</span> <span class="nx">OTLPTraceExporter</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// optional - default url is http://localhost:4318/v1/traces
</span></span></span><span class="line"><span class="cl">    <span class="nx">url</span><span class="o">:</span> <span class="s1">&#39;&lt;your-otlp-endpoint&gt;/v1/traces&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// optional - collection of custom headers to be sent with each request, empty by default
</span></span></span><span class="line"><span class="cl">    <span class="nx">headers</span><span class="o">:</span> <span class="p">{},</span>
</span></span><span class="line"><span class="cl">  <span class="p">}),</span>
</span></span><span class="line"><span class="cl">  <span class="nx">metricReader</span><span class="o">:</span> <span class="k">new</span> <span class="nx">PeriodicExportingMetricReader</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">    <span class="nx">exporter</span><span class="o">:</span> <span class="k">new</span> <span class="nx">OTLPMetricExporter</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">      <span class="nx">url</span><span class="o">:</span> <span class="s1">&#39;&lt;your-otlp-endpoint&gt;/v1/metrics&#39;</span><span class="p">,</span> <span class="c1">// url is optional and can be omitted - default is http://localhost:4318/v1/metrics
</span></span></span><span class="line"><span class="cl">      <span class="nx">headers</span><span class="o">:</span> <span class="p">{},</span> <span class="c1">// an optional object containing custom headers to be sent with each request
</span></span></span><span class="line"><span class="cl">      <span class="nx">concurrencyLimit</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span> <span class="c1">// an optional limit on pending requests
</span></span></span><span class="line"><span class="cl">    <span class="p">}),</span>
</span></span><span class="line"><span class="cl">  <span class="p">}),</span>
</span></span><span class="line"><span class="cl">  <span class="nx">instrumentations</span><span class="o">:</span> <span class="p">[</span><span class="nx">getNodeAutoInstrumentations</span><span class="p">()],</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="nx">sdk</span><span class="p">.</span><span class="nx">start</span><span class="p">();</span>
</span></span></code></pre></div>
    </div>
</div>


## Usage in the Browser

When you use the OTLP exporter in a browser-based application, you need to note
that:

1. Using gRPC for exporting is not supported
2. [Content Security Policies][] (CSPs) of your website might block your exports
3. [Cross-Origin Resource Sharing][] (CORS) headers might not allow your exports
   to be sent
4. You might need to expose your collector to the public internet

Below you will find instructions to use the right exporter, to configure your
CSPs and CORS headers and what precautions you have to take when exposing your
collector.

### Use OTLP exporter with HTTP/JSON or HTTP/protobuf

[OpenTelemetry Collector Exporter with gRPC][] works only with Node.js,
therefore you are limited to use the [OpenTelemetry Collector Exporter with
HTTP/JSON][] or [OpenTelemetry Collector Exporter with HTTP/protobuf][].

Make sure that the receiving end of your exporter (collector or observability
backend) accepts `http/json` if you are using [OpenTelemetry Collector Exporter
with HTTP/JSON][], and that you are exporting your data to the right endpoint
with your port set to 4318.

### Configure CSPs

If your website is making use of Content Security Policies (CSPs), make sure
that the domain of your OTLP endpoint is included. If your collector endpoint is
`https://collector.example.com:4318/v1/traces`, add the following directive:

```text
connect-src collector.example.com:4318/v1/traces
```

If your CSP is not including the OTLP endpoint, you will see an error message,
stating that the request to your endpoint is violating the CSP directive.

### Configure CORS headers

If your website and collector are hosted at a different origin, your browser
might block the requests going out to your collector. You need to configure
special headers for Cross-Origin Resource Sharing (CORS).

The OpenTelemetry Collector provides [a feature][] for http-based receivers to
add the required headers to allow the receiver to accept traces from a web
browser:

```yaml
receivers:
  otlp:
    protocols:
      http:
        include_metadata: true
        cors:
          allowed_origins:
            - https://foo.bar.com
            - https://*.test.com
          allowed_headers:
            - Example-Header
          max_age: 7200
```

### Securely expose your collector

To receive telemetry from a web application you need to allow the browsers of
your end-users to send data to your collector. If your web application is
accessible from the public internet, you also have to make your collector
accessible for everyone.

It is recommended that you do not expose your collector directly, but that you
put a reverse proxy (NGINX, Apache HTTP Server, ...) in front of it. The reverse
proxy can take care of SSL-offloading, setting the right CORS headers, and many
other features specific to web applications.

Below you will find a configuration for the popular NGINX web server to get you
started:

```nginx
server {
    listen 80 default_server;
    server_name _;
    location / {
        # Take care of preflight requests
        if ($request_method = 'OPTIONS') {
             add_header 'Access-Control-Max-Age' 1728000;
             add_header 'Access-Control-Allow-Origin' 'name.of.your.website.example.com' always;
             add_header 'Access-Control-Allow-Headers' 'Accept,Accept-Language,Content-Language,Content-Type' always;
             add_header 'Access-Control-Allow-Credentials' 'true' always;
             add_header 'Content-Type' 'text/plain charset=UTF-8';
             add_header 'Content-Length' 0;
             return 204;
        }

        add_header 'Access-Control-Allow-Origin' 'name.of.your.website.example.com' always;
        add_header 'Access-Control-Allow-Credentials' 'true' always;
        add_header 'Access-Control-Allow-Headers' 'Accept,Accept-Language,Content-Language,Content-Type' always;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://collector:4318;
    }
}
```

## Console

To debug your instrumentation or see the values locally in development, you can
use exporters writing telemetry data to the console (stdout).

If you followed the
[Getting Started](/docs/languages/js/getting-started/nodejs/) or
[Manual Instrumentation](/docs/languages/js/instrumentation) guides, you already
have the console exporter installed.

The `ConsoleSpanExporter` is included in the
[`@opentelemetry/sdk-trace-node`](https://www.npmjs.com/package/@opentelemetry/sdk-trace-node)
package and the `ConsoleMetricExporter` is included in the
[`@opentelemetry/sdk-metrics`](https://www.npmjs.com/package/@opentelemetry/sdk-metrics)
package:

## Jaeger

### Backend Setup {#jaeger-backend-setup}

[Jaeger](https://www.jaegertracing.io/) natively supports OTLP to receive trace
data. You can run Jaeger in a docker container with the UI accessible on port
16686 and OTLP enabled on ports 4317 and 4318:

```shell
docker run --rm \
  -e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \
  -p 16686:16686 \
  -p 4317:4317 \
  -p 4318:4318 \
  -p 9411:9411 \
  jaegertracing/all-in-one:latest
```

### Usage {#jaeger-usage}

Now following the instruction to setup the [OTLP exporters](#otlp-dependencies).
{{__hugo_ctx/}}


## Prometheus

To send your metric data to [Prometheus](https://prometheus.io/), you can either
[enable Prometheus' OTLP Receiver](https://prometheus.io/docs/guides/opentelemetry/#enable-the-otlp-receiver)
and use the [OTLP exporter](#otlp) or you can use the Prometheus exporter, a
`MetricReader` that starts an HTTP server that collects metrics and serialize to
Prometheus text format on request.

### Backend Setup {#prometheus-setup}

> [!NOTE]
>
> If you have Prometheus or a Prometheus-compatible backend already set up, you
> can skip this section and setup the [Prometheus](#prometheus-dependencies) or
> [OTLP](#otlp-dependencies) exporter dependencies for your application.

You can run [Prometheus](https://prometheus.io) in a docker container,
accessible on port `9090` by following these instructions:

Create a file called `prometheus.yml` with the following content:

```yaml
scrape_configs:
  - job_name: dice-service
    scrape_interval: 5s
    static_configs:
      - targets: [host.docker.internal:9464]
```

Run Prometheus in a docker container with the UI accessible on port `9090`:

```shell
docker run --rm -v ${PWD}/prometheus.yml:/prometheus/prometheus.yml -p 9090:9090 prom/prometheus --web.enable-otlp-receiver
```

> [!NOTE]
>
> When using Prometheus' OTLP Receiver, make sure that you set the OTLP endpoint
> for metrics in your application to `http://localhost:9090/api/v1/otlp`.
>
> Not all docker environments support `host.docker.internal`. In some cases you
> may need to replace `host.docker.internal` with `localhost` or the IP address
> of your machine.
{{__hugo_ctx/}}


## Dependencies {#prometheus-dependencies}

Install the
[exporter package](https://www.npmjs.com/package/@opentelemetry/exporter-prometheus)
as a dependency for your application:

```shell
npm install --save @opentelemetry/exporter-prometheus
```

Update your OpenTelemetry configuration to use the exporter and to send data to
your Prometheus backend:

   <ul class="nav nav-tabs" id="tabs-5" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-05-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-05-00" role="tab"
          data-td-tp-persist="typescript" aria-controls="tabs-05-00" aria-selected="true">
        TypeScript
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-05-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-05-01" role="tab"
          data-td-tp-persist="javascript" aria-controls="tabs-05-01" aria-selected="false">
        JavaScript
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-5-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-05-00" role="tabpanel" aria-labelled-by="tabs-05-00-tab" tabindex="5">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kr">import</span> <span class="o">*</span> <span class="kr">as</span> <span class="nx">opentelemetry</span> <span class="kr">from</span> <span class="s1">&#39;@opentelemetry/sdk-node&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">getNodeAutoInstrumentations</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@opentelemetry/auto-instrumentations-node&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">PrometheusExporter</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@opentelemetry/exporter-prometheus&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">sdk</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">opentelemetry</span><span class="p">.</span><span class="nx">NodeSDK</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">metricReader</span>: <span class="kt">new</span> <span class="nx">PrometheusExporter</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">    <span class="nx">port</span>: <span class="kt">9464</span><span class="p">,</span> <span class="c1">// optional - default is 9464
</span></span></span><span class="line"><span class="cl">  <span class="p">}),</span>
</span></span><span class="line"><span class="cl">  <span class="nx">instrumentations</span><span class="o">:</span> <span class="p">[</span><span class="nx">getNodeAutoInstrumentations</span><span class="p">()],</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="nx">sdk</span><span class="p">.</span><span class="nx">start</span><span class="p">();</span>
</span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-05-01" role="tabpanel" aria-labelled-by="tabs-05-01-tab" tabindex="5">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">opentelemetry</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;@opentelemetry/sdk-node&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">getNodeAutoInstrumentations</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;@opentelemetry/auto-instrumentations-node&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">PrometheusExporter</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;@opentelemetry/exporter-prometheus&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">PeriodicExportingMetricReader</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;@opentelemetry/sdk-metrics&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">sdk</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">opentelemetry</span><span class="p">.</span><span class="nx">NodeSDK</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">metricReader</span><span class="o">:</span> <span class="k">new</span> <span class="nx">PrometheusExporter</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">    <span class="nx">port</span><span class="o">:</span> <span class="mi">9464</span><span class="p">,</span> <span class="c1">// optional - default is 9464
</span></span></span><span class="line"><span class="cl">  <span class="p">}),</span>
</span></span><span class="line"><span class="cl">  <span class="nx">instrumentations</span><span class="o">:</span> <span class="p">[</span><span class="nx">getNodeAutoInstrumentations</span><span class="p">()],</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="nx">sdk</span><span class="p">.</span><span class="nx">start</span><span class="p">();</span>
</span></span></code></pre></div>
    </div>
</div>


With the above you can access your metrics at <http://localhost:9464/metrics>.
Prometheus or an OpenTelemetry Collector with the Prometheus receiver can scrape
the metrics from this endpoint.

## Zipkin

### Backend Setup {#zipkin-setup}

> [!NOTE]
>
> If you have Zipkin or a Zipkin-compatible backend already set up, you can skip
> this section and setup the
> [Zipkin exporter dependencies](#zipkin-dependencies) for your application.

You can run [Zipkin](https://zipkin.io/) on in a Docker container by executing
the following command:

```shell
docker run --rm -d -p 9411:9411 --name zipkin openzipkin/zipkin
```
{{__hugo_ctx/}}


## Dependencies {#zipkin-dependencies}

To send your trace data to [Zipkin](https://zipkin.io/), you can use the
`ZipkinExporter`.

Install the
[exporter package](https://www.npmjs.com/package/@opentelemetry/exporter-zipkin)
as a dependency for your application:

```shell
npm install --save @opentelemetry/exporter-zipkin
```

Update your OpenTelemetry configuration to use the exporter and to send data to
your Zipkin backend:

   <ul class="nav nav-tabs" id="tabs-7" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-07-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-07-00" role="tab"
          data-td-tp-persist="typescript" aria-controls="tabs-07-00" aria-selected="true">
        TypeScript
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-07-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-07-01" role="tab"
          data-td-tp-persist="javascript" aria-controls="tabs-07-01" aria-selected="false">
        JavaScript
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-7-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-07-00" role="tabpanel" aria-labelled-by="tabs-07-00-tab" tabindex="7">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kr">import</span> <span class="o">*</span> <span class="kr">as</span> <span class="nx">opentelemetry</span> <span class="kr">from</span> <span class="s1">&#39;@opentelemetry/sdk-node&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">getNodeAutoInstrumentations</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@opentelemetry/auto-instrumentations-node&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">ZipkinExporter</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@opentelemetry/exporter-zipkin&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">sdk</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">opentelemetry</span><span class="p">.</span><span class="nx">NodeSDK</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">traceExporter</span>: <span class="kt">new</span> <span class="nx">ZipkinExporter</span><span class="p">({}),</span>
</span></span><span class="line"><span class="cl">  <span class="nx">instrumentations</span><span class="o">:</span> <span class="p">[</span><span class="nx">getNodeAutoInstrumentations</span><span class="p">()],</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="nx">sdk</span><span class="p">.</span><span class="nx">start</span><span class="p">();</span>
</span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-07-01" role="tabpanel" aria-labelled-by="tabs-07-01-tab" tabindex="7">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">opentelemetry</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;@opentelemetry/sdk-node&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">getNodeAutoInstrumentations</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;@opentelemetry/auto-instrumentations-node&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">ZipkinExporter</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;@opentelemetry/exporter-zipkin&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">sdk</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">opentelemetry</span><span class="p">.</span><span class="nx">NodeSDK</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">traceExporter</span><span class="o">:</span> <span class="k">new</span> <span class="nx">ZipkinExporter</span><span class="p">({}),</span>
</span></span><span class="line"><span class="cl">  <span class="nx">instrumentations</span><span class="o">:</span> <span class="p">[</span><span class="nx">getNodeAutoInstrumentations</span><span class="p">()],</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div>
    </div>
</div>


## Custom exporters

Finally, you can also write your own exporter. For more information, see the
[SpanExporter Interface in the API documentation](https://open-telemetry.github.io/opentelemetry-js/interfaces/_opentelemetry_sdk-trace-base.SpanExporter.html).

## Batching span and log records

The OpenTelemetry SDK provides a set of default span and log record processors,
that allow you to either emit spans one-by-on ("simple") or batched. Using
batching is recommended, but if you do not want to batch your spans or log
records, you can use a simple processor instead as follows:
{{__hugo_ctx/}}


   <ul class="nav nav-tabs" id="tabs-9" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-09-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-09-00" role="tab"
          data-td-tp-persist="typescript" aria-controls="tabs-09-00" aria-selected="true">
        TypeScript
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-09-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-09-01" role="tab"
          data-td-tp-persist="javascript" aria-controls="tabs-09-01" aria-selected="false">
        JavaScript
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-9-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-09-00" role="tabpanel" aria-labelled-by="tabs-09-00-tab" tabindex="9">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="cm">/*instrumentation.ts*/</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="o">*</span> <span class="kr">as</span> <span class="nx">opentelemetry</span> <span class="kr">from</span> <span class="s1">&#39;@opentelemetry/sdk-node&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">getNodeAutoInstrumentations</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@opentelemetry/auto-instrumentations-node&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">sdk</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">NodeSDK</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">spanProcessors</span><span class="o">:</span> <span class="p">[</span><span class="k">new</span> <span class="nx">SimpleSpanProcessor</span><span class="p">(</span><span class="nx">exporter</span><span class="p">)],</span>
</span></span><span class="line"><span class="cl">  <span class="nx">instrumentations</span><span class="o">:</span> <span class="p">[</span><span class="nx">getNodeAutoInstrumentations</span><span class="p">()],</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="nx">sdk</span><span class="p">.</span><span class="nx">start</span><span class="p">();</span>
</span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-09-01" role="tabpanel" aria-labelled-by="tabs-09-01-tab" tabindex="9">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="cm">/*instrumentation.js*/</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">opentelemetry</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;@opentelemetry/sdk-node&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">getNodeAutoInstrumentations</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;@opentelemetry/auto-instrumentations-node&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">sdk</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">opentelemetry</span><span class="p">.</span><span class="nx">NodeSDK</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">spanProcessors</span><span class="o">:</span> <span class="p">[</span><span class="k">new</span> <span class="nx">SimpleSpanProcessor</span><span class="p">(</span><span class="nx">exporter</span><span class="p">)],</span>
</span></span><span class="line"><span class="cl">  <span class="nx">instrumentations</span><span class="o">:</span> <span class="p">[</span><span class="nx">getNodeAutoInstrumentations</span><span class="p">()],</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="nx">sdk</span><span class="p">.</span><span class="nx">start</span><span class="p">();</span>
</span></span></code></pre></div>
    </div>
</div>


[content security policies]:
  https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/
[cross-origin resource sharing]:
  https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
[opentelemetry collector exporter with grpc]:
  https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-grpc
[opentelemetry collector exporter with http/protobuf]:
  https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-proto
[opentelemetry collector exporter with http/json]:
  https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-http
[a feature]:
  https://github.com/open-telemetry/opentelemetry-collector/blob/main/config/confighttp/README.md
