mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-01 14:47:38 +00:00
Merge branch 'public-single-node' into pmm-6401-read-prometheus-data-files
This commit is contained in:
commit
21140318cc
172 changed files with 4996 additions and 3003 deletions
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
|
@ -15,6 +15,8 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: Code checkout
|
- name: Code checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.workflow_run.head_branch }}
|
||||||
|
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
|
|
|
@ -1085,7 +1085,9 @@ The [deduplication](#deduplication) isn't applied for the data exported in nativ
|
||||||
|
|
||||||
## How to import time series data
|
## How to import time series data
|
||||||
|
|
||||||
Time series data can be imported into VictoriaMetrics via any supported data ingestion protocol:
|
VictoriaMetrics can discover and scrape metrics from Prometheus-compatible targets (aka "pull" protocol) -
|
||||||
|
see [these docs](#how-to-scrape-prometheus-exporters-such-as-node-exporter).
|
||||||
|
Additionally, VictoriaMetrics can accept metrics via the following popular data ingestion protocols (aka "push" protocols):
|
||||||
|
|
||||||
* [Prometheus remote_write API](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_write). See [these docs](#prometheus-setup) for details.
|
* [Prometheus remote_write API](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_write). See [these docs](#prometheus-setup) for details.
|
||||||
* DataDog `submit metrics` API. See [these docs](#how-to-send-data-from-datadog-agent) for details.
|
* DataDog `submit metrics` API. See [these docs](#how-to-send-data-from-datadog-agent) for details.
|
||||||
|
|
|
@ -129,7 +129,7 @@ func setUp() {
|
||||||
storagePath = filepath.Join(os.TempDir(), testStorageSuffix)
|
storagePath = filepath.Join(os.TempDir(), testStorageSuffix)
|
||||||
processFlags()
|
processFlags()
|
||||||
logger.Init()
|
logger.Init()
|
||||||
vmstorage.InitWithoutMetrics(promql.ResetRollupResultCacheIfNeeded)
|
vmstorage.Init(promql.ResetRollupResultCacheIfNeeded)
|
||||||
vmselect.Init()
|
vmselect.Init()
|
||||||
vminsert.Init()
|
vminsert.Init()
|
||||||
go httpserver.Serve(*httpListenAddr, requestHandler)
|
go httpserver.Serve(*httpListenAddr, requestHandler)
|
||||||
|
@ -189,10 +189,8 @@ func tearDown() {
|
||||||
|
|
||||||
func TestWriteRead(t *testing.T) {
|
func TestWriteRead(t *testing.T) {
|
||||||
t.Run("write", testWrite)
|
t.Run("write", testWrite)
|
||||||
|
vmstorage.Storage.DebugFlush()
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
vmstorage.Stop()
|
|
||||||
// open storage after stop in write
|
|
||||||
vmstorage.InitWithoutMetrics(promql.ResetRollupResultCacheIfNeeded)
|
|
||||||
t.Run("read", testRead)
|
t.Run("read", testRead)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package prometheusimport
|
package prometheusimport
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmagent/common"
|
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmagent/common"
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmagent/remotewrite"
|
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmagent/remotewrite"
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/auth"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/auth"
|
||||||
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
|
||||||
parserCommon "github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/common"
|
parserCommon "github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/common"
|
||||||
parser "github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/prometheus"
|
parser "github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/prometheus"
|
||||||
|
@ -33,14 +33,9 @@ func InsertHandler(at *auth.Token, req *http.Request) error {
|
||||||
isGzipped := req.Header.Get("Content-Encoding") == "gzip"
|
isGzipped := req.Header.Get("Content-Encoding") == "gzip"
|
||||||
return parser.ParseStream(req.Body, defaultTimestamp, isGzipped, func(rows []parser.Row) error {
|
return parser.ParseStream(req.Body, defaultTimestamp, isGzipped, func(rows []parser.Row) error {
|
||||||
return insertRows(at, rows, extraLabels)
|
return insertRows(at, rows, extraLabels)
|
||||||
}, nil)
|
}, func(s string) {
|
||||||
}
|
httpserver.LogError(req, s)
|
||||||
|
})
|
||||||
// InsertHandlerForReader processes metrics from given reader with optional gzip format
|
|
||||||
func InsertHandlerForReader(r io.Reader, isGzipped bool) error {
|
|
||||||
return parser.ParseStream(r, 0, isGzipped, func(rows []parser.Row) error {
|
|
||||||
return insertRows(nil, rows, nil)
|
|
||||||
}, nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func insertRows(at *auth.Token, rows []parser.Row, extraLabels []prompbmarshal.Label) error {
|
func insertRows(at *auth.Token, rows []parser.Row, extraLabels []prompbmarshal.Label) error {
|
||||||
|
|
56
app/vmagent/prometheusimport/request_handler_test.go
Normal file
56
app/vmagent/prometheusimport/request_handler_test.go
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
package prometheusimport
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"flag"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmagent/remotewrite"
|
||||||
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
|
||||||
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
srv *httptest.Server
|
||||||
|
testOutput *bytes.Buffer
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestInsertHandler(t *testing.T) {
|
||||||
|
setUp()
|
||||||
|
defer tearDown()
|
||||||
|
req := httptest.NewRequest("POST", "/insert/0/api/v1/import/prometheus", bytes.NewBufferString(`{"foo":"bar"}
|
||||||
|
go_memstats_alloc_bytes_total 1`))
|
||||||
|
if err := InsertHandler(nil, req); err != nil {
|
||||||
|
t.Errorf("unxepected error %s", err)
|
||||||
|
}
|
||||||
|
expectedMsg := "cannot unmarshal Prometheus line"
|
||||||
|
if !strings.Contains(testOutput.String(), expectedMsg) {
|
||||||
|
t.Errorf("output %q should contain %q", testOutput.String(), expectedMsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setUp() {
|
||||||
|
srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||||
|
w.WriteHeader(204)
|
||||||
|
}))
|
||||||
|
flag.Parse()
|
||||||
|
remoteWriteFlag := "remoteWrite.url"
|
||||||
|
if err := flag.Lookup(remoteWriteFlag).Value.Set(srv.URL); err != nil {
|
||||||
|
log.Fatalf("unable to set %q with value %q, err: %v", remoteWriteFlag, srv.URL, err)
|
||||||
|
}
|
||||||
|
logger.Init()
|
||||||
|
common.StartUnmarshalWorkers()
|
||||||
|
remotewrite.Init()
|
||||||
|
testOutput = &bytes.Buffer{}
|
||||||
|
logger.SetOutputForTests(testOutput)
|
||||||
|
}
|
||||||
|
|
||||||
|
func tearDown() {
|
||||||
|
common.StopUnmarshalWorkers()
|
||||||
|
srv.Close()
|
||||||
|
logger.ResetOutputForTest()
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
package promremotewrite
|
package promremotewrite
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmagent/common"
|
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmagent/common"
|
||||||
|
@ -33,13 +32,6 @@ func InsertHandler(at *auth.Token, req *http.Request) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// InsertHandlerForReader processes metrics from given reader
|
|
||||||
func InsertHandlerForReader(at *auth.Token, r io.Reader) error {
|
|
||||||
return parser.ParseStream(r, func(tss []prompb.TimeSeries) error {
|
|
||||||
return insertRows(at, tss, nil)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func insertRows(at *auth.Token, timeseries []prompb.TimeSeries, extraLabels []prompbmarshal.Label) error {
|
func insertRows(at *auth.Token, timeseries []prompb.TimeSeries, extraLabels []prompbmarshal.Label) error {
|
||||||
ctx := common.GetPushCtx()
|
ctx := common.GetPushCtx()
|
||||||
defer common.PutPushCtx(ctx)
|
defer common.PutPushCtx(ctx)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package vmimport
|
package vmimport
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmagent/common"
|
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmagent/common"
|
||||||
|
@ -36,13 +35,6 @@ func InsertHandler(at *auth.Token, req *http.Request) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// InsertHandlerForReader processes metrics from given reader
|
|
||||||
func InsertHandlerForReader(r io.Reader, isGzipped bool) error {
|
|
||||||
return parser.ParseStream(r, isGzipped, func(rows []parser.Row) error {
|
|
||||||
return insertRows(nil, rows, nil)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func insertRows(at *auth.Token, rows []parser.Row, extraLabels []prompbmarshal.Label) error {
|
func insertRows(at *auth.Token, rows []parser.Row, extraLabels []prompbmarshal.Label) error {
|
||||||
ctx := common.GetPushCtx()
|
ctx := common.GetPushCtx()
|
||||||
defer common.PutPushCtx(ctx)
|
defer common.PutPushCtx(ctx)
|
||||||
|
|
|
@ -64,17 +64,18 @@ func TestManagerUpdateConcurrent(t *testing.T) {
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
wg.Add(workers)
|
wg.Add(workers)
|
||||||
for i := 0; i < workers; i++ {
|
for i := 0; i < workers; i++ {
|
||||||
go func() {
|
go func(n int) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
r := rand.New(rand.NewSource(int64(n)))
|
||||||
for i := 0; i < iterations; i++ {
|
for i := 0; i < iterations; i++ {
|
||||||
rnd := rand.Intn(len(paths))
|
rnd := r.Intn(len(paths))
|
||||||
cfg, err := config.Parse([]string{paths[rnd]}, notifier.ValidateTemplates, true)
|
cfg, err := config.Parse([]string{paths[rnd]}, notifier.ValidateTemplates, true)
|
||||||
if err != nil { // update can fail and this is expected
|
if err != nil { // update can fail and this is expected
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
_ = m.update(context.Background(), cfg, false)
|
_ = m.update(context.Background(), cfg, false)
|
||||||
}
|
}
|
||||||
}()
|
}(i)
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,14 +162,15 @@ consul_sd_configs:
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
wg.Add(workers)
|
wg.Add(workers)
|
||||||
for i := 0; i < workers; i++ {
|
for i := 0; i < workers; i++ {
|
||||||
go func() {
|
go func(n int) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
r := rand.New(rand.NewSource(int64(n)))
|
||||||
for i := 0; i < iterations; i++ {
|
for i := 0; i < iterations; i++ {
|
||||||
rnd := rand.Intn(len(paths))
|
rnd := r.Intn(len(paths))
|
||||||
_ = cw.reload(paths[rnd]) // update can fail and this is expected
|
_ = cw.reload(paths[rnd]) // update can fail and this is expected
|
||||||
_ = cw.notifiers()
|
_ = cw.notifiers()
|
||||||
}
|
}
|
||||||
}()
|
}(i)
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,12 +27,13 @@ func TestClient_Push(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create client: %s", err)
|
t.Fatalf("failed to create client: %s", err)
|
||||||
}
|
}
|
||||||
|
r := rand.New(rand.NewSource(1))
|
||||||
const rowsN = 1e4
|
const rowsN = 1e4
|
||||||
var sent int
|
var sent int
|
||||||
for i := 0; i < rowsN; i++ {
|
for i := 0; i < rowsN; i++ {
|
||||||
s := prompbmarshal.TimeSeries{
|
s := prompbmarshal.TimeSeries{
|
||||||
Samples: []prompbmarshal.Sample{{
|
Samples: []prompbmarshal.Sample{{
|
||||||
Value: rand.Float64(),
|
Value: r.Float64(),
|
||||||
Timestamp: time.Now().Unix(),
|
Timestamp: time.Now().Unix(),
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
|
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/app/vminsert/common"
|
"github.com/VictoriaMetrics/VictoriaMetrics/app/vminsert/common"
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/app/vminsert/relabel"
|
"github.com/VictoriaMetrics/VictoriaMetrics/app/vminsert/relabel"
|
||||||
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
|
||||||
parserCommon "github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/common"
|
parserCommon "github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/common"
|
||||||
parser "github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/prometheus"
|
parser "github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/prometheus"
|
||||||
|
@ -29,7 +30,9 @@ func InsertHandler(req *http.Request) error {
|
||||||
isGzipped := req.Header.Get("Content-Encoding") == "gzip"
|
isGzipped := req.Header.Get("Content-Encoding") == "gzip"
|
||||||
return parser.ParseStream(req.Body, defaultTimestamp, isGzipped, func(rows []parser.Row) error {
|
return parser.ParseStream(req.Body, defaultTimestamp, isGzipped, func(rows []parser.Row) error {
|
||||||
return insertRows(rows, extraLabels)
|
return insertRows(rows, extraLabels)
|
||||||
}, nil)
|
}, func(s string) {
|
||||||
|
httpserver.LogError(req, s)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func insertRows(rows []parser.Row, extraLabels []prompbmarshal.Label) error {
|
func insertRows(rows []parser.Row, extraLabels []prompbmarshal.Label) error {
|
||||||
|
|
|
@ -35,9 +35,10 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
var benchValues = func() []float64 {
|
var benchValues = func() []float64 {
|
||||||
|
r := rand.New(rand.NewSource(1))
|
||||||
values := make([]float64, 1000)
|
values := make([]float64, 1000)
|
||||||
for i := range values {
|
for i := range values {
|
||||||
values[i] = rand.Float64() * 100
|
values[i] = r.Float64() * 100
|
||||||
}
|
}
|
||||||
return values
|
return values
|
||||||
}()
|
}()
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
{
|
{
|
||||||
"files": {
|
"files": {
|
||||||
"main.css": "./static/css/main.e8e53cbf.css",
|
"main.css": "./static/css/main.9ca6b743.css",
|
||||||
"main.js": "./static/js/main.58fe7908.js",
|
"main.js": "./static/js/main.8969be5f.js",
|
||||||
"static/js/27.c1ccfd29.chunk.js": "./static/js/27.c1ccfd29.chunk.js",
|
"static/js/27.c1ccfd29.chunk.js": "./static/js/27.c1ccfd29.chunk.js",
|
||||||
|
"static/media/Lato-Regular.ttf": "./static/media/Lato-Regular.d714fec1633b69a9c2e9.ttf",
|
||||||
|
"static/media/Lato-Bold.ttf": "./static/media/Lato-Bold.32360ba4b57802daa4d6.ttf",
|
||||||
"index.html": "./index.html"
|
"index.html": "./index.html"
|
||||||
},
|
},
|
||||||
"entrypoints": [
|
"entrypoints": [
|
||||||
"static/css/main.e8e53cbf.css",
|
"static/css/main.9ca6b743.css",
|
||||||
"static/js/main.58fe7908.js"
|
"static/js/main.8969be5f.js"
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -1 +1 @@
|
||||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="./favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="VM-UI is a metric explorer for Victoria Metrics"/><link rel="apple-touch-icon" href="./apple-touch-icon.png"/><link rel="icon" type="image/png" sizes="32x32" href="./favicon-32x32.png"><link rel="manifest" href="./manifest.json"/><title>VM UI</title><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono&family=Lato:wght@300;400;700&display=swap" rel="stylesheet"><script src="./dashboards/index.js" type="module"></script><script defer="defer" src="./static/js/main.58fe7908.js"></script><link href="./static/css/main.e8e53cbf.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="./favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="UI for VictoriaMetrics"/><link rel="apple-touch-icon" href="./apple-touch-icon.png"/><link rel="icon" type="image/png" sizes="32x32" href="./favicon-32x32.png"><link rel="manifest" href="./manifest.json"/><title>VM UI</title><script src="./dashboards/index.js" type="module"></script><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="./preview.jpg"><meta name="twitter:title" content="UI for VictoriaMetrics"><meta name="twitter:description" content="Explore and troubleshoot your VictoriaMetrics data"><meta name="twitter:site" content="@VictoriaMetrics"><meta property="og:title" content="Metric explorer for VictoriaMetrics"><meta property="og:description" content="Explore and troubleshoot your VictoriaMetrics data"><meta property="og:image" content="./preview.jpg"><meta property="og:type" content="website"><script defer="defer" src="./static/js/main.8969be5f.js"></script><link href="./static/css/main.9ca6b743.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
BIN
app/vmselect/vmui/preview.jpg
Normal file
BIN
app/vmselect/vmui/preview.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 67 KiB |
1
app/vmselect/vmui/static/css/main.9ca6b743.css
Normal file
1
app/vmselect/vmui/static/css/main.9ca6b743.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
app/vmselect/vmui/static/js/main.8969be5f.js
Normal file
2
app/vmselect/vmui/static/js/main.8969be5f.js
Normal file
File diff suppressed because one or more lines are too long
|
@ -7,7 +7,7 @@
|
||||||
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @remix-run/router v1.0.5
|
* @remix-run/router v1.3.0
|
||||||
*
|
*
|
||||||
* Copyright (c) Remix Software Inc.
|
* Copyright (c) Remix Software Inc.
|
||||||
*
|
*
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* React Router DOM v6.4.5
|
* React Router DOM v6.7.0
|
||||||
*
|
*
|
||||||
* Copyright (c) Remix Software Inc.
|
* Copyright (c) Remix Software Inc.
|
||||||
*
|
*
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* React Router v6.4.5
|
* React Router v6.7.0
|
||||||
*
|
*
|
||||||
* Copyright (c) Remix Software Inc.
|
* Copyright (c) Remix Software Inc.
|
||||||
*
|
*
|
Binary file not shown.
Binary file not shown.
|
@ -85,14 +85,6 @@ func CheckTimeRange(tr storage.TimeRange) error {
|
||||||
|
|
||||||
// Init initializes vmstorage.
|
// Init initializes vmstorage.
|
||||||
func Init(resetCacheIfNeeded func(mrs []storage.MetricRow)) {
|
func Init(resetCacheIfNeeded func(mrs []storage.MetricRow)) {
|
||||||
InitWithoutMetrics(resetCacheIfNeeded)
|
|
||||||
registerStorageMetrics(Storage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InitWithoutMetrics must be called instead of Init inside tests.
|
|
||||||
//
|
|
||||||
// This allows multiple Init / Stop cycles.
|
|
||||||
func InitWithoutMetrics(resetCacheIfNeeded func(mrs []storage.MetricRow)) {
|
|
||||||
if err := encoding.CheckPrecisionBits(uint8(*precisionBits)); err != nil {
|
if err := encoding.CheckPrecisionBits(uint8(*precisionBits)); err != nil {
|
||||||
logger.Fatalf("invalid `-precisionBits`: %s", err)
|
logger.Fatalf("invalid `-precisionBits`: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -131,6 +123,7 @@ func InitWithoutMetrics(resetCacheIfNeeded func(mrs []storage.MetricRow)) {
|
||||||
sizeBytes := tm.SmallSizeBytes + tm.BigSizeBytes
|
sizeBytes := tm.SmallSizeBytes + tm.BigSizeBytes
|
||||||
logger.Infof("successfully opened storage %q in %.3f seconds; partsCount: %d; blocksCount: %d; rowsCount: %d; sizeBytes: %d",
|
logger.Infof("successfully opened storage %q in %.3f seconds; partsCount: %d; blocksCount: %d; rowsCount: %d; sizeBytes: %d",
|
||||||
*DataPath, time.Since(startTime).Seconds(), partsCount, blocksCount, rowsCount, sizeBytes)
|
*DataPath, time.Since(startTime).Seconds(), partsCount, blocksCount, rowsCount, sizeBytes)
|
||||||
|
registerStorageMetrics(Storage)
|
||||||
|
|
||||||
promdb.Init(retentionPeriod.Msecs)
|
promdb.Init(retentionPeriod.Msecs)
|
||||||
}
|
}
|
||||||
|
|
1246
app/vmui/packages/vmui/package-lock.json
generated
1246
app/vmui/packages/vmui/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -7,7 +7,7 @@
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
<meta
|
<meta
|
||||||
name="description"
|
name="description"
|
||||||
content="VM-UI is a metric explorer for Victoria Metrics"
|
content="UI for VictoriaMetrics"
|
||||||
/>
|
/>
|
||||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/apple-touch-icon.png" />
|
<link rel="apple-touch-icon" href="%PUBLIC_URL%/apple-touch-icon.png" />
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="%PUBLIC_URL%/favicon-32x32.png">
|
<link rel="icon" type="image/png" sizes="32x32" href="%PUBLIC_URL%/favicon-32x32.png">
|
||||||
|
@ -26,10 +26,18 @@
|
||||||
Learn how to configure a non-root public URL by running `npm run build`.
|
Learn how to configure a non-root public URL by running `npm run build`.
|
||||||
-->
|
-->
|
||||||
<title>VM UI</title>
|
<title>VM UI</title>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono&family=Lato:wght@300;400;700&display=swap" rel="stylesheet">
|
|
||||||
<script src="%PUBLIC_URL%/dashboards/index.js" type="module"></script>
|
<script src="%PUBLIC_URL%/dashboards/index.js" type="module"></script>
|
||||||
|
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<meta name="twitter:image" content="%PUBLIC_URL%/preview.jpg">
|
||||||
|
<meta name="twitter:title" content="UI for VictoriaMetrics">
|
||||||
|
<meta name="twitter:description" content="Explore and troubleshoot your VictoriaMetrics data">
|
||||||
|
<meta name="twitter:site" content="@VictoriaMetrics">
|
||||||
|
|
||||||
|
<meta property="og:title" content="Metric explorer for VictoriaMetrics">
|
||||||
|
<meta property="og:description" content="Explore and troubleshoot your VictoriaMetrics data">
|
||||||
|
<meta property="og:image" content="%PUBLIC_URL%/preview.jpg">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
|
BIN
app/vmui/packages/vmui/public/preview.jpg
Normal file
BIN
app/vmui/packages/vmui/public/preview.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 67 KiB |
|
@ -17,15 +17,11 @@ const App: FC = () => {
|
||||||
|
|
||||||
const [loadingTheme, setLoadingTheme] = useState(true);
|
const [loadingTheme, setLoadingTheme] = useState(true);
|
||||||
|
|
||||||
if (loadingTheme) return (
|
|
||||||
<>
|
|
||||||
<Spinner/>
|
|
||||||
<ThemeProvider setLoadingTheme={setLoadingTheme}/>;
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
<HashRouter>
|
{loadingTheme && <Spinner/>}
|
||||||
|
<ThemeProvider setLoadingTheme={setLoadingTheme}/>
|
||||||
|
|
||||||
|
<HashRouter key={`${loadingTheme}`}>
|
||||||
<AppContextProvider>
|
<AppContextProvider>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route
|
<Route
|
||||||
|
|
BIN
app/vmui/packages/vmui/src/assets/fonts/Lato/Lato-Bold.ttf
Normal file
BIN
app/vmui/packages/vmui/src/assets/fonts/Lato/Lato-Bold.ttf
Normal file
Binary file not shown.
BIN
app/vmui/packages/vmui/src/assets/fonts/Lato/Lato-Regular.ttf
Normal file
BIN
app/vmui/packages/vmui/src/assets/fonts/Lato/Lato-Regular.ttf
Normal file
Binary file not shown.
|
@ -3,11 +3,13 @@ import uPlot, { Options as uPlotOptions } from "uplot";
|
||||||
import useResize from "../../../hooks/useResize";
|
import useResize from "../../../hooks/useResize";
|
||||||
import { BarChartProps } from "./types";
|
import { BarChartProps } from "./types";
|
||||||
import "./style.scss";
|
import "./style.scss";
|
||||||
|
import { useAppState } from "../../../state/common/StateContext";
|
||||||
|
|
||||||
const BarChart: FC<BarChartProps> = ({
|
const BarChart: FC<BarChartProps> = ({
|
||||||
data,
|
data,
|
||||||
container,
|
container,
|
||||||
configs }) => {
|
configs }) => {
|
||||||
|
const { darkTheme } = useAppState();
|
||||||
|
|
||||||
const uPlotRef = useRef<HTMLDivElement>(null);
|
const uPlotRef = useRef<HTMLDivElement>(null);
|
||||||
const [uPlotInst, setUPlotInst] = useState<uPlot>();
|
const [uPlotInst, setUPlotInst] = useState<uPlot>();
|
||||||
|
@ -28,7 +30,7 @@ const BarChart: FC<BarChartProps> = ({
|
||||||
const u = new uPlot(options, data, uPlotRef.current);
|
const u = new uPlot(options, data, uPlotRef.current);
|
||||||
setUPlotInst(u);
|
setUPlotInst(u);
|
||||||
return u.destroy;
|
return u.destroy;
|
||||||
}, [uPlotRef.current, layoutSize]);
|
}, [uPlotRef.current, layoutSize, darkTheme]);
|
||||||
|
|
||||||
useEffect(() => updateChart(), [data]);
|
useEffect(() => updateChart(), [data]);
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,6 @@ $chart-tooltip-y: -1 * ($padding-small + $chart-tooltip-half-icon);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
&_sticky {
|
&_sticky {
|
||||||
background-color: $color-dove-gray;
|
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
z-index: 99;
|
z-index: 99;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import "./style.scss";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import ChartTooltip, { ChartTooltipProps } from "../ChartTooltip/ChartTooltip";
|
import ChartTooltip, { ChartTooltipProps } from "../ChartTooltip/ChartTooltip";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
import { useAppState } from "../../../state/common/StateContext";
|
||||||
|
|
||||||
export interface LineChartProps {
|
export interface LineChartProps {
|
||||||
metrics: MetricResult[];
|
metrics: MetricResult[];
|
||||||
|
@ -47,6 +48,8 @@ const LineChart: FC<LineChartProps> = ({
|
||||||
container,
|
container,
|
||||||
height
|
height
|
||||||
}) => {
|
}) => {
|
||||||
|
const { darkTheme } = useAppState();
|
||||||
|
|
||||||
const uPlotRef = useRef<HTMLDivElement>(null);
|
const uPlotRef = useRef<HTMLDivElement>(null);
|
||||||
const [isPanning, setPanning] = useState(false);
|
const [isPanning, setPanning] = useState(false);
|
||||||
const [xRange, setXRange] = useState({ min: period.start, max: period.end });
|
const [xRange, setXRange] = useState({ min: period.start, max: period.end });
|
||||||
|
@ -222,7 +225,7 @@ const LineChart: FC<LineChartProps> = ({
|
||||||
setUPlotInst(u);
|
setUPlotInst(u);
|
||||||
setXRange({ min: period.start, max: period.end });
|
setXRange({ min: period.start, max: period.end });
|
||||||
return u.destroy;
|
return u.destroy;
|
||||||
}, [uPlotRef.current, series, layoutSize, height]);
|
}, [uPlotRef.current, series, layoutSize, height, darkTheme]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.addEventListener("keydown", handleKeyDown);
|
window.addEventListener("keydown", handleKeyDown);
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { getAppModeEnable } from "../../../utils/app-mode";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import Timezones from "./Timezones/Timezones";
|
import Timezones from "./Timezones/Timezones";
|
||||||
import { useTimeDispatch, useTimeState } from "../../../state/time/TimeStateContext";
|
import { useTimeDispatch, useTimeState } from "../../../state/time/TimeStateContext";
|
||||||
|
import ThemeControl from "../ThemeControl/ThemeControl";
|
||||||
|
|
||||||
const title = "Settings";
|
const title = "Settings";
|
||||||
|
|
||||||
|
@ -82,6 +83,9 @@ const GlobalSettings: FC = () => {
|
||||||
onChange={setTimezone}
|
onChange={setTimezone}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="vm-server-configurator__input">
|
||||||
|
<ThemeControl/>
|
||||||
|
</div>
|
||||||
<div className="vm-server-configurator__footer">
|
<div className="vm-server-configurator__footer">
|
||||||
<Button
|
<Button
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
background-color: rgba($color-black, 0.06);
|
background-color: $color-hover-black;
|
||||||
padding: calc($padding-small/2);
|
padding: calc($padding-small/2);
|
||||||
border-radius: $border-radius-small;
|
border-radius: $border-radius-small;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ const GraphSettings: FC<GraphSettingsProps> = ({ yaxis, setYaxisLimits, toggleEn
|
||||||
</h3>
|
</h3>
|
||||||
<Button
|
<Button
|
||||||
size="small"
|
size="small"
|
||||||
|
variant="text"
|
||||||
startIcon={<CloseIcon/>}
|
startIcon={<CloseIcon/>}
|
||||||
onClick={handleClose}
|
onClick={handleClose}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -158,7 +158,7 @@ const StepConfigurator: FC = () => {
|
||||||
className="vm-link vm-link_colored"
|
className="vm-link vm-link_colored"
|
||||||
href="https://docs.victoriametrics.com/keyConcepts.html#range-query"
|
href="https://docs.victoriametrics.com/keyConcepts.html#range-query"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="help noreferrer"
|
||||||
>
|
>
|
||||||
Read more about Range query
|
Read more about Range query
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
padding: 0.2em 0.4em;
|
padding: 0.2em 0.4em;
|
||||||
margin: 0 0.2em;
|
margin: 0 0.2em;
|
||||||
font-size: 85%;
|
font-size: 85%;
|
||||||
background-color: rgba($color-black, 0.05);
|
background-color: $color-hover-black;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
import React from "react";
|
||||||
|
import "./style.scss";
|
||||||
|
import classNames from "classnames";
|
||||||
|
import { useAppDispatch, useAppState } from "../../../state/common/StateContext";
|
||||||
|
|
||||||
|
const options = [
|
||||||
|
{ title: "Light", value: false },
|
||||||
|
{ title: "Dark", value: true }
|
||||||
|
];
|
||||||
|
|
||||||
|
const ThemeControl = () => {
|
||||||
|
const { darkTheme } = useAppState();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
const createHandlerClickItem = (value: boolean) => () => {
|
||||||
|
dispatch({ type: "SET_DARK_THEME", payload: value });
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="vm-theme-control">
|
||||||
|
<div className="vm-server-configurator__title">
|
||||||
|
Theme preferences
|
||||||
|
</div>
|
||||||
|
<div className="vm-theme-control-options">
|
||||||
|
<div
|
||||||
|
className="vm-theme-control-options__highlight"
|
||||||
|
style={{ left: darkTheme ? "50%" : 0 }}
|
||||||
|
/>
|
||||||
|
{options.map(item => (
|
||||||
|
<div
|
||||||
|
className={classNames({
|
||||||
|
"vm-theme-control-options__item": true,
|
||||||
|
"vm-theme-control-options__item_active": item.value === darkTheme
|
||||||
|
})}
|
||||||
|
onClick={createHandlerClickItem(item.value)}
|
||||||
|
key={item.title}
|
||||||
|
>{item.title}</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ThemeControl;
|
|
@ -0,0 +1,44 @@
|
||||||
|
@use "src/styles/variables" as *;
|
||||||
|
|
||||||
|
.vm-theme-control {
|
||||||
|
&-options {
|
||||||
|
position: relative;
|
||||||
|
display: inline-flex;
|
||||||
|
border: $border-divider;
|
||||||
|
border-radius: $border-radius-medium;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
position: relative;
|
||||||
|
padding: $padding-small $padding-global;
|
||||||
|
border-right: $border-divider;
|
||||||
|
color: $color-text;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 2;
|
||||||
|
transition: color 200ms ease-out;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_active {
|
||||||
|
color: $color-primary-text;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: $box-shadow-popper;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__highlight {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
background-color: $color-primary;
|
||||||
|
height: 100%;
|
||||||
|
width: 50%;
|
||||||
|
transition: left 150ms ease-in;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,11 +13,14 @@ import useResize from "../../../../hooks/useResize";
|
||||||
import DatePicker from "../../../Main/DatePicker/DatePicker";
|
import DatePicker from "../../../Main/DatePicker/DatePicker";
|
||||||
import "./style.scss";
|
import "./style.scss";
|
||||||
import useClickOutside from "../../../../hooks/useClickOutside";
|
import useClickOutside from "../../../../hooks/useClickOutside";
|
||||||
|
import classNames from "classnames";
|
||||||
|
import { useAppState } from "../../../../state/common/StateContext";
|
||||||
|
|
||||||
export const TimeSelector: FC = () => {
|
export const TimeSelector: FC = () => {
|
||||||
|
const { darkTheme } = useAppState();
|
||||||
const wrapperRef = useRef<HTMLDivElement>(null);
|
const wrapperRef = useRef<HTMLDivElement>(null);
|
||||||
const documentSize = useResize(document.body);
|
const documentSize = useResize(document.body);
|
||||||
const displayFullDate = useMemo(() => documentSize.width > 1120, [documentSize]);
|
const displayFullDate = useMemo(() => documentSize.width > 1280, [documentSize]);
|
||||||
|
|
||||||
const [until, setUntil] = useState<string>();
|
const [until, setUntil] = useState<string>();
|
||||||
const [from, setFrom] = useState<string>();
|
const [from, setFrom] = useState<string>();
|
||||||
|
@ -120,7 +123,7 @@ export const TimeSelector: FC = () => {
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
<div ref={buttonRef}>
|
<div ref={buttonRef}>
|
||||||
<Tooltip title="Time range controls">
|
<Tooltip title={displayFullDate ? "Time range controls" : dateTitle}>
|
||||||
<Button
|
<Button
|
||||||
className={appModeEnable ? "" : "vm-header-button"}
|
className={appModeEnable ? "" : "vm-header-button"}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
|
@ -144,7 +147,12 @@ export const TimeSelector: FC = () => {
|
||||||
ref={wrapperRef}
|
ref={wrapperRef}
|
||||||
>
|
>
|
||||||
<div className="vm-time-selector-left">
|
<div className="vm-time-selector-left">
|
||||||
<div className="vm-time-selector-left-inputs">
|
<div
|
||||||
|
className={classNames({
|
||||||
|
"vm-time-selector-left-inputs": true,
|
||||||
|
"vm-time-selector-left-inputs_dark": darkTheme
|
||||||
|
})}
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
className="vm-time-selector-left-inputs__date"
|
className="vm-time-selector-left-inputs__date"
|
||||||
ref={fromRef}
|
ref={fromRef}
|
||||||
|
|
|
@ -18,6 +18,10 @@
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
|
|
||||||
|
&_dark &__date {
|
||||||
|
border-color: $color-text-disabled;
|
||||||
|
}
|
||||||
|
|
||||||
&__date {
|
&__date {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 14px;
|
grid-template-columns: 1fr 14px;
|
||||||
|
@ -70,7 +74,7 @@
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
background-color: rgba($color-black, 0.06);
|
background-color: $color-hover-black;
|
||||||
padding: calc($padding-small/2);
|
padding: calc($padding-small/2);
|
||||||
border-radius: $border-radius-small;
|
border-radius: $border-radius-small;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
code {
|
code {
|
||||||
padding: 0.2em 0.4em;
|
padding: 0.2em 0.4em;
|
||||||
font-size: 85%;
|
font-size: 85%;
|
||||||
background-color: rgba($color-black, 0.05);
|
background-color: $color-hover-black;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { FC } from "preact/compat";
|
import React, { FC } from "preact/compat";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import "./style.scss";
|
import "./style.scss";
|
||||||
import { LogoIcon } from "../../Main/Icons";
|
import { IssueIcon, LogoIcon, WikiIcon } from "../../Main/Icons";
|
||||||
|
|
||||||
const Footer: FC = () => {
|
const Footer: FC = () => {
|
||||||
const copyrightYears = `2019-${dayjs().format("YYYY")}`;
|
const copyrightYears = `2019-${dayjs().format("YYYY")}`;
|
||||||
|
@ -11,18 +11,28 @@ const Footer: FC = () => {
|
||||||
className="vm-link vm-footer__website"
|
className="vm-link vm-footer__website"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
href="https://victoriametrics.com/"
|
href="https://victoriametrics.com/"
|
||||||
rel="noreferrer"
|
rel="me noreferrer"
|
||||||
>
|
>
|
||||||
<LogoIcon/>
|
<LogoIcon/>
|
||||||
victoriametrics.com
|
victoriametrics.com
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
className="vm-link"
|
className="vm-link vm-footer__link"
|
||||||
|
target="_blank"
|
||||||
|
href="https://docs.victoriametrics.com/#vmui"
|
||||||
|
rel="help noreferrer"
|
||||||
|
>
|
||||||
|
<WikiIcon/>
|
||||||
|
Documentation
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
className="vm-link vm-footer__link"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
href="https://github.com/VictoriaMetrics/VictoriaMetrics/issues/new/choose"
|
href="https://github.com/VictoriaMetrics/VictoriaMetrics/issues/new/choose"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
create an issue
|
<IssueIcon/>
|
||||||
|
Create an issue
|
||||||
</a>
|
</a>
|
||||||
<div className="vm-footer__copyright">
|
<div className="vm-footer__copyright">
|
||||||
© {copyrightYears} VictoriaMetrics
|
© {copyrightYears} VictoriaMetrics
|
||||||
|
|
|
@ -5,10 +5,12 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: $padding-medium;
|
padding: $padding-medium;
|
||||||
gap: $padding-large;
|
gap: $padding-medium;
|
||||||
border-top: $border-divider;
|
border-top: $border-divider;
|
||||||
color: $color-text-secondary;
|
color: $color-text-secondary;
|
||||||
|
background: $color-background-body;
|
||||||
|
|
||||||
|
&__link,
|
||||||
&__website {
|
&__website {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 12px auto;
|
grid-template-columns: 12px auto;
|
||||||
|
@ -17,6 +19,14 @@
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__website {
|
||||||
|
margin-right: $padding-global;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__link {
|
||||||
|
grid-template-columns: 14px auto;
|
||||||
|
}
|
||||||
|
|
||||||
&__copyright {
|
&__copyright {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
|
|
@ -1,86 +1,58 @@
|
||||||
import React, { FC, useMemo, useState } from "preact/compat";
|
import React, { FC, useMemo } from "preact/compat";
|
||||||
import { ExecutionControls } from "../../Configurators/TimeRangeSettings/ExecutionControls/ExecutionControls";
|
import { ExecutionControls } from "../../Configurators/TimeRangeSettings/ExecutionControls/ExecutionControls";
|
||||||
import { setQueryStringWithoutPageReload } from "../../../utils/query-string";
|
import { setQueryStringWithoutPageReload } from "../../../utils/query-string";
|
||||||
import { TimeSelector } from "../../Configurators/TimeRangeSettings/TimeSelector/TimeSelector";
|
import { TimeSelector } from "../../Configurators/TimeRangeSettings/TimeSelector/TimeSelector";
|
||||||
import GlobalSettings from "../../Configurators/GlobalSettings/GlobalSettings";
|
import GlobalSettings from "../../Configurators/GlobalSettings/GlobalSettings";
|
||||||
import { useLocation, useNavigate } from "react-router-dom";
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
import router, { RouterOptions, routerOptions } from "../../../router";
|
import router, { RouterOptions, routerOptions } from "../../../router";
|
||||||
import { useEffect } from "react";
|
|
||||||
import ShortcutKeys from "../../Main/ShortcutKeys/ShortcutKeys";
|
import ShortcutKeys from "../../Main/ShortcutKeys/ShortcutKeys";
|
||||||
import { getAppModeEnable, getAppModeParams } from "../../../utils/app-mode";
|
import { getAppModeEnable, getAppModeParams } from "../../../utils/app-mode";
|
||||||
import CardinalityDatePicker from "../../Configurators/CardinalityDatePicker/CardinalityDatePicker";
|
import CardinalityDatePicker from "../../Configurators/CardinalityDatePicker/CardinalityDatePicker";
|
||||||
import { LogoFullIcon } from "../../Main/Icons";
|
import { LogoFullIcon } from "../../Main/Icons";
|
||||||
import { getCssVariable } from "../../../utils/theme";
|
import { getCssVariable } from "../../../utils/theme";
|
||||||
import Tabs from "../../Main/Tabs/Tabs";
|
|
||||||
import "./style.scss";
|
import "./style.scss";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { useDashboardsState } from "../../../state/dashboards/DashboardsStateContext";
|
|
||||||
import StepConfigurator from "../../Configurators/StepConfigurator/StepConfigurator";
|
import StepConfigurator from "../../Configurators/StepConfigurator/StepConfigurator";
|
||||||
|
import { useAppState } from "../../../state/common/StateContext";
|
||||||
|
import HeaderNav from "./HeaderNav/HeaderNav";
|
||||||
|
|
||||||
const Header: FC = () => {
|
const Header: FC = () => {
|
||||||
const primaryColor = getCssVariable("color-primary");
|
const { darkTheme } = useAppState();
|
||||||
const appModeEnable = getAppModeEnable();
|
const appModeEnable = getAppModeEnable();
|
||||||
const { dashboardsSettings } = useDashboardsState();
|
|
||||||
|
|
||||||
const { headerStyles: {
|
const primaryColor = useMemo(() => {
|
||||||
background = appModeEnable ? "#FFF" : primaryColor,
|
const variable = darkTheme ? "color-background-block" : "color-primary";
|
||||||
color = appModeEnable ? primaryColor : "#FFF",
|
return getCssVariable(variable);
|
||||||
} = {} } = getAppModeParams();
|
}, [darkTheme]);
|
||||||
|
|
||||||
|
const { background, color } = useMemo(() => {
|
||||||
|
const { headerStyles: {
|
||||||
|
background = appModeEnable ? "#FFF" : primaryColor,
|
||||||
|
color = appModeEnable ? primaryColor : "#FFF",
|
||||||
|
} = {} } = getAppModeParams();
|
||||||
|
|
||||||
|
return { background, color };
|
||||||
|
}, [primaryColor]);
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { search, pathname } = useLocation();
|
const { search, pathname } = useLocation();
|
||||||
const routes = useMemo(() => ([
|
|
||||||
{
|
|
||||||
label: routerOptions[router.home].title,
|
|
||||||
value: router.home,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: routerOptions[router.metrics].title,
|
|
||||||
value: router.metrics,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: routerOptions[router.cardinality].title,
|
|
||||||
value: router.cardinality,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: routerOptions[router.topQueries].title,
|
|
||||||
value: router.topQueries,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: routerOptions[router.trace].title,
|
|
||||||
value: router.trace,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: routerOptions[router.dashboards].title,
|
|
||||||
value: router.dashboards,
|
|
||||||
hide: appModeEnable || !dashboardsSettings.length
|
|
||||||
}
|
|
||||||
]), [appModeEnable, dashboardsSettings]);
|
|
||||||
|
|
||||||
const [activeMenu, setActiveMenu] = useState(pathname);
|
|
||||||
|
|
||||||
const headerSetup = useMemo(() => {
|
const headerSetup = useMemo(() => {
|
||||||
return ((routerOptions[pathname] || {}) as RouterOptions).header || {};
|
return ((routerOptions[pathname] || {}) as RouterOptions).header || {};
|
||||||
}, [pathname]);
|
}, [pathname]);
|
||||||
|
|
||||||
const onClickLogo = () => {
|
const onClickLogo = () => {
|
||||||
navigateHandler(router.home);
|
navigate({ pathname: router.home, search: search });
|
||||||
setQueryStringWithoutPageReload({});
|
setQueryStringWithoutPageReload({});
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
};
|
};
|
||||||
|
|
||||||
const navigateHandler = (pathname: string) => {
|
|
||||||
navigate({ pathname, search: search });
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setActiveMenu(pathname);
|
|
||||||
}, [pathname]);
|
|
||||||
|
|
||||||
return <header
|
return <header
|
||||||
className={classNames({
|
className={classNames({
|
||||||
"vm-header": true,
|
"vm-header": true,
|
||||||
"vm-header_app": appModeEnable
|
"vm-header_app": appModeEnable,
|
||||||
|
"vm-header_dark": darkTheme
|
||||||
})}
|
})}
|
||||||
style={{ background, color }}
|
style={{ background, color }}
|
||||||
>
|
>
|
||||||
|
@ -93,14 +65,10 @@ const Header: FC = () => {
|
||||||
<LogoFullIcon/>
|
<LogoFullIcon/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="vm-header-nav">
|
<HeaderNav
|
||||||
<Tabs
|
color={color}
|
||||||
isNavLink
|
background={background}
|
||||||
activeItem={activeMenu}
|
/>
|
||||||
items={routes.filter(r => !r.hide)}
|
|
||||||
color={color}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="vm-header__settings">
|
<div className="vm-header__settings">
|
||||||
{headerSetup?.stepControl && <StepConfigurator/>}
|
{headerSetup?.stepControl && <StepConfigurator/>}
|
||||||
{headerSetup?.timeSelector && <TimeSelector/>}
|
{headerSetup?.timeSelector && <TimeSelector/>}
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
import React, { FC, useMemo, useState } from "preact/compat";
|
||||||
|
import router, { routerOptions } from "../../../../router";
|
||||||
|
import { getAppModeEnable } from "../../../../utils/app-mode";
|
||||||
|
import { useLocation } from "react-router-dom";
|
||||||
|
import { useDashboardsState } from "../../../../state/dashboards/DashboardsStateContext";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import "./style.scss";
|
||||||
|
import NavItem from "./NavItem";
|
||||||
|
import NavSubItem from "./NavSubItem";
|
||||||
|
|
||||||
|
interface HeaderNavProps {
|
||||||
|
color: string
|
||||||
|
background: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const HeaderNav: FC<HeaderNavProps> = ({ color, background }) => {
|
||||||
|
const appModeEnable = getAppModeEnable();
|
||||||
|
const { dashboardsSettings } = useDashboardsState();
|
||||||
|
const { pathname } = useLocation();
|
||||||
|
|
||||||
|
const [activeMenu, setActiveMenu] = useState(pathname);
|
||||||
|
|
||||||
|
const menu = useMemo(() => ([
|
||||||
|
{
|
||||||
|
label: routerOptions[router.home].title,
|
||||||
|
value: router.home,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Explore",
|
||||||
|
submenu: [
|
||||||
|
{
|
||||||
|
label: routerOptions[router.metrics].title,
|
||||||
|
value: router.metrics,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: routerOptions[router.cardinality].title,
|
||||||
|
value: router.cardinality,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: routerOptions[router.topQueries].title,
|
||||||
|
value: router.topQueries,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: routerOptions[router.trace].title,
|
||||||
|
value: router.trace,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: routerOptions[router.dashboards].title,
|
||||||
|
value: router.dashboards,
|
||||||
|
hide: appModeEnable || !dashboardsSettings.length,
|
||||||
|
}
|
||||||
|
].filter(r => !r.hide)), [appModeEnable, dashboardsSettings]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setActiveMenu(pathname);
|
||||||
|
}, [pathname]);
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<nav className="vm-header-nav">
|
||||||
|
{menu.map(m => (
|
||||||
|
m.submenu
|
||||||
|
? (
|
||||||
|
<NavSubItem
|
||||||
|
key={m.label}
|
||||||
|
activeMenu={activeMenu}
|
||||||
|
label={m.label || ""}
|
||||||
|
submenu={m.submenu}
|
||||||
|
color={color}
|
||||||
|
background={background}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
: (
|
||||||
|
<NavItem
|
||||||
|
key={m.value}
|
||||||
|
activeMenu={activeMenu}
|
||||||
|
value={m.value}
|
||||||
|
label={m.label || ""}
|
||||||
|
color={color}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default HeaderNav;
|
|
@ -0,0 +1,30 @@
|
||||||
|
import React, { FC } from "preact/compat";
|
||||||
|
import { NavLink } from "react-router-dom";
|
||||||
|
import classNames from "classnames";
|
||||||
|
|
||||||
|
interface NavItemProps {
|
||||||
|
activeMenu: string,
|
||||||
|
label: string,
|
||||||
|
value: string,
|
||||||
|
color?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const NavItem: FC<NavItemProps> = ({
|
||||||
|
activeMenu,
|
||||||
|
label,
|
||||||
|
value,
|
||||||
|
color
|
||||||
|
}) => (
|
||||||
|
<NavLink
|
||||||
|
className={classNames({
|
||||||
|
"vm-header-nav-item": true,
|
||||||
|
"vm-header-nav-item_active": activeMenu === value // || m.submenu?.find(m => m.value === activeMenu)
|
||||||
|
})}
|
||||||
|
style={{ color }}
|
||||||
|
to={value}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</NavLink>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default NavItem;
|
|
@ -0,0 +1,96 @@
|
||||||
|
import React, { FC, useRef, useState } from "preact/compat";
|
||||||
|
import { useLocation } from "react-router-dom";
|
||||||
|
import classNames from "classnames";
|
||||||
|
import { ArrowDropDownIcon } from "../../../Main/Icons";
|
||||||
|
import Popper from "../../../Main/Popper/Popper";
|
||||||
|
import NavItem from "./NavItem";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
|
interface NavItemProps {
|
||||||
|
activeMenu: string,
|
||||||
|
label: string,
|
||||||
|
submenu: {label: string | undefined, value: string}[],
|
||||||
|
color?: string
|
||||||
|
background?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const NavSubItem: FC<NavItemProps> = ({
|
||||||
|
activeMenu,
|
||||||
|
label,
|
||||||
|
color,
|
||||||
|
background,
|
||||||
|
submenu
|
||||||
|
}) => {
|
||||||
|
const { pathname } = useLocation();
|
||||||
|
|
||||||
|
const [openSubmenu, setOpenSubmenu] = useState(false);
|
||||||
|
const [menuTimeout, setMenuTimeout] = useState<NodeJS.Timeout | null>(null);
|
||||||
|
const buttonRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const handleOpenSubmenu = () => {
|
||||||
|
setOpenSubmenu(true);
|
||||||
|
if (menuTimeout) clearTimeout(menuTimeout);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCloseSubmenu = () => {
|
||||||
|
setOpenSubmenu(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMouseLeave = () => {
|
||||||
|
if (menuTimeout) clearTimeout(menuTimeout);
|
||||||
|
const timeout = setTimeout(handleCloseSubmenu, 300);
|
||||||
|
setMenuTimeout(timeout);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMouseEnterPopup = () => {
|
||||||
|
if (menuTimeout) clearTimeout(menuTimeout);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
handleCloseSubmenu();
|
||||||
|
}, [pathname]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={classNames({
|
||||||
|
"vm-header-nav-item": true,
|
||||||
|
"vm-header-nav-item_sub": true,
|
||||||
|
"vm-header-nav-item_open": openSubmenu,
|
||||||
|
"vm-header-nav-item_active": submenu.find(m => m.value === activeMenu)
|
||||||
|
})}
|
||||||
|
style={{ color }}
|
||||||
|
onMouseEnter={handleOpenSubmenu}
|
||||||
|
onMouseLeave={handleMouseLeave}
|
||||||
|
ref={buttonRef}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
<ArrowDropDownIcon/>
|
||||||
|
|
||||||
|
<Popper
|
||||||
|
open={openSubmenu}
|
||||||
|
placement="bottom-left"
|
||||||
|
offset={{ top: 12, left: 0 }}
|
||||||
|
onClose={handleCloseSubmenu}
|
||||||
|
buttonRef={buttonRef}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="vm-header-nav-item-submenu"
|
||||||
|
style={{ background }}
|
||||||
|
onMouseLeave={handleMouseLeave}
|
||||||
|
onMouseEnter={handleMouseEnterPopup}
|
||||||
|
>
|
||||||
|
{submenu.map(sm => (
|
||||||
|
<NavItem
|
||||||
|
key={sm.value}
|
||||||
|
activeMenu={activeMenu}
|
||||||
|
value={sm.value}
|
||||||
|
label={sm.label || ""}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Popper>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default NavSubItem;
|
|
@ -0,0 +1,63 @@
|
||||||
|
@use "src/styles/variables" as *;
|
||||||
|
|
||||||
|
.vm-header-nav {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: $padding-global;
|
||||||
|
font-size: $font-size-small;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
&-item {
|
||||||
|
position: relative;
|
||||||
|
padding: $padding-global $padding-small;
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: opacity 200ms ease-in;
|
||||||
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
&_sub {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 14px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 4px;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_active {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
transition: transform 200ms ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_open {
|
||||||
|
svg {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-submenu {
|
||||||
|
display: grid;
|
||||||
|
white-space: nowrap;
|
||||||
|
padding: $padding-small;
|
||||||
|
color: $color-white;
|
||||||
|
border-radius: 2px;
|
||||||
|
opacity: 1;
|
||||||
|
transform-origin: top center;
|
||||||
|
font-size: $font-size-small;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
&-item {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,17 +6,18 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
padding: $padding-small $padding-medium;
|
padding: $padding-small $padding-medium;
|
||||||
gap: $padding-large;
|
gap: 0 $padding-large;
|
||||||
|
z-index: 99;
|
||||||
|
|
||||||
&_app {
|
&_app {
|
||||||
padding: $padding-small 0;
|
padding: $padding-small 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1200px) {
|
&_dark {
|
||||||
gap: $padding-global;
|
.vm-header-button,
|
||||||
|
button:before,
|
||||||
.vm-tabs {
|
button {
|
||||||
gap: 0;
|
background-color: $color-background-block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +46,7 @@
|
||||||
|
|
||||||
&-nav {
|
&-nav {
|
||||||
font-size: $font-size-small;
|
font-size: $font-size-small;
|
||||||
font-weight: 600;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__settings {
|
&__settings {
|
||||||
|
|
|
@ -14,7 +14,7 @@ const Layout: FC = () => {
|
||||||
|
|
||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const defaultTitle = "VM UI";
|
const defaultTitle = "vmui";
|
||||||
const routeTitle = routerOptions[pathname]?.title;
|
const routeTitle = routerOptions[pathname]?.title;
|
||||||
document.title = routeTitle ? `${routeTitle} - ${defaultTitle}` : defaultTitle;
|
document.title = routeTitle ? `${routeTitle} - ${defaultTitle}` : defaultTitle;
|
||||||
}, [pathname]);
|
}, [pathname]);
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { ReactNode } from "react";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { ErrorIcon, InfoIcon, SuccessIcon, WarningIcon } from "../Icons";
|
import { ErrorIcon, InfoIcon, SuccessIcon, WarningIcon } from "../Icons";
|
||||||
import "./style.scss";
|
import "./style.scss";
|
||||||
|
import { useAppState } from "../../../state/common/StateContext";
|
||||||
|
|
||||||
interface AlertProps {
|
interface AlertProps {
|
||||||
variant?: "success" | "error" | "info" | "warning"
|
variant?: "success" | "error" | "info" | "warning"
|
||||||
|
@ -19,12 +20,14 @@ const icons = {
|
||||||
const Alert: FC<AlertProps> = ({
|
const Alert: FC<AlertProps> = ({
|
||||||
variant,
|
variant,
|
||||||
children }) => {
|
children }) => {
|
||||||
|
const { darkTheme } = useAppState();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classNames({
|
className={classNames({
|
||||||
"vm-alert": true,
|
"vm-alert": true,
|
||||||
[`vm-alert_${variant}`]: variant
|
[`vm-alert_${variant}`]: variant,
|
||||||
|
"vm-alert_dark": darkTheme
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<div className="vm-alert__icon">{icons[variant || "info"]}</div>
|
<div className="vm-alert__icon">{icons[variant || "info"]}</div>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
border-radius: $border-radius-medium;
|
border-radius: $border-radius-medium;
|
||||||
box-shadow: $box-shadow;
|
box-shadow: $box-shadow;
|
||||||
font-size: $font-size-medium;
|
font-size: $font-size-medium;
|
||||||
font-weight: 500;
|
font-weight: normal;
|
||||||
color: $color-text;
|
color: $color-text;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
|
|
||||||
|
@ -75,4 +75,14 @@
|
||||||
background-color: $color-warning;
|
background-color: $color-warning;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&_dark {
|
||||||
|
&:after {
|
||||||
|
opacity: 0.1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&_dark &__content {
|
||||||
|
filter: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ $button-radius: 6px;
|
||||||
padding: 6px 14px;
|
padding: 6px 14px;
|
||||||
font-size: $font-size-small;
|
font-size: $font-size-small;
|
||||||
line-height: 15px;
|
line-height: 15px;
|
||||||
font-weight: 500;
|
font-weight: normal;
|
||||||
min-height: 31px;
|
min-height: 31px;
|
||||||
border-radius: $button-radius;
|
border-radius: $button-radius;
|
||||||
color: $color-white;
|
color: $color-white;
|
||||||
|
@ -21,7 +21,7 @@ $button-radius: 6px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
&:hover:after {
|
&:hover:after {
|
||||||
background-color: rgba($color-black, 0.05);
|
background-color: $color-hover-black;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:before,
|
&:before,
|
||||||
|
|
|
@ -104,7 +104,7 @@
|
||||||
transition: color 200ms ease, background-color 300ms ease-in-out;
|
transition: color 200ms ease, background-color 300ms ease-in-out;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: rgba($color-black, 0.05);
|
background-color: $color-hover-black;
|
||||||
}
|
}
|
||||||
|
|
||||||
&_empty {
|
&_empty {
|
||||||
|
@ -144,7 +144,7 @@
|
||||||
transition: color 200ms ease, background-color 300ms ease-in-out;
|
transition: color 200ms ease, background-color 300ms ease-in-out;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: rgba($color-black, 0.05);
|
background-color: $color-hover-black;
|
||||||
}
|
}
|
||||||
|
|
||||||
&_selected {
|
&_selected {
|
||||||
|
@ -270,6 +270,10 @@
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-top: $padding-global;
|
margin-top: $padding-global;
|
||||||
|
|
||||||
|
&_dark &__input {
|
||||||
|
border-color: $color-text-disabled;
|
||||||
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
margin: 0 $padding-small;
|
margin: 0 $padding-small;
|
||||||
}
|
}
|
||||||
|
@ -277,11 +281,13 @@
|
||||||
&__input {
|
&__input {
|
||||||
width: 64px;
|
width: 64px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
border: 1px solid $color-alto;
|
border: $border-divider;
|
||||||
border-radius: $border-radius-small;
|
border-radius: $border-radius-small;
|
||||||
font-size: $font-size-medium;
|
font-size: $font-size-medium;
|
||||||
padding: 2px $padding-small;
|
padding: 2px $padding-small;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
background-color: transparent;
|
||||||
|
color: $color-text;
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
border-color: $color-primary;
|
border-color: $color-primary;
|
||||||
|
|
|
@ -2,6 +2,7 @@ import React, { FC, useEffect, useMemo, useRef, useState } from "preact/compat";
|
||||||
import { Dayjs } from "dayjs";
|
import { Dayjs } from "dayjs";
|
||||||
import { FormEvent, FocusEvent } from "react";
|
import { FormEvent, FocusEvent } from "react";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
import { useAppState } from "../../../../state/common/StateContext";
|
||||||
|
|
||||||
interface CalendarTimepickerProps {
|
interface CalendarTimepickerProps {
|
||||||
selectDate: Dayjs
|
selectDate: Dayjs
|
||||||
|
@ -13,6 +14,7 @@ enum TimeUnits { hour, minutes, seconds }
|
||||||
|
|
||||||
|
|
||||||
const TimePicker: FC<CalendarTimepickerProps>= ({ selectDate, onChangeTime, onClose }) => {
|
const TimePicker: FC<CalendarTimepickerProps>= ({ selectDate, onChangeTime, onClose }) => {
|
||||||
|
const { darkTheme } = useAppState();
|
||||||
|
|
||||||
const [activeField, setActiveField] = useState<TimeUnits>(TimeUnits.hour);
|
const [activeField, setActiveField] = useState<TimeUnits>(TimeUnits.hour);
|
||||||
const [hours, setHours] = useState(selectDate.format("HH"));
|
const [hours, setHours] = useState(selectDate.format("HH"));
|
||||||
|
@ -154,7 +156,12 @@ const TimePicker: FC<CalendarTimepickerProps>= ({ selectDate, onChangeTime, onCl
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className="vm-calendar-time-picker-fields">
|
<div
|
||||||
|
className={classNames({
|
||||||
|
"vm-calendar-time-picker-fields": true,
|
||||||
|
"vm-calendar-time-picker-fields_dark": darkTheme
|
||||||
|
})}
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
className="vm-calendar-time-picker-fields__input"
|
className="vm-calendar-time-picker-fields__input"
|
||||||
value={hours}
|
value={hours}
|
||||||
|
|
|
@ -344,3 +344,48 @@ export const TimelineIcon = () => (
|
||||||
></path>
|
></path>
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const WikiIcon = () => (
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M21 5C19.89 4.65 18.67 4.5 17.5 4.5C15.55 4.5 13.45 4.9 12 6C10.55 4.9 8.45 4.5 6.5 4.5C5.33 4.5 4.11 4.65 3 5C2.25 5.25 1.6 5.55 1 6V20.6C1 20.85 1.25 21.1 1.5 21.1C1.6 21.1 1.65 21.1 1.75 21.05C3.15 20.3 4.85 20 6.5 20C8.2 20 10.65 20.65 12 21.5C13.35 20.65 15.8 20 17.5 20C19.15 20 20.85 20.3 22.25 21.05C22.35 21.1 22.4 21.1 22.5 21.1C22.75 21.1 23 20.85 23 20.6V6C22.4 5.55 21.75 5.25 21 5ZM21 18.5C19.9 18.15 18.7 18 17.5 18C15.8 18 13.35 18.65 12 19.5C10.65 18.65 8.2 18 6.5 18C5.3 18 4.1 18.15 3 18.5V7C4.1 6.65 5.3 6.5 6.5 6.5C8.2 6.5 10.65 7.15 12 8C13.35 7.15 15.8 6.5 17.5 6.5C18.7 6.5 19.9 6.65 21 7V18.5Z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M17.5 10.5C18.38 10.5 19.23 10.59 20 10.76V9.24C19.21 9.09 18.36 9 17.5 9C15.8 9 14.26 9.29 13 9.83V11.49C14.13 10.85 15.7 10.5 17.5 10.5ZM13 12.49V14.15C14.13 13.51 15.7 13.16 17.5 13.16C18.38 13.16 19.23 13.25 20 13.42V11.9C19.21 11.75 18.36 11.66 17.5 11.66C15.8 11.66 14.26 11.96 13 12.49ZM17.5 14.33C15.8 14.33 14.26 14.62 13 15.16V16.82C14.13 16.18 15.7 15.83 17.5 15.83C18.38 15.83 19.23 15.92 20 16.09V14.57C19.21 14.41 18.36 14.33 17.5 14.33Z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M6.5 10.5C5.62 10.5 4.77 10.59 4 10.76V9.24C4.79 9.09 5.64 9 6.5 9C8.2 9 9.74 9.29 11 9.83V11.49C9.87 10.85 8.3 10.5 6.5 10.5ZM11 12.49V14.15C9.87 13.51 8.3 13.16 6.5 13.16C5.62 13.16 4.77 13.25 4 13.42V11.9C4.79 11.75 5.64 11.66 6.5 11.66C8.2 11.66 9.74 11.96 11 12.49ZM6.5 14.33C8.2 14.33 9.74 14.62 11 15.16V16.82C9.87 16.18 8.3 15.83 6.5 15.83C5.62 15.83 4.77 15.92 4 16.09V14.57C4.79 14.41 5.64 14.33 6.5 14.33Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
export const IssueIcon = () => (
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M12 2C6.49 2 2 6.49 2 12s4.49 10 10 10 10-4.49 10-10S17.51 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm3-8c0 1.66-1.34 3-3 3s-3-1.34-3-3 1.34-3 3-3 3 1.34 3 3z"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const QuestionIcon = () => (
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M12 2C6.48 2 2 6.48 2 12C2 17.52 6.48 22 12 22C17.52 22 22 17.52 22 12C22 6.48 17.52 2 12 2ZM12 6C9.79 6 8 7.79 8 10H10C10 8.9 10.9 8 12 8C13.1 8 14 8.9 14 10C14 10.8792 13.4202 11.3236 12.7704 11.8217C11.9421 12.4566 11 13.1787 11 15H13C13 13.9046 13.711 13.2833 14.4408 12.6455C15.21 11.9733 16 11.2829 16 10C16 7.79 14.21 6 12 6ZM13 16V18H11V16H13Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
);
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
&-track {
|
&-track {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
background-color: rgba($color-black, 0.05);
|
background-color: $color-hover-black;
|
||||||
border-radius: $border-radius-small;
|
border-radius: $border-radius-small;
|
||||||
|
|
||||||
&__thumb {
|
&__thumb {
|
||||||
|
|
|
@ -8,7 +8,7 @@ $padding-modal: 22px;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
z-index: 100;
|
z-index: 999;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -16,9 +16,11 @@ $padding-modal: 22px;
|
||||||
|
|
||||||
&-content {
|
&-content {
|
||||||
padding: $padding-modal;
|
padding: $padding-modal;
|
||||||
background: $color-white;
|
background: $color-background-block;
|
||||||
box-shadow: 0 0 24px rgba($color-black, 0.07);
|
box-shadow: 0 0 24px rgba($color-black, 0.07);
|
||||||
border-radius: $border-radius-small;
|
border-radius: $border-radius-small;
|
||||||
|
max-height: 90vh;
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
&-header {
|
&-header {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|
|
@ -3,6 +3,7 @@ import classNames from "classnames";
|
||||||
import { ArrowDropDownIcon, CloseIcon } from "../Icons";
|
import { ArrowDropDownIcon, CloseIcon } from "../Icons";
|
||||||
import { FormEvent, MouseEvent } from "react";
|
import { FormEvent, MouseEvent } from "react";
|
||||||
import Autocomplete from "../Autocomplete/Autocomplete";
|
import Autocomplete from "../Autocomplete/Autocomplete";
|
||||||
|
import { useAppState } from "../../../state/common/StateContext";
|
||||||
import "./style.scss";
|
import "./style.scss";
|
||||||
|
|
||||||
interface SelectProps {
|
interface SelectProps {
|
||||||
|
@ -26,6 +27,7 @@ const Select: FC<SelectProps> = ({
|
||||||
autofocus,
|
autofocus,
|
||||||
onChange
|
onChange
|
||||||
}) => {
|
}) => {
|
||||||
|
const { darkTheme } = useAppState();
|
||||||
|
|
||||||
const [search, setSearch] = useState("");
|
const [search, setSearch] = useState("");
|
||||||
const autocompleteAnchorEl = useRef<HTMLDivElement>(null);
|
const autocompleteAnchorEl = useRef<HTMLDivElement>(null);
|
||||||
|
@ -106,7 +108,12 @@ const Select: FC<SelectProps> = ({
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="vm-select">
|
<div
|
||||||
|
className={classNames({
|
||||||
|
"vm-select": true,
|
||||||
|
"vm-select_dark": darkTheme
|
||||||
|
})}
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
className="vm-select-input"
|
className="vm-select-input"
|
||||||
onClick={handleToggleList}
|
onClick={handleToggleList}
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
background-color: rgba($color-black, 0.06);
|
background-color: $color-hover-black;
|
||||||
padding: 2px 2px 2px 6px;
|
padding: 2px 2px 2px 6px;
|
||||||
border-radius: $border-radius-small;
|
border-radius: $border-radius-small;
|
||||||
font-size: $font-size;
|
font-size: $font-size;
|
||||||
|
@ -60,6 +60,8 @@
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
background-color: transparent;
|
||||||
|
color: $color-text;
|
||||||
|
|
||||||
&:placeholder-shown {
|
&:placeholder-shown {
|
||||||
width: auto;
|
width: auto;
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
line-height: 2;
|
line-height: 2;
|
||||||
color: $color-text;
|
color: $color-text;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background-color: $color-white;
|
background-color: $color-background-body;
|
||||||
background-repeat: repeat-x;
|
background-repeat: repeat-x;
|
||||||
border: $border-divider;
|
border: $border-divider;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import React, { CSSProperties, FC } from "preact/compat";
|
import React, { CSSProperties, FC } from "preact/compat";
|
||||||
import "./style.scss";
|
import "./style.scss";
|
||||||
|
import classNames from "classnames";
|
||||||
|
import { getFromStorage } from "../../../utils/storage";
|
||||||
|
|
||||||
interface SpinnerProps {
|
interface SpinnerProps {
|
||||||
containerStyles?: CSSProperties;
|
containerStyles?: CSSProperties;
|
||||||
|
@ -8,7 +10,10 @@ interface SpinnerProps {
|
||||||
|
|
||||||
const Spinner: FC<SpinnerProps> = ({ containerStyles = {}, message }) => (
|
const Spinner: FC<SpinnerProps> = ({ containerStyles = {}, message }) => (
|
||||||
<div
|
<div
|
||||||
className="vm-spinner"
|
className={classNames({
|
||||||
|
"vm-spinner": true,
|
||||||
|
"vm-spinner_dark": getFromStorage("DARK_THEME")
|
||||||
|
})}
|
||||||
style={containerStyles && {}}
|
style={containerStyles && {}}
|
||||||
>
|
>
|
||||||
<div className="half-circle-spinner">
|
<div className="half-circle-spinner">
|
||||||
|
|
|
@ -15,6 +15,10 @@
|
||||||
z-index: 99;
|
z-index: 99;
|
||||||
animation: vm-fade 2s cubic-bezier(0.280, 0.840, 0.420, 1.1);
|
animation: vm-fade 2s cubic-bezier(0.280, 0.840, 0.420, 1.1);
|
||||||
|
|
||||||
|
&_dark {
|
||||||
|
background-color: rgba($color-black, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
&__message {
|
&__message {
|
||||||
margin-top: $padding-medium;
|
margin-top: $padding-medium;
|
||||||
white-space: pre-line;
|
white-space: pre-line;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React, { FC, KeyboardEvent, useEffect, useRef, HTMLInputTypeAttribute, ReactNode } from "react";
|
import React, { FC, KeyboardEvent, useEffect, useRef, HTMLInputTypeAttribute, ReactNode } from "react";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { useMemo } from "preact/compat";
|
import { useMemo } from "preact/compat";
|
||||||
|
import { useAppState } from "../../../state/common/StateContext";
|
||||||
import "./style.scss";
|
import "./style.scss";
|
||||||
|
|
||||||
interface TextFieldProps {
|
interface TextFieldProps {
|
||||||
|
@ -38,6 +39,7 @@ const TextField: FC<TextFieldProps> = ({
|
||||||
onFocus,
|
onFocus,
|
||||||
onBlur
|
onBlur
|
||||||
}) => {
|
}) => {
|
||||||
|
const { darkTheme } = useAppState();
|
||||||
|
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||||||
|
@ -81,6 +83,7 @@ const TextField: FC<TextFieldProps> = ({
|
||||||
className={classNames({
|
className={classNames({
|
||||||
"vm-text-field": true,
|
"vm-text-field": true,
|
||||||
"vm-text-field_textarea": type === "textarea",
|
"vm-text-field_textarea": type === "textarea",
|
||||||
|
"vm-text-field_dark": darkTheme
|
||||||
})}
|
})}
|
||||||
data-replicated-value={value}
|
data-replicated-value={value}
|
||||||
>
|
>
|
||||||
|
|
|
@ -67,6 +67,8 @@
|
||||||
min-height: 34px;
|
min-height: 34px;
|
||||||
resize: none;
|
resize: none;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
background-color: transparent;
|
||||||
|
color: $color-text;
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
border: 1px solid $color-primary;
|
border: 1px solid $color-primary;
|
||||||
|
|
|
@ -2,6 +2,8 @@ import { FC, useEffect } from "preact/compat";
|
||||||
import { getContrastColor } from "../../../utils/color";
|
import { getContrastColor } from "../../../utils/color";
|
||||||
import { getCssVariable, setCssVariable } from "../../../utils/theme";
|
import { getCssVariable, setCssVariable } from "../../../utils/theme";
|
||||||
import { AppParams, getAppModeParams } from "../../../utils/app-mode";
|
import { AppParams, getAppModeParams } from "../../../utils/app-mode";
|
||||||
|
import { getFromStorage } from "../../../utils/storage";
|
||||||
|
import { darkPalette, lightPalette } from "../../../constants/palette";
|
||||||
|
|
||||||
interface StyleVariablesProps {
|
interface StyleVariablesProps {
|
||||||
setLoadingTheme: (val: boolean) => void
|
setLoadingTheme: (val: boolean) => void
|
||||||
|
@ -27,13 +29,6 @@ export const ThemeProvider: FC<StyleVariablesProps> = ({ setLoadingTheme }) => {
|
||||||
setCssVariable("scrollbar-height", `${innerHeight - clientHeight}px`);
|
setCssVariable("scrollbar-height", `${innerHeight - clientHeight}px`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const setAppModePalette = () => {
|
|
||||||
colorVariables.forEach(variable => {
|
|
||||||
const colorFromAppMode = palette[variable as keyof AppParams["palette"]];
|
|
||||||
if (colorFromAppMode) setCssVariable(`color-${variable}`, colorFromAppMode);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const setContrastText = () => {
|
const setContrastText = () => {
|
||||||
colorVariables.forEach(variable => {
|
colorVariables.forEach(variable => {
|
||||||
const color = getCssVariable(`color-${variable}`);
|
const color = getCssVariable(`color-${variable}`);
|
||||||
|
@ -42,11 +37,34 @@ export const ThemeProvider: FC<StyleVariablesProps> = ({ setLoadingTheme }) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const setAppModePalette = () => {
|
||||||
|
colorVariables.forEach(variable => {
|
||||||
|
const colorFromAppMode = palette[variable as keyof AppParams["palette"]];
|
||||||
|
if (colorFromAppMode) setCssVariable(`color-${variable}`, colorFromAppMode);
|
||||||
|
});
|
||||||
|
|
||||||
|
setContrastText();
|
||||||
|
};
|
||||||
|
|
||||||
|
const setTheme = () => {
|
||||||
|
const darkTheme = getFromStorage("DARK_THEME");
|
||||||
|
const palette = darkTheme ? darkPalette : lightPalette;
|
||||||
|
Object.entries(palette).forEach(([variable, value]) => {
|
||||||
|
setCssVariable(variable, value);
|
||||||
|
});
|
||||||
|
setContrastText();
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setAppModePalette();
|
setAppModePalette();
|
||||||
setScrollbarSize();
|
setScrollbarSize();
|
||||||
setContrastText();
|
setTheme();
|
||||||
setLoadingTheme(false);
|
setLoadingTheme(false);
|
||||||
|
|
||||||
|
window.addEventListener("storage", setTheme);
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("storage", setTheme);
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -4,6 +4,7 @@ import Trace from "../Trace";
|
||||||
import { ArrowDownIcon } from "../../Main/Icons";
|
import { ArrowDownIcon } from "../../Main/Icons";
|
||||||
import "./style.scss";
|
import "./style.scss";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
import { useAppState } from "../../../state/common/StateContext";
|
||||||
|
|
||||||
interface RecursiveProps {
|
interface RecursiveProps {
|
||||||
trace: Trace;
|
trace: Trace;
|
||||||
|
@ -15,6 +16,7 @@ interface OpenLevels {
|
||||||
}
|
}
|
||||||
|
|
||||||
const NestedNav: FC<RecursiveProps> = ({ trace, totalMsec }) => {
|
const NestedNav: FC<RecursiveProps> = ({ trace, totalMsec }) => {
|
||||||
|
const { darkTheme } = useAppState();
|
||||||
const [openLevels, setOpenLevels] = useState({} as OpenLevels);
|
const [openLevels, setOpenLevels] = useState({} as OpenLevels);
|
||||||
|
|
||||||
const handleListClick = (level: number) => () => {
|
const handleListClick = (level: number) => () => {
|
||||||
|
@ -26,7 +28,12 @@ const NestedNav: FC<RecursiveProps> = ({ trace, totalMsec }) => {
|
||||||
const progress = trace.duration / totalMsec * 100;
|
const progress = trace.duration / totalMsec * 100;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="vm-nested-nav">
|
<div
|
||||||
|
className={classNames({
|
||||||
|
"vm-nested-nav": true,
|
||||||
|
"vm-nested-nav_dark": darkTheme,
|
||||||
|
})}
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
className="vm-nested-nav-header"
|
className="vm-nested-nav-header"
|
||||||
onClick={handleListClick(trace.idValue)}
|
onClick={handleListClick(trace.idValue)}
|
||||||
|
|
|
@ -5,6 +5,10 @@
|
||||||
border-radius: $border-radius-small;
|
border-radius: $border-radius-small;
|
||||||
background-color: rgba($color-tropical-blue, 0.4);
|
background-color: rgba($color-tropical-blue, 0.4);
|
||||||
|
|
||||||
|
&_dark {
|
||||||
|
background-color: rgba($color-black, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
&-header {
|
&-header {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: auto 1fr;
|
grid-template-columns: auto 1fr;
|
||||||
|
@ -15,7 +19,7 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: rgba($color-black, 0.06);
|
background-color: $color-hover-black;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__icon {
|
&__icon {
|
||||||
|
|
|
@ -14,5 +14,6 @@
|
||||||
transform: translateY(-32px);
|
transform: translateY(-32px);
|
||||||
font-size: $font-size;
|
font-size: $font-size;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
37
app/vmui/packages/vmui/src/constants/palette.ts
Normal file
37
app/vmui/packages/vmui/src/constants/palette.ts
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
export const darkPalette = {
|
||||||
|
"color-primary": "#589DF6",
|
||||||
|
"color-secondary": "#316eca",
|
||||||
|
"color-error": "#e5534b",
|
||||||
|
"color-warning": "#c69026",
|
||||||
|
"color-info": "#539bf5",
|
||||||
|
"color-success": "#57ab5a",
|
||||||
|
"color-background-body": "#22272e",
|
||||||
|
"color-background-block": "#2d333b",
|
||||||
|
"color-background-tooltip": "rgba(22, 22, 22, 0.6)",
|
||||||
|
"color-text": "#cdd9e5",
|
||||||
|
"color-text-secondary": "#768390",
|
||||||
|
"color-text-disabled": "#636e7b",
|
||||||
|
"box-shadow": "rgba(0, 0, 0, 0.16) 1px 2px 6px",
|
||||||
|
"box-shadow-popper": "rgba(0, 0, 0, 0.2) 0px 2px 8px 0px",
|
||||||
|
"border-divider": "1px solid rgba(99, 110, 123, 0.5)",
|
||||||
|
"color-hover-black": "rgba(0, 0, 0, 0.12)"
|
||||||
|
};
|
||||||
|
|
||||||
|
export const lightPalette = {
|
||||||
|
"color-primary": "#3F51B5",
|
||||||
|
"color-secondary": "#E91E63",
|
||||||
|
"color-error": "#FD080E",
|
||||||
|
"color-warning": "#FF8308",
|
||||||
|
"color-info": "#03A9F4",
|
||||||
|
"color-success": "#4CAF50",
|
||||||
|
"color-background-body": "#FEFEFF",
|
||||||
|
"color-background-block": "#FFFFFF",
|
||||||
|
"color-background-tooltip": "rgba(97,97,97, 0.92)",
|
||||||
|
"color-text": "#110f0f",
|
||||||
|
"color-text-secondary": "#706F6F",
|
||||||
|
"color-text-disabled": "#A09F9F",
|
||||||
|
"box-shadow": "rgba(0, 0, 0, 0.08) 1px 2px 6px",
|
||||||
|
"box-shadow-popper": "rgba(0, 0, 0, 0.1) 0px 2px 8px 0px",
|
||||||
|
"border-divider": "1px solid rgba(0, 0, 0, 0.15)",
|
||||||
|
"color-hover-black": "rgba(0, 0, 0, 0.06)"
|
||||||
|
};
|
430
app/vmui/packages/vmui/src/constants/timezones.ts
Normal file
430
app/vmui/packages/vmui/src/constants/timezones.ts
Normal file
|
@ -0,0 +1,430 @@
|
||||||
|
export default [
|
||||||
|
"Africa/Abidjan",
|
||||||
|
"Africa/Accra",
|
||||||
|
"Africa/Addis_Ababa",
|
||||||
|
"Africa/Algiers",
|
||||||
|
"Africa/Asmera",
|
||||||
|
"Africa/Bamako",
|
||||||
|
"Africa/Bangui",
|
||||||
|
"Africa/Banjul",
|
||||||
|
"Africa/Bissau",
|
||||||
|
"Africa/Blantyre",
|
||||||
|
"Africa/Brazzaville",
|
||||||
|
"Africa/Bujumbura",
|
||||||
|
"Africa/Cairo",
|
||||||
|
"Africa/Casablanca",
|
||||||
|
"Africa/Ceuta",
|
||||||
|
"Africa/Conakry",
|
||||||
|
"Africa/Dakar",
|
||||||
|
"Africa/Dar_es_Salaam",
|
||||||
|
"Africa/Djibouti",
|
||||||
|
"Africa/Douala",
|
||||||
|
"Africa/El_Aaiun",
|
||||||
|
"Africa/Freetown",
|
||||||
|
"Africa/Gaborone",
|
||||||
|
"Africa/Harare",
|
||||||
|
"Africa/Johannesburg",
|
||||||
|
"Africa/Juba",
|
||||||
|
"Africa/Kampala",
|
||||||
|
"Africa/Khartoum",
|
||||||
|
"Africa/Kigali",
|
||||||
|
"Africa/Kinshasa",
|
||||||
|
"Africa/Lagos",
|
||||||
|
"Africa/Libreville",
|
||||||
|
"Africa/Lome",
|
||||||
|
"Africa/Luanda",
|
||||||
|
"Africa/Lubumbashi",
|
||||||
|
"Africa/Lusaka",
|
||||||
|
"Africa/Malabo",
|
||||||
|
"Africa/Maputo",
|
||||||
|
"Africa/Maseru",
|
||||||
|
"Africa/Mbabane",
|
||||||
|
"Africa/Mogadishu",
|
||||||
|
"Africa/Monrovia",
|
||||||
|
"Africa/Nairobi",
|
||||||
|
"Africa/Ndjamena",
|
||||||
|
"Africa/Niamey",
|
||||||
|
"Africa/Nouakchott",
|
||||||
|
"Africa/Ouagadougou",
|
||||||
|
"Africa/Porto-Novo",
|
||||||
|
"Africa/Sao_Tome",
|
||||||
|
"Africa/Tripoli",
|
||||||
|
"Africa/Tunis",
|
||||||
|
"Africa/Windhoek",
|
||||||
|
"America/Adak",
|
||||||
|
"America/Anchorage",
|
||||||
|
"America/Anguilla",
|
||||||
|
"America/Antigua",
|
||||||
|
"America/Araguaina",
|
||||||
|
"America/Argentina/La_Rioja",
|
||||||
|
"America/Argentina/Rio_Gallegos",
|
||||||
|
"America/Argentina/Salta",
|
||||||
|
"America/Argentina/San_Juan",
|
||||||
|
"America/Argentina/San_Luis",
|
||||||
|
"America/Argentina/Tucuman",
|
||||||
|
"America/Argentina/Ushuaia",
|
||||||
|
"America/Aruba",
|
||||||
|
"America/Asuncion",
|
||||||
|
"America/Bahia",
|
||||||
|
"America/Bahia_Banderas",
|
||||||
|
"America/Barbados",
|
||||||
|
"America/Belem",
|
||||||
|
"America/Belize",
|
||||||
|
"America/Blanc-Sablon",
|
||||||
|
"America/Boa_Vista",
|
||||||
|
"America/Bogota",
|
||||||
|
"America/Boise",
|
||||||
|
"America/Buenos_Aires",
|
||||||
|
"America/Cambridge_Bay",
|
||||||
|
"America/Campo_Grande",
|
||||||
|
"America/Cancun",
|
||||||
|
"America/Caracas",
|
||||||
|
"America/Catamarca",
|
||||||
|
"America/Cayenne",
|
||||||
|
"America/Cayman",
|
||||||
|
"America/Chicago",
|
||||||
|
"America/Chihuahua",
|
||||||
|
"America/Coral_Harbour",
|
||||||
|
"America/Cordoba",
|
||||||
|
"America/Costa_Rica",
|
||||||
|
"America/Creston",
|
||||||
|
"America/Cuiaba",
|
||||||
|
"America/Curacao",
|
||||||
|
"America/Danmarkshavn",
|
||||||
|
"America/Dawson",
|
||||||
|
"America/Dawson_Creek",
|
||||||
|
"America/Denver",
|
||||||
|
"America/Detroit",
|
||||||
|
"America/Dominica",
|
||||||
|
"America/Edmonton",
|
||||||
|
"America/Eirunepe",
|
||||||
|
"America/El_Salvador",
|
||||||
|
"America/Fort_Nelson",
|
||||||
|
"America/Fortaleza",
|
||||||
|
"America/Glace_Bay",
|
||||||
|
"America/Godthab",
|
||||||
|
"America/Goose_Bay",
|
||||||
|
"America/Grand_Turk",
|
||||||
|
"America/Grenada",
|
||||||
|
"America/Guadeloupe",
|
||||||
|
"America/Guatemala",
|
||||||
|
"America/Guayaquil",
|
||||||
|
"America/Guyana",
|
||||||
|
"America/Halifax",
|
||||||
|
"America/Havana",
|
||||||
|
"America/Hermosillo",
|
||||||
|
"America/Indiana/Knox",
|
||||||
|
"America/Indiana/Marengo",
|
||||||
|
"America/Indiana/Petersburg",
|
||||||
|
"America/Indiana/Tell_City",
|
||||||
|
"America/Indiana/Vevay",
|
||||||
|
"America/Indiana/Vincennes",
|
||||||
|
"America/Indiana/Winamac",
|
||||||
|
"America/Indianapolis",
|
||||||
|
"America/Inuvik",
|
||||||
|
"America/Iqaluit",
|
||||||
|
"America/Jamaica",
|
||||||
|
"America/Jujuy",
|
||||||
|
"America/Juneau",
|
||||||
|
"America/Kentucky/Monticello",
|
||||||
|
"America/Kralendijk",
|
||||||
|
"America/La_Paz",
|
||||||
|
"America/Lima",
|
||||||
|
"America/Los_Angeles",
|
||||||
|
"America/Louisville",
|
||||||
|
"America/Lower_Princes",
|
||||||
|
"America/Maceio",
|
||||||
|
"America/Managua",
|
||||||
|
"America/Manaus",
|
||||||
|
"America/Marigot",
|
||||||
|
"America/Martinique",
|
||||||
|
"America/Matamoros",
|
||||||
|
"America/Mazatlan",
|
||||||
|
"America/Mendoza",
|
||||||
|
"America/Menominee",
|
||||||
|
"America/Merida",
|
||||||
|
"America/Metlakatla",
|
||||||
|
"America/Mexico_City",
|
||||||
|
"America/Miquelon",
|
||||||
|
"America/Moncton",
|
||||||
|
"America/Monterrey",
|
||||||
|
"America/Montevideo",
|
||||||
|
"America/Montreal",
|
||||||
|
"America/Montserrat",
|
||||||
|
"America/Nassau",
|
||||||
|
"America/New_York",
|
||||||
|
"America/Nipigon",
|
||||||
|
"America/Nome",
|
||||||
|
"America/Noronha",
|
||||||
|
"America/North_Dakota/Beulah",
|
||||||
|
"America/North_Dakota/Center",
|
||||||
|
"America/North_Dakota/New_Salem",
|
||||||
|
"America/Ojinaga",
|
||||||
|
"America/Panama",
|
||||||
|
"America/Pangnirtung",
|
||||||
|
"America/Paramaribo",
|
||||||
|
"America/Phoenix",
|
||||||
|
"America/Port-au-Prince",
|
||||||
|
"America/Port_of_Spain",
|
||||||
|
"America/Porto_Velho",
|
||||||
|
"America/Puerto_Rico",
|
||||||
|
"America/Punta_Arenas",
|
||||||
|
"America/Rainy_River",
|
||||||
|
"America/Rankin_Inlet",
|
||||||
|
"America/Recife",
|
||||||
|
"America/Regina",
|
||||||
|
"America/Resolute",
|
||||||
|
"America/Rio_Branco",
|
||||||
|
"America/Santa_Isabel",
|
||||||
|
"America/Santarem",
|
||||||
|
"America/Santiago",
|
||||||
|
"America/Santo_Domingo",
|
||||||
|
"America/Sao_Paulo",
|
||||||
|
"America/Scoresbysund",
|
||||||
|
"America/Sitka",
|
||||||
|
"America/St_Barthelemy",
|
||||||
|
"America/St_Johns",
|
||||||
|
"America/St_Kitts",
|
||||||
|
"America/St_Lucia",
|
||||||
|
"America/St_Thomas",
|
||||||
|
"America/St_Vincent",
|
||||||
|
"America/Swift_Current",
|
||||||
|
"America/Tegucigalpa",
|
||||||
|
"America/Thule",
|
||||||
|
"America/Thunder_Bay",
|
||||||
|
"America/Tijuana",
|
||||||
|
"America/Toronto",
|
||||||
|
"America/Tortola",
|
||||||
|
"America/Vancouver",
|
||||||
|
"America/Whitehorse",
|
||||||
|
"America/Winnipeg",
|
||||||
|
"America/Yakutat",
|
||||||
|
"America/Yellowknife",
|
||||||
|
"Antarctica/Casey",
|
||||||
|
"Antarctica/Davis",
|
||||||
|
"Antarctica/DumontDUrville",
|
||||||
|
"Antarctica/Macquarie",
|
||||||
|
"Antarctica/Mawson",
|
||||||
|
"Antarctica/McMurdo",
|
||||||
|
"Antarctica/Palmer",
|
||||||
|
"Antarctica/Rothera",
|
||||||
|
"Antarctica/Syowa",
|
||||||
|
"Antarctica/Troll",
|
||||||
|
"Antarctica/Vostok",
|
||||||
|
"Arctic/Longyearbyen",
|
||||||
|
"Asia/Aden",
|
||||||
|
"Asia/Almaty",
|
||||||
|
"Asia/Amman",
|
||||||
|
"Asia/Anadyr",
|
||||||
|
"Asia/Aqtau",
|
||||||
|
"Asia/Aqtobe",
|
||||||
|
"Asia/Ashgabat",
|
||||||
|
"Asia/Atyrau",
|
||||||
|
"Asia/Baghdad",
|
||||||
|
"Asia/Bahrain",
|
||||||
|
"Asia/Baku",
|
||||||
|
"Asia/Bangkok",
|
||||||
|
"Asia/Barnaul",
|
||||||
|
"Asia/Beirut",
|
||||||
|
"Asia/Bishkek",
|
||||||
|
"Asia/Brunei",
|
||||||
|
"Asia/Calcutta",
|
||||||
|
"Asia/Chita",
|
||||||
|
"Asia/Choibalsan",
|
||||||
|
"Asia/Colombo",
|
||||||
|
"Asia/Damascus",
|
||||||
|
"Asia/Dhaka",
|
||||||
|
"Asia/Dili",
|
||||||
|
"Asia/Dubai",
|
||||||
|
"Asia/Dushanbe",
|
||||||
|
"Asia/Famagusta",
|
||||||
|
"Asia/Gaza",
|
||||||
|
"Asia/Hebron",
|
||||||
|
"Asia/Hong_Kong",
|
||||||
|
"Asia/Hovd",
|
||||||
|
"Asia/Irkutsk",
|
||||||
|
"Asia/Jakarta",
|
||||||
|
"Asia/Jayapura",
|
||||||
|
"Asia/Jerusalem",
|
||||||
|
"Asia/Kabul",
|
||||||
|
"Asia/Kamchatka",
|
||||||
|
"Asia/Karachi",
|
||||||
|
"Asia/Katmandu",
|
||||||
|
"Asia/Khandyga",
|
||||||
|
"Asia/Krasnoyarsk",
|
||||||
|
"Asia/Kuala_Lumpur",
|
||||||
|
"Asia/Kuching",
|
||||||
|
"Asia/Kuwait",
|
||||||
|
"Asia/Macau",
|
||||||
|
"Asia/Magadan",
|
||||||
|
"Asia/Makassar",
|
||||||
|
"Asia/Manila",
|
||||||
|
"Asia/Muscat",
|
||||||
|
"Asia/Nicosia",
|
||||||
|
"Asia/Novokuznetsk",
|
||||||
|
"Asia/Novosibirsk",
|
||||||
|
"Asia/Omsk",
|
||||||
|
"Asia/Oral",
|
||||||
|
"Asia/Phnom_Penh",
|
||||||
|
"Asia/Pontianak",
|
||||||
|
"Asia/Pyongyang",
|
||||||
|
"Asia/Qatar",
|
||||||
|
"Asia/Qostanay",
|
||||||
|
"Asia/Qyzylorda",
|
||||||
|
"Asia/Rangoon",
|
||||||
|
"Asia/Riyadh",
|
||||||
|
"Asia/Saigon",
|
||||||
|
"Asia/Sakhalin",
|
||||||
|
"Asia/Samarkand",
|
||||||
|
"Asia/Seoul",
|
||||||
|
"Asia/Shanghai",
|
||||||
|
"Asia/Singapore",
|
||||||
|
"Asia/Srednekolymsk",
|
||||||
|
"Asia/Taipei",
|
||||||
|
"Asia/Tashkent",
|
||||||
|
"Asia/Tbilisi",
|
||||||
|
"Asia/Tehran",
|
||||||
|
"Asia/Thimphu",
|
||||||
|
"Asia/Tokyo",
|
||||||
|
"Asia/Tomsk",
|
||||||
|
"Asia/Ulaanbaatar",
|
||||||
|
"Asia/Urumqi",
|
||||||
|
"Asia/Ust-Nera",
|
||||||
|
"Asia/Vientiane",
|
||||||
|
"Asia/Vladivostok",
|
||||||
|
"Asia/Yakutsk",
|
||||||
|
"Asia/Yekaterinburg",
|
||||||
|
"Asia/Yerevan",
|
||||||
|
"Atlantic/Azores",
|
||||||
|
"Atlantic/Bermuda",
|
||||||
|
"Atlantic/Canary",
|
||||||
|
"Atlantic/Cape_Verde",
|
||||||
|
"Atlantic/Faeroe",
|
||||||
|
"Atlantic/Madeira",
|
||||||
|
"Atlantic/Reykjavik",
|
||||||
|
"Atlantic/South_Georgia",
|
||||||
|
"Atlantic/St_Helena",
|
||||||
|
"Atlantic/Stanley",
|
||||||
|
"Australia/Adelaide",
|
||||||
|
"Australia/Brisbane",
|
||||||
|
"Australia/Broken_Hill",
|
||||||
|
"Australia/Currie",
|
||||||
|
"Australia/Darwin",
|
||||||
|
"Australia/Eucla",
|
||||||
|
"Australia/Hobart",
|
||||||
|
"Australia/Lindeman",
|
||||||
|
"Australia/Lord_Howe",
|
||||||
|
"Australia/Melbourne",
|
||||||
|
"Australia/Perth",
|
||||||
|
"Australia/Sydney",
|
||||||
|
"Europe/Amsterdam",
|
||||||
|
"Europe/Andorra",
|
||||||
|
"Europe/Astrakhan",
|
||||||
|
"Europe/Athens",
|
||||||
|
"Europe/Belgrade",
|
||||||
|
"Europe/Berlin",
|
||||||
|
"Europe/Bratislava",
|
||||||
|
"Europe/Brussels",
|
||||||
|
"Europe/Bucharest",
|
||||||
|
"Europe/Budapest",
|
||||||
|
"Europe/Busingen",
|
||||||
|
"Europe/Chisinau",
|
||||||
|
"Europe/Copenhagen",
|
||||||
|
"Europe/Dublin",
|
||||||
|
"Europe/Gibraltar",
|
||||||
|
"Europe/Guernsey",
|
||||||
|
"Europe/Helsinki",
|
||||||
|
"Europe/Isle_of_Man",
|
||||||
|
"Europe/Istanbul",
|
||||||
|
"Europe/Jersey",
|
||||||
|
"Europe/Kaliningrad",
|
||||||
|
"Europe/Kiev",
|
||||||
|
"Europe/Kirov",
|
||||||
|
"Europe/Lisbon",
|
||||||
|
"Europe/Ljubljana",
|
||||||
|
"Europe/London",
|
||||||
|
"Europe/Luxembourg",
|
||||||
|
"Europe/Madrid",
|
||||||
|
"Europe/Malta",
|
||||||
|
"Europe/Mariehamn",
|
||||||
|
"Europe/Minsk",
|
||||||
|
"Europe/Monaco",
|
||||||
|
"Europe/Moscow",
|
||||||
|
"Europe/Oslo",
|
||||||
|
"Europe/Paris",
|
||||||
|
"Europe/Podgorica",
|
||||||
|
"Europe/Prague",
|
||||||
|
"Europe/Riga",
|
||||||
|
"Europe/Rome",
|
||||||
|
"Europe/Samara",
|
||||||
|
"Europe/San_Marino",
|
||||||
|
"Europe/Sarajevo",
|
||||||
|
"Europe/Saratov",
|
||||||
|
"Europe/Simferopol",
|
||||||
|
"Europe/Skopje",
|
||||||
|
"Europe/Sofia",
|
||||||
|
"Europe/Stockholm",
|
||||||
|
"Europe/Tallinn",
|
||||||
|
"Europe/Tirane",
|
||||||
|
"Europe/Ulyanovsk",
|
||||||
|
"Europe/Uzhgorod",
|
||||||
|
"Europe/Vaduz",
|
||||||
|
"Europe/Vatican",
|
||||||
|
"Europe/Vienna",
|
||||||
|
"Europe/Vilnius",
|
||||||
|
"Europe/Volgograd",
|
||||||
|
"Europe/Warsaw",
|
||||||
|
"Europe/Zagreb",
|
||||||
|
"Europe/Zaporozhye",
|
||||||
|
"Europe/Zurich",
|
||||||
|
"Indian/Antananarivo",
|
||||||
|
"Indian/Chagos",
|
||||||
|
"Indian/Christmas",
|
||||||
|
"Indian/Cocos",
|
||||||
|
"Indian/Comoro",
|
||||||
|
"Indian/Kerguelen",
|
||||||
|
"Indian/Mahe",
|
||||||
|
"Indian/Maldives",
|
||||||
|
"Indian/Mauritius",
|
||||||
|
"Indian/Mayotte",
|
||||||
|
"Indian/Reunion",
|
||||||
|
"Pacific/Apia",
|
||||||
|
"Pacific/Auckland",
|
||||||
|
"Pacific/Bougainville",
|
||||||
|
"Pacific/Chatham",
|
||||||
|
"Pacific/Easter",
|
||||||
|
"Pacific/Efate",
|
||||||
|
"Pacific/Enderbury",
|
||||||
|
"Pacific/Fakaofo",
|
||||||
|
"Pacific/Fiji",
|
||||||
|
"Pacific/Funafuti",
|
||||||
|
"Pacific/Galapagos",
|
||||||
|
"Pacific/Gambier",
|
||||||
|
"Pacific/Guadalcanal",
|
||||||
|
"Pacific/Guam",
|
||||||
|
"Pacific/Honolulu",
|
||||||
|
"Pacific/Johnston",
|
||||||
|
"Pacific/Kiritimati",
|
||||||
|
"Pacific/Kosrae",
|
||||||
|
"Pacific/Kwajalein",
|
||||||
|
"Pacific/Majuro",
|
||||||
|
"Pacific/Marquesas",
|
||||||
|
"Pacific/Midway",
|
||||||
|
"Pacific/Nauru",
|
||||||
|
"Pacific/Niue",
|
||||||
|
"Pacific/Norfolk",
|
||||||
|
"Pacific/Noumea",
|
||||||
|
"Pacific/Pago_Pago",
|
||||||
|
"Pacific/Palau",
|
||||||
|
"Pacific/Pitcairn",
|
||||||
|
"Pacific/Ponape",
|
||||||
|
"Pacific/Port_Moresby",
|
||||||
|
"Pacific/Rarotonga",
|
||||||
|
"Pacific/Saipan",
|
||||||
|
"Pacific/Tahiti",
|
||||||
|
"Pacific/Tarawa",
|
||||||
|
"Pacific/Tongatapu",
|
||||||
|
"Pacific/Truk",
|
||||||
|
"Pacific/Wake",
|
||||||
|
"Pacific/Wallis"
|
||||||
|
];
|
|
@ -4,11 +4,12 @@ import { useFetchQueryOptions } from "../../../hooks/useFetchQueryOptions";
|
||||||
import { ErrorTypes } from "../../../types";
|
import { ErrorTypes } from "../../../types";
|
||||||
import { useQueryDispatch, useQueryState } from "../../../state/query/QueryStateContext";
|
import { useQueryDispatch, useQueryState } from "../../../state/query/QueryStateContext";
|
||||||
import Switch from "../../../components/Main/Switch/Switch";
|
import Switch from "../../../components/Main/Switch/Switch";
|
||||||
import { PlayIcon } from "../../../components/Main/Icons";
|
import { PlayIcon, QuestionIcon } from "../../../components/Main/Icons";
|
||||||
import Button from "../../../components/Main/Button/Button";
|
import Button from "../../../components/Main/Button/Button";
|
||||||
import TextField from "../../../components/Main/TextField/TextField";
|
import TextField from "../../../components/Main/TextField/TextField";
|
||||||
import "./style.scss";
|
import "./style.scss";
|
||||||
import { useMemo } from "preact/compat";
|
import { useMemo } from "preact/compat";
|
||||||
|
import Tooltip from "../../../components/Main/Tooltip/Tooltip";
|
||||||
|
|
||||||
export interface CardinalityConfiguratorProps {
|
export interface CardinalityConfiguratorProps {
|
||||||
onSetHistory: (step: number) => void;
|
onSetHistory: (step: number) => void;
|
||||||
|
@ -92,13 +93,13 @@ const CardinalityConfigurator: FC<CardinalityConfiguratorProps> = ({
|
||||||
onChange={onFocusLabelChange}
|
onChange={onFocusLabelChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="vm-cardinality-configurator-controls__item">
|
</div>
|
||||||
<Switch
|
<div className="vm-cardinality-configurator-bottom__autocomplete">
|
||||||
label={"Autocomplete"}
|
<Switch
|
||||||
value={autocomplete}
|
label={"Autocomplete"}
|
||||||
onChange={onChangeAutocomplete}
|
value={autocomplete}
|
||||||
/>
|
onChange={onChangeAutocomplete}
|
||||||
</div>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="vm-cardinality-configurator-bottom">
|
<div className="vm-cardinality-configurator-bottom">
|
||||||
<div className="vm-cardinality-configurator-bottom__info">
|
<div className="vm-cardinality-configurator-bottom__info">
|
||||||
|
@ -106,6 +107,19 @@ const CardinalityConfigurator: FC<CardinalityConfiguratorProps> = ({
|
||||||
at <b>{date}</b>{match && <span> for series selector <b>{match}</b></span>}.
|
at <b>{date}</b>{match && <span> for series selector <b>{match}</b></span>}.
|
||||||
Show top {topN} entries per table.
|
Show top {topN} entries per table.
|
||||||
</div>
|
</div>
|
||||||
|
<a
|
||||||
|
className="vm-cardinality-configurator-bottom__docs"
|
||||||
|
href="https://victoriametrics.com/blog/cardinality-explorer/"
|
||||||
|
target="_blank"
|
||||||
|
rel="help noreferrer"
|
||||||
|
>
|
||||||
|
<Tooltip title="Example of using">
|
||||||
|
<Button
|
||||||
|
variant="text"
|
||||||
|
startIcon={<QuestionIcon/>}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
</a>
|
||||||
<Button
|
<Button
|
||||||
startIcon={<PlayIcon/>}
|
startIcon={<PlayIcon/>}
|
||||||
onClick={onRunQuery}
|
onClick={onRunQuery}
|
||||||
|
|
|
@ -18,12 +18,18 @@
|
||||||
|
|
||||||
&-bottom {
|
&-bottom {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr auto;
|
grid-template-columns: 1fr auto auto;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
gap: $padding-medium;
|
gap: $padding-small;
|
||||||
|
|
||||||
&__info {
|
&__info {
|
||||||
font-size: $font-size;
|
font-size: $font-size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__docs {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,7 @@ const TableSettings: FC<TableSettingsProps> = ({ data, defaultColumns = [], onCh
|
||||||
onClick={handleClose}
|
onClick={handleClose}
|
||||||
startIcon={<CloseIcon/>}
|
startIcon={<CloseIcon/>}
|
||||||
size="small"
|
size="small"
|
||||||
|
variant="text"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="vm-table-settings-popper-list">
|
<div className="vm-table-settings-popper-list">
|
||||||
|
|
|
@ -2,20 +2,25 @@
|
||||||
|
|
||||||
.vm-json-form {
|
.vm-json-form {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-rows: auto calc(90vh - 78px - ($padding-medium*3)) auto;
|
grid-template-rows: auto calc(70vh - 78px - ($padding-medium*3)) auto;
|
||||||
gap: $padding-global;
|
gap: $padding-global;
|
||||||
width: 70vw;
|
width: 70vw;
|
||||||
max-width: 1000px;
|
max-width: 1000px;
|
||||||
max-height: 900px;
|
max-height: 900px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
&_one-field {
|
&_one-field {
|
||||||
grid-template-rows: calc(90vh - 78px - ($padding-medium*3)) auto;
|
grid-template-rows: calc(70vh - 78px - ($padding-medium*3)) auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vm-text-field_textarea {
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
max-height: 900px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-footer {
|
&-footer {
|
||||||
|
|
|
@ -151,7 +151,7 @@ const TracePage: FC = () => {
|
||||||
className="vm-link vm-link_colored"
|
className="vm-link vm-link_colored"
|
||||||
href="https://docs.victoriametrics.com/#query-tracing"
|
href="https://docs.victoriametrics.com/#query-tracing"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="help noreferrer"
|
||||||
>
|
>
|
||||||
https://docs.victoriametrics.com/#query-tracing
|
https://docs.victoriametrics.com/#query-tracing
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -1,18 +1,22 @@
|
||||||
import { getDefaultServer } from "../../utils/default-server-url";
|
import { getDefaultServer } from "../../utils/default-server-url";
|
||||||
import { getQueryStringValue } from "../../utils/query-string";
|
import { getQueryStringValue } from "../../utils/query-string";
|
||||||
|
import { getFromStorage, saveToStorage } from "../../utils/storage";
|
||||||
|
|
||||||
export interface AppState {
|
export interface AppState {
|
||||||
serverUrl: string;
|
serverUrl: string;
|
||||||
tenantId: number;
|
tenantId: number;
|
||||||
|
darkTheme: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Action =
|
export type Action =
|
||||||
| { type: "SET_SERVER", payload: string }
|
| { type: "SET_SERVER", payload: string }
|
||||||
| { type: "SET_TENANT_ID", payload: number }
|
| { type: "SET_TENANT_ID", payload: number }
|
||||||
|
| { type: "SET_DARK_THEME", payload: boolean }
|
||||||
|
|
||||||
export const initialState: AppState = {
|
export const initialState: AppState = {
|
||||||
serverUrl: getDefaultServer(),
|
serverUrl: getDefaultServer(),
|
||||||
tenantId: Number(getQueryStringValue("g0.tenantID", 0)),
|
tenantId: Number(getQueryStringValue("g0.tenantID", 0)),
|
||||||
|
darkTheme: !!getFromStorage("DARK_THEME")
|
||||||
};
|
};
|
||||||
|
|
||||||
export function reducer(state: AppState, action: Action): AppState {
|
export function reducer(state: AppState, action: Action): AppState {
|
||||||
|
@ -27,6 +31,12 @@ export function reducer(state: AppState, action: Action): AppState {
|
||||||
...state,
|
...state,
|
||||||
tenantId: action.payload
|
tenantId: action.payload
|
||||||
};
|
};
|
||||||
|
case "SET_DARK_THEME":
|
||||||
|
saveToStorage("DARK_THEME", action.payload);
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
darkTheme: action.payload
|
||||||
|
};
|
||||||
default:
|
default:
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&_active {
|
&_active {
|
||||||
background-color: rgba($color-black, 0.06);
|
background-color: $color-hover-black;
|
||||||
}
|
}
|
||||||
|
|
||||||
&_multiselect {
|
&_multiselect {
|
||||||
|
|
|
@ -6,10 +6,11 @@
|
||||||
gap: $padding-small;
|
gap: $padding-small;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
background-color: $color-primary;
|
background-color: $color-background-block;
|
||||||
padding: $padding-small $padding-small $padding-small $padding-global;
|
padding: $padding-small $padding-small $padding-small $padding-global;
|
||||||
border-radius: $border-radius-small $border-radius-small 0 0;
|
border-radius: $border-radius-small $border-radius-small 0 0;
|
||||||
color: $color-white;
|
color: $color-text;
|
||||||
|
border-bottom: $border-divider;
|
||||||
|
|
||||||
&__title {
|
&__title {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
transition: background-color 200ms ease;
|
transition: background-color 200ms ease;
|
||||||
|
|
||||||
&:hover:not(&_header) {
|
&:hover:not(&_header) {
|
||||||
background-color: rgba($color-black, 0.05);
|
background-color: $color-hover-black;
|
||||||
}
|
}
|
||||||
|
|
||||||
&_header {
|
&_header {
|
||||||
|
@ -43,7 +43,7 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: rgba($color-black, 0.05);
|
background-color: $color-hover-black;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&_gray {
|
&_gray {
|
||||||
color: rgba($color-black, 0.4);
|
color: $color-text;
|
||||||
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
&_right {
|
&_right {
|
||||||
|
|
|
@ -9,6 +9,7 @@ html, body, #root {
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-attachment: fixed;
|
background-attachment: fixed;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
background-color: $color-background-body;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
@ -54,3 +55,24 @@ input[type=number]::-webkit-outer-spin-button {
|
||||||
svg {
|
svg {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Works on Firefox */
|
||||||
|
* {
|
||||||
|
scrollbar-width: thin;
|
||||||
|
scrollbar-color: $color-text-disabled $color-background-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Works on Chrome, Edge, and Safari */
|
||||||
|
*::-webkit-scrollbar {
|
||||||
|
width: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
*::-webkit-scrollbar-track {
|
||||||
|
background: $color-background-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
*::-webkit-scrollbar-thumb {
|
||||||
|
background-color: $color-text-disabled;
|
||||||
|
border-radius: 20px;
|
||||||
|
border: 3px solid $color-background-block;
|
||||||
|
}
|
||||||
|
|
13
app/vmui/packages/vmui/src/styles/fonts.scss
Normal file
13
app/vmui/packages/vmui/src/styles/fonts.scss
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Lato';
|
||||||
|
src: url('../assets/fonts/Lato/Lato-Regular.ttf');
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Lato';
|
||||||
|
src: url('../assets/fonts/Lato/Lato-Bold.ttf');
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
@forward "variables";
|
@forward "variables";
|
||||||
@forward "core";
|
@forward "core";
|
||||||
@forward "reset";
|
@forward "reset";
|
||||||
|
@forward "fonts";
|
||||||
|
|
||||||
@forward "./components/header-button";
|
@forward "./components/header-button";
|
||||||
@forward "./components/list";
|
@forward "./components/list";
|
||||||
|
@ -30,4 +31,17 @@
|
||||||
/* backgrounds */
|
/* backgrounds */
|
||||||
--color-background-body: #FEFEFF;
|
--color-background-body: #FEFEFF;
|
||||||
--color-background-block: #FFFFFF;
|
--color-background-block: #FFFFFF;
|
||||||
|
--color-background-tooltip: rgba(97,97,97, 0.92);
|
||||||
|
|
||||||
|
/* text */
|
||||||
|
--color-text: #110f0f;
|
||||||
|
--color-text-secondary: #706F6F;
|
||||||
|
--color-text-disabled: #A09F9F;
|
||||||
|
|
||||||
|
/* box-shadow */
|
||||||
|
--box-shadow: rgba(0, 0, 0, 0.08) 1px 2px 6px;
|
||||||
|
--box-shadow-popper: rgba(0, 0, 0, 0.1) 0px 2px 8px 0px;
|
||||||
|
|
||||||
|
--border-divider: 1px solid rgba(0, 0, 0, 0.15);
|
||||||
|
--color-hover-black: rgba(0, 0, 0, 0.06);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,14 +13,11 @@ $color-warning-text: var(--color-warning-text);
|
||||||
$color-info-text: var(--color-info-text);
|
$color-info-text: var(--color-info-text);
|
||||||
$color-success-text: var(--color-success-text);
|
$color-success-text: var(--color-success-text);
|
||||||
|
|
||||||
$color-text: #110f0f;
|
$color-text: var(--color-text);
|
||||||
$color-text-secondary: rgba($color-text, 0.6);
|
$color-text-secondary: var(--color-text-secondary);
|
||||||
$color-text-disabled: rgba($color-text, 0.4);
|
$color-text-disabled: var(--color-text-disabled);
|
||||||
|
|
||||||
$color-black: #110f0f;
|
$color-black: #110f0f;
|
||||||
$color-dove-gray: #616161;
|
|
||||||
$color-silver: #C4C4C4;
|
|
||||||
$color-alto: #D8D8D8;
|
|
||||||
$color-white: #ffffff;
|
$color-white: #ffffff;
|
||||||
|
|
||||||
$color-dodger-blue: #1A90FF;
|
$color-dodger-blue: #1A90FF;
|
||||||
|
@ -30,8 +27,7 @@ $color-tropical-blue: #C9E3F6;
|
||||||
/************* background *************/
|
/************* background *************/
|
||||||
$color-background-body: var(--color-background-body);
|
$color-background-body: var(--color-background-body);
|
||||||
$color-background-block: var(--color-background-block);
|
$color-background-block: var(--color-background-block);
|
||||||
$color-background-modal: rgba($color-black, 0.7);
|
$color-background-tooltip: var(--color-background-tooltip);
|
||||||
$color-background-tooltip: rgba($color-dove-gray, 0.92);
|
|
||||||
|
|
||||||
|
|
||||||
/************* padding *************/
|
/************* padding *************/
|
||||||
|
@ -43,7 +39,7 @@ $padding-small: 8px;
|
||||||
|
|
||||||
/************* fonts *************/
|
/************* fonts *************/
|
||||||
$font-family-global: 'Lato', sans-serif;
|
$font-family-global: 'Lato', sans-serif;
|
||||||
$font-family-monospace: 'JetBrains Mono', monospace;
|
$font-family-monospace: monospace;
|
||||||
$font-size-large: 16px;
|
$font-size-large: 16px;
|
||||||
$font-size-medium: 14px;
|
$font-size-medium: 14px;
|
||||||
$font-size: 12px;
|
$font-size: 12px;
|
||||||
|
@ -51,7 +47,7 @@ $font-size-small: 10px;
|
||||||
|
|
||||||
|
|
||||||
/************* border *************/
|
/************* border *************/
|
||||||
$border-divider: 1px solid rgba($color-black, 0.15);
|
$border-divider: var(--border-divider);
|
||||||
|
|
||||||
|
|
||||||
/************* border-radius *************/
|
/************* border-radius *************/
|
||||||
|
@ -61,6 +57,7 @@ $border-radius-large: 16px;
|
||||||
|
|
||||||
|
|
||||||
/************* box-shadows *************/
|
/************* box-shadows *************/
|
||||||
$box-shadow: 1px 2px 12px rgba($color-black, 0.08);
|
$box-shadow: var(--box-shadow);
|
||||||
$box-shadow-bottom: rgba($color-black, 0.04) 0px 3px 5px;
|
$box-shadow-popper: var(--box-shadow-popper);
|
||||||
$box-shadow-popper: rgba($color-black, 0.1) 0px 2px 8px 0px;
|
|
||||||
|
$color-hover-black: var(--color-hover-black);
|
||||||
|
|
|
@ -7,6 +7,7 @@ export type StorageKeys = "BASIC_AUTH_DATA"
|
||||||
| "SERIES_LIMITS"
|
| "SERIES_LIMITS"
|
||||||
| "TABLE_COMPACT"
|
| "TABLE_COMPACT"
|
||||||
| "TIMEZONE"
|
| "TIMEZONE"
|
||||||
|
| "DARK_THEME"
|
||||||
|
|
||||||
export const saveToStorage = (key: StorageKeys, value: string | boolean | Record<string, unknown>): void => {
|
export const saveToStorage = (key: StorageKeys, value: string | boolean | Record<string, unknown>): void => {
|
||||||
if (value) {
|
if (value) {
|
||||||
|
@ -15,6 +16,7 @@ export const saveToStorage = (key: StorageKeys, value: string | boolean | Record
|
||||||
} else {
|
} else {
|
||||||
removeFromStorage([key]);
|
removeFromStorage([key]);
|
||||||
}
|
}
|
||||||
|
window.dispatchEvent(new Event("storage"));
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: make this aware of data type that is stored
|
// TODO: make this aware of data type that is stored
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { RelativeTimeOption, TimeParams, TimePeriod, Timezone } from "../types";
|
||||||
import dayjs, { UnitTypeShort } from "dayjs";
|
import dayjs, { UnitTypeShort } from "dayjs";
|
||||||
import { getQueryStringValue } from "./query-string";
|
import { getQueryStringValue } from "./query-string";
|
||||||
import { DATE_ISO_FORMAT } from "../constants/date";
|
import { DATE_ISO_FORMAT } from "../constants/date";
|
||||||
|
import timezones from "../constants/timezones";
|
||||||
|
|
||||||
const MAX_ITEMS_PER_CHART = window.innerWidth / 4;
|
const MAX_ITEMS_PER_CHART = window.innerWidth / 4;
|
||||||
|
|
||||||
|
@ -9,7 +10,8 @@ export const limitsDurations = { min: 1, max: 1.578e+11 }; // min: 1 ms, max: 5
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
export const supportedTimezones = Intl.supportedValuesOf("timeZone") as string[];
|
const supportedValuesOf = Intl.supportedValuesOf;
|
||||||
|
export const supportedTimezones = supportedValuesOf ? supportedValuesOf("timeZone") as string[] : timezones;
|
||||||
|
|
||||||
// The list of supported units could be the following -
|
// The list of supported units could be the following -
|
||||||
// https://prometheus.io/docs/prometheus/latest/querying/basics/#time-durations
|
// https://prometheus.io/docs/prometheus/latest/querying/basics/#time-durations
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { getSecondsFromDuration, roundToMilliseconds } from "../time";
|
||||||
import { AxisRange } from "../../state/graph/reducer";
|
import { AxisRange } from "../../state/graph/reducer";
|
||||||
import { formatTicks, sizeAxis } from "./helpers";
|
import { formatTicks, sizeAxis } from "./helpers";
|
||||||
import { TimeParams } from "../../types";
|
import { TimeParams } from "../../types";
|
||||||
|
import { getCssVariable } from "../theme";
|
||||||
|
|
||||||
// see https://github.com/leeoniya/uPlot/tree/master/docs#axis--grid-opts
|
// see https://github.com/leeoniya/uPlot/tree/master/docs#axis--grid-opts
|
||||||
const timeValues = [
|
const timeValues = [
|
||||||
|
@ -22,10 +23,11 @@ export const getAxes = (series: Series[], unit?: string): Axis[] => Array.from(n
|
||||||
scale: a,
|
scale: a,
|
||||||
show: true,
|
show: true,
|
||||||
size: sizeAxis,
|
size: sizeAxis,
|
||||||
|
stroke: getCssVariable("color-text"),
|
||||||
font: "10px Arial",
|
font: "10px Arial",
|
||||||
values: (u: uPlot, ticks: number[]) => formatTicks(u, ticks, unit)
|
values: (u: uPlot, ticks: number[]) => formatTicks(u, ticks, unit)
|
||||||
};
|
};
|
||||||
if (!a) return { space: 80, values: timeValues };
|
if (!a) return { space: 80, values: timeValues, stroke: getCssVariable("color-text") };
|
||||||
if (!(Number(a) % 2)) return { ...axis, side: 1 };
|
if (!(Number(a) % 2)) return { ...axis, side: 1 };
|
||||||
return axis;
|
return axis;
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
import uPlot from "uplot";
|
import uPlot from "uplot";
|
||||||
|
import {getCssVariable} from "../theme";
|
||||||
|
|
||||||
export const seriesBarsPlugin = (opts) => {
|
export const seriesBarsPlugin = (opts) => {
|
||||||
let pxRatio;
|
let pxRatio;
|
||||||
|
@ -88,7 +89,7 @@ export const seriesBarsPlugin = (opts) => {
|
||||||
u.ctx.save();
|
u.ctx.save();
|
||||||
|
|
||||||
u.ctx.font = font;
|
u.ctx.font = font;
|
||||||
u.ctx.fillStyle = "black";
|
u.ctx.fillStyle = getCssVariable("color-text");
|
||||||
|
|
||||||
uPlot.orient(u, sidx, (
|
uPlot.orient(u, sidx, (
|
||||||
series,
|
series,
|
||||||
|
|
|
@ -2,4 +2,4 @@ route:
|
||||||
receiver: blackhole
|
receiver: blackhole
|
||||||
|
|
||||||
receivers:
|
receivers:
|
||||||
- name: blackhole
|
- name: blackhole
|
1
deployment/k8s/helm/README.md
Normal file
1
deployment/k8s/helm/README.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
### Helm chart has been moved to [helm-chart](https://github.com/VictoriaMetrics/helm-charts) repository.
|
|
@ -19,9 +19,11 @@ See also [case studies](https://docs.victoriametrics.com/CaseStudies.html).
|
||||||
* [VictoriaMetrics vs. OpenTSDB](https://blg.robot-house.us/posts/tsdbs-grow/)
|
* [VictoriaMetrics vs. OpenTSDB](https://blg.robot-house.us/posts/tsdbs-grow/)
|
||||||
* [Monitoring of multiple OpenShift clusters with VictoriaMetrics](https://medium.com/ibm-garage/monitoring-of-multiple-openshift-clusters-with-victoriametrics-d4f0979e2544)
|
* [Monitoring of multiple OpenShift clusters with VictoriaMetrics](https://medium.com/ibm-garage/monitoring-of-multiple-openshift-clusters-with-victoriametrics-d4f0979e2544)
|
||||||
* [Fly's Prometheus Metrics](https://fly.io/blog/measuring-fly/)
|
* [Fly's Prometheus Metrics](https://fly.io/blog/measuring-fly/)
|
||||||
|
* [Ultra Monitoring with Victoria Metrics](https://dev.to/aws-builders/ultra-monitoring-with-victoria-metrics-1p2)
|
||||||
* [Infrastructure monitoring with Prometheus at Zerodha](https://zerodha.tech/blog/infra-monitoring-at-zerodha/)
|
* [Infrastructure monitoring with Prometheus at Zerodha](https://zerodha.tech/blog/infra-monitoring-at-zerodha/)
|
||||||
* [Sismology: Iguana Solutions’ Monitoring System](https://medium.com/nerd-for-tech/sismology-iguana-solutions-monitoring-system-f46e4170447f)
|
* [Sismology: Iguana Solutions’ Monitoring System](https://medium.com/nerd-for-tech/sismology-iguana-solutions-monitoring-system-f46e4170447f)
|
||||||
* [Prometheus High Availability and Fault Tolerance strategy, long term storage with VictoriaMetrics](https://medium.com/miro-engineering/prometheus-high-availability-and-fault-tolerance-strategy-long-term-storage-with-victoriametrics-82f6f3f0409e)
|
* [Prometheus High Availability and Fault Tolerance strategy, long term storage with VictoriaMetrics](https://medium.com/miro-engineering/prometheus-high-availability-and-fault-tolerance-strategy-long-term-storage-with-victoriametrics-82f6f3f0409e)
|
||||||
|
* [Monitoring with Prometheus, Grafana, AlertManager and VictoriaMetrics](https://www.sensedia.com/post/monitoring-with-prometheus-grafana-alertmanager-and-victoriametrics)
|
||||||
* [How we improved our Kubernetes monitoring at Smarkets, and how you could too](https://smarketshq.com/monitoring-kubernetes-clusters-41a4b24c19e3)
|
* [How we improved our Kubernetes monitoring at Smarkets, and how you could too](https://smarketshq.com/monitoring-kubernetes-clusters-41a4b24c19e3)
|
||||||
* [Kubernetes and VictoriaMetrics in Mist v4.6](https://mist.io/blog/2021-11-26-kubernetes-and-victoriametrics-in-Mist-v4-6)
|
* [Kubernetes and VictoriaMetrics in Mist v4.6](https://mist.io/blog/2021-11-26-kubernetes-and-victoriametrics-in-Mist-v4-6)
|
||||||
* [Foiled by the Firewall: A Tale of Transition From Prometheus to VictoriaMetrics](https://www.percona.com/blog/2020/12/01/foiled-by-the-firewall-a-tale-of-transition-from-prometheus-to-victoriametrics/)
|
* [Foiled by the Firewall: A Tale of Transition From Prometheus to VictoriaMetrics](https://www.percona.com/blog/2020/12/01/foiled-by-the-firewall-a-tale-of-transition-from-prometheus-to-victoriametrics/)
|
||||||
|
@ -59,6 +61,9 @@ See also [case studies](https://docs.victoriametrics.com/CaseStudies.html).
|
||||||
* [Prometheus, Grafana, and Kubernetes, Oh My!](https://www.groundcover.com/blog/prometheus-grafana-kubernetes)
|
* [Prometheus, Grafana, and Kubernetes, Oh My!](https://www.groundcover.com/blog/prometheus-grafana-kubernetes)
|
||||||
* [Explaining modern server monitoring stacks for self-hosting](https://dataswamp.org/~solene/2022-09-11-exploring-monitoring-stacks.html)
|
* [Explaining modern server monitoring stacks for self-hosting](https://dataswamp.org/~solene/2022-09-11-exploring-monitoring-stacks.html)
|
||||||
* [How do We Keep Metrics for a Long Time in VictoriaMetrics](https://www.youtube.com/watch?v=SGZjY7xgDwE)
|
* [How do We Keep Metrics for a Long Time in VictoriaMetrics](https://www.youtube.com/watch?v=SGZjY7xgDwE)
|
||||||
|
* [Brewblox: InfluxDB to Victoria Metrics](https://www.brewblox.com/dev/decisions/20210718_victoria_metrics.html)
|
||||||
|
* [VictoriaMetrics static scraper](https://blog.differentpla.net/blog/2022/10/16/victoria-metrics-static-scraper/)
|
||||||
|
* [VictoriaMetrics and Open Cosmos boldly takes edge computing to the edge of space](https://www.iot-now.com/2022/07/19/122423-victoriametrics-and-open-cosmos-boldly-takes-edge-computing-to-the-edge-of-space/)
|
||||||
|
|
||||||
## Our articles
|
## Our articles
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,15 @@ The following tip changes can be tested by building VictoriaMetrics components f
|
||||||
|
|
||||||
## tip
|
## tip
|
||||||
|
|
||||||
|
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): add dark mode - it can be seleted via `settings` menu in the top right corner. See [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/3704).
|
||||||
|
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): improve visual appearance of the top menu. See [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3678).
|
||||||
|
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): embed fonts into binary instead of loading them from external sources. This allows using `vmui` in full from isolated networks without access to Internet. Thanks to @ScottKevill for [the pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/3696).
|
||||||
|
* FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent.html): reduce memory usage when sending stale markers for targets, which expose big number of metrics. See [this](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3668) and [this](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3675) issues.
|
||||||
|
* FEATURE: add `-internStringMaxLen` command-line flag, which can be used for fine-tuning RAM vs CPU usage in certain workloads. For example, if the stored time series contain long labels, then it may be useful reducing the `-internStringMaxLen` in order to reduce memory usage at the cost of increased CPU usage. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3692).
|
||||||
|
|
||||||
|
* BUGFIX: [VictoriaMetrics cluster](https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html): propagate all the timeout-related errors from `vmstorage` to `vmselect` when `vmstorage`. Previously some timeout errors weren't returned from `vmselect` to `vmstorage`. Instead, `vmstorage` could log the error and close the connection to `vmselect`, so `vmselect` was logging cryptic errors such as `cannot execute funcName="..." on vmstorage "...": EOF`.
|
||||||
|
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): add support for time zone selection for older versions of browsers. See [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/3680).
|
||||||
|
* BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent.html): update API version for [ec2_sd_configs](https://docs.victoriametrics.com/sd_configs.html#ec2_sd_configs) to fix [the issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3700) with missing `__meta_ec2_availability_zone_id` attribute.
|
||||||
|
|
||||||
## [v1.86.2](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.86.2)
|
## [v1.86.2](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.86.2)
|
||||||
|
|
||||||
|
|
|
@ -1086,7 +1086,9 @@ The [deduplication](#deduplication) isn't applied for the data exported in nativ
|
||||||
|
|
||||||
## How to import time series data
|
## How to import time series data
|
||||||
|
|
||||||
Time series data can be imported into VictoriaMetrics via any supported data ingestion protocol:
|
VictoriaMetrics can discover and scrape metrics from Prometheus-compatible targets (aka "pull" protocol) -
|
||||||
|
see [these docs](#how-to-scrape-prometheus-exporters-such-as-node-exporter).
|
||||||
|
Additionally, VictoriaMetrics can accept metrics via the following popular data ingestion protocols (aka "push" protocols):
|
||||||
|
|
||||||
* [Prometheus remote_write API](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_write). See [these docs](#prometheus-setup) for details.
|
* [Prometheus remote_write API](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_write). See [these docs](#prometheus-setup) for details.
|
||||||
* DataDog `submit metrics` API. See [these docs](#how-to-send-data-from-datadog-agent) for details.
|
* DataDog `submit metrics` API. See [these docs](#how-to-send-data-from-datadog-agent) for details.
|
||||||
|
|
|
@ -94,7 +94,8 @@ The helm chart repository [https://github.com/VictoriaMetrics/helm-charts/](http
|
||||||
4. Update `cluster` chart versions in [`values.yaml`](https://github.com/VictoriaMetrics/helm-charts/blob/master/charts/victoria-metrics-cluster/values.yaml), bump version for `vmselect`, `vminsert` and `vmstorage` and [`Chart.yaml`](https://github.com/VictoriaMetrics/helm-charts/blob/master/charts/victoria-metrics-cluster/Chart.yaml)
|
4. Update `cluster` chart versions in [`values.yaml`](https://github.com/VictoriaMetrics/helm-charts/blob/master/charts/victoria-metrics-cluster/values.yaml), bump version for `vmselect`, `vminsert` and `vmstorage` and [`Chart.yaml`](https://github.com/VictoriaMetrics/helm-charts/blob/master/charts/victoria-metrics-cluster/Chart.yaml)
|
||||||
5. Update `k8s-stack` chart versions in [`values.yaml`](https://github.com/VictoriaMetrics/helm-charts/blob/master/charts/victoria-metrics-k8s-stack/values.yaml), bump version for `vmselect`, `vminsert`, `vmstorage`, `vmsingle`, `vmalert`, `vmagent` and [`Chart.yaml`](https://github.com/VictoriaMetrics/helm-charts/blob/master/charts/victoria-metrics-k8s-stack/Chart.yaml)
|
5. Update `k8s-stack` chart versions in [`values.yaml`](https://github.com/VictoriaMetrics/helm-charts/blob/master/charts/victoria-metrics-k8s-stack/values.yaml), bump version for `vmselect`, `vminsert`, `vmstorage`, `vmsingle`, `vmalert`, `vmagent` and [`Chart.yaml`](https://github.com/VictoriaMetrics/helm-charts/blob/master/charts/victoria-metrics-k8s-stack/Chart.yaml)
|
||||||
6. Update `single-node` chart version in [`values.yaml`](https://github.com/VictoriaMetrics/helm-charts/blob/master/charts/victoria-metrics-single/values.yaml) and [`Chart.yaml`](https://github.com/VictoriaMetrics/helm-charts/blob/master/charts/victoria-metrics-single/Chart.yaml)
|
6. Update `single-node` chart version in [`values.yaml`](https://github.com/VictoriaMetrics/helm-charts/blob/master/charts/victoria-metrics-single/values.yaml) and [`Chart.yaml`](https://github.com/VictoriaMetrics/helm-charts/blob/master/charts/victoria-metrics-single/Chart.yaml)
|
||||||
8. Run `make gen-doc`
|
7. Update `vmgateway` chart version in [`values.yaml`](https://github.com/VictoriaMetrics/helm-charts/blob/master/charts/victoria-metrics-gateway/values.yamll) and [`Chart.yaml`](https://github.com/VictoriaMetrics/helm-charts/blob/master/charts/victoria-metrics-gateway/Chart.yaml)
|
||||||
|
8. Run `make gen-docs`
|
||||||
9. Run `make package` that creates or updates zip file with the packed chart
|
9. Run `make package` that creates or updates zip file with the packed chart
|
||||||
10. Run `make merge`. It creates or updates metadata for charts in index.yaml
|
10. Run `make merge`. It creates or updates metadata for charts in index.yaml
|
||||||
11. Push changes to master. `master` is a source of truth
|
11. Push changes to master. `master` is a source of truth
|
||||||
|
|
|
@ -1089,7 +1089,9 @@ The [deduplication](#deduplication) isn't applied for the data exported in nativ
|
||||||
|
|
||||||
## How to import time series data
|
## How to import time series data
|
||||||
|
|
||||||
Time series data can be imported into VictoriaMetrics via any supported data ingestion protocol:
|
VictoriaMetrics can discover and scrape metrics from Prometheus-compatible targets (aka "pull" protocol) -
|
||||||
|
see [these docs](#how-to-scrape-prometheus-exporters-such-as-node-exporter).
|
||||||
|
Additionally, VictoriaMetrics can accept metrics via the following popular data ingestion protocols (aka "push" protocols):
|
||||||
|
|
||||||
* [Prometheus remote_write API](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_write). See [these docs](#prometheus-setup) for details.
|
* [Prometheus remote_write API](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_write). See [these docs](#prometheus-setup) for details.
|
||||||
* DataDog `submit metrics` API. See [these docs](#how-to-send-data-from-datadog-agent) for details.
|
* DataDog `submit metrics` API. See [these docs](#how-to-send-data-from-datadog-agent) for details.
|
||||||
|
|
16
go.mod
16
go.mod
|
@ -3,7 +3,7 @@ module github.com/VictoriaMetrics/VictoriaMetrics
|
||||||
go 1.19
|
go 1.19
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go/storage v1.28.1
|
cloud.google.com/go/storage v1.29.0
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.6.1
|
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.6.1
|
||||||
github.com/VictoriaMetrics/fastcache v1.12.0
|
github.com/VictoriaMetrics/fastcache v1.12.0
|
||||||
|
@ -26,13 +26,13 @@ require (
|
||||||
github.com/golang/snappy v0.0.4
|
github.com/golang/snappy v0.0.4
|
||||||
github.com/googleapis/gax-go/v2 v2.7.0
|
github.com/googleapis/gax-go/v2 v2.7.0
|
||||||
github.com/influxdata/influxdb v1.11.0
|
github.com/influxdata/influxdb v1.11.0
|
||||||
github.com/klauspost/compress v1.15.14
|
github.com/klauspost/compress v1.15.15
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.14 // indirect
|
github.com/mattn/go-runewidth v0.0.14 // indirect
|
||||||
github.com/oklog/ulid v1.3.1
|
github.com/oklog/ulid v1.3.1
|
||||||
github.com/prometheus/common v0.39.0 // indirect
|
github.com/prometheus/common v0.39.0 // indirect
|
||||||
github.com/prometheus/prometheus v0.41.0
|
github.com/prometheus/prometheus v0.41.0
|
||||||
github.com/urfave/cli/v2 v2.23.7
|
github.com/urfave/cli/v2 v2.24.1
|
||||||
github.com/valyala/fastjson v1.6.4
|
github.com/valyala/fastjson v1.6.4
|
||||||
github.com/valyala/fastrand v1.1.0
|
github.com/valyala/fastrand v1.1.0
|
||||||
github.com/valyala/fasttemplate v1.2.2
|
github.com/valyala/fasttemplate v1.2.2
|
||||||
|
@ -42,19 +42,19 @@ require (
|
||||||
golang.org/x/net v0.5.0
|
golang.org/x/net v0.5.0
|
||||||
golang.org/x/oauth2 v0.4.0
|
golang.org/x/oauth2 v0.4.0
|
||||||
golang.org/x/sys v0.4.0
|
golang.org/x/sys v0.4.0
|
||||||
google.golang.org/api v0.107.0
|
google.golang.org/api v0.108.0
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go v0.108.0 // indirect
|
cloud.google.com/go v0.109.0 // indirect
|
||||||
cloud.google.com/go/compute v1.15.1 // indirect
|
cloud.google.com/go/compute v1.15.1 // indirect
|
||||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||||
cloud.google.com/go/iam v0.10.0 // indirect
|
cloud.google.com/go/iam v0.10.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 // indirect
|
||||||
github.com/VividCortex/ewma v1.2.0 // indirect
|
github.com/VividCortex/ewma v1.2.0 // indirect
|
||||||
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
|
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
|
||||||
github.com/aws/aws-sdk-go v1.44.180 // indirect
|
github.com/aws/aws-sdk-go v1.44.184 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect
|
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.13.8 // indirect
|
github.com/aws/aws-sdk-go-v2/credentials v1.13.8 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.21 // indirect
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.21 // indirect
|
||||||
|
@ -107,13 +107,13 @@ require (
|
||||||
go.opentelemetry.io/otel/trace v1.11.2 // indirect
|
go.opentelemetry.io/otel/trace v1.11.2 // indirect
|
||||||
go.uber.org/atomic v1.10.0 // indirect
|
go.uber.org/atomic v1.10.0 // indirect
|
||||||
go.uber.org/goleak v1.2.0 // indirect
|
go.uber.org/goleak v1.2.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20230113213754-f9f960f08ad4 // indirect
|
golang.org/x/exp v0.0.0-20230118134722-a68e582fa157 // indirect
|
||||||
golang.org/x/sync v0.1.0 // indirect
|
golang.org/x/sync v0.1.0 // indirect
|
||||||
golang.org/x/text v0.6.0 // indirect
|
golang.org/x/text v0.6.0 // indirect
|
||||||
golang.org/x/time v0.3.0 // indirect
|
golang.org/x/time v0.3.0 // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5 // indirect
|
google.golang.org/genproto v0.0.0-20230119192704-9d59e20e5cd1 // indirect
|
||||||
google.golang.org/grpc v1.52.0 // indirect
|
google.golang.org/grpc v1.52.0 // indirect
|
||||||
google.golang.org/protobuf v1.28.1 // indirect
|
google.golang.org/protobuf v1.28.1 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
|
32
go.sum
32
go.sum
|
@ -13,8 +13,8 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV
|
||||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||||
cloud.google.com/go v0.108.0 h1:xntQwnfn8oHGX0crLVinvHM+AhXvi3QHQIEcX/2hiWk=
|
cloud.google.com/go v0.109.0 h1:38CZoKGlCnPZjGdyj0ZfpoGae0/wgNfy5F0byyxg0Gk=
|
||||||
cloud.google.com/go v0.108.0/go.mod h1:lNUfQqusBJp0bgAg6qrHgYFYbTB+dOiob1itwnlD33Q=
|
cloud.google.com/go v0.109.0/go.mod h1:2sYycXt75t/CSB5R9M2wPU1tJmire7AQZTPtITcGBVE=
|
||||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||||
|
@ -39,8 +39,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
|
||||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||||
cloud.google.com/go/storage v1.28.1 h1:F5QDG5ChchaAVQhINh24U99OWHURqrW8OmQcGKXcbgI=
|
cloud.google.com/go/storage v1.29.0 h1:6weCgzRvMg7lzuUurI4697AqIRPU1SvzHhynwpW31jI=
|
||||||
cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y=
|
cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
github.com/Azure/azure-sdk-for-go v65.0.0+incompatible h1:HzKLt3kIwMm4KeJYTdx9EbjRYTySD/t8i1Ee/W5EGXw=
|
github.com/Azure/azure-sdk-for-go v65.0.0+incompatible h1:HzKLt3kIwMm4KeJYTdx9EbjRYTySD/t8i1Ee/W5EGXw=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 h1:VuHAcMq8pU1IWNT/m5yRaGqbK0BiQKHT8X4DTp9CHdI=
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 h1:VuHAcMq8pU1IWNT/m5yRaGqbK0BiQKHT8X4DTp9CHdI=
|
||||||
|
@ -87,8 +87,8 @@ github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu
|
||||||
github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||||
github.com/armon/go-metrics v0.3.10 h1:FR+drcQStOe+32sYyJYyZ7FIdgoGGBnwLl+flodp8Uo=
|
github.com/armon/go-metrics v0.3.10 h1:FR+drcQStOe+32sYyJYyZ7FIdgoGGBnwLl+flodp8Uo=
|
||||||
github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
|
github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
|
||||||
github.com/aws/aws-sdk-go v1.44.180 h1:VLZuAHI9fa/3WME5JjpVjcPCNfpGHVMiHx8sLHWhMgI=
|
github.com/aws/aws-sdk-go v1.44.184 h1:/MggyE66rOImXJKl1HqhLQITvWvqIV7w1Q4MaG6FHUo=
|
||||||
github.com/aws/aws-sdk-go v1.44.180/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
|
github.com/aws/aws-sdk-go v1.44.184/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
|
||||||
github.com/aws/aws-sdk-go-v2 v1.17.3 h1:shN7NlnVzvDUgPQ+1rLMSxY8OWRNDRYtiqe0p/PgrhY=
|
github.com/aws/aws-sdk-go-v2 v1.17.3 h1:shN7NlnVzvDUgPQ+1rLMSxY8OWRNDRYtiqe0p/PgrhY=
|
||||||
github.com/aws/aws-sdk-go-v2 v1.17.3/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
|
github.com/aws/aws-sdk-go-v2 v1.17.3/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
|
||||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs=
|
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs=
|
||||||
|
@ -316,8 +316,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||||
github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||||
github.com/klauspost/compress v1.15.14 h1:i7WCKDToww0wA+9qrUZ1xOjp218vfFo3nTU6UHp+gOc=
|
github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw=
|
||||||
github.com/klauspost/compress v1.15.14/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
|
github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4=
|
||||||
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJis0QP7YMxobob6zhzq6Yre00=
|
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJis0QP7YMxobob6zhzq6Yre00=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
@ -423,8 +423,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/urfave/cli/v2 v2.23.7 h1:YHDQ46s3VghFHFf1DdF+Sh7H4RqhcM+t0TmZRJx4oJY=
|
github.com/urfave/cli/v2 v2.24.1 h1:/QYYr7g0EhwXEML8jO+8OYt5trPnLHS0p3mrgExJ5NU=
|
||||||
github.com/urfave/cli/v2 v2.23.7/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
|
github.com/urfave/cli/v2 v2.24.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
|
||||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus=
|
github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus=
|
||||||
|
@ -487,8 +487,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||||
golang.org/x/exp v0.0.0-20230113213754-f9f960f08ad4 h1:CNkDRtCj8otM5CFz5jYvbr8ioXX8flVsLfDWEj0M5kk=
|
golang.org/x/exp v0.0.0-20230118134722-a68e582fa157 h1:fiNkyhJPUvxbRPbCqY/D9qdjmPzfHcpK3P4bM4gioSY=
|
||||||
golang.org/x/exp v0.0.0-20230113213754-f9f960f08ad4/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
golang.org/x/exp v0.0.0-20230118134722-a68e582fa157/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
@ -703,8 +703,8 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
|
||||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||||
google.golang.org/api v0.107.0 h1:I2SlFjD8ZWabaIFOfeEDg3pf0BHJDh6iYQ1ic3Yu/UU=
|
google.golang.org/api v0.108.0 h1:WVBc/faN0DkKtR43Q/7+tPny9ZoLZdIiAyG5Q9vFClg=
|
||||||
google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY=
|
google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
@ -742,8 +742,8 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc
|
||||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5 h1:wJT65XLOzhpSPCdAmmKfz94SlmnQzDzjm3Cj9k3fsXY=
|
google.golang.org/genproto v0.0.0-20230119192704-9d59e20e5cd1 h1:wSjSSQW7LuPdv3m1IrSN33nVxH/kID6OIKy+FMwGB2k=
|
||||||
google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
|
google.golang.org/genproto v0.0.0-20230119192704-9d59e20e5cd1/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
|
|
|
@ -109,7 +109,7 @@ func (cfg *Config) GetEC2APIResponse(action, filtersQueryString, nextPageToken s
|
||||||
if len(nextPageToken) > 0 {
|
if len(nextPageToken) > 0 {
|
||||||
apiURL += fmt.Sprintf("&NextToken=%s", url.QueryEscape(nextPageToken))
|
apiURL += fmt.Sprintf("&NextToken=%s", url.QueryEscape(nextPageToken))
|
||||||
}
|
}
|
||||||
apiURL += "&Version=2013-10-15"
|
apiURL += "&Version=2016-11-15"
|
||||||
req, err := newSignedGetRequest(apiURL, "ec2", cfg.region, ac)
|
req, err := newSignedGetRequest(apiURL, "ec2", cfg.region, ac)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("cannot create signed request: %w", err)
|
return nil, fmt.Errorf("cannot create signed request: %w", err)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package bytesutil
|
package bytesutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
@ -8,6 +9,9 @@ import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/fasttime"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/fasttime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var internStringMaxLen = flag.Int("internStringMaxLen", 300, "The maximum length for strings to intern. Lower limit may save memory at the cost of higher CPU usage. "+
|
||||||
|
"See https://en.wikipedia.org/wiki/String_interning")
|
||||||
|
|
||||||
// InternBytes interns b as a string
|
// InternBytes interns b as a string
|
||||||
func InternBytes(b []byte) string {
|
func InternBytes(b []byte) string {
|
||||||
s := ToUnsafeString(b)
|
s := ToUnsafeString(b)
|
||||||
|
@ -30,6 +34,12 @@ func InternString(s string) string {
|
||||||
}
|
}
|
||||||
// Make a new copy for s in order to remove references from possible bigger string s refers to.
|
// Make a new copy for s in order to remove references from possible bigger string s refers to.
|
||||||
sCopy := strings.Clone(s)
|
sCopy := strings.Clone(s)
|
||||||
|
if len(sCopy) > *internStringMaxLen {
|
||||||
|
// Do not intern long strings, since this may result in high memory usage
|
||||||
|
// like in https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3692
|
||||||
|
return sCopy
|
||||||
|
}
|
||||||
|
|
||||||
e := &ismEntry{
|
e := &ismEntry{
|
||||||
lastAccessTime: ct,
|
lastAccessTime: ct,
|
||||||
s: sCopy,
|
s: sCopy,
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue