initial commit

This commit is contained in:
2025-09-01 22:12:29 +02:00
parent b1873f9c1d
commit 02a54f61c0
5598 changed files with 903558 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
import * as tty from 'node:tty';
/**
* Handles figuring out if we can use ANSI colours and handing out the escape codes.
*
* This is for package-internal use only, and may change at any time.
*
* @private
* @internal
*/
export declare class Colours {
static enabled: boolean;
static reset: string;
static bright: string;
static dim: string;
static red: string;
static green: string;
static yellow: string;
static blue: string;
static magenta: string;
static cyan: string;
static white: string;
static grey: string;
/**
* @param stream The stream (e.g. process.stderr)
* @returns true if the stream should have colourization enabled
*/
static isEnabled(stream: tty.WriteStream): boolean;
static refresh(): void;
}

View File

@@ -0,0 +1,80 @@
"use strict";
// Copyright 2024 Google LLC
//
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.Colours = void 0;
/**
* Handles figuring out if we can use ANSI colours and handing out the escape codes.
*
* This is for package-internal use only, and may change at any time.
*
* @private
* @internal
*/
class Colours {
/**
* @param stream The stream (e.g. process.stderr)
* @returns true if the stream should have colourization enabled
*/
static isEnabled(stream) {
return (stream.isTTY &&
(typeof stream.getColorDepth === 'function'
? stream.getColorDepth() > 2
: true));
}
static refresh() {
Colours.enabled = Colours.isEnabled(process.stderr);
if (!this.enabled) {
Colours.reset = '';
Colours.bright = '';
Colours.dim = '';
Colours.red = '';
Colours.green = '';
Colours.yellow = '';
Colours.blue = '';
Colours.magenta = '';
Colours.cyan = '';
Colours.white = '';
Colours.grey = '';
}
else {
Colours.reset = '\u001b[0m';
Colours.bright = '\u001b[1m';
Colours.dim = '\u001b[2m';
Colours.red = '\u001b[31m';
Colours.green = '\u001b[32m';
Colours.yellow = '\u001b[33m';
Colours.blue = '\u001b[34m';
Colours.magenta = '\u001b[35m';
Colours.cyan = '\u001b[36m';
Colours.white = '\u001b[37m';
Colours.grey = '\u001b[90m';
}
}
}
exports.Colours = Colours;
Colours.enabled = false;
Colours.reset = '';
Colours.bright = '';
Colours.dim = '';
Colours.red = '';
Colours.green = '';
Colours.yellow = '';
Colours.blue = '';
Colours.magenta = '';
Colours.cyan = '';
Colours.white = '';
Colours.grey = '';
Colours.refresh();
//# sourceMappingURL=colours.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"colours.js","sourceRoot":"","sources":["../../src/colours.ts"],"names":[],"mappings":";AAAA,4BAA4B;AAC5B,EAAE;AACF,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,kDAAkD;AAClD,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;;AAUjC;;;;;;;GAOG;AACH,MAAa,OAAO;IAelB;;;OAGG;IACH,MAAM,CAAC,SAAS,CAAC,MAAuB;QACtC,OAAO,CACL,MAAM,CAAC,KAAK;YACZ,CAAC,OAAO,MAAM,CAAC,aAAa,KAAK,UAAU;gBACzC,CAAC,CAAC,MAAM,CAAC,aAAa,EAAE,GAAG,CAAC;gBAC5B,CAAC,CAAC,IAAI,CAAC,CACV,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,OAAO;QACZ,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACpD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC;YACnB,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC;YACpB,OAAO,CAAC,GAAG,GAAG,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,GAAG,EAAE,CAAC;YACjB,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC;YACnB,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,GAAG,EAAE,CAAC;YAClB,OAAO,CAAC,OAAO,GAAG,EAAE,CAAC;YACrB,OAAO,CAAC,IAAI,GAAG,EAAE,CAAC;YAClB,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,GAAG,EAAE,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,GAAG,WAAW,CAAC;YAC5B,OAAO,CAAC,MAAM,GAAG,WAAW,CAAC;YAC7B,OAAO,CAAC,GAAG,GAAG,WAAW,CAAC;YAC1B,OAAO,CAAC,GAAG,GAAG,YAAY,CAAC;YAC3B,OAAO,CAAC,KAAK,GAAG,YAAY,CAAC;YAC7B,OAAO,CAAC,MAAM,GAAG,YAAY,CAAC;YAC9B,OAAO,CAAC,IAAI,GAAG,YAAY,CAAC;YAC5B,OAAO,CAAC,OAAO,GAAG,YAAY,CAAC;YAC/B,OAAO,CAAC,IAAI,GAAG,YAAY,CAAC;YAC5B,OAAO,CAAC,KAAK,GAAG,YAAY,CAAC;YAC7B,OAAO,CAAC,IAAI,GAAG,YAAY,CAAC;QAC9B,CAAC;IACH,CAAC;;AAvDH,0BAwDC;AAvDQ,eAAO,GAAG,KAAK,CAAC;AAChB,aAAK,GAAG,EAAE,CAAC;AACX,cAAM,GAAG,EAAE,CAAC;AACZ,WAAG,GAAG,EAAE,CAAC;AAET,WAAG,GAAG,EAAE,CAAC;AACT,aAAK,GAAG,EAAE,CAAC;AACX,cAAM,GAAG,EAAE,CAAC;AACZ,YAAI,GAAG,EAAE,CAAC;AACV,eAAO,GAAG,EAAE,CAAC;AACb,YAAI,GAAG,EAAE,CAAC;AACV,aAAK,GAAG,EAAE,CAAC;AACX,YAAI,GAAG,EAAE,CAAC;AA6CnB,OAAO,CAAC,OAAO,EAAE,CAAC"}

