diff --git a/docs/usage/assets/images/opentelemetry_choose_trace.png b/docs/usage/assets/images/opentelemetry_choose_trace.png
new file mode 100644
index 0000000000000000000000000000000000000000..e1a28d7a55f716a566dc066dae693fdceec5906f
Binary files /dev/null and b/docs/usage/assets/images/opentelemetry_choose_trace.png differ
diff --git a/docs/usage/assets/images/opentelemetry_pick_service.png b/docs/usage/assets/images/opentelemetry_pick_service.png
new file mode 100644
index 0000000000000000000000000000000000000000..8165983fbf66bd8528ea593117f7ca2d07072adc
Binary files /dev/null and b/docs/usage/assets/images/opentelemetry_pick_service.png differ
diff --git a/docs/usage/assets/images/opentelemetry_trace_viewer.png b/docs/usage/assets/images/opentelemetry_trace_viewer.png
new file mode 100644
index 0000000000000000000000000000000000000000..098bed587bda45b5d48af3887633b710ca065149
Binary files /dev/null and b/docs/usage/assets/images/opentelemetry_trace_viewer.png differ
diff --git a/docs/usage/examples/opentelemetry.md b/docs/usage/examples/opentelemetry.md
new file mode 100644
index 0000000000000000000000000000000000000000..a86d94ab030bf0ca8b3eea23b86540e3cd447b8a
--- /dev/null
+++ b/docs/usage/examples/opentelemetry.md
@@ -0,0 +1,233 @@
+# OpenTelemetry
+
+Requirements:
+
+- docker-compose
+
+## Prepare setup
+
+Create a `docker-compose.yaml` and `otel-collector-config.yml` file as seen below in a folder.
+
+`docker-compose.yaml`:
+
+```yaml
+version: '3'
+services:
+  # Jaeger
+  jaeger:
+    image: jaegertracing/all-in-one:1
+    ports:
+      - '16686:16686'
+      - '14250'
+
+  otel-collector:
+    image: otel/opentelemetry-collector-contrib:0.52.0
+    command: ['--config=/etc/otel-collector-config.yml']
+    volumes:
+      - ./otel-collector-config.yml:/etc/otel-collector-config.yml
+    ports:
+      - '1888:1888' # pprof extension
+      - '13133:13133' # health_check extension
+      - '55679:55679' # zpages extension
+      - '4318:4318' # OTLP HTTP
+      - '4317:4317' # OTLP GRPC
+      - '9123:9123' # Prometheus exporter
+    depends_on:
+      - jaeger
+```
+
+`otel-collector-config.yml`:
+
+```yaml
+receivers:
+  otlp:
+    protocols:
+      grpc:
+      http:
+
+exporters:
+  jaeger:
+    endpoint: jaeger:14250
+    tls:
+      insecure: true
+  logging:
+  prometheus:
+    endpoint: '0.0.0.0:9123'
+
+processors:
+  batch:
+  spanmetrics:
+    metrics_exporter: prometheus
+    latency_histogram_buckets: [10ms, 100ms, 250ms, 1s, 30s, 1m, 5m]
+    dimensions:
+      - name: http.method
+      - name: http.status_code
+      - name: http.host
+    dimensions_cache_size: 1000
+    aggregation_temporality: 'AGGREGATION_TEMPORALITY_CUMULATIVE'
+
+extensions:
+  health_check:
+  pprof:
+  zpages:
+
+service:
+  extensions: [pprof, zpages, health_check]
+  pipelines:
+    traces:
+      receivers: [otlp]
+      exporters: [jaeger, logging]
+      processors: [spanmetrics, batch]
+
+    metrics:
+      receivers: [otlp]
+      exporters: [prometheus]
+```
+
+Start setup using this command inside the folder containing the files created in the earlier steps:
+
+```
+docker-compose up
+```
+
+This command will start an [OpenTelemetry Collector](https://github.com/open-telemetry/opentelemetry-collector-contrib) and an instance of [Jaeger](https://www.jaegertracing.io/).
+
+Jaeger will be now reachable under [http://localhost:16686](http://localhost:16686).
+
+## Run Renovate with OpenTelemetry
+
+To start Renovate with OpenTelemetry enabled run following command, after pointing to your `config.js` config file:
+
+```
+docker run \
+  --rm \
+  -e OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 \
+  -v "/path/to/your/config.js:/usr/src/app/config.js" \
+  renovate/renovate:latest
+```
+
+You should now see `trace_id` and `span_id` fields in the logs.
+
+```
+ INFO: Repository finished (repository=org/example)
+       "durationMs": 5574,
+       "trace_id": "f9a4c33852333fc2a0fbdc163100c987",
+       "span_id": "4ac1323eeaee
+```
+
+### Traces
+
+Open now Jaeger under [http://localhost:16686](http://localhost:16686).
+
+You should now be able to pick `renovate` under in the field `service` field.
+
+![service picker](../assets/images/opentelemetry_pick_service.png)
+
+Press `Find Traces` to search for all Renovate traces and then click on one of the found traces to open the trace view.
+
+![pick trace](../assets/images/opentelemetry_choose_trace.png)
+
+You should be able to see now the full trace view which shows each HTTP request and internal spans.
+
+![trace view](../assets/images/opentelemetry_trace_viewer.png)
+
+### Metrics
+
+Additional to the received traces some metrics are calculated.
+This is achieved using the [spanmetricsprocessor](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/spanmetricsprocessor).
+The previous implemented setup will produce following metrics, which are exposed under [http://localhost:9123/metrics](http://localhost:9123/metrics):
+
+```
+# HELP calls_total
+# TYPE calls_total counter
+
+### Example of internal spans
+calls_total{operation="renovate repository",service_name="renovate",span_kind="SPAN_KIND_INTERNAL",status_code="STATUS_CODE_UNSET"} 3
+calls_total{operation="run",service_name="renovate",span_kind="SPAN_KIND_INTERNAL",status_code="STATUS_CODE_UNSET"} 1
+### Example of http calls from Renovate to external services
+calls_total{http_host="api.github.com:443",http_method="POST",http_status_code="200",operation="HTTPS POST",service_name="renovate",span_kind="SPAN_KIND_CLIENT",status_code="STATUS_CODE_UNSET"} 9
+
+...
+
+# HELP latency
+# TYPE latency histogram
+### Example of internal spans
+latency_bucket{operation="renovate repository",service_name="renovate",span_kind="SPAN_KIND_INTERNAL",status_code="STATUS_CODE_UNSET",le="0.1"} 0
+...
+latency_bucket{operation="renovate repository",service_name="renovate",span_kind="SPAN_KIND_INTERNAL",status_code="STATUS_CODE_UNSET",le="9.223372036854775e+12"} 3
+latency_bucket{operation="renovate repository",service_name="renovate",span_kind="SPAN_KIND_INTERNAL",status_code="STATUS_CODE_UNSET",le="+Inf"} 3
+latency_sum{operation="renovate repository",service_name="renovate",span_kind="SPAN_KIND_INTERNAL",status_code="STATUS_CODE_UNSET"} 30947.4689
+latency_count{operation="renovate repository",service_name="renovate",span_kind="SPAN_KIND_INTERNAL",status_code="STATUS_CODE_UNSET"} 3
+
+...
+
+### Example of http calls from Renovate to external services
+latency_bucket{http_host="api.github.com:443",http_method="POST",http_status_code="200",operation="HTTPS POST",service_name="renovate",span_kind="SPAN_KIND_CLIENT",status_code="STATUS_CODE_UNSET",le="0.1"} 0
+...
+latency_bucket{http_host="api.github.com:443",http_method="POST",http_status_code="200",operation="HTTPS POST",service_name="renovate",span_kind="SPAN_KIND_CLIENT",status_code="STATUS_CODE_UNSET",le="250"} 3
+latency_bucket{http_host="api.github.com:443",http_method="POST",http_status_code="200",operation="HTTPS POST",service_name="renovate",span_kind="SPAN_KIND_CLIENT",status_code="STATUS_CODE_UNSET",le="9.223372036854775e+12"} 9
+latency_bucket{http_host="api.github.com:443",http_method="POST",http_status_code="200",operation="HTTPS POST",service_name="renovate",span_kind="SPAN_KIND_CLIENT",status_code="STATUS_CODE_UNSET",le="+Inf"} 9
+latency_sum{http_host="api.github.com:443",http_method="POST",http_status_code="200",operation="HTTPS POST",service_name="renovate",span_kind="SPAN_KIND_CLIENT",status_code="STATUS_CODE_UNSET"} 2306.1385999999998
+latency_count{http_host="api.github.com:443",http_method="POST",http_status_code="200",operation="HTTPS POST",service_name="renovate",span_kind="SPAN_KIND_CLIENT",status_code="STATUS_CODE_UNSET"} 9
+```
+
+The [spanmetricsprocessor](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/spanmetricsprocessor) creates two sets of metrics.
+
+#### Calls metric
+
+At first there are the `calls_total` metrics which display how often specific trace spans have been observed.
+
+For example:
+`calls_total{operation="renovate repository",service_name="renovate",span_kind="SPAN_KIND_INTERNAL",status_code="STATUS_CODE_UNSET"} 3` signals that 3 repositories have been renovated.
+`calls_total{operation="run",service_name="renovate",span_kind="SPAN_KIND_INTERNAL",status_code="STATUS_CODE_UNSET"} 1` represents how often Renovate has been run.
+
+If we combine this using the PrometheusQueryLanguage ( PromQL ), we can calculate the average count of repositories each Renovate run handles.
+
+```
+calls_total{operation="renovate repository",service_name="renovate"} / calls_total{operation="run",service_name="renovate"}
+```
+
+This metrics is also for spans generated by http calls:
+
+```yaml
+calls_total{http_host="registry.terraform.io:443",http_method="GET",http_status_code="200",operation="HTTPS GET",service_name="renovate",span_kind="SPAN_KIND_CLIENT",status_code="STATUS_CODE_UNSET"} 5
+```
+
+#### Latency buckets
+
+The second class of metrics exposed are the latency focused latency buckets which allow to create [heatmaps](https://grafana.com/docs/grafana/latest/basics/intro-histograms/#heatmaps).
+A request is added to a backed if the latency is bigger than the bucket value (`le`). `request_duration => le`
+
+As an example if we receive a request which need `1.533s` to complete get following metrics:
+
+```
+latency_bucket{http_host="api.github.com:443",le="0.1"} 0
+latency_bucket{http_host="api.github.com:443",le="1"} 0
+latency_bucket{http_host="api.github.com:443",le="2"} 1
+latency_bucket{http_host="api.github.com:443",le="6"} 1
+latency_bucket{http_host="api.github.com:443",le="10"} 1
+latency_bucket{http_host="api.github.com:443",le="100"} 1
+latency_bucket{http_host="api.github.com:443",le="250"} 1
+latency_bucket{http_host="api.github.com:443",le="9.223372036854775e+12"} 1
+latency_bucket{http_host="api.github.com:443",le="+Inf"} 1
+latency_sum{http_host="api.github.com:443"} 1.533
+latency_count{http_host="api.github.com:443"} 1
+```
+
+Now we have another request which this time takes 10s to complete:
+
+```
+latency_bucket{http_host="api.github.com:443",le="0.1"} 0
+latency_bucket{http_host="api.github.com:443",le="1"} 0
+latency_bucket{http_host="api.github.com:443",le="2"} 1
+latency_bucket{http_host="api.github.com:443",le="6"} 1
+latency_bucket{http_host="api.github.com:443",le="10"} 2
+latency_bucket{http_host="api.github.com:443",le="100"} 2
+latency_bucket{http_host="api.github.com:443",le="250"} 2
+latency_bucket{http_host="api.github.com:443",le="9.223372036854775e+12"} 2
+latency_bucket{http_host="api.github.com:443",le="+Inf"} 2
+latency_sum{http_host="api.github.com:443"} 11.533
+latency_count{http_host="api.github.com:443"} 2
+```
+
+More about the functionality can be found on the Prometheus page for [metric types](https://prometheus.io/docs/concepts/metric_types/#histogram).
diff --git a/docs/usage/opentelemetry.md b/docs/usage/opentelemetry.md
new file mode 100644
index 0000000000000000000000000000000000000000..9a00e4255efbf4114c307d25f0d57fb6e626dc49
--- /dev/null
+++ b/docs/usage/opentelemetry.md
@@ -0,0 +1,30 @@
+---
+title: OpenTelemetry
+description: How to use OpenTelemetry with Renovate
+---
+
+# OpenTelemetry and Renovate
+
+**THIS FEATURE IS EXPERIMENTAL** and is subject to change in minor versions.
+
+Renovate supports OpenTelemetry which is an emerging monitoring standard.
+
+OpenTelemetry supports three types of observability data:
+
+- traces
+- metrics
+- logs
+
+Renovate can only send traces and only via the OpenTelemetryProtocol (OTLP), other observability data or transfer protocols are not supported.
+
+## Usage
+
+To activate the instrumentation, the environment variable `OTEL_EXPORTER_OTLP_ENDPOINT` has to be set.
+This sets the endpoint where to send the telemetry data.
+If this endpoint is set, all other environment variables defined by the [OpenTelemetry specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/sdk-environment-variables.md) are supported.
+
+For debugging purposes the telemetry can also be printed to the console if the environment variable `RENOVATE_TRACING_CONSOLE_EXPORTER` is set.
+
+## Examples
+
+An usage example with a local OpenTelemetry setup can be found in the [OpenTelemetry examples](examples/opentelemetry.md)
diff --git a/docs/usage/self-hosted-experimental.md b/docs/usage/self-hosted-experimental.md
index f8941ad13ff72e258d02c44caef599203aed145a..d5f08ab2c22d43b33e4ef1ce236cd558b6e95300 100644
--- a/docs/usage/self-hosted-experimental.md
+++ b/docs/usage/self-hosted-experimental.md
@@ -62,3 +62,8 @@ Source: [AWS s3 documentation - Interface BucketEndpointInputConfig](https://doc
 ## `RENOVATE_X_EXEC_GPID_HANDLE`
 
 If set, Renovate will terminate the whole process group of a terminated child process spawned by Renovate.
+
+## `OTEL_EXPORTER_OTLP_ENDPOINT`
+
+If set, Renovate will export OpenTelemetry data to the supplied endpoint.
+For more information see [the OpenTelemetry docs](opentelemetry.md).
diff --git a/lib/instrumentation/__mocks__/index.ts b/lib/instrumentation/__mocks__/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..be8ac341cd32d33d47ad8f459044ceb414638dc1
--- /dev/null
+++ b/lib/instrumentation/__mocks__/index.ts
@@ -0,0 +1,5 @@
+import { NoopTracer } from '@opentelemetry/api/build/src/trace/NoopTracer';
+import { NoopTracerProvider } from '@opentelemetry/api/build/src/trace/NoopTracerProvider';
+
+export const getTracerProvider = jest.fn(args => new NoopTracerProvider());
+export const getTracer = jest.fn(args => new NoopTracer());
diff --git a/lib/instrumentation/__snapshots__/index.spec.ts.snap b/lib/instrumentation/__snapshots__/index.spec.ts.snap
new file mode 100644
index 0000000000000000000000000000000000000000..385b530d449f37d6bf8f9ced1654acc58d47a6e1
--- /dev/null
+++ b/lib/instrumentation/__snapshots__/index.spec.ts.snap
@@ -0,0 +1,124 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`instrumentation/index activate console logger 1`] = `
+MultiSpanProcessor {
+  "_spanProcessors": [
+    SimpleSpanProcessor {
+      "_exporter": ConsoleSpanExporter {},
+      "_shutdownOnce": BindOnceFuture {
+        "_callback": [Function],
+        "_deferred": Deferred {
+          "_promise": Promise {},
+          "_reject": [Function],
+          "_resolve": [Function],
+        },
+        "_isCalled": false,
+        "_that": [Circular],
+      },
+    },
+  ],
+}
+`;
+
+exports[`instrumentation/index activate console logger and remote logger 1`] = `
+MultiSpanProcessor {
+  "_spanProcessors": [
+    SimpleSpanProcessor {
+      "_exporter": ConsoleSpanExporter {},
+      "_shutdownOnce": BindOnceFuture {
+        "_callback": [Function],
+        "_deferred": Deferred {
+          "_promise": Promise {},
+          "_reject": [Function],
+          "_resolve": [Function],
+        },
+        "_isCalled": false,
+        "_that": [Circular],
+      },
+    },
+    BatchSpanProcessor {
+      "_exportTimeoutMillis": 30000,
+      "_exporter": OTLPTraceExporter {
+        "DEFAULT_HEADERS": {},
+        "_concurrencyLimit": Infinity,
+        "_sendingPromises": [],
+        "_shutdownOnce": BindOnceFuture {
+          "_callback": [Function],
+          "_deferred": Deferred {
+            "_promise": Promise {},
+            "_reject": [Function],
+            "_resolve": [Function],
+          },
+          "_isCalled": false,
+          "_that": [Circular],
+        },
+        "agent": undefined,
+        "compression": "none",
+        "headers": {},
+        "shutdown": [Function],
+        "timeoutMillis": 10000,
+        "url": "https://collector.example.com/v1/traces",
+      },
+      "_finishedSpans": [],
+      "_maxExportBatchSize": 512,
+      "_maxQueueSize": 2048,
+      "_scheduledDelayMillis": 5000,
+      "_shutdownOnce": BindOnceFuture {
+        "_callback": [Function],
+        "_deferred": Deferred {
+          "_promise": Promise {},
+          "_reject": [Function],
+          "_resolve": [Function],
+        },
+        "_isCalled": false,
+        "_that": [Circular],
+      },
+    },
+  ],
+}
+`;
+
+exports[`instrumentation/index activate remote logger 1`] = `
+MultiSpanProcessor {
+  "_spanProcessors": [
+    BatchSpanProcessor {
+      "_exportTimeoutMillis": 30000,
+      "_exporter": OTLPTraceExporter {
+        "DEFAULT_HEADERS": {},
+        "_concurrencyLimit": Infinity,
+        "_sendingPromises": [],
+        "_shutdownOnce": BindOnceFuture {
+          "_callback": [Function],
+          "_deferred": Deferred {
+            "_promise": Promise {},
+            "_reject": [Function],
+            "_resolve": [Function],
+          },
+          "_isCalled": false,
+          "_that": [Circular],
+        },
+        "agent": undefined,
+        "compression": "none",
+        "headers": {},
+        "shutdown": [Function],
+        "timeoutMillis": 10000,
+        "url": "https://collector.example.com/v1/traces",
+      },
+      "_finishedSpans": [],
+      "_maxExportBatchSize": 512,
+      "_maxQueueSize": 2048,
+      "_scheduledDelayMillis": 5000,
+      "_shutdownOnce": BindOnceFuture {
+        "_callback": [Function],
+        "_deferred": Deferred {
+          "_promise": Promise {},
+          "_reject": [Function],
+          "_resolve": [Function],
+        },
+        "_isCalled": false,
+        "_that": [Circular],
+      },
+    },
+  ],
+}
+`;
diff --git a/lib/instrumentation/decorator.spec.ts b/lib/instrumentation/decorator.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fdb33afd2a3149d91e3ee00e2350f861b84ed4d5
--- /dev/null
+++ b/lib/instrumentation/decorator.spec.ts
@@ -0,0 +1,49 @@
+import { afterAll } from '@jest/globals';
+import { instrument } from './decorator';
+import { disableInstrumentations } from '.';
+
+afterAll(disableInstrumentations);
+
+describe('instrumentation/decorator', () => {
+  const spy = jest.fn(() => Promise.resolve());
+
+  beforeEach(() => {
+    jest.clearAllMocks();
+  });
+
+  it('should instrument async function', async () => {
+    class MyClass {
+      @instrument({ name: 'getNumber' })
+      public async getNumber(): Promise<number> {
+        await spy();
+        return Math.random();
+      }
+    }
+    const myClass = new MyClass();
+    const result = await myClass.getNumber();
+
+    expect(result).toBeDefined();
+    expect(result).toBeNumber();
+
+    expect(spy).toHaveBeenCalledTimes(1);
+  });
+
+  it('should instrument multiple async function calls', async () => {
+    class MyClass {
+      @instrument({ name: 'getNumber' })
+      public async getNumber(): Promise<number> {
+        await spy();
+        return Math.random();
+      }
+    }
+    const myClass = new MyClass();
+    await myClass.getNumber();
+    await myClass.getNumber();
+    const result = await myClass.getNumber();
+
+    expect(result).toBeDefined();
+    expect(result).toBeNumber();
+
+    expect(spy).toHaveBeenCalledTimes(3);
+  });
+});
diff --git a/lib/instrumentation/decorator.ts b/lib/instrumentation/decorator.ts
new file mode 100644
index 0000000000000000000000000000000000000000..39f1d365a84e39a51c7e3932b76a565664569470
--- /dev/null
+++ b/lib/instrumentation/decorator.ts
@@ -0,0 +1,21 @@
+import { Decorator, decorate } from '../util/decorator';
+import type { SpanParameters } from './types';
+import { instrument as instrumentFunc } from '.';
+
+/**
+ * instruments a decorated method.
+ */
+export function instrument<T>({
+  name,
+  attributes,
+  ignoreParentSpan,
+  kind,
+}: SpanParameters): Decorator<T> {
+  return decorate(async ({ callback }) => {
+    return await instrumentFunc(name, callback, {
+      attributes,
+      root: ignoreParentSpan,
+      kind,
+    });
+  });
+}
diff --git a/lib/instrumentation/index.spec.ts b/lib/instrumentation/index.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b2cd369a4586f2bb4b08f1a1791a8128a4681acc
--- /dev/null
+++ b/lib/instrumentation/index.spec.ts
@@ -0,0 +1,121 @@
+import { afterAll } from '@jest/globals';
+import { ProxyTracerProvider } from '@opentelemetry/api';
+import * as api from '@opentelemetry/api';
+import { NoopTracerProvider } from '@opentelemetry/api/build/src/trace/NoopTracerProvider';
+import { MultiSpanProcessor } from '@opentelemetry/sdk-trace-base/build/src/MultiSpanProcessor';
+import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
+import {
+  disableInstrumentations,
+  getTracerProvider,
+  init,
+  instrument,
+} from '.';
+
+afterAll(disableInstrumentations);
+
+describe('instrumentation/index', () => {
+  const oldEnv = process.env;
+
+  beforeEach(() => {
+    jest.clearAllMocks();
+    api.trace.disable(); // clear global components
+    process.env = { ...oldEnv };
+  });
+
+  afterAll(() => {
+    process.env = oldEnv; // Restore old environment
+  });
+
+  it('should use NoopTraceProvider if not activated', () => {
+    init();
+    const traceProvider = getTracerProvider();
+    expect(traceProvider).toBeInstanceOf(ProxyTracerProvider);
+    const provider = traceProvider as ProxyTracerProvider;
+    expect(provider.getDelegate()).toBeInstanceOf(NoopTracerProvider);
+  });
+
+  it('activate console logger', () => {
+    process.env.RENOVATE_TRACING_CONSOLE_EXPORTER = 'true';
+
+    init();
+    const traceProvider = getTracerProvider();
+    expect(traceProvider).toBeInstanceOf(ProxyTracerProvider);
+    const proxyProvider = traceProvider as ProxyTracerProvider;
+    const delegateProvider = proxyProvider.getDelegate();
+    expect(delegateProvider).toBeInstanceOf(NodeTracerProvider);
+    const nodeProvider = delegateProvider as NodeTracerProvider;
+    const provider = nodeProvider.getActiveSpanProcessor();
+    expect(provider).toBeInstanceOf(MultiSpanProcessor);
+    expect(provider).toMatchSnapshot();
+  });
+
+  it('activate remote logger', () => {
+    process.env.OTEL_EXPORTER_OTLP_ENDPOINT = 'https://collector.example.com';
+
+    init();
+    const traceProvider = getTracerProvider();
+    expect(traceProvider).toBeInstanceOf(ProxyTracerProvider);
+    const proxyProvider = traceProvider as ProxyTracerProvider;
+    const delegateProvider = proxyProvider.getDelegate();
+    expect(delegateProvider).toBeInstanceOf(NodeTracerProvider);
+    const nodeProvider = delegateProvider as NodeTracerProvider;
+    const provider = nodeProvider.getActiveSpanProcessor();
+    expect(provider).toBeInstanceOf(MultiSpanProcessor);
+    expect(provider).toMatchSnapshot();
+  });
+
+  it('activate console logger and remote logger', () => {
+    process.env.RENOVATE_TRACING_CONSOLE_EXPORTER = 'true';
+    process.env.OTEL_EXPORTER_OTLP_ENDPOINT = 'https://collector.example.com';
+
+    init();
+    const traceProvider = getTracerProvider();
+    expect(traceProvider).toBeInstanceOf(ProxyTracerProvider);
+    const proxyProvider = traceProvider as ProxyTracerProvider;
+    const delegateProvider = proxyProvider.getDelegate();
+    expect(delegateProvider).toBeInstanceOf(NodeTracerProvider);
+    const nodeProvider = delegateProvider as NodeTracerProvider;
+    const provider = nodeProvider.getActiveSpanProcessor();
+    expect(provider).toBeInstanceOf(MultiSpanProcessor);
+    expect(provider).toMatchSnapshot();
+  });
+
+  describe('instrument', () => {
+    it('should return result', () => {
+      const value = 'testResult';
+      const result = instrument('test', () => {
+        return value;
+      });
+      expect(result).toStrictEqual(value);
+    });
+
+    it('should rethrow exception', () => {
+      const error = new Error('testError');
+      expect(() =>
+        instrument('test', () => {
+          throw error;
+        })
+      ).toThrow(error);
+    });
+
+    it('should return result for async fn', async () => {
+      const value = 'testResult';
+      const result = await instrument('test', async () => {
+        return await new Promise((resolve) => {
+          resolve(value);
+        });
+      });
+      expect(result).toStrictEqual(value);
+    });
+
+    it('should rethrow exception for async fn', async () => {
+      const error = new Error('testError');
+      await expect(
+        instrument('test', async () => {
+          await Promise.resolve();
+          throw error;
+        })
+      ).rejects.toThrow(error);
+    });
+  });
+});
diff --git a/lib/instrumentation/index.ts b/lib/instrumentation/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..43a95d12187371b43060566f1e7d75007d921d91
--- /dev/null
+++ b/lib/instrumentation/index.ts
@@ -0,0 +1,165 @@
+import { ClientRequest } from 'http';
+import type {
+  Context,
+  Span,
+  SpanOptions,
+  Tracer,
+  TracerProvider,
+} from '@opentelemetry/api';
+import * as api from '@opentelemetry/api';
+import { ProxyTracerProvider, SpanStatusCode } from '@opentelemetry/api';
+import { AsyncLocalStorageContextManager } from '@opentelemetry/context-async-hooks';
+import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
+import {
+  Instrumentation,
+  registerInstrumentations,
+} from '@opentelemetry/instrumentation';
+import { BunyanInstrumentation } from '@opentelemetry/instrumentation-bunyan';
+import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
+import { Resource } from '@opentelemetry/resources';
+import {
+  BatchSpanProcessor,
+  ConsoleSpanExporter,
+  SimpleSpanProcessor,
+} from '@opentelemetry/sdk-trace-base';
+import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
+import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
+import { pkg } from '../expose.cjs';
+import {
+  isTraceDebuggingEnabled,
+  isTraceSendingEnabled,
+  isTracingEnabled,
+} from './utils';
+
+let instrumentations: Instrumentation[] = [];
+
+init();
+
+export function init(): void {
+  if (!isTracingEnabled()) {
+    return;
+  }
+
+  const traceProvider = new NodeTracerProvider({
+    resource: new Resource({
+      // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#semantic-attributes-with-sdk-provided-default-value
+      [SemanticResourceAttributes.SERVICE_NAME]: 'renovate',
+      [SemanticResourceAttributes.SERVICE_NAMESPACE]: 'renovatebot.com',
+      [SemanticResourceAttributes.SERVICE_VERSION]: pkg.version,
+    }),
+  });
+
+  // add processors
+  if (isTraceDebuggingEnabled()) {
+    traceProvider.addSpanProcessor(
+      new SimpleSpanProcessor(new ConsoleSpanExporter())
+    );
+  }
+
+  // OTEL specification environment variable
+  if (isTraceSendingEnabled()) {
+    const exporter = new OTLPTraceExporter();
+    traceProvider.addSpanProcessor(new BatchSpanProcessor(exporter));
+  }
+
+  const contextManager = new AsyncLocalStorageContextManager();
+  traceProvider.register({
+    contextManager,
+  });
+
+  instrumentations = [
+    new HttpInstrumentation({
+      applyCustomAttributesOnSpan: /* istanbul ignore next */ (
+        span,
+        request,
+        response
+      ) => {
+        // ignore 404 errors when the branch protection of Github could not be found. This is expected if no rules are configured
+        if (
+          request instanceof ClientRequest &&
+          request.host === `api.github.com` &&
+          request.path.endsWith(`/protection`) &&
+          response.statusCode === 404
+        ) {
+          span.setStatus({ code: SpanStatusCode.OK });
+        }
+      },
+    }),
+    new BunyanInstrumentation(),
+  ];
+  registerInstrumentations({
+    instrumentations,
+  });
+}
+
+/* istanbul ignore next */
+
+// https://github.com/open-telemetry/opentelemetry-js-api/issues/34
+export async function shutdown(): Promise<void> {
+  const traceProvider = getTracerProvider();
+  if (traceProvider instanceof NodeTracerProvider) {
+    await traceProvider.shutdown();
+  } else if (traceProvider instanceof ProxyTracerProvider) {
+    const delegateProvider = traceProvider.getDelegate();
+    if (delegateProvider instanceof NodeTracerProvider) {
+      await delegateProvider.shutdown();
+    }
+  }
+}
+
+/* istanbul ignore next */
+export function disableInstrumentations(): void {
+  for (const instrumentation of instrumentations) {
+    instrumentation.disable();
+  }
+}
+
+export function getTracerProvider(): TracerProvider {
+  return api.trace.getTracerProvider();
+}
+
+function getTracer(): Tracer {
+  return getTracerProvider().getTracer('renovate');
+}
+
+export function instrument<F extends (span: Span) => ReturnType<F>>(
+  name: string,
+  fn: F
+): ReturnType<F>;
+export function instrument<F extends (span: Span) => ReturnType<F>>(
+  name: string,
+  fn: F,
+  options: SpanOptions
+): ReturnType<F>;
+export function instrument<F extends (span: Span) => ReturnType<F>>(
+  name: string,
+  fn: F,
+  options: SpanOptions = {},
+  context: Context = api.context.active()
+): ReturnType<F> {
+  return getTracer().startActiveSpan(name, options, context, (span: Span) => {
+    try {
+      const ret = fn(span);
+      if (ret instanceof Promise) {
+        return ret
+          .catch((e) => {
+            span.setStatus({
+              code: SpanStatusCode.ERROR,
+              message: e,
+            });
+            throw e;
+          })
+          .finally(() => span.end()) as ReturnType<F>;
+      }
+      span.end();
+      return ret;
+    } catch (e) {
+      span.setStatus({
+        code: SpanStatusCode.ERROR,
+        message: e,
+      });
+      span.end();
+      throw e;
+    }
+  });
+}
diff --git a/lib/instrumentation/types.ts b/lib/instrumentation/types.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8b312d03d754d24ef3077e7dc751d74221a6720a
--- /dev/null
+++ b/lib/instrumentation/types.ts
@@ -0,0 +1,26 @@
+import type { Attributes, SpanKind } from '@opentelemetry/api';
+
+/**
+ * The instrumentation decorator parameters.
+ */
+export interface SpanParameters {
+  /**
+   * The name of the span
+   */
+  name: string;
+
+  /**
+   * Attributes which should be added to the span
+   */
+  attributes?: Attributes;
+
+  /**
+   * Should this span be added to the root span or to the current active span
+   */
+  ignoreParentSpan?: boolean;
+
+  /**
+   * Type of span this represents. Default: SpanKind.Internal
+   */
+  kind?: SpanKind;
+}
diff --git a/lib/instrumentation/utils.ts b/lib/instrumentation/utils.ts
new file mode 100644
index 0000000000000000000000000000000000000000..15066be3a31f423be457a77448cffcae81f1219a
--- /dev/null
+++ b/lib/instrumentation/utils.ts
@@ -0,0 +1,11 @@
+export function isTracingEnabled(): boolean {
+  return isTraceDebuggingEnabled() || isTraceSendingEnabled();
+}
+
+export function isTraceDebuggingEnabled(): boolean {
+  return !!process.env.RENOVATE_TRACING_CONSOLE_EXPORTER;
+}
+
+export function isTraceSendingEnabled(): boolean {
+  return !!process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
+}
diff --git a/lib/renovate.ts b/lib/renovate.ts
index 50ee830e6be7e868aa9bb6b62461918c049f164c..9b7c126ca100c71ae2901fe7550ab6af2830cd14 100644
--- a/lib/renovate.ts
+++ b/lib/renovate.ts
@@ -1,5 +1,6 @@
 #!/usr/bin/env node
 
+import { instrument, shutdown as telemetryShutdown } from './instrumentation'; // has to be imported before logger and other libraries which are instrumentalised
 import { logger } from './logger';
 import * as proxy from './proxy';
 import * as globalWorker from './workers/global';
@@ -13,7 +14,9 @@ proxy.bootstrap();
 
 // eslint-disable-next-line @typescript-eslint/no-floating-promises
 (async (): Promise<void> => {
-  process.exitCode = await globalWorker.start();
+  process.exitCode = await instrument('run', () => globalWorker.start());
+  await telemetryShutdown(); //gracefully shutdown OpenTelemetry
+
   // istanbul ignore if
   if (process.env.RENOVATE_X_HARD_EXIT) {
     process.exit(process.exitCode);
diff --git a/lib/workers/global/index.ts b/lib/workers/global/index.ts
index 75a0daf0728f8b8519f6be736151b0ef7283bc72..88919445eefc3083a2f64b6e4bda2becf38812cb 100644
--- a/lib/workers/global/index.ts
+++ b/lib/workers/global/index.ts
@@ -15,6 +15,7 @@ import type {
 } from '../../config/types';
 import { CONFIG_PRESETS_INVALID } from '../../constants/error-messages';
 import { pkg } from '../../expose.cjs';
+import { instrument } from '../../instrumentation';
 import { getProblems, logger, setMeta } from '../../logger';
 import * as hostRules from '../../util/host-rules';
 import * as queue from '../../util/http/queue';
@@ -107,30 +108,37 @@ export async function resolveGlobalExtends(
 export async function start(): Promise<number> {
   let config: AllConfig;
   try {
-    // read global config from file, env and cli args
-    config = await getGlobalConfig();
-    if (config?.globalExtends) {
-      // resolve global presets immediately
-      config = mergeChildConfig(
-        config,
-        await resolveGlobalExtends(config.globalExtends)
-      );
-    }
-    // initialize all submodules
-    config = await globalInitialize(config);
+    await instrument('config', async () => {
+      // read global config from file, env and cli args
+      config = await getGlobalConfig();
+      if (config?.globalExtends) {
+        // resolve global presets immediately
+        config = mergeChildConfig(
+          config,
+          await resolveGlobalExtends(config.globalExtends)
+        );
+      }
+      // initialize all submodules
+      config = await globalInitialize(config);
 
-    // Set platform and endpoint in case local presets are used
-    GlobalConfig.set({ platform: config.platform, endpoint: config.endpoint });
+      // Set platform and endpoint in case local presets are used
+      GlobalConfig.set({
+        platform: config.platform,
+        endpoint: config.endpoint,
+      });
 
-    await validatePresets(config);
+      await validatePresets(config);
 
-    checkEnv();
+      checkEnv();
 
-    // validate secrets. Will throw and abort if invalid
-    validateConfigSecrets(config);
+      // validate secrets. Will throw and abort if invalid
+      validateConfigSecrets(config);
+    });
 
     // autodiscover repositories (needs to come after platform initialization)
-    config = await autodiscoverRepositories(config);
+    config = await instrument('discover', () =>
+      autodiscoverRepositories(config)
+    );
 
     if (is.nonEmptyString(config.writeDiscoveredRepos)) {
       const content = JSON.stringify(config.repositories);
@@ -146,19 +154,32 @@ export async function start(): Promise<number> {
       if (haveReachedLimits()) {
         break;
       }
-      const repoConfig = await getRepositoryConfig(config, repository);
-      if (repoConfig.hostRules) {
-        logger.debug('Reinitializing hostRules for repo');
-        hostRules.clear();
-        repoConfig.hostRules.forEach((rule) => hostRules.add(rule));
-        repoConfig.hostRules = [];
-      }
-
-      // host rules can change concurrency
-      queue.clear();
-
-      await repositoryWorker.renovateRepository(repoConfig);
-      setMeta({});
+      await instrument(
+        'repository',
+        async () => {
+          const repoConfig = await getRepositoryConfig(config, repository);
+          if (repoConfig.hostRules) {
+            logger.debug('Reinitializing hostRules for repo');
+            hostRules.clear();
+            repoConfig.hostRules.forEach((rule) => hostRules.add(rule));
+            repoConfig.hostRules = [];
+          }
+
+          // host rules can change concurrency
+          queue.clear();
+
+          await repositoryWorker.renovateRepository(repoConfig);
+          setMeta({});
+        },
+        {
+          attributes: {
+            repository:
+              typeof repository === 'string'
+                ? repository
+                : repository.repository,
+          },
+        }
+      );
     }
   } catch (err) /* istanbul ignore next */ {
     if (err.message.startsWith('Init: ')) {
diff --git a/lib/workers/repository/index.ts b/lib/workers/repository/index.ts
index 03b70d28b750afc6d3a07f4ad318907d02f602e6..d59d4bab40f6af725e8aae19dc093be8f1daf170 100644
--- a/lib/workers/repository/index.ts
+++ b/lib/workers/repository/index.ts
@@ -3,6 +3,7 @@ import { GlobalConfig } from '../../config/global';
 import { applySecretsToConfig } from '../../config/secrets';
 import type { RenovateConfig } from '../../config/types';
 import { pkg } from '../../expose.cjs';
+import { instrument } from '../../instrumentation';
 import { logger, setMeta } from '../../logger';
 import { removeDanglingContainers } from '../../util/exec/docker';
 import { deleteLocalFile, privateCacheDir } from '../../util/fs';
@@ -42,16 +43,22 @@ export async function renovateRepository(
     logger.debug('Using localDir: ' + localDir);
     config = await initRepo(config);
     addSplit('init');
-    const { branches, branchList, packageFiles } = await extractDependencies(
-      config
+    const { branches, branchList, packageFiles } = await instrument(
+      'extract',
+      () => extractDependencies(config)
     );
     if (
       GlobalConfig.get('dryRun') !== 'lookup' &&
       GlobalConfig.get('dryRun') !== 'extract'
     ) {
-      await ensureOnboardingPr(config, packageFiles, branches);
+      await instrument('onboarding', () =>
+        ensureOnboardingPr(config, packageFiles, branches)
+      );
       addSplit('onboarding');
-      const res = await updateRepo(config, branches);
+
+      const res = await instrument('update', () =>
+        updateRepo(config, branches)
+      );
       setMeta({ repository: config.repository });
       addSplit('update');
       await setBranchCache(branches);
diff --git a/package.json b/package.json
index 0b93ce3c4bbc5b0600b99a877a00276a26bddb4e..31241f778e3479875f9f914c9b413c13cc18d755 100644
--- a/package.json
+++ b/package.json
@@ -145,6 +145,16 @@
     "@cheap-glitch/mi-cron": "1.0.1",
     "@iarna/toml": "2.2.5",
     "@renovatebot/osv-offline": "1.0.5",
+    "@opentelemetry/api": "1.2.0",
+    "@opentelemetry/context-async-hooks": "1.6.0",
+    "@opentelemetry/exporter-trace-otlp-http": "0.32.0",
+    "@opentelemetry/instrumentation": "0.32.0",
+    "@opentelemetry/instrumentation-bunyan": "0.29.0",
+    "@opentelemetry/instrumentation-http": "0.32.0",
+    "@opentelemetry/resources": "1.6.0",
+    "@opentelemetry/sdk-trace-base": "1.6.0",
+    "@opentelemetry/sdk-trace-node": "1.6.0",
+    "@opentelemetry/semantic-conventions": "1.6.0",
     "@renovatebot/pep440": "2.1.5",
     "@renovatebot/ruby-semver": "1.1.6",
     "@sindresorhus/is": "4.6.0",
diff --git a/yarn.lock b/yarn.lock
index e3f08ff25974355faf89b48de04310f3421b5ba9..4c4d2d3b531d046d3b5f4a55445c8a76006cfe4a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2313,10 +2313,172 @@
   resolved "https://registry.yarnpkg.com/@openpgp/web-stream-tools/-/web-stream-tools-0.0.12.tgz#8a80170c7590ecee2af4220c5cb1efe1a02946eb"
   integrity sha512-OGQ7a7UlALBOPxTWqLjPoa6YjHtLYF5ETb3zwx2A2Qq3YsstJX4q/OvYx60v2MavmBBJELsBQNugdJu0uMBhSw==
 
+"@opentelemetry/api-metrics@0.29.2":
+  version "0.29.2"
+  resolved "https://registry.yarnpkg.com/@opentelemetry/api-metrics/-/api-metrics-0.29.2.tgz#daa823e0965754222b49a6ae6133df8b39ff8fd2"
+  integrity sha512-yRdF5beqKuEdsPNoO7ijWCQ9HcyN0Tlgicf8RS6gzGOI54d6Hj7yKquJ6+X9XV+CSRbRWJYb+lOsXyso7uyX2g==
+  dependencies:
+    "@opentelemetry/api" "^1.0.0"
+
+"@opentelemetry/api-metrics@0.32.0":
+  version "0.32.0"
+  resolved "https://registry.yarnpkg.com/@opentelemetry/api-metrics/-/api-metrics-0.32.0.tgz#0f09f78491a4b301ddf54a8b8a38ffa99981f645"
+  integrity sha512-g1WLhpG8B6iuDyZJFRGsR+JKyZ94m5LEmY2f+duEJ9Xb4XRlLHrZvh6G34OH6GJ8iDHxfHb/sWjJ1ZpkI9yGMQ==
+  dependencies:
+    "@opentelemetry/api" "^1.0.0"
+
+"@opentelemetry/api@1.2.0":
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.2.0.tgz#89ef99401cde6208cff98760b67663726ef26686"
+  integrity sha512-0nBr+VZNKm9tvNDZFstI3Pq1fCTEDK5OZTnVKNvBNAKgd0yIvmwsP4m61rEv7ZP+tOUjWJhROpxK5MsnlF911g==
+
+"@opentelemetry/api@^1.0.0":
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.1.0.tgz#563539048255bbe1a5f4f586a4a10a1bb737f44a"
+  integrity sha512-hf+3bwuBwtXsugA2ULBc95qxrOqP2pOekLz34BJhcAKawt94vfeNyUKpYc0lZQ/3sCP6LqRa7UAdHA7i5UODzQ==
+
+"@opentelemetry/context-async-hooks@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@opentelemetry/context-async-hooks/-/context-async-hooks-1.6.0.tgz#e3839bf8c010d7e660d9762fe2407171d352b88e"
+  integrity sha512-7xpyfHfuHnuCm5eAk4j4MIZjRM/hsiLlKEFIwI8SXNlbxqmb/JRrntOjN/AT+KeihkMw+xAx+0lsYPUANCSaQw==
+
+"@opentelemetry/core@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.6.0.tgz#c55f8ab7496acef7dbd8c4eedef6a4d4a0143c95"
+  integrity sha512-MsEhsyCTfYme6frK8/AqEWwbS9SB3Ta5bjgz4jPQJjL7ijUM3JiLVvqh/kHo1UlUjbUbLmGG7jA5Nw4d7SMcLQ==
+  dependencies:
+    "@opentelemetry/semantic-conventions" "1.6.0"
+
+"@opentelemetry/exporter-trace-otlp-http@0.32.0":
+  version "0.32.0"
+  resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.32.0.tgz#55773290a221855c4e8c422e8fb5e7ff4aa5f04e"
+  integrity sha512-8n44NDoEFoYG3mMToZxNyUKkHSGfzSShw6I2V5FApcH7rid20LmKiNuzc7lACneDIZBld+GGpLRuFhWniW8JhA==
+  dependencies:
+    "@opentelemetry/core" "1.6.0"
+    "@opentelemetry/otlp-exporter-base" "0.32.0"
+    "@opentelemetry/otlp-transformer" "0.32.0"
+    "@opentelemetry/resources" "1.6.0"
+    "@opentelemetry/sdk-trace-base" "1.6.0"
+
+"@opentelemetry/instrumentation-bunyan@0.29.0":
+  version "0.29.0"
+  resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-bunyan/-/instrumentation-bunyan-0.29.0.tgz#04132ef917e39200d76331e32b36a968bafbfbd3"
+  integrity sha512-i1FZ+W96vQCIpkMKPZW0HOA79ve9PLIcTAFH0adU/CvtRRMSxyKPTKzWMGHcWr6DueKIPEorpMG+nO2Z/yk9iQ==
+  dependencies:
+    "@opentelemetry/instrumentation" "^0.29.2"
+    "@types/bunyan" "1.8.7"
+
+"@opentelemetry/instrumentation-http@0.32.0":
+  version "0.32.0"
+  resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-http/-/instrumentation-http-0.32.0.tgz#63ea9e3a3d114a7e3f922e3a39b57afa874e6478"
+  integrity sha512-EbNdJl6IjouphbxPVGV8/utiqB2DhveyH5TD6vxjc2OXlQ3A/mKg3fYSSWB+rYQBuuli+jWQfBJe2ntOFZtTMw==
+  dependencies:
+    "@opentelemetry/core" "1.6.0"
+    "@opentelemetry/instrumentation" "0.32.0"
+    "@opentelemetry/semantic-conventions" "1.6.0"
+    semver "^7.3.5"
+
+"@opentelemetry/instrumentation@0.32.0":
+  version "0.32.0"
+  resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.32.0.tgz#27c5975a323a2ba83d9bf2ea8b11faaab37c5827"
+  integrity sha512-y6ADjHpkUz/v1nkyyYjsQa/zorhX+0qVGpFvXMcbjU4sHnBnC02c6wcc93sIgZfiQClIWo45TGku1KQxJ5UUbQ==
+  dependencies:
+    "@opentelemetry/api-metrics" "0.32.0"
+    require-in-the-middle "^5.0.3"
+    semver "^7.3.2"
+    shimmer "^1.2.1"
+
+"@opentelemetry/instrumentation@^0.29.2":
+  version "0.29.2"
+  resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.29.2.tgz#70e6d4e1a84508f5e9d8c7c426adcd7b0dba6c95"
+  integrity sha512-LXx5V0ONNATQFCE8C5uqnxWSm4rcXLssdLHdXjtGdxRmURqj/JO8jYefqXCD0LzsqEQ6yxOx2GZ0dgXvhBVdTw==
+  dependencies:
+    "@opentelemetry/api-metrics" "0.29.2"
+    require-in-the-middle "^5.0.3"
+    semver "^7.3.2"
+    shimmer "^1.2.1"
+
+"@opentelemetry/otlp-exporter-base@0.32.0":
+  version "0.32.0"
+  resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.32.0.tgz#37dde162835a8fd23fa040f07e2938deb335fc4b"
+  integrity sha512-Dscxu4VNKrkD1SwGKdc7bAtLViGFJC8ah6Dr/vZn22NFHXSa53lSzDdTKeSTNNWH9sCGu/65LS45VMd4PsRvwQ==
+  dependencies:
+    "@opentelemetry/core" "1.6.0"
+
+"@opentelemetry/otlp-transformer@0.32.0":
+  version "0.32.0"
+  resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-transformer/-/otlp-transformer-0.32.0.tgz#652c8f4c56c95f7d7ec39e20573b885d27ca13f1"
+  integrity sha512-PFAqfKgJpTOZryPe1UMm7R578PLxsK0wCAuKSt6m8v1bN/4DO8DX4HD7k3mYGZVU5jNg8tVZSwyIpY6ryrHDMQ==
+  dependencies:
+    "@opentelemetry/api-metrics" "0.32.0"
+    "@opentelemetry/core" "1.6.0"
+    "@opentelemetry/resources" "1.6.0"
+    "@opentelemetry/sdk-metrics" "0.32.0"
+    "@opentelemetry/sdk-trace-base" "1.6.0"
+
+"@opentelemetry/propagator-b3@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@opentelemetry/propagator-b3/-/propagator-b3-1.6.0.tgz#db0dee4f28cb4f1830f3cd35013b652b8078f355"
+  integrity sha512-azs3aCIFrr3qkA/6lNIAYJ+wgDQ6cFoyeHVcZXP0E96AiOeVqtAu5ZXSA63Cw/63pSw0Itmx6CHUGu41enc0TQ==
+  dependencies:
+    "@opentelemetry/core" "1.6.0"
+
+"@opentelemetry/propagator-jaeger@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@opentelemetry/propagator-jaeger/-/propagator-jaeger-1.6.0.tgz#e3e910d71967efb7923674ac407b14c117ea7f31"
+  integrity sha512-QgvWVgRS+APP7aHGPHgKo7HXJg2BbwW394kDNW1HeIxrywliUdAk8h5SJ/VGehy/dTzCFwbDd5Y3TMQRUNCHDg==
+  dependencies:
+    "@opentelemetry/core" "1.6.0"
+
+"@opentelemetry/resources@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.6.0.tgz#9756894131b9b0dfbcc0cecb5d4bd040d9c1b09d"
+  integrity sha512-07GlHuq72r2rnJugYVdGumviQvfrl8kEPidkZSVoseLVfIjV7nzxxt5/vqs9pK7JItWOrvjRdr/jTBVayFBr/w==
+  dependencies:
+    "@opentelemetry/core" "1.6.0"
+    "@opentelemetry/semantic-conventions" "1.6.0"
+
+"@opentelemetry/sdk-metrics@0.32.0":
+  version "0.32.0"
+  resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-metrics/-/sdk-metrics-0.32.0.tgz#463cd3a2b267f044db9aaab85887a171710345a0"
+  integrity sha512-zC9RCOIsXRqOHWmWfcxArtDHbip2/jaIH1yu/OKau/shDZYFluAxY6zAEYIb4YEAzKKEF+fpaoRgpodDWNGVGA==
+  dependencies:
+    "@opentelemetry/api-metrics" "0.32.0"
+    "@opentelemetry/core" "1.6.0"
+    "@opentelemetry/resources" "1.6.0"
+    lodash.merge "4.6.2"
+
+"@opentelemetry/sdk-trace-base@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.6.0.tgz#8b1511c0b0f3e6015e345f5ed4a683adf03e3e3c"
+  integrity sha512-yx/uuzHdT0QNRSEbCgXHc0GONk90uvaFcPGaNowIFSl85rTp4or4uIIMkG7R8ckj8xWjDSjsaztH6yQxoZrl5g==
+  dependencies:
+    "@opentelemetry/core" "1.6.0"
+    "@opentelemetry/resources" "1.6.0"
+    "@opentelemetry/semantic-conventions" "1.6.0"
+
+"@opentelemetry/sdk-trace-node@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.6.0.tgz#fb15e030b19931f1cd6ad755add2bfd77fb915b6"
+  integrity sha512-rE6hL68QuSS2vDXZBhNiAkeN7kzDGrrJdzGeeyxQahmugnId5jmu1OYERIeULiKHQVkBjvycfmwPYsCL+3PsHQ==
+  dependencies:
+    "@opentelemetry/context-async-hooks" "1.6.0"
+    "@opentelemetry/core" "1.6.0"
+    "@opentelemetry/propagator-b3" "1.6.0"
+    "@opentelemetry/propagator-jaeger" "1.6.0"
+    "@opentelemetry/sdk-trace-base" "1.6.0"
+    semver "^7.3.5"
+
+"@opentelemetry/semantic-conventions@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.6.0.tgz#ed410c9eb0070491cff9fe914246ce41f88d6f74"
+  integrity sha512-aPfcBeLErM/PPiAuAbNFLN5sNbZLc3KZlar27uohllN8Zs6jJbHyJU1y7cMA6W/zuq+thkaG8mujiS+3iD/FWQ==
+
 "@pkgr/utils@^2.3.1":
   version "2.3.1"
   resolved "https://registry.yarnpkg.com/@pkgr/utils/-/utils-2.3.1.tgz#0a9b06ffddee364d6642b3cd562ca76f55b34a03"
   integrity sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==
+
   dependencies:
     cross-spawn "^7.0.3"
     is-glob "^4.0.3"
@@ -2733,6 +2895,13 @@
   dependencies:
     "@babel/types" "^7.3.0"
 
+"@types/bunyan@1.8.7":
+  version "1.8.7"
+  resolved "https://registry.yarnpkg.com/@types/bunyan/-/bunyan-1.8.7.tgz#63cc65b5ecff6217d1509409a575e7b991f80831"
+  integrity sha512-jaNt6xX5poSmXuDAkQrSqx2zkR66OrdRDuVnU8ldvn3k/Ci/7Sf5nooKspQWimDnw337Bzt/yirqSThTjvrHkg==
+  dependencies:
+    "@types/node" "*"
+
 "@types/bunyan@1.8.8":
   version "1.8.8"
   resolved "https://registry.yarnpkg.com/@types/bunyan/-/bunyan-1.8.8.tgz#8d6d33f090f37c07e2a80af30ae728450a101008"
@@ -7208,7 +7377,7 @@ lodash.memoize@4.x:
   resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
   integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==
 
-lodash.merge@^4.6.2:
+lodash.merge@4.6.2, lodash.merge@^4.6.2:
   version "4.6.2"
   resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
   integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
@@ -7649,6 +7818,11 @@ modify-values@^1.0.0:
   resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022"
   integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==
 
+module-details-from-path@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b"
+  integrity sha1-EUyUlnPiqKNenTV4hSeqN7Z52is=
+
 moment@^2.19.3:
   version "2.29.4"
   resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
@@ -8897,6 +9071,15 @@ require-directory@^2.1.1:
   resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
   integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
 
+require-in-the-middle@^5.0.3:
+  version "5.1.0"
+  resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-5.1.0.tgz#b768f800377b47526d026bbf5a7f727f16eb412f"
+  integrity sha512-M2rLKVupQfJ5lf9OvqFGIT+9iVLnTmjgbOmpil12hiSQNn5zJTKGPoIisETNjfK+09vP3rpm1zJajmErpr2sEQ==
+  dependencies:
+    debug "^4.1.1"
+    module-details-from-path "^1.0.3"
+    resolve "^1.12.0"
+
 resolve-alpn@^1.0.0:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9"
@@ -8924,7 +9107,7 @@ resolve.exports@^1.1.0:
   resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9"
   integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==
 
-resolve@^1.1.6, resolve@^1.10.0, resolve@^1.20.0, resolve@^1.22.0:
+resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.20.0, resolve@^1.22.0:
   version "1.22.1"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
   integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
@@ -9157,6 +9340,11 @@ shelljs@0.8.5:
     interpret "^1.0.0"
     rechoir "^0.6.2"
 
+shimmer@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337"
+  integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==
+
 shlex@2.1.2:
   version "2.1.2"
   resolved "https://registry.yarnpkg.com/shlex/-/shlex-2.1.2.tgz#5b5384d603885281c1dee05d56975865edddcba0"