Skip to content

Commit c193502

Browse files
authored
fix(instrumentation): remove dependency on the shimmer module (#5652)
1 parent 4919fd1 commit c193502

File tree

10 files changed

+982
-22
lines changed

10 files changed

+982
-22
lines changed

doc/contributing/dependencies.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ An exception is granted for dependencies on `@opentelemetry/api`, which, if used
2323

2424
## Third-Party Library Dependencies
2525

26-
Packages categorized as third-party and listed under the `"dependencies"` section (e.g., @grpc/grpc-js, @grpc/proto-loader, shimmer, etc.) should remain unpinned and utilize the caret (`^`) symbol. This approach offers several advantages:
26+
Packages categorized as third-party and listed under the `"dependencies"` section (e.g., @grpc/grpc-js, @grpc/proto-loader, etc.) should remain unpinned and utilize the caret (`^`) symbol. This approach offers several advantages:
2727

2828
- Our users could get bug fixes of those 3rd-party packages easily, without waiting for us to update our library.
2929
- In cases where multiple packages have dependencies on different versions of the same package, npm will opt for the most recent version, saving space and preventing potential disruptions.

experimental/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2
1414

1515
### :bug: Bug Fixes
1616

17+
* fix(instrumentation): remove dependency on the shimmer module [#5652](https://github.com/open-telemetry/opentelemetry-js/pull/5652) @cjihrig
18+
1719
### :books: Documentation
1820

1921
### :house: Internal
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
BSD 2-Clause License
2+
3+
Copyright (c) 2013-2019, Forrest L Norvell
4+
All rights reserved.
5+
6+
Redistribution and use in source and binary forms, with or without
7+
modification, are permitted provided that the following conditions are met:
8+
9+
* Redistributions of source code must retain the above copyright notice, this
10+
list of conditions and the following disclaimer.
11+
12+
* Redistributions in binary form must reproduce the above copyright notice,
13+
this list of conditions and the following disclaimer in the documentation
14+
and/or other materials provided with the distribution.
15+
16+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

experimental/packages/opentelemetry-instrumentation/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ Instrumentations for external modules (e.g. express, mongodb,...) hooks the `req
245245

246246
Apache 2.0 - See [LICENSE][license-url] for more information.
247247

248+
Third-party licenses and copyright notices can be found in the [LICENSES directory](./LICENSES).
249+
248250
## Useful links
249251

250252
- For more information on OpenTelemetry, visit: <https://opentelemetry.io/>

experimental/packages/opentelemetry-instrumentation/package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"hook.mjs",
3636
"doc",
3737
"LICENSE",
38+
"LICENSES/**/*",
3839
"README.md"
3940
],
4041
"scripts": {
@@ -71,10 +72,8 @@
7172
},
7273
"dependencies": {
7374
"@opentelemetry/api-logs": "0.201.1",
74-
"@types/shimmer": "^1.2.0",
7575
"import-in-the-middle": "^1.8.1",
76-
"require-in-the-middle": "^7.1.1",
77-
"shimmer": "^1.2.1"
76+
"require-in-the-middle": "^7.1.1"
7877
},
7978
"peerDependencies": {
8079
"@opentelemetry/api": "^1.3.0"

experimental/packages/opentelemetry-instrumentation/src/instrumentation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
Span,
2727
} from '@opentelemetry/api';
2828
import { Logger, LoggerProvider, logs } from '@opentelemetry/api-logs';
29-
import * as shimmer from 'shimmer';
29+
import * as shimmer from './shimmer';
3030
import {
3131
InstrumentationModuleDefinition,
3232
Instrumentation,

experimental/packages/opentelemetry-instrumentation/src/platform/node/instrumentation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import * as types from '../../types';
1818
import * as path from 'path';
1919
import { types as utilTypes } from 'util';
2020
import { satisfies } from '../../semver';
21-
import { wrap, unwrap, massWrap, massUnwrap } from 'shimmer';
21+
import { wrap, unwrap, massWrap, massUnwrap } from '../../shimmer';
2222
import { InstrumentationAbstract } from '../../instrumentation';
2323
import {
2424
RequireInTheMiddleSingleton,
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/*
18+
* BSD 2-Clause License
19+
*
20+
* Copyright (c) 2013-2019, Forrest L Norvell
21+
* All rights reserved.
22+
*
23+
* Redistribution and use in source and binary forms, with or without
24+
* modification, are permitted provided that the following conditions are met:
25+
*
26+
* * Redistributions of source code must retain the above copyright notice, this
27+
* list of conditions and the following disclaimer.
28+
*
29+
* * Redistributions in binary form must reproduce the above copyright notice,
30+
* this list of conditions and the following disclaimer in the documentation
31+
* and/or other materials provided with the distribution.
32+
*
33+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
34+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
37+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
40+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
41+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
42+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43+
*/
44+
45+
/* Modified by OpenTelemetry Authors
46+
* - converted to TypeScript
47+
* - aligned with style-guide
48+
*/
49+
50+
import { ShimWrapped } from './types';
51+
52+
// Default to complaining loudly when things don't go according to plan.
53+
// eslint-disable-next-line no-console
54+
let logger: typeof console.error = console.error.bind(console);
55+
56+
// Sets a property on an object, preserving its enumerability.
57+
// This function assumes that the property is already writable.
58+
function defineProperty(obj: object, name: PropertyKey, value: unknown): void {
59+
const enumerable =
60+
!!obj[name as keyof typeof obj] &&
61+
Object.prototype.propertyIsEnumerable.call(obj, name);
62+
63+
Object.defineProperty(obj, name, {
64+
configurable: true,
65+
enumerable,
66+
writable: true,
67+
value,
68+
});
69+
}
70+
71+
export const wrap = <Nodule extends object, FieldName extends keyof Nodule>(
72+
nodule: Nodule,
73+
name: FieldName,
74+
wrapper: (original: Nodule[FieldName], name: FieldName) => Nodule[FieldName]
75+
): ShimWrapped | undefined => {
76+
if (!nodule || !nodule[name]) {
77+
logger('no original function ' + String(name) + ' to wrap');
78+
return;
79+
}
80+
81+
if (!wrapper) {
82+
logger('no wrapper function');
83+
logger(new Error().stack);
84+
return;
85+
}
86+
87+
const original = nodule[name];
88+
89+
if (typeof original !== 'function' || typeof wrapper !== 'function') {
90+
logger('original object and wrapper must be functions');
91+
return;
92+
}
93+
94+
const wrapped = wrapper(original, name) as object;
95+
96+
defineProperty(wrapped, '__original', original);
97+
defineProperty(wrapped, '__unwrap', () => {
98+
if (nodule[name] === wrapped) {
99+
defineProperty(nodule, name, original);
100+
}
101+
});
102+
defineProperty(wrapped, '__wrapped', true);
103+
defineProperty(nodule, name, wrapped);
104+
return wrapped as ShimWrapped;
105+
};
106+
107+
export const massWrap = <Nodule extends object, FieldName extends keyof Nodule>(
108+
nodules: Nodule[],
109+
names: FieldName[],
110+
wrapper: (original: Nodule[FieldName]) => Nodule[FieldName]
111+
): void => {
112+
if (!nodules) {
113+
logger('must provide one or more modules to patch');
114+
logger(new Error().stack);
115+
return;
116+
} else if (!Array.isArray(nodules)) {
117+
nodules = [nodules];
118+
}
119+
120+
if (!(names && Array.isArray(names))) {
121+
logger('must provide one or more functions to wrap on modules');
122+
return;
123+
}
124+
125+
nodules.forEach(nodule => {
126+
names.forEach(name => {
127+
wrap(nodule, name, wrapper);
128+
});
129+
});
130+
};
131+
132+
export const unwrap = <Nodule extends object>(
133+
nodule: Nodule,
134+
name: keyof Nodule
135+
): void => {
136+
if (!nodule || !nodule[name]) {
137+
logger('no function to unwrap.');
138+
logger(new Error().stack);
139+
return;
140+
}
141+
142+
const wrapped = nodule[name] as unknown as ShimWrapped;
143+
144+
if (!wrapped.__unwrap) {
145+
logger(
146+
'no original to unwrap to -- has ' +
147+
String(name) +
148+
' already been unwrapped?'
149+
);
150+
} else {
151+
wrapped.__unwrap();
152+
return;
153+
}
154+
};
155+
156+
export const massUnwrap = <Nodule extends object>(
157+
nodules: Nodule[],
158+
names: Array<keyof Nodule>
159+
): void => {
160+
if (!nodules) {
161+
logger('must provide one or more modules to patch');
162+
logger(new Error().stack);
163+
return;
164+
} else if (!Array.isArray(nodules)) {
165+
nodules = [nodules];
166+
}
167+
168+
if (!(names && Array.isArray(names))) {
169+
logger('must provide one or more functions to unwrap on modules');
170+
return;
171+
}
172+
173+
nodules.forEach(nodule => {
174+
names.forEach(name => {
175+
unwrap(nodule, name);
176+
});
177+
});
178+
};
179+
180+
export interface ShimmerOptions {
181+
logger?: typeof console.error;
182+
}
183+
184+
export default function shimmer(options: ShimmerOptions): void {
185+
if (options && options.logger) {
186+
if (typeof options.logger !== 'function') {
187+
logger("new logger isn't a function, not replacing");
188+
} else {
189+
logger = options.logger;
190+
}
191+
}
192+
}
193+
194+
shimmer.wrap = wrap;
195+
shimmer.massWrap = massWrap;
196+
shimmer.unwrap = unwrap;
197+
shimmer.massUnwrap = massUnwrap;

0 commit comments

Comments
 (0)