Skip to content

Latest commit

 

History

History
94 lines (71 loc) · 5.56 KB

conventions.md

File metadata and controls

94 lines (71 loc) · 5.56 KB

Instrumentation Libraries Conventions

This document is an extension to the open telemetry Trace Semantic Conventions document. It records additional conventions which we found useful for the instrumentations in this repo.

Instrumentation Configuration

moduleVersionAttributeName

Type: string
Required in each plugin: true
Default: undefined

Instrumentation SHOULD support automatic collection of instrumented library version into a span attribute. The span attribute name is the value of the moduleVersionAttributeName option, and the span attribute value is the version of the instrumented library.

If instrumentation library is patching multiple npm packages, each with a different version, then the library should pick the version of the most suited package and attach it to this attribute.

suppressInternalInstrumentation

Type: boolean
Required in each plugin: false
Default: false

Some instrumented libraries are using internally other packages which are instrumented as well. For example:

  • aws-sdk is using http for the internal RPC requests to various services.
  • elasticsearch client is communicating with the db via http.
  • mongoose (and other ORMs), are using database drivers to access the database.

For some users, viewing the internal details of clients underlying protocol is important. Others only takes interest in the client instrumentation, and instrumenting the communication protocol just creates extra visual and performance load.

If this attribute is set to true, then the instrumentation library should suppress the internal spans which are generated by calls to library functions.

This is an optional config option, which should be used only in libraries which use an instrumented underlying protocol. Notice that suppressInstrumentation is not recommended when context needs to be propagated. So if propagation of context is used in some use case (supported by the receiving side), then this option should not be used.

ignoreOrphanedSpans

Type: boolean
Required in each plugin: false
Default: false

The ignoreOrphanedSpans is not well standardized across the opentelemetry js ecosystem. It is sometimes called by the names requireParent and requireParentSpan in contrib and core repo.

In general, we can categorized traces into two categories:

  1. Traces that starts due to some external input to the application, usually a user-triggered event (incoming http request, message received on queue, etc).
  2. Traces that are triggered by some internal behavior:
  • Timers
  • Initialization code
  • Operation that have a trace context, but it was lost while running the code. This can happen when using thenables, event emitters, and other cases which break context management.

Some users want to see all the operations in the application, not hiding anything. Those users will set ignoreOrphanedSpans to false (or leave it with the default value which is false).

Other users may want to see only "external-triggered" traces, and reduce the noisy and performance impact by not instrumenting the internal operations. Those users will want to set the ignoreOrphanedSpans option to true.

Ignoring spans can be done in many flavors, and the relevant considerations should be taken into account for each case, and documented for each library.

  • skip instrumentation - just call the original function and don't executed any instrumentation related code.
  • suppressInstrumentation - this method will also ignore downstream spans, which might not be desired.
  • NoRecordingSpan - create no recording span instead of a regular recording span. This method can influence downstream spans which are using parent based sampling. Unless there is a good reason not to, instrumentation libraries should ignore orphaned spans by skipping instrumentation (calling original.apply(this, arguments)).

Hooks

Type: function
Required in each plugin: true
Default: undefined

Each instrumentation library should expose hooks which can be configured to add custom logic and attributes to span on various lifecycle events. This will usually be requestHook and responseHook, but can be anything depending on the specific case.

Each hook is a function that receives relevant parameters. Some common parameters are:

  • The current span which is relevant to the hook
  • Original call parameters
  • Response that will be returned to user
  • Version of the instrumented library.

The hooks can be used for any purpose, but some common use cases are:

  • Capturing additional operation data into custom span attributes (http headers, payloads, etc).
  • Registering to event emitters or patching objects for custom instrumentation extensions.
  • Setting global attributes for the component which are not part of the semantic conventions.

Exceptions should not be thrown from hook functions, but instrumentation should protect itself for this case by catching hooks exceptions and write to diag logger.

Logging

Instrumentations should write diagnostic logs to diag api in @opentelemetry/api. Events that should be written are:

  • (info) Patching and unpatching of library functions
  • (error) Exception thrown from custom hook

The log message should have the prefix ${component} instrumentation: ${message}, for example: mongoose instrumentation: patching mongoose Aggregate exec prototype.

Instrumentation Class

All the private functions in instrumentation class should have camelCase, with no leading underscore: (private patchConnect(...)).