Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(amqplib): stop importing from amqplib directly in compiled types #1394

Merged
merged 2 commits into from
Feb 14, 2023
Merged

fix(amqplib): stop importing from amqplib directly in compiled types #1394

merged 2 commits into from
Feb 14, 2023

Conversation

dotboris
Copy link
Contributor

@dotboris dotboris commented Feb 13, 2023

Which problem is this PR solving?

I started getting type checking errors when using node auto instrumentation:

$ tsc --skipLibCheck false --incremental false
node_modules/@opentelemetry/instrumentation-amqplib/build/src/utils.d.ts:3:28 - error TS2307: Cannot find module 'amqplib' or its corresponding type declarations.

3 import type * as amqp from 'amqplib';
                             ~~~~~~~~~


Found 1 error in node_modules/@opentelemetry/instrumentation-amqplib/build/src/utils.d.ts:3

Turns out that the compiled utils.d.ts imports amqplib directly which breaks. This worked fine before #1320 which moved @types/amqplib as a dev dependency. The PR adjusted most places where amqplib was imported but it missed one.

Short description of the changes

  • Make getConsumePatch, getConfirmedPublishPatch and getPublishPatch in AmqplibInstrumentation private. They used to be protected.
  • Reduce the number of vendor'd types in types.ts

The generate amqplib.d.ts now looks like this: (no longer imports ./utils which imports amqplib)

