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

[ resource generation processor] add new processor skeleton and configuration examples #3266

Merged
merged 26 commits into from
May 17, 2021

Conversation

hossain-rayhan
Copy link
Contributor

Signed-off-by: Rayhan Hossain [email protected]

This PR adds the skeleton and configuration examples of a new processor metricsgenerationprocessor.

Description:
The metrics generation processor (metricsgenerationprocessor) can be used to create new metrics using existing metrics following a given rule. Currently it supports following two approaches for creating a new metric.

  1. It can create a new metric using two existing metrics applying one of the follwing arithmatic operations: add, subtract, multiply, divide and percent. One use case is to calculate the pod.memory.utilization metric like the following equation-
    pod.memory.utilization = (pod.memory.usage.bytes / node.memory.limit)
  2. It can create a new metric by scaling the value of an existing metric with a given constant number. One use case is to convert pod.memory.usage metric values from Megabytes to Bytes (multiply the existing metric's value by 1000000)

Configuration

Configuration is specified through a list of generation rules. Generation rules find the metrics which
matche the given metric names and apply the operation to those metrics.

processors:
    # processor name: metricsgeneration
    metricsgeneration:

        # specify the metric generation rules
        generation_rules:
              # name of the new metric. this is a required field
            - new_metric_name: <new_metric_name>

              # generation_type describes how the metric will be generated. it can either be calculate or scale calculate generates a metric applying the given operation on two operand metrics. scale operates only on  operand1 metric to generate the new metric.
              generation_type: {calculate, scale}

              # this is a required field
              operand1_metric: <first_operand_metric>

              # this field is required only if the generation_type is calculate
              operand2_metric: <second_operand_metric>

              # operation specifies which atrithmatic operation to apply. it can be one of the five supported operations.
              operation: {add, subtract, multiply, divide, percent}

              # scale_by is only required if the generation_type is scale
              scale_by: 1000

Example Configurations

Create a new metric using two existing metrics

# create pod.cpu.utilized following (pod.cpu.usage / node.cpu.limit)
generation_rules:
    - new_metric_name: pod.cpu.utilized
      generation_type: calculate
      operand1_metric: pod.cpu.usage
      operand2_metric: node.cpu.limit
      operation: divide

Create a new metric scaling the value of an existing metric

# create pod.memory.usage.bytes from pod.memory.usage.megabytes
generation_rules:
    - new_metric_name: pod.memory.usage.bytes
      generation_type: scale
      operand1_metric: pod.memory.usage.megabytes
      operation: multiply
      scale_by: 1000000

Link to tracking Issue:
#2722

Testing:
Added unit tests. This is the skeleton only. Will add more test later.

Documentation:
README updated.

@hossain-rayhan hossain-rayhan requested a review from a team April 28, 2021 12:27
@dashpole
Copy link
Contributor

Related PR, which just wants to add the ability to scale metrics to the existing metricstransformprocessor: #3177

@hossain-rayhan
Copy link
Contributor Author

@bogdandrutu Would you please take a look on this?

@hossain-rayhan
Copy link
Contributor Author

Hi @bogdandrutu a review is really appreciated.

processor/metricsgenerationprocessor/README.md Outdated Show resolved Hide resolved
processor/metricsgenerationprocessor/README.md Outdated Show resolved Hide resolved
processor/metricsgenerationprocessor/README.md Outdated Show resolved Hide resolved
metricsgeneration:

# specify the metric generation rules
generation_rules:
Copy link
Member

Choose a reason for hiding this comment

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

Would simply rules be a better name for this field? I imagine it's always going to follow the declaration of the metricsgeneration processor and seems to stutter in that way. Similarly, some of the rule field names could be simplified by making use of their context:

processors:
  metricsgeneration:
    rules:
      - name: <new metric name>
        type: {calculate, scale}
        metric1: <first metric>
        metric2: <second metric>
        operation: ...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Makes sense. will update.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated.

processor/metricsgenerationprocessor/README.md Outdated Show resolved Hide resolved
processor/metricsgenerationprocessor/doc.go Show resolved Hide resolved
cfg config.Processor,
nextConsumer consumer.Metrics,
) (component.MetricsProcessor, error) {
processorConfig := cfg.(*Config)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
processorConfig := cfg.(*Config)
processorConfig, ok := cfg.(*Config)
if !ok {
// handle this error
}

This coercion should be checked to avoid a potential panic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated.

processor/metricsgenerationprocessor/factory.go Outdated Show resolved Hide resolved
processor/metricsgenerationprocessor/factory.go Outdated Show resolved Hide resolved
Comment on lines 33 to 40
type internalGenerationRule struct {
NewMetricName string
Type GenerationType
Operand1Metric string
Operand2Metric string
Operation OperationType
ScaleBy float64
}
Copy link
Member

Choose a reason for hiding this comment

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

Why is there a new type that mirrors the exported GenerationRule type?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated.

}

