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

Implement Python API for setting check metadata #4686

Merged
merged 2 commits into from
Oct 8, 2019
Merged

Implement Python API for setting check metadata #4686

merged 2 commits into from
Oct 8, 2019

Conversation

ofek
Copy link
Contributor

@ofek ofek commented Oct 5, 2019

What does this PR do?

API

This adds a method set_metadata to the AgentCheck base class that updates cached metadata values, which are then sent by the Agent at regular intervals.

It requires 2 arguments:

  1. name - the name of the metadata
  2. value - the value for the metadata. if name has no transformer defined then the raw value will be submitted and therefore it must be a str

The method also accepts arbitrary keyword arguments that are forwarded to any defined transformers.

Transformers

Transformers are defined via a class level attribute METADATA_TRANSFORMERS.

This is a mapping of metadata names to functions. When you call self.set_metadata(name, value, **options), if name is in this mapping then the corresponding function will be called with the value, and the return value(s) will be sent instead.

Transformer functions must satisfy the following signature:

def transform_<NAME>(value: Any, options: dict) -> Union[str, Dict[str, str]]:

If the return type is a string, then it will be sent as the value for name. If the return type is a mapping type, then each key will be considered a name and will be sent with its (str) value.

Initially, there are 2 default transformers: version and config

version

This transforms a version like 1.2.3-rc.4+5 to its constituent parts. In all cases, the metadata names version.raw and version.scheme will be sent.

If a scheme is defined then it will be looked up from our known schemes. If no scheme is defined then it will default to semver.

The scheme may be set to regex in which case a pattern must also be defined. Any matching named subgroups will then be sent as version.<GROUP_NAME>. In this case, the check name will be used as the value of version.scheme unless final_scheme is also set, which will take precedence.

config

This transforms a dict of arbitrary user configuration. A section must be defined indicating what the configuration represents e.g. init_config.

The metadata name submitted will become config.<section>.

The value will be a JSON str with the root being an array. There will be one map element for every allowed field. Every map may have 2 entries:

  1. is_set - a boolean indicating whether or not the field exists
  2. value - the value of the field. this is only set if the field exists and the value is a primitive type (None | bool | float | int | str)

The allowed fields are derived from the optional whitelist and blacklist. By default, nothing will be sent.

User configuration can override defaults allowing complete, granular control of metadata submissions. In any section, one may set metadata_whitelist and/or metadata_blacklist which will override their keyword argument counterparts. In following our standard, blacklists take precedence over whitelists.

Blacklists are special in that each item is considered a regular expression.

Motivation

DataDog/datadog-agent#4234
DataDog/datadog-agent#4158

Additional Notes

In another PR I will implement a mechanism to automatically perform config metadata collection to avoid redundant calls in every check.

@ofek
Copy link
Contributor Author

ofek commented Oct 5, 2019

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 2 pipeline(s).

@codecov
Copy link

codecov bot commented Oct 6, 2019

therve
therve previously approved these changes Oct 7, 2019
Copy link
Contributor

@therve therve left a comment

Choose a reason for hiding this comment

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

Looks good, some minor questions.

FlorianVeaux
FlorianVeaux previously approved these changes Oct 7, 2019
Copy link
Member

@FlorianVeaux FlorianVeaux left a comment

Choose a reason for hiding this comment

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

This is great, just a couple minor points:

  • I agree with Thomas, having a default blacklist to prevent passwords and other secrets to be submitted would help.
  • The backend will only receive json formatted data for configs. Do we know how well that is supported? I think this is a good idea because we don't want to index every single field, but I'm not sure how the backend would handle JSON

@ofek ofek dismissed stale reviews from FlorianVeaux and therve via 5bf9ad5 October 7, 2019 16:57
@ofek
Copy link
Contributor Author

ofek commented Oct 8, 2019

@FlorianVeaux As far as I know this will be supported, but the backend parsing has yet to be written

@ofek ofek merged commit 3349866 into master Oct 8, 2019
@ofek ofek deleted the ofek/metadata branch October 8, 2019 02:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants