From 50839209063e75996b2a57bd7664760e0e5331ca Mon Sep 17 00:00:00 2001 From: Denis DelGrosso <85250797+ddelgrosso1@users.noreply.github.com> Date: Thu, 13 Jul 2023 15:07:08 -0400 Subject: [PATCH] feat: add header for deno runtime for metrics tracking (#2220) * feat: add header for deno runtime for metrics tracking * Update src/util.ts Co-authored-by: Ruy Adorno * linter fix --------- Co-authored-by: Ruy Adorno --- src/nodejs-common/service.ts | 3 ++- src/nodejs-common/util.ts | 3 ++- src/resumable-upload.ts | 13 ++++++++++--- src/util.ts | 24 ++++++++++++++++++++++++ test/headers.ts | 30 +++++++++++++++++++++++++++++- 5 files changed, 67 insertions(+), 6 deletions(-) diff --git a/src/nodejs-common/service.ts b/src/nodejs-common/service.ts index 152d4a400..8ef28c8db 100644 --- a/src/nodejs-common/service.ts +++ b/src/nodejs-common/service.ts @@ -26,6 +26,7 @@ import { PackageJson, util, } from './util'; +import {getRuntimeTrackingString} from '../util'; export const DEFAULT_PROJECT_ID_TOKEN = '{{projectId}}'; @@ -246,7 +247,7 @@ export class Service { } reqOpts.headers = extend({}, reqOpts.headers, { 'User-Agent': userAgent, - 'x-goog-api-client': `gl-node/${process.versions.node} gccl/${ + 'x-goog-api-client': `${getRuntimeTrackingString()} gccl/${ pkg.version } gccl-invocation-id/${uuid.v4()}`, }); diff --git a/src/nodejs-common/util.ts b/src/nodejs-common/util.ts index 787a88b21..970eac1b5 100644 --- a/src/nodejs-common/util.ts +++ b/src/nodejs-common/util.ts @@ -33,6 +33,7 @@ import {teenyRequest} from 'teeny-request'; import {Interceptor} from './service-object'; import * as uuid from 'uuid'; import {DEFAULT_PROJECT_ID_TOKEN} from './service'; +import {getRuntimeTrackingString} from '../util'; const packageJson = require('../../../package.json'); @@ -1011,7 +1012,7 @@ export class Util { _getDefaultHeaders() { return { 'User-Agent': util.getUserAgentFromPackageJson(packageJson), - 'x-goog-api-client': `gl-node/${process.versions.node} gccl/${ + 'x-goog-api-client': `${getRuntimeTrackingString()} gccl/${ packageJson.version } gccl-invocation-id/${uuid.v4()}`, }; diff --git a/src/resumable-upload.ts b/src/resumable-upload.ts index da90bdca1..d7487f75e 100644 --- a/src/resumable-upload.ts +++ b/src/resumable-upload.ts @@ -27,6 +27,7 @@ import {Readable, Writable, WritableOptions} from 'stream'; import retry = require('async-retry'); import {RetryOptions, PreconditionOptions} from './storage'; import * as uuid from 'uuid'; +import {getRuntimeTrackingString} from './util'; const NOT_FOUND_STATUS_CODE = 404; const RESUMABLE_INCOMPLETE_STATUS_CODE = 308; @@ -597,7 +598,9 @@ export class Upload extends Writable { ), data: metadata, headers: { - 'x-goog-api-client': `gl-node/${process.versions.node} gccl/${packageJson.version} gccl-invocation-id/${this.currentInvocationId.uri}`, + 'x-goog-api-client': `${getRuntimeTrackingString()} gccl/${ + packageJson.version + } gccl-invocation-id/${this.currentInvocationId.uri}`, ...headers, }, }; @@ -764,7 +767,9 @@ export class Upload extends Writable { }); const headers: GaxiosOptions['headers'] = { - 'x-goog-api-client': `gl-node/${process.versions.node} gccl/${packageJson.version} gccl-invocation-id/${this.currentInvocationId.chunk}`, + 'x-goog-api-client': `${getRuntimeTrackingString()} gccl/${ + packageJson.version + } gccl-invocation-id/${this.currentInvocationId.chunk}`, }; // If using multiple chunk upload, set appropriate header @@ -905,7 +910,9 @@ export class Upload extends Writable { headers: { 'Content-Length': 0, 'Content-Range': 'bytes */*', - 'x-goog-api-client': `gl-node/${process.versions.node} gccl/${packageJson.version} gccl-invocation-id/${this.currentInvocationId.offset}`, + 'x-goog-api-client': `${getRuntimeTrackingString()} gccl/${ + packageJson.version + } gccl-invocation-id/${this.currentInvocationId.offset}`, }, }; try { diff --git a/src/util.ts b/src/util.ts index a9710554c..6704fb91c 100644 --- a/src/util.ts +++ b/src/util.ts @@ -168,6 +168,30 @@ export function formatAsUTCISO( return resultString; } +/** + * Examines the runtime environment and returns the appropriate tracking string. + * @returns {string} metrics tracking string based on the current runtime environment. + */ +export function getRuntimeTrackingString(): string { + if ( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + globalThis.Deno && + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + globalThis.Deno.version && + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + globalThis.Deno.version.deno + ) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + return `gl-deno/${globalThis.Deno.version.deno}`; + } else { + return `gl-node/${process.versions.node}`; + } +} + export class PassThroughShim extends PassThrough { private shouldEmitReading = true; private shouldEmitWriting = true; diff --git a/test/headers.ts b/test/headers.ts index 0d9249122..a03e24683 100644 --- a/test/headers.ts +++ b/test/headers.ts @@ -51,7 +51,13 @@ describe('headers', () => { }, }); - it('populates x-goog-api-client header', async () => { + afterEach(() => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + globalThis.Deno = undefined; + }); + + it('populates x-goog-api-client header (node)', async () => { const storage = new Storage(); const bucket = storage.bucket('foo-bucket'); try { @@ -65,4 +71,26 @@ describe('headers', () => { ) ); }); + + it('populates x-goog-api-client header (deno)', async () => { + const storage = new Storage(); + const bucket = storage.bucket('foo-bucket'); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + globalThis.Deno = { + version: { + deno: '0.00.0', + }, + }; + try { + await bucket.create(); + } catch (err) { + if (err !== error) throw err; + } + assert.ok( + /^gl-deno\/0.00.0 gccl\/(?[^W]+) gccl-invocation-id\/(?[^W]+)$/.test( + requests[1].headers['x-goog-api-client'] + ) + ); + }); });