View File

@@ -0,0 +1 @@
export * from './logging-utils';

View File

@@ -0,0 +1,31 @@
"use strict";
// Copyright 2024 Google LLC
//
// 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.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./logging-utils"), exports);
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA,4BAA4B;AAC5B,EAAE;AACF,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,kDAAkD;AAClD,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;;;;;;;;;;;;;;;AAEjC,kDAAgC"}

View File

@@ -0,0 +1,222 @@
import { EventEmitter } from 'node:events';
/**
* This module defines an ad-hoc debug logger for Google Cloud Platform
* client libraries in Node. An ad-hoc debug logger is a tool which lets
* users use an external, unified interface (in this case, environment
* variables) to determine what logging they want to see at runtime. This
* isn't necessarily fed into the console, but is meant to be under the
* control of the user. The kind of logging that will be produced by this
* is more like "call retry happened", not "event you'd want to record
* in Cloud Logger".
*
* More for Googlers implementing libraries with it:
* go/cloud-client-logging-design
*/
/**
* Possible log levels. These are a subset of Cloud Observability levels.
* https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#LogSeverity
*/
export declare enum LogSeverity {
DEFAULT = "DEFAULT",
DEBUG = "DEBUG",
INFO = "INFO",
WARNING = "WARNING",
ERROR = "ERROR"
}
/**
* A set of suggested log metadata fields.
*/
export interface LogFields {
/**
* Log level - undefined/null === DEFAULT.
*/
severity?: LogSeverity;
/**
* If this log is associated with an OpenTelemetry trace, you can put the
* trace ID here to pass on that association.
*/
telemetryTraceId?: string;
/**
* If this log is associated with an OpenTelemetry trace, you can put the
* span ID here to pass on that association.
*/
telemetrySpanId?: string;
/**
* This is a catch-all for any other items you might want to go into
* structured logs. Library implementers, please see the spec docs above
* for the items envisioned to go here.
*/
other?: unknown;
}
/**
* Adds typings for event sinks.
*/
export declare interface AdhocDebugLogger {
on(event: 'log', listener: (fields: LogFields, args: unknown[]) => void): this;
on(event: string, listener: Function): this;
}
/**
* Our logger instance. This actually contains the meat of dealing
* with log lines, including EventEmitter. This contains the function
* that will be passed back to users of the package.
*/
export declare class AdhocDebugLogger extends EventEmitter {
namespace: string;
upstream: AdhocDebugLogCallable;
func: AdhocDebugLogFunction;
/**
* @param upstream The backend will pass a function that will be
* called whenever our logger function is invoked.
*/
constructor(namespace: string, upstream: AdhocDebugLogCallable);
invoke(fields: LogFields, ...args: unknown[]): void;
invokeSeverity(severity: LogSeverity, ...args: unknown[]): void;
}
/**
* This can be used in place of a real logger while waiting for Promises or disabling logging.
*/
export declare const placeholder: AdhocDebugLogFunction;
/**
* When the user receives a log function (below), this will be the basic function
* call interface for it.
*/
export interface AdhocDebugLogCallable {
(fields: LogFields, ...args: unknown[]): void;
}
/**
* Adds typing info for the EventEmitter we're adding to the returned function.
*
* Note that this interface may change at any time, as we're reserving the
* right to add new backends at the logger level.
*
* @private
* @internal
*/
export interface AdhocDebugLogFunction extends AdhocDebugLogCallable {
instance: AdhocDebugLogger;
on(event: 'log', listener: (fields: LogFields, args: unknown[]) => void): this;
debug(...args: unknown[]): void;
info(...args: unknown[]): void;
warn(...args: unknown[]): void;
error(...args: unknown[]): void;
sublog(namespace: string): AdhocDebugLogFunction;
}
/**
* One of these can be passed to support a third-party backend, like "debug".
* We're splitting this out because ESM can complicate optional module loading.
*
* Note that this interface may change at any time, as we're reserving the
* right to add new backends at the logger level.
*
* @private
* @internal
*/
export interface DebugLogBackend {
/**
* Outputs a log to this backend.
*
* @param namespace The "system" that will be used for filtering. This may also
* include a "subsystem" in the form "system:subsystem".
* @param fields Logging fields to be included as metadata.
* @param args Any parameters to passed to a utils.format() type formatter.
*/
log(namespace: string, fields: LogFields, ...args: unknown[]): void;
/**
* Passes in the system/subsystem filters from the global environment variables.
* This lets the backend merge with any native ones.
*
* @param filters A list of wildcards matching systems or system:subsystem pairs.
*/
setFilters(filters: string[]): void;
}
/**
* The base class for debug logging backends. It's possible to use this, but the
* same non-guarantees above still apply (unstable interface, etc).
*
* @private
* @internal
*/
export declare abstract class DebugLogBackendBase implements DebugLogBackend {
cached: Map<string, AdhocDebugLogCallable>;
filters: string[];
filtersSet: boolean;
constructor();
/**
* Creates a callback function that we can call to send log lines out.
*
* @param namespace The system/subsystem namespace.
*/
abstract makeLogger(namespace: string): AdhocDebugLogCallable;
/**
* Provides a callback for the subclass to hook if it needs to do something
* specific with `this.filters`.
*/
abstract setFilters(): void;
log(namespace: string, fields: LogFields, ...args: unknown[]): void;
}
/**
* @returns A backend based on Node util.debuglog; this is the default.
*/
export declare function getNodeBackend(): DebugLogBackend;
type DebugPackage = any;
/**
* Creates a "debug" package backend. The user must call require('debug') and pass
* the resulting object to this function.
*
* ```
* setBackend(getDebugBackend(require('debug')))
* ```
*
* https://www.npmjs.com/package/debug
*
* Note: Google does not explicitly endorse or recommend this package; it's just
* being provided as an option.
*
* @returns A backend based on the npm "debug" package.
*/
export declare function getDebugBackend(debugPkg: DebugPackage): DebugLogBackend;
/**
* Creates a "structured logging" backend. This pretty much works like the
* Node logger, but it outputs structured logging JSON matching Google
* Cloud's ingestion specs instead of plain text.
*
* ```
* setBackend(getStructuredBackend())
* ```
*
* @param upstream If you want to use something besides the Node backend to
* write the actual log lines into, pass that here.
* @returns A backend based on Google Cloud structured logging.
*/
export declare function getStructuredBackend(upstream?: DebugLogBackend): DebugLogBackend;
/**
* The environment variables that we standardized on, for all ad-hoc logging.
*/
export declare const env: {
/**
* Filter wildcards specific to the Node syntax, and similar to the built-in
* utils.debuglog() environment variable. If missing, disables logging.
*/
nodeEnables: string;
};
/**
* Set the backend to use for our log output.
* - A backend object
* - null to disable logging
* - undefined for "nothing yet", defaults to the Node backend
*
* @param backend Results from one of the get*Backend() functions.
*/
export declare function setBackend(backend: DebugLogBackend | null): void;
/**
* Creates a logging function. Multiple calls to this with the same namespace
* will produce the same logger, with the same event emitter hooks.
*
* Namespaces can be a simple string ("system" name), or a qualified string
* (system:subsystem), which can be used for filtering, or for "system:*".
*
* @param namespace The namespace, a descriptive text string.
* @returns A function you can call that works similar to console.log().
*/
export declare function log(namespace: string, parent?: AdhocDebugLogFunction): AdhocDebugLogFunction;
export {};

