or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

auto-registration.mdbase-instrumentation.mdindex.mdmodule-definitions.mdsemconv-stability.mdutilities.md

utilities.mddocs/

0

# Utilities

1

2

Utility functions for safe execution, function wrapping detection, and error handling in instrumentation code.

3

4

## Capabilities

5

6

### Safe Execution Functions

7

8

Functions for executing code safely with error handling and recovery mechanisms.

9

10

```typescript { .api }

11

/**

12

* Execute function safely with error handling

13

* @param execute Function to execute

14

* @param onFinish Callback executed after completion (success or failure)

15

* @param preventThrowingError If true, prevents rethrowing errors

16

* @returns Result of execution

17

*/

18

function safeExecuteInTheMiddle<T>(

19

execute: () => T,

20

onFinish: (e: Error | undefined, result: T | undefined) => void,

21

preventThrowingError?: boolean

22

): T;

23

24

/**

25

* Execute async function safely with error handling

26

* @param execute Async function to execute

27

* @param onFinish Callback executed after completion (success or failure)

28

* @param preventThrowingError If true, prevents rethrowing errors

29

* @returns Promise with result of execution

30

*/

31

function safeExecuteInTheMiddleAsync<T>(

32

execute: () => T,

33

onFinish: (e: Error | undefined, result: T | undefined) => void,

34

preventThrowingError?: boolean

35

): Promise<T>;

36

```

37

38

**Usage Examples:**

39

40

```typescript

41

import { safeExecuteInTheMiddle, safeExecuteInTheMiddleAsync } from "@opentelemetry/instrumentation";

42

43

// Synchronous safe execution

44

const result = safeExecuteInTheMiddle(

45

() => {

46

// Potentially risky operation

47

return JSON.parse(someJsonString);

48

},

49

(error, result) => {

50

if (error) {

51

console.error('JSON parsing failed:', error);

52

// Log or handle error

53

} else {

54

console.log('JSON parsed successfully:', result);

55

}

56

},

57

true // Prevent throwing error, handle gracefully

58

);

59

60

// Asynchronous safe execution

61

const asyncResult = await safeExecuteInTheMiddleAsync(

62

async () => {

63

// Potentially risky async operation

64

const response = await fetch('https://api.example.com/data');

65

return response.json();

66

},

67

(error, result) => {

68

if (error) {

69

console.error('API request failed:', error);

70

// Could emit metrics or traces here

71

} else {

72

console.log('API request successful');

73

}

74

}

75

);

76

77

// Use in instrumentation context

78

class HttpInstrumentation extends InstrumentationBase {

79

private _patchRequest(original: Function) {

80

const instrumentation = this;

81

82

return function(this: any, ...args: any[]) {

83

return safeExecuteInTheMiddle(

84

() => {

85

// Create span and add instrumentation

86

const span = instrumentation.tracer.startSpan('http.request');

87

const result = original.apply(this, args);

88

span.end();

89

return result;

90

},

91

(error, result) => {

92

if (error) {

93

instrumentation._diag.error('Failed to instrument HTTP request:', error);

94

}

95

},

96

true // Don't break original functionality on instrumentation errors

97

);

98

};

99

}

100

}

101

```

102

103

### Function Wrapping Detection

104

105

Utility to check if a function has been wrapped by the shimmer library.

106

107

```typescript { .api }

108

/**

109

* Check if a function has been wrapped by shimmer

110

* @param func Function to check

111

* @returns True if function is wrapped

112

*/

113

function isWrapped(func: unknown): func is ShimWrapped;

114

115

/**

116

* Interface for wrapped functions with shimmer metadata

117

*/

118

interface ShimWrapped extends Function {

119

/** Indicates the function is wrapped */

120

__wrapped: boolean;

121

/** Unwrap function to restore original */

122

__unwrap: Function;

123

/** Reference to original function */

124

__original: Function;

125

}

126

```

127

128

**Usage Examples:**

129

130

```typescript

131

import { isWrapped } from "@opentelemetry/instrumentation";

132

import * as shimmer from "shimmer";

133

134

class InstrumentationExample extends InstrumentationBase {

135

enable() {

136

const http = require('http');

137

138

// Check if already wrapped to avoid double-wrapping

139

if (!isWrapped(http.request)) {

140

shimmer.wrap(http, 'request', this._wrapRequest.bind(this));

141

} else {

142

this._diag.debug('http.request is already wrapped');

143

}

144

}

145

146

disable() {

147

const http = require('http');

148

149

// Only unwrap if it's actually wrapped

150

if (isWrapped(http.request)) {

151

shimmer.unwrap(http, 'request');

152

}

153

}

154

155

private _inspectWrapping() {

156

const http = require('http');

157

158

if (isWrapped(http.request)) {

159

const wrapped = http.request as ShimWrapped;

160

console.log('Function is wrapped:', wrapped.__wrapped);

161

console.log('Original function available:', typeof wrapped.__original);

162

console.log('Unwrap function available:', typeof wrapped.__unwrap);

163

164

// Could access original if needed

165

const originalRequest = wrapped.__original;

166

}

167

}

168

169

private _conditionalWrap(target: any, property: string, wrapper: Function) {

170

// Defensive wrapping pattern

171

if (target && typeof target[property] === 'function') {

172

if (!isWrapped(target[property])) {

173

shimmer.wrap(target, property, wrapper);

174

this._diag.debug(`Wrapped ${property}`);

175

} else {

176

this._diag.debug(`${property} already wrapped, skipping`);

177

}

178

} else {

179

this._diag.warn(`Cannot wrap ${property}: not a function or target invalid`);

180

}

181

}

182

}

183

```

