@opentelemetry/instrumentation-pg
Version:
OpenTelemetry instrumentation for `pg` and `pg-pool` database client for PostgreSQL
1 lines • 20.5 kB
Source Map (JSON)
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n context,\n trace,\n Span,\n SpanStatusCode,\n Tracer,\n SpanKind,\n diag,\n UpDownCounter,\n Attributes,\n} from '@opentelemetry/api';\nimport { AttributeNames } from './enums/AttributeNames';\nimport {\n ATTR_ERROR_TYPE,\n SEMATTRS_DB_SYSTEM,\n SEMATTRS_DB_NAME,\n SEMATTRS_DB_CONNECTION_STRING,\n SEMATTRS_NET_PEER_NAME,\n SEMATTRS_NET_PEER_PORT,\n SEMATTRS_DB_USER,\n SEMATTRS_DB_STATEMENT,\n DBSYSTEMVALUES_POSTGRESQL,\n} from '@opentelemetry/semantic-conventions';\nimport {\n ATTR_DB_CLIENT_CONNECTION_POOL_NAME,\n ATTR_DB_CLIENT_CONNECTION_STATE,\n DB_CLIENT_CONNECTION_STATE_VALUE_USED,\n DB_CLIENT_CONNECTION_STATE_VALUE_IDLE,\n} from './semconv';\nimport {\n PgClientExtended,\n PostgresCallback,\n PgPoolCallback,\n PgPoolExtended,\n PgParsedConnectionParams,\n PgPoolOptionsParams,\n} from './internal-types';\nimport { PgInstrumentationConfig } from './types';\nimport type * as pgTypes from 'pg';\nimport { safeExecuteInTheMiddle } from '@opentelemetry/instrumentation';\nimport { SpanNames } from './enums/SpanNames';\n\n/**\n * Helper function to get a low cardinality span name from whatever info we have\n * about the query.\n *\n * This is tricky, because we don't have most of the information (table name,\n * operation name, etc) the spec recommends using to build a low-cardinality\n * value w/o parsing. So, we use db.name and assume that, if the query's a named\n * prepared statement, those `name` values will be low cardinality. If we don't\n * have a named prepared statement, we try to parse an operation (despite the\n * spec's warnings).\n *\n * @params dbName The name of the db against which this query is being issued,\n * which could be missing if no db name was given at the time that the\n * connection was established.\n * @params queryConfig Information we have about the query being issued, typed\n * to reflect only the validation we've actually done on the args to\n * `client.query()`. This will be undefined if `client.query()` was called\n * with invalid arguments.\n */\nexport function getQuerySpanName(\n dbName: string | undefined,\n queryConfig?: { text: string; name?: unknown }\n) {\n // NB: when the query config is invalid, we omit the dbName too, so that\n // someone (or some tool) reading the span name doesn't misinterpret the\n // dbName as being a prepared statement or sql commit name.\n if (!queryConfig) return SpanNames.QUERY_PREFIX;\n\n // Either the name of a prepared statement; or an attempted parse\n // of the SQL command, normalized to uppercase; or unknown.\n const command =\n typeof queryConfig.name === 'string' && queryConfig.name\n ? queryConfig.name\n : parseNormalizedOperationName(queryConfig.text);\n\n return `${SpanNames.QUERY_PREFIX}:${command}${dbName ? ` ${dbName}` : ''}`;\n}\n\nexport function parseNormalizedOperationName(queryText: string) {\n const indexOfFirstSpace = queryText.indexOf(' ');\n let sqlCommand =\n indexOfFirstSpace === -1\n ? queryText\n : queryText.slice(0, indexOfFirstSpace);\n sqlCommand = sqlCommand.toUpperCase();\n\n // Handle query text being \"COMMIT;\", which has an extra semicolon before the space.\n return sqlCommand.endsWith(';') ? sqlCommand.slice(0, -1) : sqlCommand;\n}\n\nexport function parseAndMaskConnectionString(connectionString: string): string {\n try {\n // Parse the connection string\n const url = new URL(connectionString);\n\n // Remove all auth information (username and password)\n url.username = '';\n url.password = '';\n\n return url.toString();\n } catch (e) {\n // If parsing fails, return a generic connection string\n return 'postgresql://localhost:5432/';\n }\n}\n\nexport function getConnectionString(\n params: PgParsedConnectionParams | PgPoolOptionsParams\n) {\n if ('connectionString' in params && params.connectionString) {\n return parseAndMaskConnectionString(params.connectionString);\n }\n const host = params.host || 'localhost';\n const port = params.port || 5432;\n const database = params.database || '';\n return `postgresql://${host}:${port}/${database}`;\n}\n\nfunction getPort(port: number | undefined): number | undefined {\n // Port may be NaN as parseInt() is used on the value, passing null will result in NaN being parsed.\n // https://github.com/brianc/node-postgres/blob/2a8efbee09a284be12748ed3962bc9b816965e36/packages/pg/lib/connection-parameters.js#L66\n if (Number.isInteger(port)) {\n return port;\n }\n\n // Unable to find the default used in pg code, so falling back to 'undefined'.\n return undefined;\n}\n\nexport function getSemanticAttributesFromConnection(\n params: PgParsedConnectionParams\n) {\n return {\n [SEMATTRS_DB_SYSTEM]: DBSYSTEMVALUES_POSTGRESQL,\n [SEMATTRS_DB_NAME]: params.database, // required\n [SEMATTRS_DB_CONNECTION_STRING]: getConnectionString(params), // required\n [SEMATTRS_NET_PEER_NAME]: params.host, // required\n [SEMATTRS_NET_PEER_PORT]: getPort(params.port),\n [SEMATTRS_DB_USER]: params.user,\n };\n}\n\nexport function getSemanticAttributesFromPool(params: PgPoolOptionsParams) {\n let url: URL | undefined;\n try {\n url = params.connectionString\n ? new URL(params.connectionString)\n : undefined;\n } catch (e) {\n url = undefined;\n }\n\n return {\n [SEMATTRS_DB_SYSTEM]: DBSYSTEMVALUES_POSTGRESQL,\n [SEMATTRS_DB_NAME]: url?.pathname.slice(1) ?? params.database, // required\n [SEMATTRS_DB_CONNECTION_STRING]: getConnectionString(params), // required\n [SEMATTRS_NET_PEER_NAME]: url?.hostname ?? params.host, // required\n [SEMATTRS_NET_PEER_PORT]: Number(url?.port) || getPort(params.port),\n [SEMATTRS_DB_USER]: url?.username ?? params.user,\n [AttributeNames.IDLE_TIMEOUT_MILLIS]: params.idleTimeoutMillis,\n [AttributeNames.MAX_CLIENT]: params.maxClient,\n };\n}\n\nexport function shouldSkipInstrumentation(\n instrumentationConfig: PgInstrumentationConfig\n) {\n return (\n instrumentationConfig.requireParentSpan === true &&\n trace.getSpan(context.active()) === undefined\n );\n}\n\n// Create a span from our normalized queryConfig object,\n// or return a basic span if no queryConfig was given/could be created.\nexport function handleConfigQuery(\n this: PgClientExtended,\n tracer: Tracer,\n instrumentationConfig: PgInstrumentationConfig,\n queryConfig?: { text: string; values?: unknown; name?: unknown }\n) {\n // Create child span.\n const { connectionParameters } = this;\n const dbName = connectionParameters.database;\n\n const spanName = getQuerySpanName(dbName, queryConfig);\n const span = tracer.startSpan(spanName, {\n kind: SpanKind.CLIENT,\n attributes: getSemanticAttributesFromConnection(connectionParameters),\n });\n\n if (!queryConfig) {\n return span;\n }\n\n // Set attributes\n if (queryConfig.text) {\n span.setAttribute(SEMATTRS_DB_STATEMENT, queryConfig.text);\n }\n\n if (\n instrumentationConfig.enhancedDatabaseReporting &&\n Array.isArray(queryConfig.values)\n ) {\n try {\n const convertedValues = queryConfig.values.map(value => {\n if (value == null) {\n return 'null';\n } else if (value instanceof Buffer) {\n return value.toString();\n } else if (typeof value === 'object') {\n if (typeof value.toPostgres === 'function') {\n return value.toPostgres();\n }\n return JSON.stringify(value);\n } else {\n //string, number\n return value.toString();\n }\n });\n span.setAttribute(AttributeNames.PG_VALUES, convertedValues);\n } catch (e) {\n diag.error('failed to stringify ', queryConfig.values, e);\n }\n }\n\n // Set plan name attribute, if present\n if (typeof queryConfig.name === 'string') {\n span.setAttribute(AttributeNames.PG_PLAN, queryConfig.name);\n }\n\n return span;\n}\n\nexport function handleExecutionResult(\n config: PgInstrumentationConfig,\n span: Span,\n pgResult: pgTypes.QueryResult | pgTypes.QueryArrayResult | unknown\n) {\n if (typeof config.responseHook === 'function') {\n safeExecuteInTheMiddle(\n () => {\n config.responseHook!(span, {\n data: pgResult as pgTypes.QueryResult | pgTypes.QueryArrayResult,\n });\n },\n err => {\n if (err) {\n diag.error('Error running response hook', err);\n }\n },\n true\n );\n }\n}\n\nexport function patchCallback(\n instrumentationConfig: PgInstrumentationConfig,\n span: Span,\n cb: PostgresCallback,\n attributes: Attributes,\n recordDuration: { (): void }\n): PostgresCallback {\n return function patchedCallback(\n this: PgClientExtended,\n err: Error,\n res: object\n ) {\n if (err) {\n if (Object.prototype.hasOwnProperty.call(err, 'code')) {\n attributes[ATTR_ERROR_TYPE] = (err as any)['code'];\n }\n\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message,\n });\n } else {\n handleExecutionResult(instrumentationConfig, span, res);\n }\n\n recordDuration();\n span.end();\n cb.call(this, err, res);\n };\n}\n\nexport function getPoolName(pool: PgPoolOptionsParams): string {\n let poolName = '';\n poolName += (pool?.host ? `${pool.host}` : 'unknown_host') + ':';\n poolName += (pool?.port ? `${pool.port}` : 'unknown_port') + '/';\n poolName += pool?.database ? `${pool.database}` : 'unknown_database';\n\n return poolName.trim();\n}\n\nexport interface poolConnectionsCounter {\n used: number;\n idle: number;\n pending: number;\n}\n\nexport function updateCounter(\n poolName: string,\n pool: PgPoolExtended,\n connectionCount: UpDownCounter,\n connectionPendingRequests: UpDownCounter,\n latestCounter: poolConnectionsCounter\n): poolConnectionsCounter {\n const all = pool.totalCount;\n const pending = pool.waitingCount;\n const idle = pool.idleCount;\n const used = all - idle;\n\n connectionCount.add(used - latestCounter.used, {\n [ATTR_DB_CLIENT_CONNECTION_STATE]: DB_CLIENT_CONNECTION_STATE_VALUE_USED,\n [ATTR_DB_CLIENT_CONNECTION_POOL_NAME]: poolName,\n });\n\n connectionCount.add(idle - latestCounter.idle, {\n [ATTR_DB_CLIENT_CONNECTION_STATE]: DB_CLIENT_CONNECTION_STATE_VALUE_IDLE,\n [ATTR_DB_CLIENT_CONNECTION_POOL_NAME]: poolName,\n });\n\n connectionPendingRequests.add(pending - latestCounter.pending, {\n [ATTR_DB_CLIENT_CONNECTION_POOL_NAME]: poolName,\n });\n\n return { used: used, idle: idle, pending: pending };\n}\n\nexport function patchCallbackPGPool(\n span: Span,\n cb: PgPoolCallback\n): PgPoolCallback {\n return function patchedCallback(\n this: PgPoolExtended,\n err: Error,\n res: object,\n done: any\n ) {\n if (err) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message,\n });\n }\n span.end();\n cb.call(this, err, res, done);\n };\n}\n\nexport function patchClientConnectCallback(span: Span, cb: Function): Function {\n return function patchedClientConnectCallback(\n this: pgTypes.Client,\n err: Error\n ) {\n if (err) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message,\n });\n }\n span.end();\n cb.apply(this, arguments);\n };\n}\n\n/**\n * Attempt to get a message string from a thrown value, while being quite\n * defensive, to recognize the fact that, in JS, any kind of value (even\n * primitives) can be thrown.\n */\nexport function getErrorMessage(e: unknown) {\n return typeof e === 'object' && e !== null && 'message' in e\n ? String((e as { message?: unknown }).message)\n : undefined;\n}\n\nexport function isObjectWithTextString(it: unknown): it is ObjectWithText {\n return (\n typeof it === 'object' &&\n typeof (it as null | { text?: unknown })?.text === 'string'\n );\n}\n\nexport type ObjectWithText = {\n text: string;\n [k: string]: unknown;\n};\n"]}