Node.js - pg

You will need your project token for initializing your library. You can get your project token from Projects Page

1. Install

Run the following command to install the SDK and pg if it is not installed:
npm install --save pg @metis-data/pg-interceptor
If it is the first time you set up opentelemetry, some more opentelemetry packages are required:
npm install --save @opentelemetry/api \
@opentelemetry/context-async-hooks \
@opentelemetry/instrumentation \
@opentelemetry/instrumentation-http \
@opentelemetry/resources \
@opentelemetry/sdk-trace-base \
@opentelemetry/semantic-conventions

2. Setup tracer

In opentelemetry, tracing should be set before application bootstrap.
  1. 1.
    Create tracer file and add the following code:
TypeScript
JavaScript
1
// tracer.ts
2
import opentelemetry from '@opentelemetry/api';
3
import { registerInstrumentations } from '@opentelemetry/instrumentation';
4
import {
5
BasicTracerProvider,
6
BatchSpanProcessor,
7
ConsoleSpanExporter,
8
SimpleSpanProcessor,
9
} from '@opentelemetry/sdk-trace-base';
10
import {
11
getMetisExporter,
12
MetisHttpInstrumentation,
13
MetisPgInstrumentation,
14
getResource,
15
} from '@metis-data/pg-interceptor';
16
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
17
18
let tracerProvider: BasicTracerProvider;
19
const connectionString = process.env.PG_CONNECTION_STRING;
20
21
export const startMetisInstrumentation = () => {
22
tracerProvider = new BasicTracerProvider({
23
resource: getResource(process.env.METIS_SERVICE_NAME, 'service-version'),
24
});
25
26
const metisExporter = getMetisExporter(process.env.METIS_API_KEY);
27
28
tracerProvider.addSpanProcessor(
29
new BatchSpanProcessor(metisExporter)
30
);
31
32
if (process.env.OTEL_DEBUG) {
33
tracerProvider.addSpanProcessor(
34
new SimpleSpanProcessor(new ConsoleSpanExporter())
35
);
36
}
37
38
const contextManager = new AsyncHooksContextManager();
39
40
contextManager.enable();
41
opentelemetry.context.setGlobalContextManager(contextManager);
42
43
tracerProvider.register();
44
45
// Urls regex to exclude from instrumentation
46
const excludeUrls = [/favicon.ico/];
47
registerInstrumentations({
48
instrumentations: [
49
new MetisPgInstrumentation({ connectionString }),
50
new MetisHttpInstrumentation(excludeUrls)
51
],
52
});
53
};
1
// tracer.js
2
import opentelemetry from '@opentelemetry/api';
3
import { registerInstrumentations } from '@opentelemetry/instrumentation';
4
import {
5
BasicTracerProvider,
6
BatchSpanProcessor,
7
ConsoleSpanExporter,
8
SimpleSpanProcessor,
9
} from '@opentelemetry/sdk-trace-base';
10
import {
11
getMetisExporter,
12
MetisHttpInstrumentation,
13
MetisPgInstrumentation,
14
getResource,
15
} from '@metis-data/pg-interceptor';
16
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
17
18
let tracerProvider;
19
const connectionString = process.env.PG_CONNECTION_STRING;
20
21
export const startMetisInstrumentation = () => {
22
tracerProvider = new BasicTracerProvider({
23
resource: getResource(process.env.METIS_SERVICE_NAME, 'service-version'),
24
});
25
26
const metisExporter = getMetisExporter(process.env.METIS_API_KEY);
27
28
tracerProvider.addSpanProcessor(
29
new BatchSpanProcessor(metisExporter)
30
);
31
32
if (process.env.OTEL_DEBUG) {
33
tracerProvider.addSpanProcessor(
34
new SimpleSpanProcessor(new ConsoleSpanExporter())
35
);
36
}
37
38
const contextManager = new AsyncHooksContextManager();
39
40
contextManager.enable();
41
opentelemetry.context.setGlobalContextManager(contextManager);
42
43
tracerProvider.register();
44
45
// Urls regex to exclude from instrumentation
46
const excludeUrls = [/favicon.ico/];
47
registerInstrumentations({
48
instrumentations: [
49
new MetisPgInstrumentation({ connectionString }),
50
new MetisHttpInstrumentation(excludeUrls)
51
],
52
});
53
};
Setup
  • Line 19 - A valid connection string is required postgres://user:[email protected]:port/database
If for any reason connectionString is not defined yet, please follow step 3.
  • Line 46 - If you wish to exclude certain incoming urls from being instrumented, it is possible to add their Regex here. For example: /favicon.ico/ will ignore this route calls.
  1. 2.
    After creating the tracer it should be called from application root where the bootstrap happens:
1
// main.ts
2
import { startMetisInstrumentation } from './tracer';
3
startMetisInstrumentation();
4
5
// imports...
6
// bootstrap()

Environment Variables

Variable Name
Description
METIS_API_KEY
<String> API Key to use
METIS_ENVIRONMENT
<String> Text used to identify the source that sends the instrumentation data.
We suggest you Read This Page to fully understand this feature
METIS_PLAN_MODE
<String> Can be set to one of [none, actual, estimated] to choose which query plan to fetch, default actual.
METIS_DISABLED
<Boolean> If True Metis Instrumentation is fully disabled. We strongly advise to disable the instrumentation when in production to prevent sensitive data from leaving your organization's database.
METIS_SERVICE_NAME
<String> Gives ability to distinguish between services. Useful when working with Micro Services.
OTEL_DEBUG
<Boolean> If True, console exporter is added to print incoming spans to console.

3. Setup connection (optional)

If for any reason (like dynamic address) the connection string is not available during the tracer setup, you can define it later with the following code:
import { setPgConnection } from '@metis-data/pg-interceptor';
// When the connectionString available
setPgConnection(connectionString);
Until the connection will be defined, instrumentation will work and show the SQL queries, but won't show the queries plans and the insight derived from them.

4. Send Data

Now you can run your application as you normally would, and interact with it in a manner that causes the server to interact with your database.

5. Check for Success

Open Up Metis Recent Activity to view your insights!