if !rule.Type.isValid() {
return fmt.Errorf("%q must be in %q", GenerationTypeFieldName, generationTypes)
Copy link
Member

Choose a reason for hiding this comment

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

generationTypes is now a map[GenerationType]struct{}, so is this output still appropriate? Same with operationTypes below.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think I understand what you said.

Copy link
Member

Choose a reason for hiding this comment

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

https://play.golang.org/p/B6CLhHkdkDj

Map:	map["bar":{} "foo":{}]
Slice:	["foo" "bar"]
MapKeys:	["foo" "bar"]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh I see. Thanks. will update.

return fmt.Errorf("missing required field %q for generation type %q", Operand2MetricFieldName, Calculate)
}

if rule.Type == Scale && rule.ScaleBy <= 0 {
Copy link
Member

Choose a reason for hiding this comment

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

If addition is a valid operation should we allow 0? I'm not sure whether it makes sense to use this to copy a metric.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For generation type calculate or scale I think this seems to be OK. For renaming, we may introduce another generation type rename which will filter based on metric labels and create a new one. The rename was part of our first proposal. But right now this is out of scope and we can achieve it with metricstransformprocessor.

Comment on lines 48 to 52
- new_metric_name: pod.cpu.utilized
generation_type: calculate
operand1_metric: pod.cpu.usage
operand2_metric: node.cpu.limit
operation: divide
Copy link
Member

Choose a reason for hiding this comment

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

I still think the rest of these field names should be simplified as well:

processors:
  metricsgeneration:
    rules:
      - name: <new metric name>
        type: {calculate, scale}
        metric1: <first metric>
        metric2: <second metric>
        operation: ...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I prefer generation_type so that people don't mix it up with metric type. Also, I saw other examples where we used the prefix operand1_ which gives them clear idea about numerator and denominator. This design was discussed and I feel like current namings are OK. Expecting a second thought.

Copy link
Member

Choose a reason for hiding this comment

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

v0v

I feel that the current names are overly verbose and somewhat awkward, but it's not a hill I want to fight on.

Copy link
Contributor

Choose a reason for hiding this comment

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

Let's go with @Aneurysm9's suggested names, they look much better to me

processor/metricsgenerationprocessor/README.md Outdated Show resolved Hide resolved
processor/metricsgenerationprocessor/factory.go Outdated Show resolved Hide resolved
processor/metricsgenerationprocessor/go.mod Outdated Show resolved Hide resolved
@mxiamxia
Copy link
Member

mxiamxia commented May 5, 2021

pls rebase

Copy link
Member

@mxiamxia mxiamxia left a comment

Choose a reason for hiding this comment

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

LGTM!

Comment on lines 48 to 52
- new_metric_name: pod.cpu.utilized
generation_type: calculate
operand1_metric: pod.cpu.usage
operand2_metric: node.cpu.limit
operation: divide
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's go with @Aneurysm9's suggested names, they look much better to me

processor/metricsgenerationprocessor/factory.go Outdated Show resolved Hide resolved
processor/metricsgenerationprocessor/processor.go Outdated Show resolved Hide resolved
Copy link
Contributor

@anuraaga anuraaga left a comment

Choose a reason for hiding this comment

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

Just a couple more renames, thanks

processor/metricsgenerationprocessor/config.go Outdated Show resolved Hide resolved
processor/metricsgenerationprocessor/config.go Outdated Show resolved Hide resolved
hossain-rayhan and others added 13 commits May 10, 2021 10:06
@hossain-rayhan
Copy link
Contributor Author

hossain-rayhan commented May 10, 2021

Rebased again to see if we can pass the unexpected windows and trace test failure. Now the load-test for logs is failing which is not related to this change.

@alolita alolita added the ready to merge Code review completed; ready to merge by maintainers label May 11, 2021
@alolita
Copy link
Member

alolita commented May 11, 2021

@bogdandrutu this PR has been reviewed by approved and should be ready-to-merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready to merge Code review completed; ready to merge by maintainers
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants