Skip to content
This repository was archived by the owner on Mar 11, 2026. It is now read-only.
This repository was archived by the owner on Mar 11, 2026. It is now read-only.

feat: Simple Synchronous Logger w/ Error Reporting Support #1407

Description

@danielbankhead

It would be cool if this library included a simple, ready-to-go synchronous logger that:

  • Offers simplicity like console.* (one function call that prepares the Entry for customers)
  • Sends Errors to Error Reporting

I often reuse a class like this between projects: https://github.com/danielbankhead/picture-playlist/blob/main/src/lib/logger.ts

/**
 * Copyright 2021 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.
 */

import {Logging, SeverityNames, Entry} from '@google-cloud/logging';

import {config} from './config.js';
import {packageJson} from './utils/package.js';

const logging = new Logging();
await logging.setProjectId();
await logging.setDetectedResource();

const log = logging.logSync(packageJson.name);

enum LoggingTypes {
  /**
   * @link https://cloud.google.com/error-reporting/docs/formatting-error-messages
   */
  ReportedErrorEvent = 'type.googleapis.com/google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent',
}

type Meta = Entry['metadata'];
type Data = Entry['data'];

type SeverityFunctions = {
  [_ in SeverityNames]: (message: unknown, data?: Data, meta?: Meta) => void;
};

class Logger implements SeverityFunctions {
  /**
   * Internal method for logging for each severity
   */
  #log(s: SeverityNames, message: unknown, data?: Data, meta?: Meta) {
    const payload: {message: unknown; data?: Data; '@type'?: string} = {
      message,
      data,
    };

    if (message instanceof Error && message.stack) {
      // Allows error to be pick up by Error Reporting
      // https://cloud.google.com/error-reporting/docs/formatting-error-messages
      payload.message = message.stack;
      payload['@type'] = LoggingTypes.ReportedErrorEvent;
    }

    const entry = log.entry(meta, payload);

    log[s](entry);
  }

  info(message: unknown, data?: Data, meta?: Meta) {
    return this.#log('info', message, data, meta);
  }

  emergency(message: unknown, data?: Data, meta?: Meta) {
    return this.#log('emergency', message, data, meta);
  }

  alert(message: unknown, data?: Data, meta?: Meta) {
    return this.#log('alert', message, data, meta);
  }

  critical(message: unknown, data?: Data, meta?: Meta) {
    return this.#log('critical', message, data, meta);
  }

  error(message: unknown, data?: Data, meta?: Meta) {
    return this.#log('error', message, data, meta);
  }

  warning(message: unknown, data?: Data, meta?: Meta) {
    return this.#log('warning', message, data, meta);
  }

  notice(message: unknown, data?: Data, meta?: Meta) {
    return this.#log('notice', message, data, meta);
  }

  debug(message: unknown, data?: Data, meta?: Meta) {
    if (config.logging.verbose) {
      this.#log('debug', message, data, meta);
    }
  }
}

export const logger = new Logger();

Let me know if you have any questions or need help integrating!

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    api: loggingIssues related to the googleapis/nodejs-logging API.priority: p3Desirable enhancement or fix. May not be included in next release.type: feature request‘Nice-to-have’ improvement, new feature or different behavior or design.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions