diff --git a/app/vmselect/promql/exec_test.go b/app/vmselect/promql/exec_test.go index 1f956b4b8a..fc9212e861 100644 --- a/app/vmselect/promql/exec_test.go +++ b/app/vmselect/promql/exec_test.go @@ -224,10 +224,12 @@ func TestExecSuccess(t *testing.T) { t.Run("timezone_offset(America/New_York)", func(t *testing.T) { t.Parallel() q := `timezone_offset("America/New_York")` - offset, err := getTimezoneOffset("America/New_York") + loc, err := time.LoadLocation("America/New_York") if err != nil { t.Fatalf("cannot obtain timezone: %s", err) } + at := time.Unix(timestampsExpected[0]/1000, 0) + _, offset := at.In(loc).Zone() off := float64(offset) r := netstorage.Result{ MetricName: metricNameExpected, @@ -240,10 +242,12 @@ func TestExecSuccess(t *testing.T) { t.Run("timezone_offset(Local)", func(t *testing.T) { t.Parallel() q := `timezone_offset("Local")` - offset, err := getTimezoneOffset("Local") + loc, err := time.LoadLocation("Local") if err != nil { t.Fatalf("cannot obtain timezone: %s", err) } + at := time.Unix(timestampsExpected[0]/1000, 0) + _, offset := at.In(loc).Zone() off := float64(offset) r := netstorage.Result{ MetricName: metricNameExpected, diff --git a/app/vmselect/promql/transform.go b/app/vmselect/promql/transform.go index 16d7ff5b14..a893e217ee 100644 --- a/app/vmselect/promql/transform.go +++ b/app/vmselect/promql/transform.go @@ -2178,21 +2178,22 @@ func transformTimezoneOffset(tfa *transformFuncArg) ([]*timeseries, error) { if err != nil { return nil, fmt.Errorf("cannot get timezone name: %w", err) } - tzOffset, err := getTimezoneOffset(tzString) - if err != nil { - return nil, fmt.Errorf("cannot get timezone offset for %q: %w", tzString, err) - } - rv := evalNumber(tfa.ec, float64(tzOffset)) - return rv, nil -} - -func getTimezoneOffset(tzString string) (int, error) { loc, err := time.LoadLocation(tzString) if err != nil { - return 0, fmt.Errorf("cannot load timezone %q: %w", tzString, err) + return nil, fmt.Errorf("cannot load timezone %q: %w", tzString, err) } - _, tzOffset := time.Now().In(loc).Zone() - return tzOffset, nil + + var ts timeseries + ts.denyReuse = true + timestamps := tfa.ec.getSharedTimestamps() + values := make([]float64, len(timestamps)) + for i, v := range timestamps { + _, offset := time.Unix(v/1000, 0).In(loc).Zone() + values[i] = float64(offset) + } + ts.Values = values + ts.Timestamps = timestamps + return []*timeseries{&ts}, nil } func transformTime(tfa *transformFuncArg) ([]*timeseries, error) { diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 9644a6fad0..b251c5e2f7 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -58,6 +58,7 @@ scrape_configs: * BUGFIX: limit max memory occupied by the cache, which stores parsed regular expressions. Previously too long regular expressions passed in [MetricsQL queries](https://docs.victoriametrics.com/MetricsQL.html) could result in big amounts of used memory (e.g. multiple of gigabytes). Now the max cache size for parsed regexps is limited to a a few megabytes. * BUGFIX: [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html): properly handle partial counter resets when calculating [rate](https://docs.victoriametrics.com/MetricsQL.html#rate), [irate](https://docs.victoriametrics.com/MetricsQL.html#irate) and [increase](https://docs.victoriametrics.com/MetricsQL.html#increase) functions. Previously these functions could return zero values after partial counter resets until the counter increases to the last value before partial counter reset. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2787). * BUGFIX: [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html): properly calculate [histogram_quantile](https://docs.victoriametrics.com/MetricsQL.html#histogram_quantile) over Prometheus buckets with unexpected values. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2819). +* BUGFIX: [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html): properly evaluate [timezone_offset](https://docs.victoriametrics.com/MetricsQL.html#timezone_offset) function over time range covering time zone offset switches. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2771). * BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent.html): properly add service-level labels (`__meta_kubernetes_service_*`) to discovered targets for `role: endpointslice` in [kubernetes_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config). Previously these labels were missing. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2823). * BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent.html): make sure that [stale markers](https://docs.victoriametrics.com/vmagent.html#prometheus-staleness-markers) are generated with the actual timestamp when unsuccessful scrape occurs. This should prevent from possible time series overlap on scrape target restart in dynmaic envirnoments such as Kubernetes. * BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent.html): properly reload changed `-promscrape.config` file when `-promscrape.configCheckInterval` option is set. The changed config file wasn't reloaded in this case since [v1.69.0](#v1690). See [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/2786). Thanks to @ttyv for the fix.