View File

@@ -0,0 +1,406 @@
"use strict";
// Copyright 2021-2024 Google LLC
//
// 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.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.env = exports.DebugLogBackendBase = exports.placeholder = exports.AdhocDebugLogger = exports.LogSeverity = void 0;
exports.getNodeBackend = getNodeBackend;
exports.getDebugBackend = getDebugBackend;
exports.getStructuredBackend = getStructuredBackend;
exports.setBackend = setBackend;
exports.log = log;
const node_events_1 = require("node:events");
const process = __importStar(require("node:process"));
const util = __importStar(require("node:util"));
const colours_1 = require("./colours");
// Some functions (as noted) are based on the Node standard library, from
// the following file:
//
// https://github.com/nodejs/node/blob/main/lib/internal/util/debuglog.js
/**
* This module defines an ad-hoc debug logger for Google Cloud Platform
* client libraries in Node. An ad-hoc debug logger is a tool which lets
* users use an external, unified interface (in this case, environment
* variables) to determine what logging they want to see at runtime. This
* isn't necessarily fed into the console, but is meant to be under the
* control of the user. The kind of logging that will be produced by this
* is more like "call retry happened", not "event you'd want to record
* in Cloud Logger".
*
* More for Googlers implementing libraries with it:
* go/cloud-client-logging-design
*/
/**
* Possible log levels. These are a subset of Cloud Observability levels.
* https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#LogSeverity
*/
var LogSeverity;
(function (LogSeverity) {
LogSeverity["DEFAULT"] = "DEFAULT";
LogSeverity["DEBUG"] = "DEBUG";
LogSeverity["INFO"] = "INFO";
LogSeverity["WARNING"] = "WARNING";
LogSeverity["ERROR"] = "ERROR";
})(LogSeverity || (exports.LogSeverity = LogSeverity = {}));
/**
* Our logger instance. This actually contains the meat of dealing
* with log lines, including EventEmitter. This contains the function
* that will be passed back to users of the package.
*/
class AdhocDebugLogger extends node_events_1.EventEmitter {
/**
* @param upstream The backend will pass a function that will be
* called whenever our logger function is invoked.
*/
constructor(namespace, upstream) {
super();
this.namespace = namespace;
this.upstream = upstream;
this.func = Object.assign(this.invoke.bind(this), {
// Also add an instance pointer back to us.
instance: this,
// And pull over the EventEmitter functionality.
on: (event, listener) => this.on(event, listener),
});
// Convenience methods for log levels.
this.func.debug = (...args) => this.invokeSeverity(LogSeverity.DEBUG, ...args);
this.func.info = (...args) => this.invokeSeverity(LogSeverity.INFO, ...args);
this.func.warn = (...args) => this.invokeSeverity(LogSeverity.WARNING, ...args);
this.func.error = (...args) => this.invokeSeverity(LogSeverity.ERROR, ...args);
this.func.sublog = (namespace) => log(namespace, this.func);
}
invoke(fields, ...args) {
// Push out any upstream logger first.
if (this.upstream) {
this.upstream(fields, ...args);
}
// Emit sink events.
this.emit('log', fields, args);
}
invokeSeverity(severity, ...args) {
this.invoke({ severity }, ...args);
}
}
exports.AdhocDebugLogger = AdhocDebugLogger;
/**
* This can be used in place of a real logger while waiting for Promises or disabling logging.
*/
exports.placeholder = new AdhocDebugLogger('', () => { }).func;
/**
* The base class for debug logging backends. It's possible to use this, but the
* same non-guarantees above still apply (unstable interface, etc).
*
* @private
* @internal
*/
class DebugLogBackendBase {
constructor() {
var _a;
this.cached = new Map();
this.filters = [];
this.filtersSet = false;
// Look for the Node config variable for what systems to enable. We'll store
// these for the log method below, which will call setFilters() once.
let nodeFlag = (_a = process.env[exports.env.nodeEnables]) !== null && _a !== void 0 ? _a : '*';
if (nodeFlag === 'all') {
nodeFlag = '*';
}
this.filters = nodeFlag.split(',');
}
log(namespace, fields, ...args) {
try {
if (!this.filtersSet) {
this.setFilters();
this.filtersSet = true;
}
let logger = this.cached.get(namespace);
if (!logger) {
logger = this.makeLogger(namespace);
this.cached.set(namespace, logger);
}
logger(fields, ...args);
}
catch (e) {
// Silently ignore all errors; we don't want them to interfere with
// the user's running app.
// e;
console.error(e);
}
}
}
exports.DebugLogBackendBase = DebugLogBackendBase;
// The basic backend. This one definitely works, but it's less feature-filled.
//
// Rather than using util.debuglog, this implements the same basic logic directly.
// The reason for this decision is that debuglog checks the value of the
// NODE_DEBUG environment variable before any user code runs; we therefore
// can't pipe our own enables into it (and util.debuglog will never print unless
// the user duplicates it into NODE_DEBUG, which isn't reasonable).
//
class NodeBackend extends DebugLogBackendBase {
constructor() {
super(...arguments);
// Default to allowing all systems, since we gate earlier based on whether the
// variable is empty.
this.enabledRegexp = /.*/g;
}
isEnabled(namespace) {
return this.enabledRegexp.test(namespace);
}
makeLogger(namespace) {
if (!this.enabledRegexp.test(namespace)) {
return () => { };
}
return (fields, ...args) => {
var _a;
// TODO: `fields` needs to be turned into a string here, one way or another.
const nscolour = `${colours_1.Colours.green}${namespace}${colours_1.Colours.reset}`;
const pid = `${colours_1.Colours.yellow}${process.pid}${colours_1.Colours.reset}`;
let level;
switch (fields.severity) {
case LogSeverity.ERROR:
level = `${colours_1.Colours.red}${fields.severity}${colours_1.Colours.reset}`;
break;
case LogSeverity.INFO:
level = `${colours_1.Colours.magenta}${fields.severity}${colours_1.Colours.reset}`;
break;
case LogSeverity.WARNING:
level = `${colours_1.Colours.yellow}${fields.severity}${colours_1.Colours.reset}`;
break;
default:
level = (_a = fields.severity) !== null && _a !== void 0 ? _a : LogSeverity.DEFAULT;
break;
}
const msg = util.formatWithOptions({ colors: colours_1.Colours.enabled }, ...args);
const filteredFields = Object.assign({}, fields);
delete filteredFields.severity;
const fieldsJson = Object.getOwnPropertyNames(filteredFields).length
? JSON.stringify(filteredFields)
: '';
const fieldsColour = fieldsJson
? `${colours_1.Colours.grey}${fieldsJson}${colours_1.Colours.reset}`
: '';
console.error('%s [%s|%s] %s%s', pid, nscolour, level, msg, fieldsJson ? ` ${fieldsColour}` : '');
};
}
// Regexp patterns below are from here:
// https://github.com/nodejs/node/blob/c0aebed4b3395bd65d54b18d1fd00f071002ac20/lib/internal/util/debuglog.js#L36
setFilters() {
const totalFilters = this.filters.join(',');
const regexp = totalFilters
.replace(/[|\\{}()[\]^$+?.]/g, '\\$&')
.replace(/\*/g, '.*')
.replace(/,/g, '$|^');
this.enabledRegexp = new RegExp(`^${regexp}$`, 'i');
}
}
/**
* @returns A backend based on Node util.debuglog; this is the default.
*/
function getNodeBackend() {
return new NodeBackend();
}
class DebugBackend extends DebugLogBackendBase {
constructor(pkg) {
super();
this.debugPkg = pkg;
}
makeLogger(namespace) {
const debugLogger = this.debugPkg(namespace);
return (fields, ...args) => {
// TODO: `fields` needs to be turned into a string here.
debugLogger(args[0], ...args.slice(1));
};
}
setFilters() {
var _a;
const existingFilters = (_a = process.env['NODE_DEBUG']) !== null && _a !== void 0 ? _a : '';
process.env['NODE_DEBUG'] = `${existingFilters}${existingFilters ? ',' : ''}${this.filters.join(',')}`;
}
}
/**
* Creates a "debug" package backend. The user must call require('debug') and pass
* the resulting object to this function.
*
* ```
* setBackend(getDebugBackend(require('debug')))
* ```
*
* https://www.npmjs.com/package/debug
*
* Note: Google does not explicitly endorse or recommend this package; it's just
* being provided as an option.
*
* @returns A backend based on the npm "debug" package.
*/
function getDebugBackend(debugPkg) {
return new DebugBackend(debugPkg);
}
/**
* This pretty much works like the Node logger, but it outputs structured
* logging JSON matching Google Cloud's ingestion specs. Rather than handling
* its own output, it wraps another backend. The passed backend must be a subclass
* of `DebugLogBackendBase` (any of the backends exposed by this package will work).
*/
class StructuredBackend extends DebugLogBackendBase {
constructor(upstream) {
var _a;
super();
this.upstream = (_a = upstream) !== null && _a !== void 0 ? _a : new NodeBackend();
}
makeLogger(namespace) {
const debugLogger = this.upstream.makeLogger(namespace);
return (fields, ...args) => {
var _a;
const severity = (_a = fields.severity) !== null && _a !== void 0 ? _a : LogSeverity.INFO;
const json = Object.assign({
severity,
message: util.format(...args),
}, fields);
const jsonString = JSON.stringify(json);
debugLogger(fields, jsonString);
};
}
setFilters() {
this.upstream.setFilters();
}
}
/**
* Creates a "structured logging" backend. This pretty much works like the
* Node logger, but it outputs structured logging JSON matching Google
* Cloud's ingestion specs instead of plain text.
*
* ```
* setBackend(getStructuredBackend())
* ```
*
* @param upstream If you want to use something besides the Node backend to
* write the actual log lines into, pass that here.
* @returns A backend based on Google Cloud structured logging.
*/
function getStructuredBackend(upstream) {
return new StructuredBackend(upstream);
}
/**
* The environment variables that we standardized on, for all ad-hoc logging.
*/
exports.env = {
/**
* Filter wildcards specific to the Node syntax, and similar to the built-in
* utils.debuglog() environment variable. If missing, disables logging.
*/
nodeEnables: 'GOOGLE_SDK_NODE_LOGGING',
};
// Keep a copy of all namespaced loggers so users can reliably .on() them.
// Note that these cached functions will need to deal with changes in the backend.
const loggerCache = new Map();
// Our current global backend. This might be:
let cachedBackend = undefined;
/**
* Set the backend to use for our log output.
* - A backend object
* - null to disable logging
* - undefined for "nothing yet", defaults to the Node backend
*
* @param backend Results from one of the get*Backend() functions.
*/
function setBackend(backend) {
cachedBackend = backend;
loggerCache.clear();
}
/**
* Creates a logging function. Multiple calls to this with the same namespace
* will produce the same logger, with the same event emitter hooks.
*
* Namespaces can be a simple string ("system" name), or a qualified string
* (system:subsystem), which can be used for filtering, or for "system:*".
*
* @param namespace The namespace, a descriptive text string.
* @returns A function you can call that works similar to console.log().
*/
function log(namespace, parent) {
// If the enable flag isn't set, do nothing.
const enablesFlag = process.env[exports.env.nodeEnables];
if (!enablesFlag) {
return exports.placeholder;
}
// This might happen mostly if the typings are dropped in a user's code,
// or if they're calling from JavaScript.
if (!namespace) {
return exports.placeholder;
}
// Handle sub-loggers.
if (parent) {
namespace = `${parent.instance.namespace}:${namespace}`;
}
// Reuse loggers so things like event sinks are persistent.
const existing = loggerCache.get(namespace);
if (existing) {
return existing.func;
}
// Do we have a backend yet?
if (cachedBackend === null) {
// Explicitly disabled.
return exports.placeholder;
}
else if (cachedBackend === undefined) {
// One hasn't been made yet, so default to Node.
cachedBackend = getNodeBackend();
}
// The logger is further wrapped so we can handle the backend changing out.
const logger = (() => {
let previousBackend = undefined;
const newLogger = new AdhocDebugLogger(namespace, (fields, ...args) => {
if (previousBackend !== cachedBackend) {
// Did the user pass a custom backend?
if (cachedBackend === null) {
// Explicitly disabled.
return;
}
else if (cachedBackend === undefined) {
// One hasn't been made yet, so default to Node.
cachedBackend = getNodeBackend();
}
previousBackend = cachedBackend;
}
cachedBackend === null || cachedBackend === void 0 ? void 0 : cachedBackend.log(namespace, fields, ...args);
});
return newLogger;
})();
loggerCache.set(namespace, logger);
return logger.func;
}
//# sourceMappingURL=logging-utils.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,45 @@
/**
* Simplified interface analogous to the tc39 Temporal.Duration
* parameter to from(). This doesn't support the full gamut (years, days).
*/
export interface DurationLike {
hours?: number;
minutes?: number;
seconds?: number;
millis?: number;
}
/**
* Simplified list of values to pass to Duration.totalOf(). This
* list is taken from the tc39 Temporal.Duration proposal, but
* larger and smaller units have been left off.
*/
export type TotalOfUnit = 'hour' | 'minute' | 'second' | 'millisecond';
/**
* Duration class with an interface similar to the tc39 Temporal
* proposal. Since it's not fully finalized, and polyfills have
* inconsistent compatibility, for now this shim class will be
* used to set durations in Pub/Sub.
*
* This class will remain here for at least the next major version,
* eventually to be replaced by the tc39 Temporal built-in.
*
* https://tc39.es/proposal-temporal/docs/duration.html
*/
export declare class Duration {
private millis;
private static secondInMillis;
private static minuteInMillis;
private static hourInMillis;
private constructor();
/**
* Calculates the total number of units of type 'totalOf' that would
* fit inside this duration.
*/
totalOf(totalOf: TotalOfUnit): number;
/**
* Creates a Duration from a DurationLike, which is an object
* containing zero or more of the following: hours, seconds,
* minutes, millis.
*/
static from(durationLike: DurationLike): Duration;
}