184

185

### Advanced Safe Execution Patterns

186

187

Advanced patterns for instrumentation error handling and recovery.

188

189

**Usage Examples:**

190

191

```typescript

192

import { safeExecuteInTheMiddle } from "@opentelemetry/instrumentation";

193

194

class RobustInstrumentation extends InstrumentationBase {

195

private _metrics = {

196

instrumentationErrors: this.meter.createCounter('instrumentation_errors_total'),

197

executionTime: this.meter.createHistogram('instrumentation_execution_duration')

198

};

199

200

private _safeWrap(target: any, property: string, wrapper: Function) {

201

return safeExecuteInTheMiddle(

202

() => {

203

const original = target[property];

204

if (typeof original !== 'function') {

205

throw new Error(`${property} is not a function`);

206

}

207

208

target[property] = wrapper(original);

209

return target[property];

210

},

211

(error, result) => {

212

if (error) {

213

this._metrics.instrumentationErrors.add(1, {

214

operation: 'wrap',

215

target: property,

216

error: error.message

217

});

218

this._diag.error(`Failed to wrap ${property}:`, error);

219

} else {

220

this._diag.debug(`Successfully wrapped ${property}`);

221

}

222

},

223

true // Don't throw, allow application to continue

224

);

225

}

226

227

private _createTimedWrapper(name: string, original: Function) {

228

const instrumentation = this;

229

230

return function(this: any, ...args: any[]) {

231

const startTime = Date.now();

232

233

return safeExecuteInTheMiddle(

234

() => {

235

// Execute original with instrumentation

236

const span = instrumentation.tracer.startSpan(`${name}.call`);

237

try {

238

const result = original.apply(this, args);

239

span.setStatus({ code: 1 }); // OK

240

return result;

241

} catch (error) {

242

span.recordException(error as Error);

243

span.setStatus({ code: 2, message: (error as Error).message }); // ERROR

244

throw error;

245

} finally {

246

span.end();

247

}

248

},

249

(error, result) => {

250

const duration = Date.now() - startTime;

251

instrumentation._metrics.executionTime.record(duration, {

252

operation: name,

253

success: error ? 'false' : 'true'

254

});

255

256

if (error) {

257

instrumentation._diag.error(`Error in ${name}:`, error);

258

}

259

}

260

);

261

};

262

}

263

}

264

```

265

266

### Utility Composition

267

268

Combining safe execution with wrapping detection for robust instrumentation.

269

270

**Usage Example:**

271

272

```typescript

273

import { safeExecuteInTheMiddle, isWrapped } from "@opentelemetry/instrumentation";

274

275

class CompositeInstrumentation extends InstrumentationBase {

276

enable() {

277

this._instrumentModuleSafely('http', ['request', 'get']);

278

this._instrumentModuleSafely('https', ['request', 'get']);

279

}

280

281

disable() {

282

this._uninstrumentModuleSafely('http', ['request', 'get']);

283

this._uninstrumentModuleSafely('https', ['request', 'get']);

284

}

285

286

private _instrumentModuleSafely(moduleName: string, methods: string[]) {

287

safeExecuteInTheMiddle(

288

() => {

289

const module = require(moduleName);

290

291

methods.forEach(method => {

292

if (module[method] && !isWrapped(module[method])) {

293

shimmer.wrap(module, method, this._createWrapper(method));

294

this._diag.debug(`Wrapped ${moduleName}.${method}`);

295

} else if (isWrapped(module[method])) {

296

this._diag.debug(`${moduleName}.${method} already wrapped`);

297

} else {

298

this._diag.warn(`${moduleName}.${method} not found or not a function`);

299

}

300

});

301

302

return module;

303

},

304

(error) => {

305

if (error) {

306

this._diag.error(`Failed to instrument ${moduleName}:`, error);

307

}

308

},

309

true // Don't fail application startup on instrumentation errors

310

);

311

}

312

313

private _uninstrumentModuleSafely(moduleName: string, methods: string[]) {

314

safeExecuteInTheMiddle(

315

() => {

316

const module = require(moduleName);

317

318

methods.forEach(method => {

319

if (isWrapped(module[method])) {

320

shimmer.unwrap(module, method);

321

this._diag.debug(`Unwrapped ${moduleName}.${method}`);

322

}

323

});

324

325

return module;

326

},

327

(error) => {

328

if (error) {

329

this._diag.error(`Failed to uninstrument ${moduleName}:`, error);

330

}

331

},

332

true

333

);

334

}

335

336

private _createWrapper(methodName: string) {

337

return (original: Function) => {

338

const instrumentation = this;

339

340

return function(this: any, ...args: any[]) {

341

return safeExecuteInTheMiddleAsync(

342

async () => {

343

const span = instrumentation.tracer.startSpan(`${methodName}.call`);

344

try {

345

const result = await original.apply(this, args);

346

return result;

347

} finally {

348

span.end();

349

}

350

},

351

(error) => {

352

if (error) {

353

instrumentation._diag.error(`Error in wrapped ${methodName}:`, error);

354

}

355

}

356

);

357

};

358

};

359

}

360

}