UNPKG

@google-cloud/logging

Version:
1,012 lines 39.8 kB
"use strict"; /*! * Copyright 2015 Google Inc. All Rights Reserved. * * 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. */ 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 }); exports.v2 = exports.protos = exports.Logging = exports.Sink = exports.LogSync = exports.formatLogName = exports.assignSeverityToEntries = exports.Severity = exports.Log = exports.Entry = exports.detectServiceContext = exports.middleware = void 0; const common_1 = require("@google-cloud/common"); const paginator_1 = require("@google-cloud/paginator"); const projectify_1 = require("@google-cloud/projectify"); const promisify_1 = require("@google-cloud/promisify"); const arrify = require("arrify"); const extend = require("extend"); const gax = require("google-gax"); // eslint-disable-next-line @typescript-eslint/no-var-requires const pumpify = require('pumpify'); const streamEvents = require("stream-events"); const middleware = require("./middleware"); exports.middleware = middleware; const metadata_1 = require("./utils/metadata"); Object.defineProperty(exports, "detectServiceContext", { enumerable: true, get: function () { return metadata_1.detectServiceContext; } }); const version = require('../../package.json').version; // eslint-disable-next-line @typescript-eslint/no-var-requires const v2 = require('@google-cloud/logging-api'); exports.v2 = v2; const entry_1 = require("./entry"); Object.defineProperty(exports, "Entry", { enumerable: true, get: function () { return entry_1.Entry; } }); const log_common_1 = require("./utils/log-common"); Object.defineProperty(exports, "Severity", { enumerable: true, get: function () { return log_common_1.Severity; } }); Object.defineProperty(exports, "formatLogName", { enumerable: true, get: function () { return log_common_1.formatLogName; } }); Object.defineProperty(exports, "assignSeverityToEntries", { enumerable: true, get: function () { return log_common_1.assignSeverityToEntries; } }); const log_1 = require("./log"); Object.defineProperty(exports, "Log", { enumerable: true, get: function () { return log_1.Log; } }); const log_sync_1 = require("./log-sync"); Object.defineProperty(exports, "LogSync", { enumerable: true, get: function () { return log_sync_1.LogSync; } }); const sink_1 = require("./sink"); Object.defineProperty(exports, "Sink", { enumerable: true, get: function () { return sink_1.Sink; } }); const stream_1 = require("stream"); const logging_api_1 = require("@google-cloud/logging-api"); Object.defineProperty(exports, "protos", { enumerable: true, get: function () { return logging_api_1.protos; } }); /** * @typedef {object} ClientConfig * @property {string} [projectId] The project ID from the Google Developer's * Console, e.g. 'grape-spaceship-123'. We will also check the environment * variable `GCLOUD_PROJECT` for your project ID. If your app is running in * an environment which supports {@link * https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application * Application Default Credentials}, your project ID will be detected * automatically. * @property {string} [keyFilename] Full path to the a .json, .pem, or .p12 key * downloaded from the Google Developers Console. If you provide a path to a * JSON file, the `projectId` option above is not necessary. NOTE: .pem and * .p12 require you to specify the `email` option as well. * @property {string} [email] Account email address. Required when using a .pem * or .p12 keyFilename. * @property {object} [credentials] Credentials object. * @property {string} [credentials.client_email] * @property {string} [credentials.private_key] * @property {boolean} [autoRetry=true] Automatically retry requests if the * response is related to rate limits or certain intermittent server errors. * We will exponentially backoff subsequent requests by default. * @property {number} [maxRetries=3] Maximum number of automatic retries * attempted before returning the error. * @property {Constructor} [promise] Custom promise module to use instead of * native Promises. */ /** * {@link https://cloud.google.com/logging/docs| Cloud Logging} allows you to * store, search, analyze, monitor, and alert on log data and events from Google * Cloud Platform and Amazon Web Services (AWS). * * @class * * See {@link https://cloud.google.com/logging/docs| What is Cloud Logging?} * * See {@link https://cloud.google.com/logging/docs/api| Introduction to the Cloud Logging API} * * See {@link https://www.npmjs.com/package/@google-cloud/logging-bunyan| Logging to Google Cloud from Bunyan} * * See {@link https://www.npmjs.com/package/@google-cloud/logging-winston| Logging to Google Cloud from Winston} * * @param {ClientConfig} [options] Configuration options. * * @example Import the client library * ``` * const {Logging} = require('@google-cloud/logging'); * * ``` * @example Create a client that uses <a href="https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application">Application Default Credentials (ADC)</a>: * ``` * const logging = new Logging(); * * ``` * @example Create a client with <a href="https://cloud.google.com/docs/authentication/production#obtaining_and_providing_service_account_credentials_manually">explicitcredentials</a>: * ``` * const logging = new Logging({ projectId: * 'your-project-id', keyFilename: '/path/to/keyfile.json' * }); * * ``` * @example <caption>include:samples/quickstart.js</caption> * region_tag:logging_quickstart * Full quickstart example: */ class Logging { constructor(options, gaxInstance) { // Determine what scopes are needed. // It is the union of the scopes on all three clients. const scopes = []; const clientClasses = [ v2.ConfigServiceV2Client, v2.LoggingServiceV2Client, v2.MetricsServiceV2Client, ]; for (const clientClass of clientClasses) { for (const scope of clientClass.scopes) { if (scopes.indexOf(scope) === -1) { scopes.push(scope); } } } const options_ = extend({ libName: 'gccl', libVersion: version, scopes, }, options); this.api = {}; this.auth = new (gaxInstance !== null && gaxInstance !== void 0 ? gaxInstance : gax).GoogleAuth(options_); this.options = options_; this.projectId = this.options.projectId || '{{projectId}}'; this.configService = new v2.ConfigServiceV2Client(this.options, gaxInstance); this.loggingService = new v2.LoggingServiceV2Client(this.options, gaxInstance); } // jscs:disable maximumLineLength /** * Create a sink. * * See {@link https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.sinks|Sink Overview} * See {@link https://cloud.google.com/logging/docs/view/advanced_filters|Advanced Logs Filters} * See {@link https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.sinks/create|projects.sinks.create API Documentation} * * @param {string} name Name of the sink. * @param {CreateSinkRequest} config Config to set for the sink. * @param {CreateSinkCallback} [callback] Callback function. * @returns {Promise<CreateSinkResponse>} * @throws {Error} If a name is not provided. * @throws {Error} if a config object is not provided. * @see Sink#create * * @example * ``` * const {Storage} = require('@google-cloud/storage'); * const storage = new Storage({ * projectId: 'grape-spaceship-123' * }); * const {Logging} = require('@google-cloud/logging'); * const logging = new Logging(); * * const config = { * destination: storage.bucket('logging-bucket'), * filter: 'severity = ALERT' * }; * * function callback(err, sink, apiResponse) { * // `sink` is a Sink object. * } * * logging.createSink('new-sink-name', config, callback); * * //- * // If the callback is omitted, we'll return a Promise. * //- * logging.createSink('new-sink-name', config).then(data => { * const sink = data[0]; * const apiResponse = data[1]; * }); * * ``` * @example <caption>include:samples/sinks.js</caption> * region_tag:logging_create_sink * Another example: */ async createSink(name, config) { if (typeof name !== 'string') { throw new Error('A sink name must be provided.'); } if (typeof config !== 'object') { throw new Error('A sink configuration object must be provided.'); } if (common_1.util.isCustomType(config.destination, 'bigquery/dataset')) { await this.setAclForDataset_(config); } if (common_1.util.isCustomType(config.destination, 'pubsub/topic')) { await this.setAclForTopic_(config); } if (common_1.util.isCustomType(config.destination, 'storage/bucket')) { await this.setAclForBucket_(config); } const reqOpts = { parent: 'projects/' + this.projectId, sink: extend({}, config, { name }), uniqueWriterIdentity: config.uniqueWriterIdentity, }; delete reqOpts.sink.gaxOptions; delete reqOpts.sink.uniqueWriterIdentity; await this.setProjectId(reqOpts); const [resp] = await this.configService.createSink(reqOpts, config.gaxOptions); const sink = this.sink(resp.name); sink.metadata = resp; return [sink, resp]; } /** * Create an entry object. * * Using this method will not itself make any API requests. You will use * the object returned in other API calls, such as * {@link Log#write}. * * Note, {@link https://cloud.google.com/logging/quotas|Cloud Logging Quotas and limits} * dictates that the maximum log entry size, including all * [LogEntry Resource properties]{@link https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry}, * cannot exceed _approximately_ 256 KB. * * See {@link https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry|LogEntry JSON representation} * * @param {?object|?string} [resource] See a * [Monitored * Resource](https://cloud.google.com/logging/docs/reference/v2/rest/v2/MonitoredResource). * @param {object|string} data The data to use as the value for this log * entry. * @returns {Entry} * * @example * ``` * const {Logging} = require('@google-cloud/logging'); * const logging = new Logging(); * * const resource = { * type: 'gce_instance', * labels: { * zone: 'global', * instance_id: '3' * } * }; * * const entry = logging.entry(resource, { * delegate: 'my_username' * }); * * entry.toJSON(); * // { * // resource: { * // type: 'gce_instance', * // labels: { * // zone: 'global', * // instance_id: '3' * // } * // }, * // jsonPayload: { * // delegate: 'my_username' * // } * // } * ``` */ entry(resource, data) { return new entry_1.Entry(resource, data); } async getEntries(opts) { const options = opts ? opts : {}; // By default, sort entries by descending timestamp let reqOpts = extend({ orderBy: 'timestamp desc' }, options); // By default, filter entries to last 24 hours only const time = new Date(); time.setDate(time.getDate() - 1); const timeFilter = `timestamp >= "${time.toISOString()}"`; if (!options.filter) { reqOpts = extend({ filter: timeFilter }, reqOpts); } else if (!options.filter.includes('timestamp')) { reqOpts.filter += ` AND ${timeFilter}`; } this.projectId = await this.auth.getProjectId(); const resourceName = 'projects/' + this.projectId; reqOpts.resourceNames = arrify(reqOpts.resourceNames); if (reqOpts.resourceNames.length === 0) { // If no resource names are provided, default to the current project. reqOpts.resourceNames.push(resourceName); } delete reqOpts.autoPaginate; delete reqOpts.gaxOptions; let gaxOptions = extend({ autoPaginate: options.autoPaginate, }, options.gaxOptions); if (options === null || options === void 0 ? void 0 : options.maxResults) { gaxOptions = extend({ maxResults: options.maxResults, }, gaxOptions); } const resp = await this.loggingService.listLogEntries(reqOpts, gaxOptions); const [entries] = resp; if (entries) { resp[0] = entries.map(entry_1.Entry.fromApiResponse_); } return resp; } /** * List the {@link Entry} objects in your logs as a readable object * stream. * * @method Logging#getEntriesStream * @param {GetEntriesRequest} [query] Query object for listing entries. * @returns {ReadableStream} A readable stream that emits {@link Entry} * instances. * * @example * ``` * const {Logging} = require('@google-cloud/logging'); * const logging = new Logging(); * * logging.getEntriesStream() * .on('error', console.error) * .on('data', entry => { * // `entry` is a Cloud Logging entry object. * // See the `data` property to read the data from the entry. * }) * .on('end', function() { * // All entries retrieved. * }); * * //- * // If you anticipate many results, you can end a stream early to prevent * // unnecessary processing and API requests. * //- * logging.getEntriesStream() * .on('data', function(entry) { * this.end(); * }); * ``` */ getEntriesStream(options = {}) { let requestStream; const userStream = streamEvents(pumpify.obj()); userStream.abort = () => { if (requestStream) { requestStream.abort(); } }; const toEntryStream = new stream_1.Transform({ objectMode: true, transform: (chunk, encoding, callback) => { callback(null, entry_1.Entry.fromApiResponse_(chunk)); }, }); userStream.once('reading', () => { this.auth.getProjectId().then(projectId => { this.projectId = projectId; if (options.log) { if (options.filter) { options.filter = `(${options.filter}) AND logName="${(0, log_common_1.formatLogName)(this.projectId, options.log)}"`; } else { options.filter = `logName="${(0, log_common_1.formatLogName)(this.projectId, options.log)}"`; } delete options.log; } const reqOpts = extend({ orderBy: 'timestamp desc', }, options); reqOpts.resourceNames = arrify(reqOpts.resourceNames); reqOpts.resourceNames.push(`projects/${this.projectId}`); delete reqOpts.autoPaginate; delete reqOpts.gaxOptions; const gaxOptions = extend({ autoPaginate: options.autoPaginate, }, options.gaxOptions); let gaxStream; requestStream = streamEvents(new stream_1.PassThrough({ objectMode: true })); requestStream.abort = () => { if (gaxStream && gaxStream.cancel) { gaxStream.cancel(); } }; // eslint-disable-next-line @typescript-eslint/no-explicit-any if (!global.GCLOUD_SANDBOX_ENV) { requestStream.once('reading', () => { try { gaxStream = this.loggingService.listLogEntriesStream(reqOpts, gaxOptions); } catch (error) { requestStream.destroy(error); return; } gaxStream .on('error', (err) => { requestStream.destroy(err); }) .pipe(requestStream); return; }); } // eslint-disable-next-line @typescript-eslint/no-explicit-any userStream.setPipeline(requestStream, toEntryStream); }); }); return userStream; } /** * Query object for streaming entries. * * @typedef {object} TailEntriesRequest * @property {Array.<string>|string} [resourceNames] Names of project * resources to stream logs out of. * @property {string} [filter] An * [advanced logs * filter](https://cloud.google.com/logging/docs/view/advanced_filters). An * empty filter matches all log entries. * @property {number} [bufferWindow=2] A setting to balance the tradeoff * between viewing the log entries as they are being written and viewing * them in ascending order. * @property {string} [log] A name of the log specifying to only return * entries from this log. * @property {object} [gaxOptions] Request configuration options, outlined * here: https://googleapis.github.io/gax-nodejs/global.html#CallOptions. */ /** * Streaming read of live logs as log entries are ingested. Until the stream * is terminated, it will continue reading logs. * * @method Logging#tailEntries * @param {TailEntriesRequest} [query] Query object for tailing entries. * @returns {DuplexStream} A duplex stream that emits TailEntriesResponses * containing an array of {@link Entry} instances. * * @example * ``` * const {Logging} = require('@google-cloud/logging'); * const logging = new Logging(); * * logging.tailEntries() * .on('error', console.error) * .on('data', resp => { * console.log(resp.entries); * console.log(resp.suppressionInfo); * }) * .on('end', function() { * // All entries retrieved. * }); * * //- * // If you anticipate many results, you can end a stream early to prevent * // unnecessary processing and API requests. * //- * logging.getEntriesStream() * .on('data', function(entry) { * this.end(); * }); * ``` */ tailEntries(options = {}) { const userStream = streamEvents(pumpify.obj()); // eslint-disable-next-line @typescript-eslint/no-explicit-any let gaxStream; userStream.abort = () => { if (gaxStream && gaxStream.cancel) { gaxStream.cancel(); } }; const transformStream = new stream_1.Transform({ objectMode: true, transform: (chunk, encoding, callback) => { callback(null, (() => { const formattedEntries = []; chunk.entries.forEach((entry) => { formattedEntries.push(entry_1.Entry.fromApiResponse_(entry)); }); const resp = { entries: formattedEntries, suppressionInfo: chunk.suppressionInfo, }; return resp; })()); }, }); this.auth.getProjectId().then(projectId => { this.projectId = projectId; if (options.log) { if (options.filter) { options.filter = `(${options.filter}) AND logName="${(0, log_common_1.formatLogName)(this.projectId, options.log)}"`; } else { options.filter = `logName="${(0, log_common_1.formatLogName)(this.projectId, options.log)}"`; } } options.resourceNames = arrify(options.resourceNames); options.resourceNames.push(`projects/${this.projectId}`); const writeOptions = { resourceNames: options.resourceNames, ...(options.filter && { filter: options.filter }), ...(options.bufferWindow && { bufferwindow: options.bufferWindow }), }; // eslint-disable-next-line @typescript-eslint/no-explicit-any if (!global.GCLOUD_SANDBOX_ENV) { gaxStream = this.loggingService.tailLogEntries(options.gaxOptions); // Write can only be called once in a single tail streaming session. gaxStream.write(writeOptions); // eslint-disable-next-line @typescript-eslint/no-explicit-any userStream.setPipeline(gaxStream, transformStream); } }); return userStream; } async getLogs(opts) { const options = opts ? opts : {}; this.projectId = await this.auth.getProjectId(); const reqOpts = extend({}, options, { parent: 'projects/' + this.projectId, }); delete reqOpts.autoPaginate; delete reqOpts.gaxOptions; const gaxOptions = extend({ autoPaginate: options.autoPaginate, }, options.gaxOptions); const resp = await this.loggingService.listLogs(reqOpts, gaxOptions); const [logs] = resp; if (logs) { resp[0] = logs.map((logName) => this.log(logName)); } return resp; } /** * List the {@link Log} objects in your project as a readable object stream. * * @method Logging#getLogsStream * @param {GetLogsRequest} [query] Query object for listing entries. * @returns {ReadableStream} A readable stream that emits {@link Log} * instances. * * @example * ``` * const {Logging} = require('@google-cloud/logging'); * const logging = new Logging(); * * logging.getLogsStream() * .on('error', console.error) * .on('data', log => { * // `log` is a Cloud Logging log object. * }) * .on('end', function() { * // All logs retrieved. * }); * * //- * // If you anticipate many results, you can end a stream early to prevent * // unnecessary processing and API requests. * //- * logging.getLogsStream() * .on('data', log => { * this.end(); * }); * ``` */ getLogsStream(options = {}) { options = options || {}; let requestStream; const userStream = streamEvents(pumpify.obj()); userStream.abort = () => { if (requestStream) { requestStream.abort(); } }; const toLogStream = new stream_1.Transform({ objectMode: true, transform: (chunk, encoding, callback) => { callback(null, this.log(chunk)); }, }); userStream.once('reading', () => { this.auth.getProjectId().then(projectId => { this.projectId = projectId; const reqOpts = extend({}, options, { parent: 'projects/' + this.projectId, }); delete reqOpts.gaxOptions; const gaxOptions = extend({ autoPaginate: options.autoPaginate, }, options.gaxOptions); let gaxStream; requestStream = streamEvents(new stream_1.PassThrough({ objectMode: true })); requestStream.abort = () => { if (gaxStream && gaxStream.cancel) { gaxStream.cancel(); } }; requestStream.once('reading', () => { try { gaxStream = this.loggingService.listLogsStream(reqOpts, gaxOptions); } catch (error) { requestStream.destroy(error); return; } gaxStream .on('error', (err) => { requestStream.destroy(err); }) .pipe(requestStream); return; }); // eslint-disable-next-line @typescript-eslint/no-explicit-any userStream.setPipeline(requestStream, toLogStream); }); }); return userStream; } async getSinks(opts) { const options = opts ? opts : {}; this.projectId = await this.auth.getProjectId(); const reqOpts = extend({}, options, { parent: 'projects/' + this.projectId, }); delete reqOpts.autoPaginate; delete reqOpts.gaxOptions; const gaxOptions = extend({ autoPaginate: options.autoPaginate, }, options.gaxOptions); const resp = await this.configService.listSinks(reqOpts, gaxOptions); const [sinks] = resp; if (sinks) { resp[0] = sinks.map((sink) => { const sinkInstance = this.sink(sink.name); sinkInstance.metadata = sink; return sinkInstance; }); } return resp; } /** * Get the {@link Sink} objects associated with this project as a * readable object stream. * * @method Logging#getSinksStream * @param {GetSinksRequest} [query] Query object for listing sinks. * @returns {ReadableStream} A readable stream that emits {@link Sink} * instances. * * @example * ``` * const {Logging} = require('@google-cloud/logging'); * const logging = new Logging(); * * logging.getSinksStream() * .on('error', console.error) * .on('data', sink => { * // `sink` is a Sink object. * }) * .on('end', function() { * // All sinks retrieved. * }); * * //- * // If you anticipate many results, you can end a stream early to prevent * // unnecessary processing and API requests. * //- * logging.getSinksStream() * .on('data', function(sink) { * this.end(); * }); * ``` */ getSinksStream(options) { // eslint-disable-next-line @typescript-eslint/no-this-alias const self = this; options = options || {}; let requestStream; const userStream = streamEvents(pumpify.obj()); userStream.abort = () => { if (requestStream) { requestStream.abort(); } }; const toSinkStream = new stream_1.Transform({ objectMode: true, transform: (chunk, encoding, callback) => { const sinkInstance = self.sink(chunk.name); sinkInstance.metadata = chunk; callback(null, sinkInstance); }, }); userStream.once('reading', () => { this.auth.getProjectId().then(projectId => { this.projectId = projectId; const reqOpts = extend({}, options, { parent: 'projects/' + self.projectId, }); delete reqOpts.gaxOptions; const gaxOptions = extend({ autoPaginate: options.autoPaginate, }, options.gaxOptions); let gaxStream; requestStream = streamEvents(new stream_1.PassThrough({ objectMode: true })); requestStream.abort = () => { if (gaxStream && gaxStream.cancel) { gaxStream.cancel(); } }; // eslint-disable-next-line @typescript-eslint/no-explicit-any if (!global.GCLOUD_SANDBOX_ENV) { requestStream.once('reading', () => { try { gaxStream = this.configService.listSinksStream(reqOpts, gaxOptions); } catch (error) { requestStream.destroy(error); return; } gaxStream .on('error', (err) => { requestStream.destroy(err); }) .pipe(requestStream); return; }); } // eslint-disable-next-line @typescript-eslint/no-explicit-any userStream.setPipeline(requestStream, toSinkStream); }); }); return userStream; } /** * Get a reference to a Cloud Logging log. * * See {@link https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.logs|Log Overview} * * @param {string} name Name of the existing log. * @param {object} [options] Configuration object. * @param {boolean} [options.removeCircular] Replace circular references in * logged objects with a string value, `[Circular]`. (Default: false) * @returns {Log} * * @example * ``` * const {Logging} = require('@google-cloud/logging'); * const logging = new Logging(); * const log = logging.log('my-log'); * ``` */ log(name, options) { return new log_1.Log(this, name, options); } /** * Get a reference to a Cloud Logging logSync. * * @param {string} name Name of the existing log. * @param {object} transport An optional write stream. * @param {LogSyncOptions} options An optional configuration object. * @returns {LogSync} * * @example * ``` * const {Logging} = require('@google-cloud/logging'); * const logging = new Logging(); * * // Optional: enrich logs with additional context * await logging.setProjectId(); * await logging.setDetectedResource(); * * // Default transport writes to process.stdout * const log = logging.logSync('my-log'); * ``` */ logSync(name, transport, options) { return new log_sync_1.LogSync(this, name, transport, options); } /** * Get a reference to a Cloud Logging sink. * * See {@link https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.sinks|Sink Overview} * * @param {string} name Name of the existing sink. * @returns {Sink} * * @example * ``` * const {Logging} = require('@google-cloud/logging'); * const logging = new Logging(); * const sink = logging.sink('my-sink'); * ``` */ sink(name) { return new sink_1.Sink(this, name); } /** * Funnel all API requests through this method, to be sure we have a project * ID. * * @param {object} config Configuration object. * @param {object} config.gaxOpts GAX options. * @param {function} config.method The gax method to call. * @param {object} config.reqOpts Request options. * @param {function} [callback] Callback function. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any request(config, callback) { // eslint-disable-next-line @typescript-eslint/no-this-alias const self = this; const isStreamMode = !callback; let gaxStream; let stream; if (isStreamMode) { stream = streamEvents(new stream_1.PassThrough({ objectMode: true })); stream.abort = () => { if (gaxStream && gaxStream.cancel) { gaxStream.cancel(); } }; stream.once('reading', makeRequestStream); } else { makeRequestCallback(); } function prepareGaxRequest(callback) { self.auth.getProjectId((err, projectId) => { if (err) { callback(err); return; } self.projectId = projectId; let gaxClient = self.api[config.client]; if (!gaxClient) { // Lazily instantiate client. gaxClient = new v2[config.client](self.options); self.api[config.client] = gaxClient; } let reqOpts = extend(true, {}, config.reqOpts); reqOpts = (0, projectify_1.replaceProjectIdToken)(reqOpts, projectId); const requestFn = gaxClient[config.method].bind(gaxClient, reqOpts, config.gaxOpts); callback(null, requestFn); }); } function makeRequestCallback() { // eslint-disable-next-line @typescript-eslint/no-explicit-any if (global.GCLOUD_SANDBOX_ENV) { return; } prepareGaxRequest((err, requestFn) => { if (err) { callback(err); return; } requestFn(callback); }); } function makeRequestStream() { // eslint-disable-next-line @typescript-eslint/no-explicit-any if (global.GCLOUD_SANDBOX_ENV) { return new stream_1.PassThrough({ objectMode: true }); } prepareGaxRequest((err, requestFn) => { if (err) { stream.destroy(err); return; } gaxStream = requestFn(); gaxStream .on('error', (err) => { stream.destroy(err); }) .pipe(stream); }); return; } return stream; } /** * This method is called when creating a sink with a Bucket destination. The * bucket must first grant proper ACL access to the Cloud Logging * account. * * The parameters are the same as what {@link Logging#createSink} accepts. * * @private */ async setAclForBucket_(config) { const bucket = config.destination; // eslint-disable-next-line @typescript-eslint/no-explicit-any await bucket.acl.owners.addGroup('cloud-logs@google.com'); config.destination = 'storage.googleapis.com/' + bucket.name; } /** * This method is called when creating a sink with a Dataset destination. The * dataset must first grant proper ACL access to the Cloud Logging * account. * * The parameters are the same as what {@link Logging#createSink} accepts. * * @private */ async setAclForDataset_(config) { const dataset = config.destination; const [metadata] = await dataset.getMetadata(); // eslint-disable-next-line @typescript-eslint/no-explicit-any const access = [].slice.call(arrify(metadata.access)); access.push({ role: 'WRITER', groupByEmail: 'cloud-logs@google.com', }); await dataset.setMetadata({ access, }); const baseUrl = 'bigquery.googleapis.com'; const pId = dataset.parent.projectId; const dId = dataset.id; config.destination = `${baseUrl}/projects/${pId}/datasets/${dId}`; } /** * This method is called when creating a sink with a Topic destination. The * topic must first grant proper ACL access to the Cloud Logging * account. * * The parameters are the same as what {@link Logging#createSink} accepts. * * @private */ async setAclForTopic_(config) { const topic = config.destination; const [policy] = await topic.iam.getPolicy(); policy.bindings = arrify(policy.bindings); policy.bindings.push({ role: 'roles/pubsub.publisher', members: ['serviceAccount:cloud-logs@system.gserviceaccount.com'], }); await topic.iam.setPolicy(policy); const baseUrl = 'pubsub.googleapis.com'; const topicName = topic.name; config.destination = `${baseUrl}/${topicName}`; } /** * setProjectId detects and sets a projectId string on the Logging instance. * It can be invoked once to ensure ensuing LogSync entries have a projectID. * @param reqOpts */ // eslint-disable-next-line @typescript-eslint/no-unused-vars async setProjectId(reqOpts) { if (this.projectId === '{{projectId}}') this.projectId = await this.auth.getProjectId(); if (reqOpts) reqOpts = (0, projectify_1.replaceProjectIdToken)(reqOpts, this.projectId); } /** * setResource detects and sets a detectedresource object on the Logging * instance. It can be invoked once to ensure ensuing LogSync entries contain * resource context. */ async setDetectedResource() { if (!this.detectedResource) { this.detectedResource = await (0, metadata_1.getDefaultResource)(this.auth); } } } exports.Logging = Logging; /*! Developer Documentation * All async methods (except for streams) will execute a callback in the event * that a callback is provided. */ (0, promisify_1.callbackifyAll)(Logging, { exclude: ['request'], }); /*! Developer Documentation * * These methods can be auto-paginated. */ paginator_1.paginator.extend(Logging, ['getEntries', 'getLogs', 'getSinks']); /** * Reference to the low-level auto-generated clients for the V2 Logging service. * * @type {object} * @property {constructor} LoggingServiceV2Client * Reference to {@link v2.LoggingServiceV2Client} * @property {constructor} ConfigServiceV2Client * Reference to {@link v2.ConfigServiceV2Client} * @property {constructor} MetricsServiceV2Client * Reference to {@link v2.MetricsServiceV2Client} */ module.exports.v2 = v2; __exportStar(require("@opentelemetry/api"), exports); //# sourceMappingURL=index.js.map