This package is in the form of Sequelize.Client.prototype.query
wrapper whose purpose is to augment a SQL statement right before execution, with
information about the controller and user code to help correlate them with SQL statements emitted by Sequelize.js.
Besides plain sequelize.js wrapping, we also provide a wrapper for the following frameworks:
We can add integration into our applications in the following ways:
Please read installing sqlcommenter-nodejs from source
Add to your package.json the dependency
{
"@opentelemetry/sqlcommenter-sequelize": "*"
}
and then run npm install
to get the latest version or
npm install @opentelemetry/sqlcommenter-sequelize --save
const {wrapSequelize} = require('@opentelemetry/sqlcommenter-sequelize');
const Sequelize = require('sequelize');
// Create the sequelize client.
const sequelize = new Sequelize(options);
// Finally wrap the sequelize client.
wrapSequelize(sequelize);
This wrapper/middleware can be used as is or better with express.js
const {wrapSequelizeAsMiddleware} = require('@opentelemetry/sqlcommenter-sequelize');
const Sequelize = require('sequelize');
const sequelize = new Sequelize(options);
const app = require('express')();
// Use the sequelize+express middleware.
app.use(wrapSequelizeAsMiddleware(sequelize));
In the database server logs, the comment’s fields are:
route='%5E%2Fpolls%2F'
key='value'
=
) sign e.g route='%5Epolls/%24'
. so should be URL-unquotedField | Format | Description | Example |
---|---|---|---|
client_timezone |
<string> |
URL quoted name of the timezone used when converting a date from the database into a JavaScript date | '+00:00' |
db_driver |
<sequelize> |
URL quoted name and version of the database driver | db_driver='sequelize' |
route |
<the route used> |
URL quoted route used to match the express.js controller | route='%5E%2Fpolls%2F |
traceparent |
<traceparent header> |
URL quoted W3C traceparent header |
traceparent='00-3e2914ebce6af09508dd1ff1128493a8-81d09ab4d8cde7cf-01' |
tracestate |
<tracestate header> |
URL quoted W3C tracestate header |
tracestate='rojo%253D00f067aa0ba902b7%2Ccongo%253Dt61rcWkgMzE' |
When creating the middleware, one can optionally configure the injected
comments by passing in the include
and options
objects:
wrapMainSequelizeAsMiddleware(Sequelize, include={...}, options={...});
include
configA map of values to be optionally included in the SQL comments.
Field | On by default |
---|---|
client_timezone | ❌ |
db_driver | ❌ |
route | ✔ |
traceparent | ❌ |
tracestate | ❌ |
options
configA configuration object specifying where to collect trace data from. Accepted
fields are: TraceProvider: Should be either OpenCensus
or OpenTelemetry
,
indicating which library to collect trace context from.
Field | Possible values |
---|---|
TraceProvider | OpenCensus or OpenTelemetry |
wrapMainSequelizeAsMiddleware(
Sequelize,
include={ traceparent: true, tracestate: true },
options={ TraceProvider: 'OpenTelemetry' }
);
wrapMainSequelizeAsMiddleware(Sequelize, include={client_timezone: true});
wrapMainSequelizeAsMiddleware(Sequelize, include={route: true});
wrapMainSequelizeAsMiddleware(Sequelize, include={db_driver: true});
// Manually set all the variables.
wrapMainSequelizeAsMiddleware(
Sequelize,
include={
client_timezone: true,
db_driver: true,
route: true,
traceparent: true,
tracestate: true,
},
options={ TraceProvider: 'OpenTelemetry' }
);
Check out a full express + opentelemetry example here.
// In file app.js.
const tracing = require('@opencensus/nodejs');
const {B3Format} = require('@opencensus/propagation-b3');
const {ZipkinTraceExporter} = require('@opencensus/exporter-zipkin');
const {wrapSequelizeAsMiddleware} = require('@opentelemetry/sqlcommenter-sequelize');
const Sequelize = require('sequelize');
const express = require('express');
const exporter = new ZipkinTraceExporter({
url: process.env.ZIPKIN_TRACE_URL || 'localhost://9411/api/v2/spans',
serviceName: 'trace-542'
});
const b3 = new B3Format();
const traceOptions = {
samplingRate: 1, // Always sample
propagation: b3,
exporter: exporter
};
// start tracing
tracing.start(traceOptions);
// Using a connection URI
const sequelize = new Sequelize('postgres://user:pass@example.com:5432/dbname');
const app = express();
const port = process.env.APP_PORT || 3000;
// Use the sequelize+express middleware with trace attributes
app.use(wrapSequelizeAsMiddleware(
sequelize,
{ traceparent: true, tracestate: true, route: false },
{ TraceProvider: "OpenCensus" },
));
app.get('/', (req, res) => res.send('Hello, sqlcommenter-nodejs!!'));
app.get('^/polls/:param', function(req, res) {
sequelize.query('SELECT * from polls_question').then(function(polls) {
const blob = JSON.stringify(polls);
res.send(blob);
}).catch(function(err) {
console.log(err);
res.send(500);
});
});
app.listen(port, () => console.log(`Application listening on ${port}`));
// In file app.js.
const { NodeTracerProvider } = require("@opentelemetry/node");
const { BatchSpanProcessor } = require("@opentelemetry/tracing");
const {
TraceExporter,
} = require("@google-cloud/opentelemetry-cloud-trace-exporter");
const tracerProvider = new NodeTracerProvider();
// Export to Google Cloud Trace
tracerProvider.addSpanProcessor(
new BatchSpanProcessor(new TraceExporter({ logger }), {
bufferSize: 500,
bufferTimeout: 5 * 1000,
})
);
tracerProvider.register();
// OpenTelemetry initialization should happen before importing any libraries
// that it instruments
const { Sequelize } = require("sequelize");
const {
wrapSequelizeAsMiddleware,
} = require("@opentelemetry/sqlcommenter-sequelize");
const sequelize = new Sequelize("postgres://user:pass@example.com:5432/dbname");
const express = require("express");
const app = express();
const port = process.env.APP_PORT || 3000;
// SQLCommenter express middleware injects the route into the traces
app.use(
wrapSequelizeAsMiddleware(
sequelize,
{
client_timezone: true,
db_driver: true,
route: true,
traceparent: true,
tracestate: true,
},
{ TraceProvider: "OpenTelemetry" }
)
);
app.get("/", (req, res) => res.send("Hello, sqlcommenter-nodejs!!"));
app.get("^/polls/:param", function (req, res) {
sequelize
.query("SELECT * from polls_question")
.then(function (polls) {
const blob = JSON.stringify(polls);
res.send(blob);
})
.catch(function (err) {
console.log(err);
res.send(500);
});
});
app.listen(port, () => console.log(`Application listening on ${port}`));
// In file app.js.
const Sequelize = require('sequelize');
const {wrapSequelizeAsMiddleware} = require('@opentelemetry/sqlcommenter-sequelize');
const express = require('express');
// Using a connection URI
const sequelize = new Sequelize('postgres://user:pass@example.com:5432/dbname');
const app = express();
const port = process.env.APP_PORT || 3000;
// Use the sequelize+express middleware with route
app.use(wrapSequelizeAsMiddleware(sequelize, {route: true}));
app.get('/', (req, res) => res.send('Hello, sqlcommenter-nodejs!!'));
app.get('^/polls/:param', function(req, res) {
sequelize.query('SELECT * from polls_question').then(function(polls) {
const blob = JSON.stringify(polls);
res.send(blob);
}).catch(function(err) {
console.log(err);
res.send(500);
});
});
app.listen(port, () => console.log(`Application listening on ${port}`));
// In file app.js
const Sequelize = require('sequelize');
const {wrapSequelizeAsMiddleware} = require('@opentelemetry/sqlcommenter-sequelize');
const express = require('express');
// Using a connection URI
const sequelize = new Sequelize('postgres://user:pass@example.com:5432/dbname');
const app = express();
const port = process.env.APP_PORT || 3000;
// Use the sequelize+express middleware with db driver and timezone
app.use(wrapSequelizeAsMiddleware(sequelize, {
db_driver: true,
client_timezone: true
}));
app.get('/', (req, res) => res.send('Hello, sqlcommenter-nodejs!!'));
app.get('^/polls/:param', function(req, res) {
sequelize.query('SELECT * from polls_question').then(function(polls) {
const blob = JSON.stringify(polls);
res.send(blob);
}).catch(function(err) {
console.log(err);
res.send(500);
});
});
app.listen(port, () => console.log(`Application listening on ${port}`));
// In file app.js.
const tracing = require('@opencensus/nodejs');
const {B3Format} = require('@opencensus/propagation-b3');
const {ZipkinTraceExporter} = require('@opencensus/exporter-zipkin');
const Sequelize = require('sequelize');
const {wrapSequelizeAsMiddleware} = require('@opentelemetry/sqlcommenter-sequelize');
const express = require('express');
const exporter = new ZipkinTraceExporter({
url: process.env.ZIPKIN_TRACE_URL || 'localhost:9411/api/v2/spans',
serviceName: 'trace-542'
});
const b3 = new B3Format();
const traceOptions = {
samplingRate: 1, // Always sample
propagation: b3,
exporter: exporter
};
// start tracing
tracing.start(traceOptions);
// Using a connection URI
const sequelize = new Sequelize('postgres://user:pass@example.com:5432/dbname');
const app = express();
const port = process.env.APP_PORT || 3000;
// Use the sequelize+express middleware with all attributes set
app.use(wrapSequelizeAsMiddleware(
sequelize,
{
traceparent: true,
tracestate: true,
// Optional
route: false,
db_driver: false,
client_timezone: false
},
{
TraceProvider: "OpenCensus",
},
));
app.get('/', (req, res) => res.send('Hello, sqlcommenter-nodejs!!'));
app.get('^/polls/:param', function(req, res) {
sequelize.query('SELECT * from polls_question').then(function(polls) {
const blob = JSON.stringify(polls);
res.send(blob);
}).catch(function(err) {
console.log(err);
res.send(500);
});
});
app.listen(port, () => console.log(`Application listening on ${port}`));
which after running by
$ node app.js
Application listening on 3000
On making a request to that server at http://localhost:3000/polls/1000
, the PostgreSQL logs show:
2019-06-03 14:32:10.842 PDT [32004] LOG: statement: SELECT * from polls_question
/*traceparent='00-11000000000000ff-020000ee-01',tracestate='brazzaville=t61rcWkgMzE,rondo=00f067aa0ba902b7'*/
2019-06-03 14:32:10.842 PDT [32004] LOG: statement: SELECT * from polls_question
/*route='%5E%2Fpolls%2F%1000'*/
2019-06-03 14:32:10.842 PDT [32004] LOG: statement: SELECT * from polls_question
/*client_timezone:'%2B00%3A00',db_driver='sequelize%3A0.0.1'*/
2019-06-03 14:32:10.842 PDT [32004] LOG: statement: SELECT * from polls_question
/*client_timezone:'%2B00%3A00',db_driver='sequelize%3A0.0.1',route='%5E%2Fpolls%2F%1000',traceparent='00-11000000000000ff-020000ee-01',tracestate='brazzaville=t61rcWkgMzE,rondo=00f067aa0ba902b7'*/
Resource | URL |
---|---|
@opentelemetry/sqlcommenter-sequelize on npm | https://www.npmjs.com/package/@opentelemetry/sqlcommenter-sequelize |
express.js | https://expressjs.com/ |