From 8910c63e7fa161479c6d8eefe435347a17adf5d5 Mon Sep 17 00:00:00 2001 From: bailey Date: Wed, 26 Feb 2025 10:30:22 -0700 Subject: [PATCH 1/4] add logging --- .evergreen/config.in.yml | 28 ++++++++++ .evergreen/config.yml | 22 ++++++++ src/cmap/connection.ts | 71 +++++++++++++++++++++--- test/tools/runner/hooks/configuration.ts | 3 + 4 files changed, 117 insertions(+), 7 deletions(-) diff --git a/.evergreen/config.in.yml b/.evergreen/config.in.yml index caa7f202e83..76285b74bdf 100644 --- a/.evergreen/config.in.yml +++ b/.evergreen/config.in.yml @@ -107,6 +107,20 @@ functions: binary: bash args: - .evergreen/run-tests.sh + - command: s3.put + params: + aws_key: ${aws_key} + aws_secret: ${aws_secret} + local_file: src/connection-logs.txt + optional: true + # Upload the coverage report for all tasks in a single build to the same directory. + # TODO NODE-4707 - change upload directory to ${UPLOAD_BUCKET} + # This change will require changing the `download and merge coverage` func as well + remote_file: mongo-node-driver/${revision}/${version_id}/${build_variant}/${task_name}/connection-logs.txt + bucket: mciuploads + permissions: public-read + content_type: text/plain + display_name: "Connection Logs" "run serverless tests": - command: timeout.update @@ -127,6 +141,20 @@ functions: add_expansions_to_env: true args: - .evergreen/run-serverless-tests.sh + - command: s3.put + params: + aws_key: ${aws_key} + aws_secret: ${aws_secret} + local_file: src/connection-logs.txt + optional: true + # Upload the coverage report for all tasks in a single build to the same directory. + # TODO NODE-4707 - change upload directory to ${UPLOAD_BUCKET} + # This change will require changing the `download and merge coverage` func as well + remote_file: mongo-node-driver/${revision}/${version_id}/${build_variant}/${task_name}/connection-logs.txt + bucket: mciuploads + permissions: public-read + content_type: text/plain + display_name: "Connection Logs" "start-load-balancer": - command: shell.exec diff --git a/.evergreen/config.yml b/.evergreen/config.yml index 31610208b2d..977159b91bc 100644 --- a/.evergreen/config.yml +++ b/.evergreen/config.yml @@ -80,6 +80,17 @@ functions: binary: bash args: - .evergreen/run-tests.sh + - command: s3.put + params: + aws_key: ${aws_key} + aws_secret: ${aws_secret} + local_file: src/connection-logs.txt + optional: true + remote_file: mongo-node-driver/${revision}/${version_id}/${build_variant}/${task_name}/connection-logs.txt + bucket: mciuploads + permissions: public-read + content_type: text/plain + display_name: Connection Logs run serverless tests: - command: timeout.update params: @@ -99,6 +110,17 @@ functions: add_expansions_to_env: true args: - .evergreen/run-serverless-tests.sh + - command: s3.put + params: + aws_key: ${aws_key} + aws_secret: ${aws_secret} + local_file: src/connection-logs.txt + optional: true + remote_file: mongo-node-driver/${revision}/${version_id}/${build_variant}/${task_name}/connection-logs.txt + bucket: mciuploads + permissions: public-read + content_type: text/plain + display_name: Connection Logs start-load-balancer: - command: shell.exec params: diff --git a/src/cmap/connection.ts b/src/cmap/connection.ts index b6d92f56e0c..68d78f43b28 100644 --- a/src/cmap/connection.ts +++ b/src/cmap/connection.ts @@ -1,3 +1,4 @@ +import { createWriteStream } from 'fs'; import { type Readable, Transform, type TransformCallback } from 'stream'; import { clearTimeout, setTimeout } from 'timers'; @@ -6,6 +7,7 @@ import { deserialize, type DeserializeOptions, type Document, + EJSON, type ObjectId } from '../bson'; import { type AutoEncrypter } from '../client-side-encryption/auto_encrypter'; @@ -179,6 +181,43 @@ function streamIdentifier(stream: Stream, options: ConnectionOptions): string { return uuidV4().toString('hex'); } +export const logger = createWriteStream('connection-logs.txt'); +export const write = (payload: Document) => { + payload.timestamp = new Date(); + payload.hostname = process.env.HOSTNAME; + const log = EJSON.stringify(payload); + logger.write(log); + logger.write('\n'); +}; + +const writeEvent = + (event: string) => + (payload: T) => { + (payload as T & { event: string }).event = event; + write(payload); + }; + +export const writeStarted = writeEvent('commandStarted')<{ + requestId: number; + connectionId: number | ''; +}>; + +export const readStarted = writeEvent('readStarted')<{ + requestId: number; + connectionId: number | ''; +}>; + +export const readSucceeded = writeEvent('readSucceeded')<{ + requestId: number; + connectionId: number | ''; +}>; + +export const readFailed = writeEvent('readFailed')<{ + requestId: number; + connectionId: number | ''; + error: Error; +}>; + /** @internal */ export class Connection extends TypedEventEmitter { public id: number | ''; @@ -451,7 +490,13 @@ export class Connection extends TypedEventEmitter { this.socketTimeoutMS; this.socket.setTimeout(timeout); + const payload = { + connectionId: this.id, + requestId: message.requestId + }; try { + writeStarted(payload); + await this.writeCommand(message, { agreedCompressor: this.description.compressor ?? 'none', zlibCompressionLevel: this.description.zlibCompressionLevel, @@ -476,16 +521,28 @@ export class Connection extends TypedEventEmitter { ); } - for await (const response of this.readMany(options)) { - this.socket.setTimeout(0); - const bson = response.parse(); + readStarted(payload); + try { + for await (const response of this.readMany(options)) { + readSucceeded(payload); + this.socket.setTimeout(0); + const bson = response.parse(); - const document = (responseType ?? MongoDBResponse).make(bson); + const document = (responseType ?? MongoDBResponse).make(bson); - yield document; - this.throwIfAborted(); + yield document; - this.socket.setTimeout(timeout); + readStarted(payload); + this.throwIfAborted(); + + this.socket.setTimeout(timeout); + } + } catch (error) { + readFailed({ + ...payload, + error + }); + throw error; } } finally { this.socket.setTimeout(0); diff --git a/test/tools/runner/hooks/configuration.ts b/test/tools/runner/hooks/configuration.ts index ee31fc506f3..2c6b01b68ad 100644 --- a/test/tools/runner/hooks/configuration.ts +++ b/test/tools/runner/hooks/configuration.ts @@ -22,6 +22,7 @@ import { NodeVersionFilter } from '../filters/node_version_filter'; import { OSFilter } from '../filters/os_filter'; import { ServerlessFilter } from '../filters/serverless_filter'; import { type Filter } from '../filters/filter'; +import { spawnSync } from 'child_process'; // Default our tests to have auth enabled // A better solution will be tackled in NODE-3714 @@ -46,6 +47,8 @@ const loadBalanced = SINGLE_MONGOS_LB_URI && MULTI_MONGOS_LB_URI; const filters: Filter[] = []; let initializedFilters = false; + +process.env.HOSTNAME = spawnSync('hostname', { encoding: 'utf-8' }).stdout; async function initializeFilters(client): Promise> { if (initializedFilters) { return {}; From 5d51f1e24b3208e4ebcbe99dcc9ad8d05e498710 Mon Sep 17 00:00:00 2001 From: bailey Date: Wed, 26 Feb 2025 11:51:50 -0700 Subject: [PATCH 2/4] asdf --- src/cmap/connection.ts | 8 +++++--- test/tools/runner/hooks/configuration.ts | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/cmap/connection.ts b/src/cmap/connection.ts index 68d78f43b28..e18c24550f8 100644 --- a/src/cmap/connection.ts +++ b/src/cmap/connection.ts @@ -183,9 +183,11 @@ function streamIdentifier(stream: Stream, options: ConnectionOptions): string { export const logger = createWriteStream('connection-logs.txt'); export const write = (payload: Document) => { - payload.timestamp = new Date(); - payload.hostname = process.env.HOSTNAME; - const log = EJSON.stringify(payload); + payload.timestamp = new Date().toISOString(); + payload.hostname = process.env.MONGODB_URI; + payload.ip = process.env.IP; + + const log = JSON.stringify(payload); logger.write(log); logger.write('\n'); }; diff --git a/test/tools/runner/hooks/configuration.ts b/test/tools/runner/hooks/configuration.ts index 2c6b01b68ad..e3760a581f0 100644 --- a/test/tools/runner/hooks/configuration.ts +++ b/test/tools/runner/hooks/configuration.ts @@ -48,7 +48,8 @@ const filters: Filter[] = []; let initializedFilters = false; -process.env.HOSTNAME = spawnSync('hostname', { encoding: 'utf-8' }).stdout; +process.env.IP = spawnSync('curl ifconfig.me', { encoding: 'utf-8' }).stdout; + async function initializeFilters(client): Promise> { if (initializedFilters) { return {}; From b52c453e14607944d6efff399eecedf5a96f48cb Mon Sep 17 00:00:00 2001 From: bailey Date: Wed, 26 Feb 2025 14:15:01 -0700 Subject: [PATCH 3/4] asdf --- .evergreen/config.in.yml | 28 ++++++++++++------------ .evergreen/config.yml | 22 +++++++++---------- src/cmap/connect.ts | 12 ++++++++-- src/error.ts | 8 +++++++ test/tools/runner/hooks/configuration.ts | 2 +- 5 files changed, 44 insertions(+), 28 deletions(-) diff --git a/.evergreen/config.in.yml b/.evergreen/config.in.yml index 76285b74bdf..c7cac89b737 100644 --- a/.evergreen/config.in.yml +++ b/.evergreen/config.in.yml @@ -141,20 +141,6 @@ functions: add_expansions_to_env: true args: - .evergreen/run-serverless-tests.sh - - command: s3.put - params: - aws_key: ${aws_key} - aws_secret: ${aws_secret} - local_file: src/connection-logs.txt - optional: true - # Upload the coverage report for all tasks in a single build to the same directory. - # TODO NODE-4707 - change upload directory to ${UPLOAD_BUCKET} - # This change will require changing the `download and merge coverage` func as well - remote_file: mongo-node-driver/${revision}/${version_id}/${build_variant}/${task_name}/connection-logs.txt - bucket: mciuploads - permissions: public-read - content_type: text/plain - display_name: "Connection Logs" "start-load-balancer": - command: shell.exec @@ -1016,6 +1002,20 @@ task_groups: - .evergreen/setup-serverless.sh teardown_group: + - command: s3.put + params: + aws_key: ${aws_key} + aws_secret: ${aws_secret} + local_file: src/connection-logs.txt + optional: true + # Upload the coverage report for all tasks in a single build to the same directory. + # TODO NODE-4707 - change upload directory to ${UPLOAD_BUCKET} + # This change will require changing the `download and merge coverage` func as well + remote_file: mongo-node-driver/${revision}/${version_id}/${build_variant}/${task_name}/connection-logs.txt + bucket: mciuploads + permissions: public-read + content_type: text/plain + display_name: "Connection Logs" - func: "upload test results" - command: subprocess.exec params: diff --git a/.evergreen/config.yml b/.evergreen/config.yml index 977159b91bc..c6c4f62d8c7 100644 --- a/.evergreen/config.yml +++ b/.evergreen/config.yml @@ -110,17 +110,6 @@ functions: add_expansions_to_env: true args: - .evergreen/run-serverless-tests.sh - - command: s3.put - params: - aws_key: ${aws_key} - aws_secret: ${aws_secret} - local_file: src/connection-logs.txt - optional: true - remote_file: mongo-node-driver/${revision}/${version_id}/${build_variant}/${task_name}/connection-logs.txt - bucket: mciuploads - permissions: public-read - content_type: text/plain - display_name: Connection Logs start-load-balancer: - command: shell.exec params: @@ -2896,6 +2885,17 @@ task_groups: args: - .evergreen/setup-serverless.sh teardown_group: + - command: s3.put + params: + aws_key: ${aws_key} + aws_secret: ${aws_secret} + local_file: src/connection-logs.txt + optional: true + remote_file: mongo-node-driver/${revision}/${version_id}/${build_variant}/${task_name}/connection-logs.txt + bucket: mciuploads + permissions: public-read + content_type: text/plain + display_name: Connection Logs - func: upload test results - command: subprocess.exec params: diff --git a/src/cmap/connect.ts b/src/cmap/connect.ts index 394b70689ca..4edbe203d7b 100644 --- a/src/cmap/connect.ts +++ b/src/cmap/connect.ts @@ -391,7 +391,12 @@ export async function makeSocket(options: MakeConnectionOptions): Promise resolve(socket)) .once('error', cause => - reject(new MongoNetworkError(MongoError.buildErrorMessage(cause), { cause })) + reject( + new MongoNetworkError( + MongoError.buildErrorMessage(cause) + '- error encountered while establishing socket', + { cause } + ) + ) ) .once('timeout', () => { reject( @@ -489,7 +494,10 @@ async function makeSocks5Connection(options: MakeConnectionOptions): Promise> { if (initializedFilters) { From a52160d2e845d6be3230617c1f72e6532a76c937 Mon Sep 17 00:00:00 2001 From: bailey Date: Wed, 26 Feb 2025 14:24:57 -0700 Subject: [PATCH 4/4] asdf --- src/error.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/error.ts b/src/error.ts index 9e4778f376a..b542808bb53 100644 --- a/src/error.ts +++ b/src/error.ts @@ -1,5 +1,4 @@ import type { Document } from './bson'; -import { write } from './cmap/connection'; import { type ClientBulkWriteError, type ClientBulkWriteResult @@ -1050,6 +1049,7 @@ export class MongoNetworkError extends MongoError { super(message, { cause: options?.cause }); this.beforeHandshake = !!options?.beforeHandshake; + const { write } = require('./cmap/connection'); write({ event: 'network error', message,