View File

@@ -0,0 +1,68 @@
"use strict";
// Copyright 2022-2024 Google LLC
//
// 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
//
// http://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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.Duration = void 0;
/**
* Duration class with an interface similar to the tc39 Temporal
* proposal. Since it's not fully finalized, and polyfills have
* inconsistent compatibility, for now this shim class will be
* used to set durations in Pub/Sub.
*
* This class will remain here for at least the next major version,
* eventually to be replaced by the tc39 Temporal built-in.
*
* https://tc39.es/proposal-temporal/docs/duration.html
*/
class Duration {
constructor(millis) {
this.millis = millis;
}
/**
* Calculates the total number of units of type 'totalOf' that would
* fit inside this duration.
*/
totalOf(totalOf) {
switch (totalOf) {
case 'hour':
return this.millis / Duration.hourInMillis;
case 'minute':
return this.millis / Duration.minuteInMillis;
case 'second':
return this.millis / Duration.secondInMillis;
case 'millisecond':
return this.millis;
default:
throw new Error(`Invalid unit in call to totalOf(): ${totalOf}`);
}
}
/**
* Creates a Duration from a DurationLike, which is an object
* containing zero or more of the following: hours, seconds,
* minutes, millis.
*/
static from(durationLike) {
var _a, _b, _c, _d;
let millis = (_a = durationLike.millis) !== null && _a !== void 0 ? _a : 0;
millis += ((_b = durationLike.seconds) !== null && _b !== void 0 ? _b : 0) * Duration.secondInMillis;
millis += ((_c = durationLike.minutes) !== null && _c !== void 0 ? _c : 0) * Duration.minuteInMillis;
millis += ((_d = durationLike.hours) !== null && _d !== void 0 ? _d : 0) * Duration.hourInMillis;
return new Duration(millis);
}
}
exports.Duration = Duration;
Duration.secondInMillis = 1000;
Duration.minuteInMillis = Duration.secondInMillis * 60;
Duration.hourInMillis = Duration.minuteInMillis * 60;
//# sourceMappingURL=temporal.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"temporal.js","sourceRoot":"","sources":["../../src/temporal.ts"],"names":[],"mappings":";AAAA,iCAAiC;AACjC,EAAE;AACF,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,kDAAkD;AAClD,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;;AA6BjC;;;;;;;;;;GAUG;AACH,MAAa,QAAQ;IAOnB,YAAoB,MAAc;QAChC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED;;;OAGG;IACH,OAAO,CAAC,OAAoB;QAC1B,QAAQ,OAAO,EAAE,CAAC;YAChB,KAAK,MAAM;gBACT,OAAO,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC,YAAY,CAAC;YAC7C,KAAK,QAAQ;gBACX,OAAO,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC,cAAc,CAAC;YAC/C,KAAK,QAAQ;gBACX,OAAO,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC,cAAc,CAAC;YAC/C,KAAK,aAAa;gBAChB,OAAO,IAAI,CAAC,MAAM,CAAC;YACrB;gBACE,MAAM,IAAI,KAAK,CAAC,sCAAsC,OAAO,EAAE,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,IAAI,CAAC,YAA0B;;QACpC,IAAI,MAAM,GAAG,MAAA,YAAY,CAAC,MAAM,mCAAI,CAAC,CAAC;QACtC,MAAM,IAAI,CAAC,MAAA,YAAY,CAAC,OAAO,mCAAI,CAAC,CAAC,GAAG,QAAQ,CAAC,cAAc,CAAC;QAChE,MAAM,IAAI,CAAC,MAAA,YAAY,CAAC,OAAO,mCAAI,CAAC,CAAC,GAAG,QAAQ,CAAC,cAAc,CAAC;QAChE,MAAM,IAAI,CAAC,MAAA,YAAY,CAAC,KAAK,mCAAI,CAAC,CAAC,GAAG,QAAQ,CAAC,YAAY,CAAC;QAE5D,OAAO,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;;AA1CH,4BA2CC;AAxCgB,uBAAc,GAAG,IAAI,CAAC;AACtB,uBAAc,GAAG,QAAQ,CAAC,cAAc,GAAG,EAAE,CAAC;AAC9C,qBAAY,GAAG,QAAQ,CAAC,cAAc,GAAG,EAAE,CAAC"}