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

chore: more advanced plugin configuration #628

Closed
wants to merge 17 commits into from

Conversation

dyladan
Copy link
Member

@dyladan dyladan commented Dec 16, 2019

Which problem is this PR solving?

Short description of the changes

NodeTracer configs can now be configured in the following ways:

Default configuration and plugins

const tracer = new NodeTracer()

Configure a plugin with options

In this scenario, the http plugin will receive the httpPluginOption configuration.

new NodeTracer({
  plugins: {
    http: {
      enabled: true,
      path: "",
      options: {
        httpPluginOption: "value",
      }
    }
  }
});

Configure shared plugin options

In this scenario, the http plugin will receive the httpPluginOption configuration, the https plugin will receive the httpsPluginOption configuration, and both will receive the sharedPluginOption configuration.

new NodeTracer({
  plugins: {
    http: {
      enabled: true,
      path: "",
      options: {
        httpPluginOption: "value",
      }
    },
    https: {
      enabled: true,
      path: "",
      options: {
        httpsPluginOption: "value",
      }
    }
  },
  sharedPluginOptions: {
    sharedPluginOption: "value",
  }
});

Disable a plugin and leave all others enabled

new NodeTracer({
  http: { enabled: false }
});

You no longer need to explicitly give the whole configuration object

new NodeTracer({
  http: { 
    // no need for `enabled` or `path` if the defaults are used
    options: { configOption: 1 }
  },
})

@codecov-io
Copy link

codecov-io commented Dec 16, 2019

Codecov Report

Merging #628 into master will increase coverage by 1.74%.
The diff coverage is 87.43%.

@@            Coverage Diff             @@
##           master     #628      +/-   ##
==========================================
+ Coverage    89.6%   91.35%   +1.74%     
==========================================
  Files         191      215      +24     
  Lines       10034     9932     -102     
  Branches      925      913      -12     
==========================================
+ Hits         8991     9073      +82     
+ Misses       1043      859     -184
Impacted Files Coverage Δ
...telemetry-plugin-document-load/src/documentLoad.ts 97.91% <ø> (-0.03%) ⬇️
packages/opentelemetry-plugin-grpc/src/grpc.ts 96.23% <ø> (-0.03%) ⬇️
...-plugin-postgres/opentelemetry-plugin-pg/src/pg.ts 91.22% <ø> (-0.16%) ⬇️
packages/opentelemetry-base/src/version.ts 0% <ø> (ø)
...ges/opentelemetry-scope-async-hooks/src/version.ts 0% <0%> (ø)
packages/opentelemetry-plugin-https/src/version.ts 0% <0%> (ø)
packages/opentelemetry-plugin-dns/src/version.ts 0% <0%> (ø)
...kages/opentelemetry-exporter-jaeger/src/version.ts 0% <0%> (ø)
...s/opentelemetry-plugin-mongodb-core/src/version.ts 0% <0%> (ø)
packages/opentelemetry-plugin-http/src/version.ts 0% <0%> (ø)
... and 93 more

@mayurkale22
Copy link
Member

This is a great start. What are the valid use-cases of sharedPluginOptions? Currrently, looks like enhancedDatabaseReporting (database specific) and ignoreUrls (http/https specific) options are part of sharedPluginOptions.

@dyladan
Copy link
Member Author

dyladan commented Dec 17, 2019

This is a great start. What are the valid use-cases of sharedPluginOptions? Currrently, looks like enhancedDatabaseReporting (database specific) and ignoreUrls (http/https specific) options are part of sharedPluginOptions.

Right now the plugin options are the same regardless of if they're shared or if they're set on a single plugin, and only a couple exist. I was going to go through all plugins today and look at which configurations they use and create a set of options interfaces in types that generalizes them like DatabasePluginOptions which would have things like enhanced db reporting and RPCPluginOptions which would have things like ignore urls. This prevents the types interfaces from relying on plugins and instead plugins would just use the configuration interfaces exported from types.

@dyladan
Copy link
Member Author

dyladan commented Dec 17, 2019

