googleapis / googleapis/google-cloud-node
Feature Proposal: Formal way to disable automatic diagnostic/instrumentation log entries
- Dominant language
- TypeScript
- Stars
- 3.2k
- Forks
- 712
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 99
Description
The library currently automatically injects an "instrumentation" log entry (containing version and runtime info) upon the first log write in a process. While the library attempts to ensure this happens only once per process lifecycle, this behavior is problematic in several modern use cases:
1. **Ephemeral Environments:** In Serverless functions (FaaS), CLI tools, or rapid `child_process` executions, the "once per lifecycle" rationale breaks down, resulting in a significant percentage of "noise" logs that the developer did not request and cannot easily suppress.
2. **Log Volume/Cost:** For users with high-frequency, short-lived processes, these mandatory entries contribute to unnecessary ingestion costs and log clutter.
3. **Library Isolation:** Modern library design favors deterministic behavior without side-effects. Emitting log entries implicitly at the transport layer makes the library harder to embed safely in other tools.
4. **Limited User Benefit:** These entries consume user log quota and clutter streams while providing limited or no actionable value to application developers, who already know their runtime and library versions.
5. **Element of surprise:** A logging client emitting entries the user did not explicitly request violates the principle of least surprise.
## Current Workaround
Users can currently suppress this by setting:
```javascript
global.shouldSkipInstrumentationCheck = true
```
before the first log write, but this is undocumented and relies on internal implementation details.
## Technical Concerns in current implementation (`src/utils/instrumentation.ts`)
Beyond the lack of an opt-out, the current implementation has several architectural issues:
1. **In-place Data Mutation:** In `populateInstrumentationInfo`, the library mutates the user's `entryItem.data` object in-place (Lines [74-75](https://github.com/googleapis/nodejs-logging/blob/9cfdde70b9d79d9b76d5bc97d34a6ca10fbf07da/src/utils/instrumentation.ts#L74-L75)). This can lead to unexpected side-effects if the caller re-uses data objects.
2. **Global State Pollution:** The use of `global.instrumentationAdded` and `global.shouldSkipInstrumentationCheck` may conflict with other libraries and user code.
3. **Performance Overhead:** On the first write, the library performs an O(N) scan of all entries in a batch to look for existing instrumentation metadata, even if the user has no intention of providing it.
4. **Library Misidentification:** If a third-party library uses this package, its name is forcibly overwritten to "nodejs" unless it follows a specific prefixing convention (Lines [108-110](https://github.com/googleapis/nodejs-logging/blob/9cfdde70b9d79d9b76d5bc97d34a6ca10fbf07da/src/utils/instrumentation.ts#L108-L110)).
5. **Runtime Identification:** In environments like Bun, Deno or edge runtimes, reporting as "nodejs" without reporting the actual runtime is misleading.
## Proposed Solution
1. Add `disableInstrumentationLogging` to the `LoggingOptions` interface to allow the callers to skip instrumentation logging.
2. Instead of generic `shouldSkipInstrumentationCheck` and `instrumentationAdded` in the global object, use a singleton class addressed via `global[Symbol.for('google-cloud-logging-instrumentation')]` exposing getters/setters for the internal state.
3. Maintain backward compatibility by typeguarding `typeof global.shouldSkipInstrumentationCheck === 'boolean'` and `typeof global.instrumentationAdded === 'boolean'` during singleton initialization.
4. Avoid scanning or mutating user log entries. Instrumentation should be logged deterministically (once per process) - consistent with the [Go client implementation](https://github.com/googleapis/google-cloud-go/tree/main/logging), only when `loggingOptions.disableInstrumentationLogging` is not `true`.
5. Document the default instrumentation behavior and the opt-out mechanism in the README.
Contributor guide
Assessment
This issue has not been assessed yet.