<commit_before>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package translator

import (
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/GoogleCloudPlatform/k8s-stackdriver/custom-metrics-stackdriver-adapter/pkg/adapter/translator/utils"
	"github.com/GoogleCloudPlatform/k8s-stackdriver/custom-metrics-stackdriver-adapter/pkg/config"
	stackdriver "google.golang.org/api/monitoring/v3"
	v1 "k8s.io/api/core/v1"
	apierr "k8s.io/apimachinery/pkg/api/errors"
	apimeta "k8s.io/apimachinery/pkg/api/meta"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/selection"
	"k8s.io/klog"
)

var (
	// allowedExternalMetricsLabelPrefixes and allowedExternalMetricsFullLabelNames specify all metric labels allowed for querying
	// External Metrics API.
	allowedExternalMetricsLabelPrefixes  = []string{"metric.labels", "resource.labels", "metadata.system_labels", "metadata.user_labels"}
	allowedExternalMetricsFullLabelNames = []string{"resource.type", "reducer"}
	// allowedCustomMetricsLabelPrefixes and allowedCustomMetricsFullLabelNames specify all metric labels allowed for querying
	allowedCustomMetricsLabelPrefixes  = []string{"metric.labels"}
	allowedCustomMetricsFullLabelNames = []string{"reducer"}
	allowedReducers                    = map[string]bool{
		"REDUCE_NONE":          true,
		"REDUCE_MEAN":          true,
		"REDUCE_MIN":           true,
		"REDUCE_MAX":           true,
		"REDUCE_SUM":           true,
		"REDUCE_STDDEV":        true,
		"REDUCE_COUNT":         true,
		"REDUCE_COUNT_TRUE":    true,
		"REDUCE_COUNT_FALSE":   true,
		"REDUCE_FRACTION_TRUE": true,
		"REDUCE_PERCENTILE_99": true,
		"REDUCE_PERCENTILE_95": true,
		"REDUCE_PERCENTILE_50": true,
		"REDUCE_PERCENTILE_05": true,
	}
)

const (
	// AllNamespaces is constant to indicate that there is no namespace filter in query
	AllNamespaces = ""
	// MaxNumOfArgsInOneOfFilter is the maximum value of one_of() function allowed in Stackdriver Filters
	MaxNumOfArgsInOneOfFilter = 100
	// PrometheusMetricPrefix is the prefix for prometheus metrics
	PrometheusMetricPrefix = "prometheus.googleapis.com"
)

type clock interface {
	Now() time.Time
}

type realClock struct{}

func (c realClock) Now() time.Time {
	return time.Now()
}

// Translator is a structure used to translate between Custom Metrics API and Stackdriver API
type Translator struct {
	service              *stackdriver.Service
	config               *config.GceConfig
	reqWindow            time.Duration
	alignmentPeriod      time.Duration
	clock                clock
	mapper               apimeta.RESTMapper
	useNewResourceModel  bool
	supportDistributions bool
}

// podValues is a helper struct to hold pods values
type podValues struct {
	pods     *v1.PodList
	podNames []string
}

// isPodValuesValid checks if podValues is valid to be used
//
// this only happens when the both pods & podNames are provided,
// for example, when WithPods() and WithPodNames() are both used in QueryBuilder
func (pc podValues) isPodValuesValid() bool {
	return !(len(pc.podNames) > 0 && pc.pods != nil && len(pc.pods.Items) > 0)
}

// isPodsEmpty checks if pods container is empty
func (pc podValues) isPodValuesEmpty() bool {
	return len(pc.podNames) == 0 && (pc.pods == nil || len(pc.pods.Items) == 0)
}

