Skip to content

Conversation

@SoumyaRaikwar
Copy link

@SoumyaRaikwar SoumyaRaikwar commented Oct 14, 2025

What this PR does

This PR adds a valueType field to custom resource state metrics gauge configuration, enabling explicit parsing of Go duration strings to seconds. This is particularly useful for resources like cert-manager Certificates that store durations as strings (e.g., "2160h", "720h").

Currently, kube-state-metrics automatically detects value types but fails to parse Go duration strings, resulting in errors like:

strconv.ParseFloat: parsing "2160h": invalid syntax

Which issue(s) this PR fixes:

Fixes #2625

Implementation Details

Code Changes

  • Added ValueType field to MetricGauge struct with options: duration, quantity, and default (empty string)
  • Implemented parseDurationValue() function using Go's time.ParseDuration
  • Updated gauge value extraction to respect valueType in both direct path and optimization code paths
  • Maintains full backward compatibility

Documentation

  • Added "Value Type Specification" section to customresourcestate-metrics.md
  • Documented all available value types and usage scenarios
  • Included complete cert-manager Certificate monitoring example
  • Added duration format reference (Go time.ParseDuration formats)

Example Usage

kind: CustomResourceStateMetrics
spec:
  resources:
    - groupVersionKind:
        group: cert-manager.io
        version: v1
        kind: Certificate
      metrics:
        - name: "certificate_duration_seconds"
          help: "Certificate validity duration in seconds"
          each:
            type: Gauge
            gauge:
              path: [spec, duration]
              valueType: duration  # Parses "2160h" → 7776000.0 seconds

        - name: "certificate_renew_before_seconds"
          help: "Time before expiration when certificate should be renewed"
          each:
            type: Gauge
            gauge:
              path: [spec, renewBefore]
              valueType: duration  # Parses "720h" → 2592000.0 seconds

Resulting metrics:

kube_customresource_certificate_duration_seconds{customresource_group="cert-manager.io",customresource_kind="Certificate",customresource_version="v1",name="example-cert",namespace="default"} 7776000
kube_customresource_certificate_renew_before_seconds{customresource_group="cert-manager.io",customresource_kind="Certificate",customresource_version="v1",name="example-cert",namespace="default"} 2592000

Supported Duration Formats

The duration valueType supports Go's time.ParseDuration format:

  • Hours: "1h", "24h", "2160h" (90 days)
  • Minutes: "30m", "90m"
  • Seconds: "45s"
  • Milliseconds: "500ms"
  • Microseconds: "100us" or "100µs"
  • Nanoseconds: "1000ns"
  • Combined: "1h30m45s", "2h15m30s"

All durations are converted to seconds as float64 for Prometheus compatibility.

Backward Compatibility

Fully backward compatible

  • Empty or omitted valueType field continues to use existing auto-detection behavior
  • No breaking changes to existing configurations
  • All existing tests pass without modification
  • No changes to default behavior

- Add valueType field to MetricGauge struct (duration, quantity, default)
- Implement parseDurationValue() function using time.ParseDuration
- Add duration parsing support in gauge value extraction
- Add 18 comprehensive test cases covering all scenarios
- Document valueType field with cert-manager examples

This enables explicit parsing of Go duration strings (e.g., '2160h', '30m')
to seconds for metrics, particularly useful for cert-manager Certificate
resources and other CRs with duration fields.

Signed-off-by: SoumyaRaikwar <somuraik@gmail.com>
@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. labels Oct 14, 2025
@k8s-ci-robot
Copy link
Contributor

This issue is currently awaiting triage.

If kube-state-metrics contributors determine this is a relevant issue, they will accept it by applying the triage/accepted label and provide further guidance.

The triage/accepted label can be added by org members by writing /triage accepted in a comment.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: SoumyaRaikwar
Once this PR has been reviewed and has the lgtm label, please assign mrueg for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@github-project-automation github-project-automation bot moved this to Needs Triage in SIG Instrumentation Oct 14, 2025
@k8s-ci-robot k8s-ci-robot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Oct 14, 2025
@SoumyaRaikwar
Copy link
Author

@mrueg @rexagod , could you please review my pr ?

@SoumyaRaikwar
Copy link
Author

@nmn3m could you please review my pr

var gotFloat float64
var err error

switch c.valueType {
Copy link
Member

Choose a reason for hiding this comment

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

The value type switching logic is duplicated in two places
Suggestion: Extract this into a helper function:

func (c *compiledGauge) parseValue(value interface{}) (float64, error) {
    switch c.valueType {
    case ValueTypeDuration:
        return parseDurationValue(value)
    case ValueTypeQuantity, ValueTypeDefault:
        return toFloat64(value, c.NilIsZero)
    default:
        return 0, fmt.Errorf("unknown valueType: %s", c.valueType)
    }
}

Then use it in both locations:
gotFloat, err := c.parseValue(it)

// Check if explicit valueType is specified
var value float64
var err error
switch c.valueType {
Copy link
Member

Choose a reason for hiding this comment

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

As mentioned above.

@nmn3m
Copy link
Member

nmn3m commented Oct 23, 2025

@SoumyaRaikwar, There are linting issues in docs file, please read summary at line 71 to fix them link

// The parsed duration is converted to seconds as a float64 for Prometheus compatibility.
ValueTypeDuration ValueType = "duration"
// ValueTypeQuantity parses Kubernetes resource quantities (e.g., "250m" for millicores, "1Gi" for memory).
ValueTypeQuantity ValueType = "quantity"
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure the difference between ValueTypeDefault and ValueTypeQuantity , Both cases call toFloat64(), which already includes automatic quantity detection.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

Status: Needs Triage

Development

Successfully merging this pull request may close these issues.

Add support for parsing duration (time.ParseDuration) on custom resource state metrics

3 participants