@mayurkale22 one use case of shared configurations might be to set enhanced db reporting true for all db modules (mysql, pg, pg-pool, redis).

new NodeTracer({
  sharedPluginOptions: {
    enhancedDatabaseReporting: true,
  }
});

You may also want to set it true in general, but then disable for a single module which is also possible.

new NodeTracer({
  plugins: {
    redis: {
      options: {
        enhancedDatabaseReporting: false,
      },
    },
  },
  sharedPluginOptions: {
    enhancedDatabaseReporting: true,
  },
});

@mayurkale22
Copy link
Member

I see, let's discuss this in tomorrow's SIG meeting.

@obecny
Copy link
Member

obecny commented Dec 18, 2019

should we have some rules about naming params to avoid some problems with namespacing later? For example
enhancedDatabaseReporting maybe it should be db.enhancedReporting etc.
'ignoreUrls->http.ignoreUrls`

or maybe if param can be shared among all plugins it should start always with some prefix for example sharedEnhancedDatabaseReporting or shared.EnhancedDatabaseReporting.
Basically we will have more and more plugins and in theory it may happen that the same param can means different thing for different plugins. To avoid such situation I would strongly encourage to add something to the name so we can safely indicate that param can be shared.

Another thing is that the shared params should be immutable so the plugins won't be able to overwrite it (Object.freeze)

@dyladan
Copy link
Member Author

dyladan commented Dec 18, 2019

@obecny good point. maybe we're overcomplicating it. instead maybe we should just have a single configuration object shared to all plugins?

new NodeTracer({
  options: {
    http: {
      ignoreUrls: ["localhost"],
    },
    db: {
      enhancedDatabaseReporting: true,
    }
  },
});

Then the whole options object is frozen with Object.freeze and sent to all plugins. So the dns plugin can look into the http options and see which urls are ignored. All db related plugins like mysql and pg can look into the db options object and so on.

@obecny
Copy link
Member

obecny commented Dec 18, 2019

@obecny good point. maybe we're overcomplicating it. instead maybe we should just have a single configuration object shared to all plugins?

new NodeTracer({
  options: {
    http: {
      ignoreUrls: ["localhost"],
    },
    db: {
      enhancedDatabaseReporting: true,
    }
  },
});

Then the whole options object is frozen with Object.freeze and sent to all plugins. So the dns plugin can look into the http options and see which urls are ignored. All db related plugins like mysql and pg can look into the db options object and so on.

This looks cleaner for me and I think you won't be able to pollute the the config with param that can break some other plugins.

@OlivierAlbertini
Copy link
Member

OlivierAlbertini commented Dec 19, 2019

So the dns plugin can look into the http options and see which urls are ignored. All db related plugins like mysql and pg can look into the db options object and so on.

This looks cleaner for me and I think you won't be able to pollute the the config with param that can break some other plugins.

Unfortunately, ignoring some urls doesn't mean you want to ignore dns lookup as well...
Besides, dns would require to access to the exporter config not http plugin config. As discussed in the SIG, developer will make manual configuration.

This looks cleaner for me too and passing the whole config can have some benefits (http/https/http2).

@dyladan
Copy link
Member Author

dyladan commented Dec 19, 2019

This looks cleaner for me too and passing the whole config can have some benefits (http/https/http2).

Fully agree. It simplifies the implementation too. I'll update the PR today.

@dyladan
Copy link
Member Author

dyladan commented Dec 30, 2019

@obecny @OlivierAlbertini take a look. It is drastically simpler now. The shared options object and the plugin-specific options are the same "shape" now. They have a few "sections" like dns and http which can be used by whatever plugins deem appropriate.

new NodeTracer({
  options: {
    http: {
      ignoreIncomingPaths: ["/healthcheck"],
    },
    database: {
      enhancedDatabaseReporting: true,
    },
    dns: {
      ignoreHostnames: ["localhost"]
    }
  },
});

Copy link
Member

@obecny obecny left a comment

Choose a reason for hiding this comment

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

I have left few comments, my biggest concern is mixing the configs between web and node which I think is bad idea and we should have clear separation for that, we can discuss this on sig meeting

