Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(mysql): add enhancedDatabaseReporting to mysql #1337

Merged
merged 25 commits into from
Jan 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
4a172de
fix(mysql): add DbStatementSerializer tp mysql
haddasbronfman Dec 29, 2022
6bf3383
fix(mysql): lint
haddasbronfman Dec 29, 2022
a6befae
fix(mysql): lint 2
haddasbronfman Dec 29, 2022
5452306
fix(mysql db.statement): revert to regular function behaviour
haddasbronfman Jan 1, 2023
b4bb965
Merge branch 'main' into mysql-db-statement
haddasbronfman Jan 1, 2023
9f09d7e
fix(mysql db.statement): improve code
haddasbronfman Jan 1, 2023
872dbc4
Merge branch 'mysql-db-statement' of github.com:haddasbronfman/opente…
haddasbronfman Jan 1, 2023
8a39df6
fix(mysql db.statement): use enhancedDatabaseReporting and not dbStat…
haddasbronfman Jan 4, 2023
d7e1db2
fix(mysql db.statement): lint
haddasbronfman Jan 4, 2023
016710d
Merge branch 'main' into mysql-db-statement
haddasbronfman Jan 5, 2023
d18dab0
fix(mysql db.statement): remove format
haddasbronfman Jan 9, 2023
34ac9d1
Merge branch 'mysql-db-statement' of github.com:haddasbronfman/opente…
haddasbronfman Jan 9, 2023
29b5add
fix(mysql db.statement): add enhancedDatabaseReporting to README
haddasbronfman Jan 10, 2023
0170ed4
fix(mysql db.statement): use use template literals
haddasbronfman Jan 10, 2023
4f5a7a3
fix(mysql db.statement): add default to enhancedDatabaseReporting
haddasbronfman Jan 10, 2023
31427f5
fix(mysql db.statement): remove redundant argument
haddasbronfman Jan 10, 2023
f2ca7ca
fix(mysql db.statement): remove redundant argument
haddasbronfman Jan 10, 2023
39afaea
fix(mysql db.statement): lint
haddasbronfman Jan 10, 2023
ad9775e
fix(mysql db.statement): remove format
haddasbronfman Jan 11, 2023
9847ccb
fix(mysql db.statement): lint
haddasbronfman Jan 11, 2023
59ba629
fix(mysql db.statement): lint README
haddasbronfman Jan 11, 2023
941362a
fix(mysql db.statement): fixes
haddasbronfman Jan 11, 2023
1a8864d
fix(mysql db.statement): lint
haddasbronfman Jan 11, 2023
ac9f7dc
Merge branch 'main' into mysql-db-statement
blumamir Jan 15, 2023
75d0fab
Merge branch 'main' into mysql-db-statement
blumamir Jan 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions plugins/node/opentelemetry-instrumentation-mysql/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ registerInstrumentations({

See [examples](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-mysql/examples) for a short example.

### MySQL instrumentation Options

| Options | Type | Default | Description |
| ------- | ---- | --------| ----------- |
| [`enhancedDatabaseReporting`](./src/types.ts#L24) | `boolean` | `false` | If true, an attribute containing the query's parameters will be attached the spans generated to represent the query |
|

## Useful links

- For more information on OpenTelemetry, visit: <https://opentelemetry.io/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Mysql specific attributes not covered by semantic conventions
export enum AttributeNames {
MYSQL_VALUES = 'db.mysql.values',
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,19 @@ import {
DbSystemValues,
SemanticAttributes,
} from '@opentelemetry/semantic-conventions';
import * as mysqlTypes from 'mysql';
import type * as mysqlTypes from 'mysql';
import { AttributeNames } from './AttributeNames';
import { MySQLInstrumentationConfig } from './types';
import {
getConnectionAttributes,
getDbStatement,
getDbValues,
getSpanName,
getPoolName,
} from './utils';
import { VERSION } from './version';
import { UpDownCounter, MeterProvider } from '@opentelemetry/api';

type formatType = typeof mysqlTypes.format;

type getConnectionCallbackType = (
err: mysqlTypes.MysqlError,
connection: mysqlTypes.PoolConnection
Expand Down Expand Up @@ -94,7 +94,7 @@ export class MySQLInstrumentation extends InstrumentationBase<
this._wrap(
moduleExports,
'createConnection',
this._patchCreateConnection(moduleExports.format) as any
this._patchCreateConnection() as any
);

diag.debug('Patching mysql.createPool');
Expand All @@ -104,7 +104,7 @@ export class MySQLInstrumentation extends InstrumentationBase<
this._wrap(
moduleExports,
'createPool',
this._patchCreatePool(moduleExports.format) as any
this._patchCreatePool() as any
);

diag.debug('Patching mysql.createPoolCluster');
Expand All @@ -114,7 +114,7 @@ export class MySQLInstrumentation extends InstrumentationBase<
this._wrap(
moduleExports,
'createPoolCluster',
this._patchCreatePoolCluster(moduleExports.format) as any
this._patchCreatePoolCluster() as any
);

return moduleExports;
Expand All @@ -130,7 +130,7 @@ export class MySQLInstrumentation extends InstrumentationBase<
}

// global export function
private _patchCreateConnection(format: formatType) {
private _patchCreateConnection() {
return (originalCreateConnection: Function) => {
const thisPlugin = this;
diag.debug('MySQLInstrumentation#patch: patched mysql createConnection');
Expand All @@ -144,7 +144,7 @@ export class MySQLInstrumentation extends InstrumentationBase<
thisPlugin._wrap(
originalResult,
'query',
thisPlugin._patchQuery(originalResult, format) as any
thisPlugin._patchQuery(originalResult) as any
);

return originalResult;
Expand All @@ -153,18 +153,18 @@ export class MySQLInstrumentation extends InstrumentationBase<
}

// global export function
private _patchCreatePool(format: formatType) {
private _patchCreatePool() {
return (originalCreatePool: Function) => {
const thisPlugin = this;
diag.debug('MySQLInstrumentation#patch: patched mysql createPool');
return function createPool(_config: string | mysqlTypes.PoolConfig) {
const pool = originalCreatePool(...arguments);

thisPlugin._wrap(pool, 'query', thisPlugin._patchQuery(pool, format));
thisPlugin._wrap(pool, 'query', thisPlugin._patchQuery(pool));
thisPlugin._wrap(
pool,
'getConnection',
thisPlugin._patchGetConnection(pool, format)
thisPlugin._patchGetConnection(pool)
);
thisPlugin._wrap(pool, 'end', thisPlugin._patchPoolEnd(pool));
thisPlugin._setPoolcallbacks(pool, thisPlugin, '');
Expand Down Expand Up @@ -196,7 +196,7 @@ export class MySQLInstrumentation extends InstrumentationBase<
}

// global export function
private _patchCreatePoolCluster(format: formatType) {
private _patchCreatePoolCluster() {
return (originalCreatePoolCluster: Function) => {
const thisPlugin = this;
diag.debug('MySQLInstrumentation#patch: patched mysql createPoolCluster');
Expand All @@ -207,15 +207,15 @@ export class MySQLInstrumentation extends InstrumentationBase<
thisPlugin._wrap(
cluster,
'getConnection',
thisPlugin._patchGetConnection(cluster, format)
thisPlugin._patchGetConnection(cluster)
);
thisPlugin._wrap(cluster, 'add', thisPlugin._patchAdd(cluster, format));
thisPlugin._wrap(cluster, 'add', thisPlugin._patchAdd(cluster));

return cluster;
};
};
}
private _patchAdd(cluster: mysqlTypes.PoolCluster, format: formatType) {
private _patchAdd(cluster: mysqlTypes.PoolCluster) {
return (originalAdd: Function) => {
const thisPlugin = this;
diag.debug('MySQLInstrumentation#patch: patched mysql pool cluster add');
Expand All @@ -241,10 +241,7 @@ export class MySQLInstrumentation extends InstrumentationBase<
}

// method on cluster or pool
private _patchGetConnection(
pool: mysqlTypes.Pool | mysqlTypes.PoolCluster,
format: formatType
) {
private _patchGetConnection(pool: mysqlTypes.Pool | mysqlTypes.PoolCluster) {
return (originalGetConnection: Function) => {
const thisPlugin = this;
diag.debug(
Expand All @@ -264,22 +261,19 @@ export class MySQLInstrumentation extends InstrumentationBase<

if (arguments.length === 1 && typeof arg1 === 'function') {
const patchFn = thisPlugin._getConnectionCallbackPatchFn(
arg1 as getConnectionCallbackType,
format
arg1 as getConnectionCallbackType
);
return originalGetConnection.call(pool, patchFn);
}
if (arguments.length === 2 && typeof arg2 === 'function') {
const patchFn = thisPlugin._getConnectionCallbackPatchFn(
arg2 as getConnectionCallbackType,
format
arg2 as getConnectionCallbackType
);
return originalGetConnection.call(pool, arg1, patchFn);
}
if (arguments.length === 3 && typeof arg3 === 'function') {
const patchFn = thisPlugin._getConnectionCallbackPatchFn(
arg3 as getConnectionCallbackType,
format
arg3 as getConnectionCallbackType
);
return originalGetConnection.call(pool, arg1, arg2, patchFn);
}
Expand All @@ -289,10 +283,7 @@ export class MySQLInstrumentation extends InstrumentationBase<
};
}

private _getConnectionCallbackPatchFn(
cb: getConnectionCallbackType,
format: formatType
) {
private _getConnectionCallbackPatchFn(cb: getConnectionCallbackType) {
const thisPlugin = this;
const activeContext = context.active();
return function (
Expand All @@ -307,7 +298,7 @@ export class MySQLInstrumentation extends InstrumentationBase<
thisPlugin._wrap(
connection,
'query',
thisPlugin._patchQuery(connection, format)
thisPlugin._patchQuery(connection)
);
}
}
Expand All @@ -317,10 +308,7 @@ export class MySQLInstrumentation extends InstrumentationBase<
};
}

private _patchQuery(
connection: mysqlTypes.Connection | mysqlTypes.Pool,
format: formatType
) {
private _patchQuery(connection: mysqlTypes.Connection | mysqlTypes.Pool) {
return (originalQuery: Function): mysqlTypes.QueryFunction => {
const thisPlugin = this;
diag.debug('MySQLInstrumentation: patched mysql query');
Expand All @@ -343,19 +331,29 @@ export class MySQLInstrumentation extends InstrumentationBase<
},
});

let values;

if (Array.isArray(_valuesOrCallback)) {
values = _valuesOrCallback;
} else if (arguments[2]) {
values = [_valuesOrCallback];
}

span.setAttribute(
SemanticAttributes.DB_STATEMENT,
getDbStatement(query, format, values)
blumamir marked this conversation as resolved.
Show resolved Hide resolved
getDbStatement(query)
);

const instrumentationConfig: MySQLInstrumentationConfig =
thisPlugin.getConfig();

if (instrumentationConfig.enhancedDatabaseReporting) {
let values;

if (Array.isArray(_valuesOrCallback)) {
values = _valuesOrCallback;
} else if (arguments[2]) {
values = [_valuesOrCallback];
}

span.setAttribute(
blumamir marked this conversation as resolved.
Show resolved Hide resolved
AttributeNames.MYSQL_VALUES,
getDbValues(query, values)
);
}

const cbIndex = Array.from(arguments).findIndex(
arg => typeof arg === 'function'
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,10 @@

import { InstrumentationConfig } from '@opentelemetry/instrumentation';

export type MySQLInstrumentationConfig = InstrumentationConfig;
export interface MySQLInstrumentationConfig extends InstrumentationConfig {
/**
* If true, an attribute containing the query's parameters will be attached
* the spans generated to represent the query.
blumamir marked this conversation as resolved.
Show resolved Hide resolved
*/
enhancedDatabaseReporting?: boolean;
blumamir marked this conversation as resolved.
Show resolved Hide resolved
}
29 changes: 16 additions & 13 deletions plugins/node/opentelemetry-instrumentation-mysql/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,28 +72,26 @@ function getJDBCString(
}

/**
* Conjures up the value for the db.statement attribute by formatting a SQL query.
*
* @returns the database statement being executed.
*/
export function getDbStatement(
export function getDbStatement(query: string | Query | QueryOptions): string {
if (typeof query === 'string') {
return query;
} else {
return query.sql;
}
}

export function getDbValues(
query: string | Query | QueryOptions,
format: (
sql: string,
values: any[],
stringifyObjects?: boolean,
timeZone?: string
) => string,
values?: any[]
): string {
if (typeof query === 'string') {
return values ? format(query, values) : query;
return arrayStringifyHelper(values);
} else {
// According to https://github.com/mysqljs/mysql#performing-queries
// The values argument will override the values in the option object.
return values || query.values
? format(query.sql, values || query.values)
: query.sql;
return arrayStringifyHelper(values || query.values);
}
}

Expand All @@ -110,6 +108,11 @@ export function getSpanName(query: string | Query | QueryOptions): string {
return query.split(' ')[0];
}

export function arrayStringifyHelper(arr: Array<unknown> | undefined): string {
if (arr) return `[${arr.toString()}]`;
return '';
}

export function getPoolName(pool: mysqlTypes.Pool): string {
const c = pool.config.connectionConfig;
let poolName = '';
Expand Down
Loading