// getPodNames gets pod names from podValues is any provided
func (pc podValues) getPodNames() []string {<commit_msg>fix typo<commit_after>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package translator

import (
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/GoogleCloudPlatform/k8s-stackdriver/custom-metrics-stackdriver-adapter/pkg/adapter/translator/utils"
	"github.com/GoogleCloudPlatform/k8s-stackdriver/custom-metrics-stackdriver-adapter/pkg/config"
	stackdriver "google.golang.org/api/monitoring/v3"
	v1 "k8s.io/api/core/v1"
	apierr "k8s.io/apimachinery/pkg/api/errors"
	apimeta "k8s.io/apimachinery/pkg/api/meta"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/selection"
	"k8s.io/klog"
)

var (
	// allowedExternalMetricsLabelPrefixes and allowedExternalMetricsFullLabelNames specify all metric labels allowed for querying
	// External Metrics API.
	allowedExternalMetricsLabelPrefixes  = []string{"metric.labels", "resource.labels", "metadata.system_labels", "metadata.user_labels"}
	allowedExternalMetricsFullLabelNames = []string{"resource.type", "reducer"}
	// allowedCustomMetricsLabelPrefixes and allowedCustomMetricsFullLabelNames specify all metric labels allowed for querying
	allowedCustomMetricsLabelPrefixes  = []string{"metric.labels"}
	allowedCustomMetricsFullLabelNames = []string{"reducer"}
	allowedReducers                    = map[string]bool{
		"REDUCE_NONE":          true,
		"REDUCE_MEAN":          true,
		"REDUCE_MIN":           true,
		"REDUCE_MAX":           true,
		"REDUCE_SUM":           true,
		"REDUCE_STDDEV":        true,
		"REDUCE_COUNT":         true,
		"REDUCE_COUNT_TRUE":    true,
		"REDUCE_COUNT_FALSE":   true,
		"REDUCE_FRACTION_TRUE": true,
		"REDUCE_PERCENTILE_99": true,
		"REDUCE_PERCENTILE_95": true,
		"REDUCE_PERCENTILE_50": true,
		"REDUCE_PERCENTILE_05": true,
	}
)

const (
	// AllNamespaces is constant to indicate that there is no namespace filter in query
	AllNamespaces = ""
	// MaxNumOfArgsInOneOfFilter is the maximum value of one_of() function allowed in Stackdriver Filters
	MaxNumOfArgsInOneOfFilter = 100
	// PrometheusMetricPrefix is the prefix for prometheus metrics
	PrometheusMetricPrefix = "prometheus.googleapis.com"
)

type clock interface {
	Now() time.Time
}

type realClock struct{}

func (c realClock) Now() time.Time {
	return time.Now()
}

// Translator is a structure used to translate between Custom Metrics API and Stackdriver API
type Translator struct {
	service              *stackdriver.Service
	config               *config.GceConfig
	reqWindow            time.Duration
	alignmentPeriod      time.Duration
	clock                clock
	mapper               apimeta.RESTMapper
	useNewResourceModel  bool
	supportDistributions bool
}

// podValues is a helper struct to hold pods values
type podValues struct {
	pods     *v1.PodList
	podNames []string
}

// isPodValuesValid checks if podValues is valid to be used
//
// this only happens when the both pods & podNames are provided,
// for example, when WithPods() and WithPodNames() are both used in QueryBuilder
func (pc podValues) isPodValuesValid() bool {
	return !(len(pc.podNames) > 0 && pc.pods != nil && len(pc.pods.Items) > 0)
}

// isPodValuesEmpty checks if pods container is empty
func (pc podValues) isPodValuesEmpty() bool {
	return len(pc.podNames) == 0 && (pc.pods == nil || len(pc.pods.Items) == 0)
}

// getPodNames gets pod names from podValues is any provided
func (pc podValues) getPodNames() []string {
{'fraction_non_alphanumeric': 0.0932892730045755, 'fraction_numerical': 0.009659379766141332, 'mean_word_length': 3.999364675984752, 'pattern_counts': {'":': 28, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5538252', 'n_tokens_mistral': 2559, 'n_tokens_neox': 2450, 'n_words': 699}