packages/opentelemetry-core/src/utils/url.ts Outdated Show resolved Hide resolved
packages/opentelemetry-core/src/utils/url.ts Outdated Show resolved Hide resolved
packages/opentelemetry-core/src/utils/url.ts Show resolved Hide resolved
packages/opentelemetry-core/src/utils/url.ts Outdated Show resolved Hide resolved
packages/opentelemetry-core/src/utils/url.ts Outdated Show resolved Hide resolved

// how long to wait for observer to collect information about resources
// this is needed as event "load" is called before observer
// hard to say how long it should really wait, seems like 300ms is
// safe enough
const OBSERVER_WAIT_TIME_MS = 300;

/**
Copy link
Member

Choose a reason for hiding this comment

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

why did you remove that ?

Copy link
Member Author

Choose a reason for hiding this comment

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

All plugin configurations are being centralized. That is the point of this PR


/**
Copy link
Member

Choose a reason for hiding this comment

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

I think mixing plugin options between web and node is very bad idea. Things like database, dns etc will never be shared on web, and xhr will never be shared on node.
I think that such changes w discuss could discuss on sig meeting and how we want to handle that. I would rather have web and node separation like this is done for example in core/platform.

Copy link
Member Author

Choose a reason for hiding this comment

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

We can talk about it in SIG but I thought this was already pretty much agreed. We've had a couple discussions about it already.

packages/opentelemetry-core/test/utils/url.test.ts Outdated Show resolved Hide resolved
*
* @param options config objects to merge
*/
export function mergeOptions(
Copy link
Member

Choose a reason for hiding this comment

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

Missing unit tests.
This function doesn't guarantee the "frozen state" when option is array or object.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll take another pass at this

packages/opentelemetry-core/src/utils/url.ts Outdated Show resolved Hide resolved
Copy link
Member

@OlivierAlbertini OlivierAlbertini left a comment

Choose a reason for hiding this comment

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

Perhaps instead of checking each time if this._options.http exists (and for other plugin)

this._options.http &&

We could ensure that it is not null/undefined when we pass the options during the call at the enable method ? WDYT ?

@@ -31,7 +31,10 @@ const tracer = new NodeTracer({
// You may use a package name or absolute path to the file.
path: '@opentelemetry/plugin-http',
// http plugin options
options: {}
Copy link
Member

Choose a reason for hiding this comment

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

if I understand correctly your comment #628 (comment),

This change should be updated, right ?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, they just match now and are merged together. You can still configure one plugin to have different ignoreUrls for example than the rest of the plugins.

if (this._config.applyCustomAttributesOnSpan) {
if (
this._options.http &&
this._options.http.applyCustomAttributesOnSpan
Copy link
Member

Choose a reason for hiding this comment

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

this._options.http?.applyCustomAttributesOnSpan

Copy link
Member Author

Choose a reason for hiding this comment

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

was having issues getting the compile to work with the new ts features for some reason. didn't feel like spending a lot of time to figure out what was wrong.

dns?: DNSPluginOptions;
http?: HttpPluginOptions;
xhr?: XMLHttpRequestPluginOptions;
custom?: CustomPluginOptions;
Copy link
Member

Choose a reason for hiding this comment

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

what about:
[custom: string]: any;
People would be able to add their own plugin like this:

const options: PluginOptions = {
  http: {
    serverName: 'hello',
  },
  amqp: {
    something: 'else'
  }
}

I don't have a strong opinion on this, I'm just curious.

Copy link
Member Author

Choose a reason for hiding this comment

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

There is a whole section named custom which allows you to put custom config options there.

@dyladan
Copy link
Member Author

dyladan commented Jan 3, 2020

We could ensure that it is not null/undefined when we pass the options during the call at the enable method ? WDYT ?

good idea

@dyladan dyladan closed this Feb 5, 2020
@Flarna Flarna deleted the config branch August 12, 2020 23:10
pichlermarc pushed a commit to dynatrace-oss-contrib/opentelemetry-js that referenced this pull request Dec 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
document Documentation-related
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants