Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,10 @@ const db = marklogic.createDatabaseClient({
user: 'admin',
password: 'admin',
authType: 'DIGEST',
// enableGzippedResponses is optional and can be set to true in order to request MarkLogic to compress the response for better performance,
// the client will automatically decompress the response before it returns a value.
// Set to true to suppress the ML-Agent-ID header in each request to MarkLogic.
// See https://docs.progress.com/bundle/marklogic-server-monitor-12/page/topics/telemetry.html
disableTelemetryHeader: false,
// Optional; set to true to request compressed responses for improved performance. The client automatically decompresses returned values.
enableGzippedResponses: true
});

Expand All @@ -70,10 +72,9 @@ const db = marklogic.createDatabaseClient({
authType: 'cloud',
// basePath is optional.
basePath: '/marklogic/test',
// accessTokenDuration (in seconds) is optional and can be used to customize the expiration of the access token.
// Optional (in seconds); customizes the expiration of the access token.
accessTokenDuration: 10,
// enableGzippedResponses is optional and can be set to true in order to request MarkLogic to compress the response for better performance,
// the client will automatically decompress the response before it returns a value.
// Set to true to request compressed responses for improved performance. The client automatically decompresses returned values.
enableGzippedResponses: true
});

Expand Down
2 changes: 2 additions & 0 deletions lib/marklogic.js
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ function expandExtlibsWrapper(action, args) {
* to use for SSL
* @param {string} [passphrase] - the passphrase for the PKCS12 file
* @param {string} [token] - the SAML token to use for authentication with the REST server
* @param {boolean} [disableTelemetryHeader=false] - when true, suppresses the ML-Agent-ID telemetry header on outbound requests
* @returns {DatabaseClient} a client for accessing the database
* as the user
*/
Expand Down Expand Up @@ -718,6 +719,7 @@ function initClient(client, inputParams) {
}

const keys = ['host', 'port', 'database', 'user', 'password', 'authType', 'token', 'basePath','apiKey','accessTokenDuration',
'disableTelemetryHeader',
'enableGzippedResponses', 'oauthToken'];
if(isSSL) {
keys.push('ca', 'cert', 'ciphers', 'clientCertEngine', 'crl', 'dhparam', 'ecdhCurve', 'honorCipherOrder', 'key', 'passphrase',
Expand Down
4 changes: 3 additions & 1 deletion lib/requester.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,9 @@ function startRequest(operation) {
options.headers = headers;
}
headers['X-Error-Accept'] = 'application/json';
headers['ML-Agent-ID'] = 'nodejs'; // Telemetry header
if (!options.disableTelemetryHeader) {
headers['ML-Agent-ID'] = 'nodejs'; // Telemetry header
}

if(options.enableGzippedResponses) {
headers['Accept-Encoding'] = 'gzip';
Expand Down
2 changes: 2 additions & 0 deletions marklogic.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ declare module 'marklogic' {
token?: string;
/** Connection pooling agent */
agent?: any;
/** When true, disables telemetry usage; see https://docs.progress.com/bundle/marklogic-server-monitor-12/page/topics/telemetry.html */
disableTelemetryHeader?: boolean;
/** API version to use */
apiVersion?: string;
}
Expand Down
66 changes: 66 additions & 0 deletions test-basic/telemetry-header-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2015-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
*/

'use strict';

const assert = require('assert');
const marklogic = require('../');
const mlutil = require('../lib/mlutil');
const requester = require('../lib/requester');

function buildRequestOptions(connectionParams) {
return mlutil.newRequestOptions(connectionParams, '/v1/ping', 'HEAD');
}

describe('ML-Agent-ID telemetry header', function() {
it('should include ML-Agent-ID header by default', function() {
const client = marklogic.createDatabaseClient({
host: 'localhost',
port: 8000,
user: 'admin',
password: 'admin',
authType: 'digest'
});

const options = buildRequestOptions(client.connectionParams);
const operation = {
options: options,
requestType: 'invalid-request-type'
};

assert.throws(
() => requester.startRequest(operation),
/unknown request type invalid-request-type/
);
assert.strictEqual(options.headers['ML-Agent-ID'], 'nodejs');

client.release();
});

it('should omit ML-Agent-ID header when disableTelemetryHeader is true', function() {
const client = marklogic.createDatabaseClient({
host: 'localhost',
port: 8000,
user: 'admin',
password: 'admin',
authType: 'digest',
disableTelemetryHeader: true
});

const options = buildRequestOptions(client.connectionParams);
const operation = {
options: options,
requestType: 'invalid-request-type'
};

assert.throws(
() => requester.startRequest(operation),
/unknown request type invalid-request-type/
);
assert.strictEqual(client.connectionParams.disableTelemetryHeader, true);
assert.strictEqual(options.headers['ML-Agent-ID'], undefined);

client.release();
});
});
8 changes: 8 additions & 0 deletions test-typescript/basic-types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ const minimalConfig: marklogic.DatabaseClientConfig = {
password: 'admin'
};

// Test 5b: Telemetry header opt-out option should type-check
const telemetryConfig: marklogic.DatabaseClientConfig = {
user: 'admin',
password: 'admin',
disableTelemetryHeader: true
};
const telemetryDb = marklogic.createDatabaseClient(telemetryConfig);

// Test 6: Testing all auth types (all should be valid)
const authTypes: Array<marklogic.DatabaseClientConfig['authType']> = [
'basic',
Expand Down
59 changes: 59 additions & 0 deletions test-typescript/telemetry-header-runtime.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2015-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
*/

/// <reference path="../marklogic.d.ts" />

import assert = require('assert');

const marklogic = require('..');
const mlutil = require('../lib/mlutil');
const requester = require('../lib/requester');

type DatabaseClientConfig = import('marklogic').DatabaseClientConfig;

function verifyTelemetryHeader(config: DatabaseClientConfig, expectedHeader: string | undefined): void {
const client = marklogic.createDatabaseClient(config);
const options = mlutil.newRequestOptions(client.connectionParams, '/v1/ping', 'HEAD');
const operation = {
options,
requestType: 'invalid-request-type'
};

assert.throws(
() => requester.startRequest(operation),
/unknown request type invalid-request-type/
);
assert.strictEqual(options.headers['ML-Agent-ID'], expectedHeader);

client.release();
}

describe('telemetry header runtime validation', function() {
it('includes ML-Agent-ID by default', function() {
verifyTelemetryHeader(
{
host: 'localhost',
port: 8000,
user: 'admin',
password: 'admin',
authType: 'digest'
},
'nodejs'
);
});

it('omits ML-Agent-ID when disableTelemetryHeader is true', function() {
verifyTelemetryHeader(
{
host: 'localhost',
port: 8000,
user: 'admin',
password: 'admin',
authType: 'digest',
disableTelemetryHeader: true
},
undefined
);
});
});
Loading