import { InstrumentationBase, InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation';
import { AmqplibInstrumentationConfig } from './types';
export declare class AmqplibInstrumentation extends InstrumentationBase {
    protected _config: AmqplibInstrumentationConfig;
    constructor(config?: AmqplibInstrumentationConfig);
    setConfig(config?: AmqplibInstrumentationConfig): void;
    protected init(): InstrumentationNodeModuleDefinition<unknown>;
    private patchConnect;
    private unpatchConnect;
    private patchChannelModel;
    private unpatchChannelModel;
    private getConnectPatch;
    private getChannelEmitPatch;
    private getAckAllPatch;
    private getAckPatch;
    private getConsumePatch;
    private getConfirmedPublishPatch;
    private getPublishPatch;
    private createPublishSpan;
    private endConsumerSpan;
    private endAllSpansOnChannel;
    private callConsumeEndHook;
    private checkConsumeTimeoutOnChannel;
}
//# sourceMappingURL=amqplib.d.ts.map

@dotboris dotboris marked this pull request as ready for review February 13, 2023 16:34
@dotboris dotboris requested a review from a team February 13, 2023 16:34
@github-actions github-actions bot requested a review from blumamir February 13, 2023 16:35
@codecov
Copy link

codecov bot commented Feb 13, 2023

Codecov Report

Merging #1394 (7682ad0) into main (00cc8d6) will not change coverage.
The diff coverage is n/a.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1394   +/-   ##
=======================================
  Coverage   96.10%   96.10%           
=======================================
  Files          14       14           
  Lines         898      898           
  Branches      192      192           
=======================================
  Hits          863      863           
  Misses         35       35           

@Flarna
Copy link
Member

Flarna commented Feb 13, 2023

Failed test is unrelated => lerna/lerna#3536

@blumamir
Copy link
Member

blumamir commented Feb 14, 2023

Thanks for reporting this.
The fix LGTM, but I think the real issue is that utils.d.ts is exported in the public interface where it shouldn't

amqplib.d.ts:

import { InstrumentationBase, InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation';
import { AmqplibInstrumentationConfig, ConsumeMessage, Options, Replies } from './types';
import { InstrumentationConsumeChannel, InstrumentationPublishChannel } from './utils';
export declare class AmqplibInstrumentation extends InstrumentationBase {
    protected _config: AmqplibInstrumentationConfig;
    constructor(config?: AmqplibInstrumentationConfig);
    setConfig(config?: AmqplibInstrumentationConfig): void;
    protected init(): InstrumentationNodeModuleDefinition<unknown>;
    private patchConnect;
    private unpatchConnect;
    private patchChannelModel;
    private unpatchChannelModel;
    private getConnectPatch;
    private getChannelEmitPatch;
    private getAckAllPatch;
    private getAckPatch;
    protected getConsumePatch(moduleVersion: string | undefined, original: Function): (this: InstrumentationConsumeChannel, queue: string, onMessage: (msg: ConsumeMessage | null) => void, options?: Options.Consume | undefined) => Promise<Replies.Consume>;
    protected getConfirmedPublishPatch(moduleVersion: string | undefined, original: Function): (this: InstrumentationConsumeChannel, exchange: string, routingKey: string, content: Buffer, options?: Options.Publish | undefined, callback?: ((err: any, ok: Replies.Empty) => void) | undefined) => boolean;
    protected getPublishPatch(moduleVersion: string | undefined, original: Function): (this: InstrumentationPublishChannel, exchange: string, routingKey: string, content: Buffer, options?: Options.Publish | undefined) => boolean;
    private createPublishSpan;
    private endConsumerSpan;
    private endAllSpansOnChannel;
    private callConsumeEndHook;
    private checkConsumeTimeoutOnChannel;
}
//# sourceMappingURL=amqplib.d.ts.map

I think a possible alternative fix will be to make the getConsumePatch, getConfirmedPublishPatch and getPublishPatch functions private (I don't see a good reason for them to be protected anyway). That would remove them from the public API which will also remove the import { InstrumentationConsumeChannel, InstrumentationPublishChannel } from './utils'; part

This will reduce the number of types we need to copy into the instrumentation code, which hopefully can make it a bit simpler to maintain. WDYT? @dotboris @Flarna

@Flarna
Copy link
Member

Flarna commented Feb 14, 2023

moving more APIs to private sounds good. can be also done as followup depending on @dotboris motivation to rework this PR.

@blumamir
Copy link
Member

can be also done as followup depending on @dotboris motivation to rework this PR.

If I got it right, that would mean we don't need to vendor any new amqplib type in types.ts in this PR (export interface Channel extends EventEmitter { etc).

@dotboris
Copy link
Contributor Author

I'll give making the methods private a shot to see how it goes.

Previously the `amqplib.d.ts` file would import `./utils` (resolved as
`utils.d.ts`) which imports `amqplib` directly. This can cause
typechecking issues for users who don't use `amqplib` but still import
the `amqplib` instrumentation through the node autoinstrumentation.

The `./utils` import was generated by typescript because some of the
protected methods have their argument and return types defined in
`utils.ts`. Now that these methods are private, typescript no longer
needs to generate the type information for those methods and omits the
`./utils` import.

Signed-off-by: Boris Bera <bbera@coveo.com>
Signed-off-by: Boris Bera <bbera@coveo.com>
@blumamir
Copy link
Member

I'll give making the methods private a shot to see how it goes.

Thanks for updating the PR. Do we still need the changes in types.ts? (all the new vendored types)

@dotboris
Copy link
Contributor Author

dotboris commented Feb 14, 2023

Thanks for updating the PR. Do we still need the changes in types.ts? (all the new vendored types)

I have reverted the additional types that I previously vendored. I've also removed a bunch of types that did not need to be there anymore. The rest of the vendored types are required because they're used as part of the instrumentation config.

To answer your question more directly: yes we still need them.

Copy link
Member

@blumamir blumamir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for the fix 🙏

@blumamir blumamir merged commit 9d0198c into open-telemetry:main Feb 14, 2023
@dotboris dotboris deleted the fix-amqplib-type-import branch February 14, 2023 13:53
@dyladan dyladan mentioned this pull request Feb 14, 2023
Abinet18 pushed a commit to Abinet18/opentelemetry-js-contrib that referenced this pull request Feb 25, 2023
open-telemetry#1394)

* fix(amqplib): make all instrumentation methods private

Previously the `amqplib.d.ts` file would import `./utils` (resolved as
`utils.d.ts`) which imports `amqplib` directly. This can cause
typechecking issues for users who don't use `amqplib` but still import
the `amqplib` instrumentation through the node autoinstrumentation.

The `./utils` import was generated by typescript because some of the
protected methods have their argument and return types defined in
`utils.ts`. Now that these methods are private, typescript no longer
needs to generate the type information for those methods and omits the
`./utils` import.

Signed-off-by: Boris Bera <bbera@coveo.com>

* fix(amqplib): reduce the number of vendored types

Signed-off-by: Boris Bera <bbera@coveo.com>

---------

Signed-off-by: Boris Bera <bbera@coveo.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants