| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- package prom
- import (
- "bytes"
- "context"
- "fmt"
- "io"
- "net/http"
- "net/url"
- "testing"
- "time"
- "github.com/rs/zerolog"
- zerologger "github.com/rs/zerolog/log"
- )
- func initLogging(t *testing.T, logLevel string, colorEnabled bool) {
- zerolog.TimeFieldFormat = time.RFC3339Nano
- zerologger.Logger = zerologger.Output(zerolog.ConsoleWriter{
- Out: zerolog.NewTestWriter(t),
- TimeFormat: time.RFC3339Nano,
- NoColor: !colorEnabled,
- })
- logLevelParsed, err := zerolog.ParseLevel(logLevel)
- if err != nil {
- logLevelParsed = zerolog.DebugLevel
- }
- zerolog.SetGlobalLevel(logLevelParsed)
- }
- type SingleLogWriter struct {
- Log string
- }
- // Write to testing.TB.
- func (slw *SingleLogWriter) Write(p []byte) (n int, err error) {
- err = nil
- n = len(p)
- slw.Log = string(p)
- return
- }
- type NoOpPromClient struct {
- }
- func (mpc *NoOpPromClient) URL(ep string, args map[string]string) *url.URL {
- return &url.URL{}
- }
- func (mpc *NoOpPromClient) Do(c context.Context, req *http.Request) (*http.Response, []byte, error) {
- return &http.Response{
- StatusCode: http.StatusOK,
- Body: io.NopCloser(bytes.NewReader([]byte{})),
- },
- []byte{},
- nil
- }
- func TestQueryLogs(t *testing.T) {
- // init logging
- initLogging(t, "debug", false)
- // use a single log writer so we can examine the logs after each query
- logWriter := new(SingleLogWriter)
- zerologger.Logger = zerologger.Output(zerolog.ConsoleWriter{
- Out: logWriter,
- TimeFormat: "",
- NoColor: true,
- PartsExclude: []string{
- zerolog.TimestampFieldName,
- zerolog.LevelFieldName,
- zerolog.CallerFieldName,
- },
- })
- // reinitialize logging when tests are complete
- defer initLogging(t, "debug", false)
- t.Setenv("PROMETHEUS_SERVER_ENDPOINT", "nowhere")
- config, err := NewOpenCostPrometheusConfigFromEnv()
- if err != nil {
- t.Fatalf("Failed to create OpenCost Prometheus config: %v", err)
- return
- }
- mock := new(NoOpPromClient)
- contextFactory := NewContextFactory(mock, config)
- querier := newPrometheusMetricsQuerier(config, mock, contextFactory)
- queryEnd := time.Now().UTC().Truncate(time.Hour).Add(time.Hour)
- queryStart := queryEnd.Add(-24 * time.Hour)
- tests := map[string]func(time.Time, time.Time){
- "QueryPVActiveMinutes": func(s, e time.Time) { querier.QueryPVActiveMinutes(s, e) },
- "QueryPVUsedAverage": func(s, e time.Time) { querier.QueryPVUsedAverage(s, e) },
- "QueryPVUsedMax": func(s, e time.Time) { querier.QueryPVUsedMax(s, e) },
- "QueryLocalStorageActiveMinutes": func(s, e time.Time) { querier.QueryLocalStorageActiveMinutes(s, e) },
- "QueryLocalStorageUsedAvg": func(s, e time.Time) { querier.QueryLocalStorageUsedAvg(s, e) },
- "QueryLocalStorageUsedMax": func(s, e time.Time) { querier.QueryLocalStorageUsedMax(s, e) },
- "QueryLocalStorageBytes": func(s, e time.Time) { querier.QueryLocalStorageBytes(s, e) },
- "QueryNodeActiveMinutes": func(s, e time.Time) { querier.QueryNodeActiveMinutes(s, e) },
- "QueryNodeCPUCoresCapacity": func(s, e time.Time) { querier.QueryNodeCPUCoresCapacity(s, e) },
- "QueryNodeCPUCoresAllocatable": func(s, e time.Time) { querier.QueryNodeCPUCoresAllocatable(s, e) },
- "QueryNodeRAMBytesCapacity": func(s, e time.Time) { querier.QueryNodeRAMBytesCapacity(s, e) },
- "QueryNodeRAMBytesAllocatable": func(s, e time.Time) { querier.QueryNodeRAMBytesAllocatable(s, e) },
- "QueryNodeGPUCount": func(s, e time.Time) { querier.QueryNodeGPUCount(s, e) },
- "QueryNodeCPUModeTotal": func(s, e time.Time) { querier.QueryNodeCPUModeTotal(s, e) },
- "QueryNodeIsSpot": func(s, e time.Time) { querier.QueryNodeIsSpot(s, e) },
- "QueryNodeRAMSystemPercent": func(s, e time.Time) { querier.QueryNodeRAMSystemPercent(s, e) },
- "QueryNodeRAMUserPercent": func(s, e time.Time) { querier.QueryNodeRAMUserPercent(s, e) },
- "QueryLBActiveMinutes": func(s, e time.Time) { querier.QueryLBActiveMinutes(s, e) },
- "QueryLBPricePerHr": func(s, e time.Time) { querier.QueryLBPricePerHr(s, e) },
- "QueryClusterManagementDuration": func(s, e time.Time) { querier.QueryClusterManagementDuration(s, e) },
- "QueryClusterManagementPricePerHr": func(s, e time.Time) { querier.QueryClusterManagementPricePerHr(s, e) },
- "QueryPods": func(s, e time.Time) { querier.QueryPods(s, e) },
- "QueryPodsUID": func(s, e time.Time) { querier.QueryPodsUID(s, e) },
- "QueryRAMBytesAllocated": func(s, e time.Time) { querier.QueryRAMBytesAllocated(s, e) },
- "QueryRAMRequests": func(s, e time.Time) { querier.QueryRAMRequests(s, e) },
- "QueryRAMLimits": func(s, e time.Time) { querier.QueryRAMLimits(s, e) },
- "QueryRAMUsageAvg": func(s, e time.Time) { querier.QueryRAMUsageAvg(s, e) },
- "QueryRAMUsageMax": func(s, e time.Time) { querier.QueryRAMUsageMax(s, e) },
- "QueryNodeRAMPricePerGiBHr": func(s, e time.Time) { querier.QueryNodeRAMPricePerGiBHr(s, e) },
- "QueryCPUCoresAllocated": func(s, e time.Time) { querier.QueryCPUCoresAllocated(s, e) },
- "QueryCPURequests": func(s, e time.Time) { querier.QueryCPURequests(s, e) },
- "QueryCPULimits": func(s, e time.Time) { querier.QueryCPULimits(s, e) },
- "QueryCPUUsageAvg": func(s, e time.Time) { querier.QueryCPUUsageAvg(s, e) },
- "QueryCPUUsageMax": func(s, e time.Time) { querier.QueryCPUUsageMax(s, e) },
- "QueryNodeCPUPricePerHr": func(s, e time.Time) { querier.QueryNodeCPUPricePerHr(s, e) },
- "QueryGPUsAllocated": func(s, e time.Time) { querier.QueryGPUsAllocated(s, e) },
- "QueryGPUsRequested": func(s, e time.Time) { querier.QueryGPUsRequested(s, e) },
- "QueryGPUsUsageAvg": func(s, e time.Time) { querier.QueryGPUsUsageAvg(s, e) },
- "QueryGPUsUsageMax": func(s, e time.Time) { querier.QueryGPUsUsageMax(s, e) },
- "QueryNodeGPUPricePerHr": func(s, e time.Time) { querier.QueryNodeGPUPricePerHr(s, e) },
- "QueryGPUInfo": func(s, e time.Time) { querier.QueryGPUInfo(s, e) },
- "QueryIsGPUShared": func(s, e time.Time) { querier.QueryIsGPUShared(s, e) },
- "QueryPodPVCAllocation": func(s, e time.Time) { querier.QueryPodPVCAllocation(s, e) },
- "QueryPVCBytesRequested": func(s, e time.Time) { querier.QueryPVCBytesRequested(s, e) },
- "QueryPVCInfo": func(s, e time.Time) { querier.QueryPVCInfo(s, e) },
- "QueryPVBytes": func(s, e time.Time) { querier.QueryPVBytes(s, e) },
- "QueryPVPricePerGiBHour": func(s, e time.Time) { querier.QueryPVPricePerGiBHour(s, e) },
- "QueryPVInfo": func(s, e time.Time) { querier.QueryPVInfo(s, e) },
- "QueryNetZoneGiB": func(s, e time.Time) { querier.QueryNetZoneGiB(s, e) },
- "QueryNetZonePricePerGiB": func(s, e time.Time) { querier.QueryNetZonePricePerGiB(s, e) },
- "QueryNetRegionGiB": func(s, e time.Time) { querier.QueryNetRegionGiB(s, e) },
- "QueryNetRegionPricePerGiB": func(s, e time.Time) { querier.QueryNetRegionPricePerGiB(s, e) },
- "QueryNetInternetGiB": func(s, e time.Time) { querier.QueryNetInternetGiB(s, e) },
- "QueryNetInternetPricePerGiB": func(s, e time.Time) { querier.QueryNetInternetPricePerGiB(s, e) },
- "QueryNetInternetServiceGiB": func(s, e time.Time) { querier.QueryNetInternetServiceGiB(s, e) },
- "QueryNetTransferBytes": func(s, e time.Time) { querier.QueryNetTransferBytes(s, e) },
- "QueryNetZoneIngressGiB": func(s, e time.Time) { querier.QueryNetZoneIngressGiB(s, e) },
- "QueryNetRegionIngressGiB": func(s, e time.Time) { querier.QueryNetRegionIngressGiB(s, e) },
- "QueryNetInternetIngressGiB": func(s, e time.Time) { querier.QueryNetInternetIngressGiB(s, e) },
- "QueryNetInternetServiceIngressGiB": func(s, e time.Time) { querier.QueryNetInternetServiceIngressGiB(s, e) },
- "QueryNetReceiveBytes": func(s, e time.Time) { querier.QueryNetReceiveBytes(s, e) },
- "QueryNamespaceAnnotations": func(s, e time.Time) { querier.QueryNamespaceAnnotations(s, e) },
- "QueryPodAnnotations": func(s, e time.Time) { querier.QueryPodAnnotations(s, e) },
- "QueryNodeLabels": func(s, e time.Time) { querier.QueryNodeLabels(s, e) },
- "QueryNamespaceLabels": func(s, e time.Time) { querier.QueryNamespaceLabels(s, e) },
- "QueryPodLabels": func(s, e time.Time) { querier.QueryPodLabels(s, e) },
- "QueryServiceLabels": func(s, e time.Time) { querier.QueryServiceLabels(s, e) },
- "QueryDeploymentLabels": func(s, e time.Time) { querier.QueryDeploymentLabels(s, e) },
- "QueryStatefulSetLabels": func(s, e time.Time) { querier.QueryStatefulSetLabels(s, e) },
- "QueryDaemonSetLabels": func(s, e time.Time) { querier.QueryDaemonSetLabels(s, e) },
- "QueryJobLabels": func(s, e time.Time) { querier.QueryJobLabels(s, e) },
- "QueryPodsWithReplicaSetOwner": func(s, e time.Time) { querier.QueryPodsWithReplicaSetOwner(s, e) },
- "QueryReplicaSetsWithoutOwners": func(s, e time.Time) { querier.QueryReplicaSetsWithoutOwners(s, e) },
- "QueryReplicaSetsWithRollout": func(s, e time.Time) { querier.QueryReplicaSetsWithRollout(s, e) },
- "QueryResourceQuotaSpecCPURequestAverage": func(s, e time.Time) { querier.QueryResourceQuotaSpecCPURequestAverage(s, e) },
- "QueryResourceQuotaSpecCPURequestMax": func(s, e time.Time) { querier.QueryResourceQuotaSpecCPURequestMax(s, e) },
- "QueryResourceQuotaSpecRAMRequestAverage": func(s, e time.Time) { querier.QueryResourceQuotaSpecRAMRequestAverage(s, e) },
- "QueryResourceQuotaSpecRAMRequestMax": func(s, e time.Time) { querier.QueryResourceQuotaSpecRAMRequestMax(s, e) },
- "QueryResourceQuotaSpecCPULimitAverage": func(s, e time.Time) { querier.QueryResourceQuotaSpecCPULimitAverage(s, e) },
- "QueryResourceQuotaSpecCPULimitMax": func(s, e time.Time) { querier.QueryResourceQuotaSpecCPULimitMax(s, e) },
- "QueryResourceQuotaSpecRAMLimitAverage": func(s, e time.Time) { querier.QueryResourceQuotaSpecRAMLimitAverage(s, e) },
- "QueryResourceQuotaSpecRAMLimitMax": func(s, e time.Time) { querier.QueryResourceQuotaSpecRAMLimitMax(s, e) },
- "QueryResourceQuotaStatusUsedCPURequestAverage": func(s, e time.Time) { querier.QueryResourceQuotaStatusUsedCPURequestAverage(s, e) },
- "QueryResourceQuotaStatusUsedCPURequestMax": func(s, e time.Time) { querier.QueryResourceQuotaStatusUsedCPURequestMax(s, e) },
- "QueryResourceQuotaStatusUsedRAMRequestAverage": func(s, e time.Time) { querier.QueryResourceQuotaStatusUsedRAMRequestAverage(s, e) },
- "QueryResourceQuotaStatusUsedRAMRequestMax": func(s, e time.Time) { querier.QueryResourceQuotaStatusUsedRAMRequestMax(s, e) },
- "QueryResourceQuotaStatusUsedCPULimitAverage": func(s, e time.Time) { querier.QueryResourceQuotaStatusUsedCPULimitAverage(s, e) },
- "QueryResourceQuotaStatusUsedCPULimitMax": func(s, e time.Time) { querier.QueryResourceQuotaStatusUsedCPULimitMax(s, e) },
- "QueryResourceQuotaStatusUsedRAMLimitAverage": func(s, e time.Time) { querier.QueryResourceQuotaStatusUsedRAMLimitAverage(s, e) },
- "QueryResourceQuotaStatusUsedRAMLimitMax": func(s, e time.Time) { querier.QueryResourceQuotaStatusUsedRAMLimitMax(s, e) },
- }
- for testName, queryFunc := range tests {
- t.Run(fmt.Sprintf("TestQueryLog_%s", testName), func(t *testing.T) {
- checkQueryLog(t, logWriter, queryFunc, testName, queryStart, queryEnd)
- })
- }
- }
- func checkQueryLog(t *testing.T, logWriter *SingleLogWriter, query func(time.Time, time.Time), queryName string, start time.Time, end time.Time) {
- t.Helper()
- // remove the query formatting for the log
- var headerFormat = PrometheusMetricsQueryLogFormat[:len(PrometheusMetricsQueryLogFormat)-3]
- query(start, end)
- // get log output from executing query
- output := logWriter.Log
- expectedHeader := fmt.Sprintf(headerFormat, queryName, end.Unix())
- headerLen := len(expectedHeader)
- if len(output) < headerLen {
- t.Errorf("Expected log header length %d, but got %d", headerLen, len(output))
- return
- }
- actual := output[:headerLen]
- if actual != expectedHeader {
- t.Errorf("Expected log header '%s', but got '%s'", expectedHeader, actual)
- return
- }
- }
|