Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
doodoocoder
prometheus
提交
a6ee1f85
P
prometheus
项目概览
doodoocoder
/
prometheus
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
prometheus
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
a6ee1f85
编写于
9月 09, 2020
作者:
J
Julien Pivotto
提交者:
GitHub
9月 09, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #7913 from prometheus/release-2.21
Merge release 2.21 into master
上级
8219b442
e55b0be9
变更
13
隐藏空白更改
内联
并排
Showing
13 changed file
with
162 addition
and
45 deletion
+162
-45
CHANGELOG.md
CHANGELOG.md
+39
-0
VERSION
VERSION
+1
-1
discovery/hetzner/robot.go
discovery/hetzner/robot.go
+9
-2
discovery/hetzner/robot_test.go
discovery/hetzner/robot_test.go
+16
-1
docs/configuration/configuration.md
docs/configuration/configuration.md
+3
-0
storage/merge.go
storage/merge.go
+54
-23
storage/merge_test.go
storage/merge_test.go
+2
-2
web/api/v1/api.go
web/api/v1/api.go
+2
-1
web/api/v1/api_test.go
web/api/v1/api_test.go
+26
-7
web/ui/react-app/src/pages/targets/TargetLabels.test.tsx
web/ui/react-app/src/pages/targets/TargetLabels.test.tsx
+4
-2
web/ui/react-app/src/pages/targets/TargetLabels.tsx
web/ui/react-app/src/pages/targets/TargetLabels.tsx
+1
-1
web/ui/react-app/src/pages/targets/__snapshots__/TargetLabels.test.tsx.snap
...rc/pages/targets/__snapshots__/TargetLabels.test.tsx.snap
+3
-3
web/ui/templates/rules.html
web/ui/templates/rules.html
+2
-2
未找到文件。
CHANGELOG.md
浏览文件 @
a6ee1f85
## 2.21.0-rc.1 / 2020-09-08
This release is built with Go 1.15, which deprecates
[
X.509
CommonName
](
https://golang.org/doc/go1.15#commonname
)
in TLS certificates
validation.
In the unlikely case that you use the gRPC API v2 (which is limited to TSDB
admin commands), please note that we will remove this experimental API in the
next minor release 2.22.
*
[CHANGE] Disable HTTP2 because of concerns with the Go HTTP/2 client. #7588 #7701
*
[CHANGE] PromQL:
`query_log_file`
path is now relative to the config file. #7701
*
[CHANGE] Promtool: Replace the tsdb command line tool by a promtool tsdb subcommand. #6088
*
[CHANGE] Rules: Label
`rule_group_iterations`
metric with group name. #7823
*
[FEATURE] Eureka SD: New service discovery. #3369
*
[FEATURE] Hetzner SD: New service discovery. #7822
*
[FEATURE] Kubernetes SD: Support Kubernetes EndpointSlices. #6838
*
[FEATURE] Scrape: Add per scrape-config targets limit. #7554
*
[ENHANCEMENT] Support composite durations in PromQL, config and UI, e.g. 1h30m. #7713 #7833
*
[ENHANCEMENT] DNS SD: Add SRV record target and port meta labels. #7678
*
[ENHANCEMENT] Docker Swarm SD: Support tasks and service without published ports. #7686
*
[ENHANCEMENT] PromQL: Reduce the amount of data queried by remote read when a subquery has an offset. #7667
*
[ENHANCEMENT] Promtool: Add
`--time`
option to query instant command. #7829
*
[ENHANCEMENT] UI: Respect the
`--web.page-title`
parameter in the React UI. #7607
*
[ENHANCEMENT] UI: Add duration, labels, annotations to alerts page in the React UI. #7605
*
[ENHANCEMENT] UI: Add duration on the React UI rules page, hide annotation and labels if empty. #7606
*
[BUGFIX] API: Deduplicate series in /api/v1/series. #7862
*
[BUGFIX] PromQL: Drop metric name in bool comparison between two instant vectors. #7819
*
[BUGFIX] PromQL: Exit with an error when time parameters can't be parsed. #7505
*
[BUGFIX] Rules: Detect extra fields in rule files. #7767
*
[BUGFIX] Rules: Disallow overwriting the metric name in the
`labels`
section of recording rules. #7787
*
[BUGFIX] Rules: Keep evaluation timestamp across reloads. #7775
*
[BUGFIX] Scrape: Do not stop scrapes in progress during reload. #7752
*
[BUGFIX] TSDB: Fix
`chunks.HeadReadWriter: maxt of the files are not set`
error. #7856
*
[BUGFIX] TSDB: Delete blocks atomically to prevent corruption when there is a panic/crash during deletion. #7772
*
[BUGFIX] Triton SD: Fix a panic when triton_sd_config is nil. #7671
*
[BUGFIX] UI: Fix react UI bug with series going on and off. #7804
*
[BUGFIX] Web: Stop CMUX and GRPC servers even with stale connections, preventing the server to stop on SIGTERM. #7810
## 2.20.1 / 2020-08-05
*
[BUGFIX] SD: Reduce the Consul watch timeout to 2m and adjust the request timeout accordingly. #7724
...
...
VERSION
浏览文件 @
a6ee1f85
2.2
0
.1
2.2
1.0-rc
.1
discovery/hetzner/robot.go
浏览文件 @
a6ee1f85
...
...
@@ -26,7 +26,8 @@ import (
"time"
"github.com/go-kit/kit/log"
config_util
"github.com/prometheus/common/config"
"github.com/pkg/errors"
"github.com/prometheus/common/config"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/discovery/refresh"
"github.com/prometheus/prometheus/discovery/targetgroup"
...
...
@@ -54,7 +55,7 @@ func newRobotDiscovery(conf *SDConfig, logger log.Logger) (*robotDiscovery, erro
endpoint
:
conf
.
robotEndpoint
,
}
rt
,
err
:=
config
_util
.
NewRoundTripperFromConfig
(
conf
.
HTTPClientConfig
,
"hetzner_sd"
,
false
,
false
)
rt
,
err
:=
config
.
NewRoundTripperFromConfig
(
conf
.
HTTPClientConfig
,
"hetzner_sd"
,
false
,
false
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -70,10 +71,16 @@ func (d *robotDiscovery) refresh(ctx context.Context) ([]*targetgroup.Group, err
if
err
!=
nil
{
return
nil
,
err
}
defer
func
()
{
io
.
Copy
(
ioutil
.
Discard
,
resp
.
Body
)
resp
.
Body
.
Close
()
}()
if
resp
.
StatusCode
/
100
!=
2
{
return
nil
,
errors
.
Errorf
(
"non 2xx status '%d' response during hetzner service discovery with role robot"
,
resp
.
StatusCode
)
}
var
servers
serversList
err
=
json
.
NewDecoder
(
resp
.
Body
)
.
Decode
(
&
servers
)
if
err
!=
nil
{
...
...
discovery/hetzner/robot_test.go
浏览文件 @
a6ee1f85
...
...
@@ -37,7 +37,6 @@ func (s *robotSDTestSuite) SetupTest(t *testing.T) {
func
TestRobotSDRefresh
(
t
*
testing
.
T
)
{
suite
:=
&
robotSDTestSuite
{}
suite
.
SetupTest
(
t
)
cfg
:=
DefaultSDConfig
cfg
.
HTTPClientConfig
.
BasicAuth
=
&
config
.
BasicAuth
{
Username
:
robotTestUsername
,
Password
:
robotTestPassword
}
cfg
.
robotEndpoint
=
suite
.
Mock
.
Endpoint
()
...
...
@@ -84,3 +83,19 @@ func TestRobotSDRefresh(t *testing.T) {
})
}
}
func
TestRobotSDRefreshHandleError
(
t
*
testing
.
T
)
{
suite
:=
&
robotSDTestSuite
{}
suite
.
SetupTest
(
t
)
cfg
:=
DefaultSDConfig
cfg
.
robotEndpoint
=
suite
.
Mock
.
Endpoint
()
d
,
err
:=
newRobotDiscovery
(
&
cfg
,
log
.
NewNopLogger
())
testutil
.
Ok
(
t
,
err
)
targetGroups
,
err
:=
d
.
refresh
(
context
.
Background
())
testutil
.
NotOk
(
t
,
err
)
testutil
.
Equals
(
t
,
"non 2xx status '401' response during hetzner service discovery with role robot"
,
err
.
Error
())
testutil
.
Equals
(
t
,
0
,
len
(
targetGroups
))
}
docs/configuration/configuration.md
浏览文件 @
a6ee1f85
...
...
@@ -936,6 +936,7 @@ changed with relabeling, as demonstrated in [the Prometheus hetzner-sd
configuration file
](
/documentation/examples/prometheus-hetzner.yml
)
.
The following meta labels are available on all targets during
[
relabeling
](
#relabel_config
)
:
*
`__meta_hetzner_server_id`
: the ID of the server
*
`__meta_hetzner_server_name`
: the name of the server
*
`__meta_hetzner_server_status`
: the status of the server
...
...
@@ -944,6 +945,7 @@ The following meta labels are available on all targets during [relabeling](#rela
*
`__meta_hetzner_datacenter`
: the datacenter of the server
The labels below are only available for targets with
`role`
set to
`hcloud`
:
*
`__meta_hetzner_hcloud_image_name`
: the image name of the server
*
`__meta_hetzner_hcloud_image_description`
: the description of the server image
*
`__meta_hetzner_hcloud_image_os_flavor`
: the OS flavor of the server image
...
...
@@ -960,6 +962,7 @@ The labels below are only available for targets with `role` set to `hcloud`:
*
`__meta_hetzner_hcloud_label_<labelname>`
: each label of the server
The labels below are only available for targets with
`role`
set to
`robot`
:
*
`__meta_hetzner_robot_product`
: the product of the server
*
`__meta_hetzner_robot_cancelled`
: the server cancellation status
...
...
storage/merge.go
浏览文件 @
a6ee1f85
...
...
@@ -16,6 +16,7 @@ package storage
import
(
"bytes"
"container/heap"
"math"
"sort"
"strings"
"sync"
...
...
@@ -331,7 +332,7 @@ func (c *genericMergeSeriesSet) Next() bool {
// If, for the current label set, all the next series sets come from
// failed remote storage sources, we want to keep trying with the next label set.
for
{
// Firstly advance all the current series sets. If any of them have run out
// Firstly advance all the current series sets. If any of them have run out
,
// we can drop them, otherwise they should be inserted back into the heap.
for
_
,
set
:=
range
c
.
currentSets
{
if
set
.
Next
()
{
...
...
@@ -418,8 +419,7 @@ func (h *genericSeriesSetHeap) Pop() interface{} {
// with "almost" the same data, e.g. from 2 Prometheus HA replicas. This is fine, since from the Prometheus perspective
// this never happens.
//
// NOTE: Use this merge function only when you see potentially overlapping series, as this introduces a small overhead
// to handle overlaps between series.
// It's optimized for non-overlap cases as well.
func
ChainedSeriesMerge
(
series
...
Series
)
Series
{
if
len
(
series
)
==
0
{
return
nil
...
...
@@ -438,16 +438,20 @@ func ChainedSeriesMerge(series ...Series) Series {
// chainSampleIterator is responsible to iterate over samples from different iterators of the same time series in timestamps
// order. If one or more samples overlap, one sample from random overlapped ones is kept and all others with the same
// timestamp are dropped.
// timestamp are dropped.
It's optimized for non-overlap cases as well.
type
chainSampleIterator
struct
{
iterators
[]
chunkenc
.
Iterator
h
samplesIteratorHeap
curr
chunkenc
.
Iterator
lastt
int64
}
func
newChainSampleIterator
(
iterators
[]
chunkenc
.
Iterator
)
chunkenc
.
Iterator
{
return
&
chainSampleIterator
{
iterators
:
iterators
,
h
:
nil
,
lastt
:
math
.
MinInt64
,
}
}
...
...
@@ -458,47 +462,74 @@ func (c *chainSampleIterator) Seek(t int64) bool {
heap
.
Push
(
&
c
.
h
,
iter
)
}
}
return
len
(
c
.
h
)
>
0
if
len
(
c
.
h
)
>
0
{
c
.
curr
=
heap
.
Pop
(
&
c
.
h
)
.
(
chunkenc
.
Iterator
)
return
true
}
c
.
curr
=
nil
return
false
}
func
(
c
*
chainSampleIterator
)
At
()
(
t
int64
,
v
float64
)
{
if
len
(
c
.
h
)
==
0
{
panic
(
"chainSampleIterator.At() called after .Next() returned false."
)
if
c
.
curr
==
nil
{
panic
(
"chainSampleIterator.At() called
before first .Next() or
after .Next() returned false."
)
}
return
c
.
h
[
0
]
.
At
()
return
c
.
curr
.
At
()
}
func
(
c
*
chainSampleIterator
)
Next
()
bool
{
if
c
.
h
==
nil
{
for
_
,
iter
:=
range
c
.
iterators
{
c
.
h
=
samplesIteratorHeap
{}
// We call c.curr.Next() as the first thing below.
// So, we don't call Next() on it here.
c
.
curr
=
c
.
iterators
[
0
]
for
_
,
iter
:=
range
c
.
iterators
[
1
:
]
{
if
iter
.
Next
()
{
heap
.
Push
(
&
c
.
h
,
iter
)
}
}
return
len
(
c
.
h
)
>
0
}
if
len
(
c
.
h
)
==
0
{
if
c
.
curr
==
nil
{
return
false
}
currt
,
_
:=
c
.
At
()
for
len
(
c
.
h
)
>
0
{
nextt
,
_
:=
c
.
h
[
0
]
.
At
()
// All but one of the overlapping samples will be dropped.
if
nextt
!=
currt
{
break
var
currt
int64
for
{
if
c
.
curr
.
Next
()
{
currt
,
_
=
c
.
curr
.
At
()
if
currt
==
c
.
lastt
{
// Ignoring sample for the same timestamp.
continue
}
if
len
(
c
.
h
)
==
0
{
// curr is the only iterator remaining,
// no need to check with the heap.
break
}
// Check current iterator with the top of the heap.
if
nextt
,
_
:=
c
.
h
[
0
]
.
At
();
currt
<
nextt
{
// Current iterator has smaller timestamp than the heap.
break
}
// Current iterator does not hold the smallest timestamp.
heap
.
Push
(
&
c
.
h
,
c
.
curr
)
}
else
if
len
(
c
.
h
)
==
0
{
// No iterator left to iterate.
c
.
curr
=
nil
return
false
}
iter
:=
heap
.
Pop
(
&
c
.
h
)
.
(
chunkenc
.
Iterator
)
if
iter
.
Next
()
{
heap
.
Push
(
&
c
.
h
,
iter
)
c
.
curr
=
heap
.
Pop
(
&
c
.
h
)
.
(
chunkenc
.
Iterator
)
currt
,
_
=
c
.
curr
.
At
()
if
currt
!=
c
.
lastt
{
break
}
}
return
len
(
c
.
h
)
>
0
c
.
lastt
=
currt
return
true
}
func
(
c
*
chainSampleIterator
)
Err
()
error
{
...
...
storage/merge_test.go
浏览文件 @
a6ee1f85
...
...
@@ -448,10 +448,10 @@ func TestCompactingChunkSeriesMerger(t *testing.T) {
name
:
"three in chained overlap"
,
input
:
[]
ChunkSeries
{
NewListChunkSeriesFromSamples
(
labels
.
FromStrings
(
"bar"
,
"baz"
),
[]
tsdbutil
.
Sample
{
sample
{
1
,
1
},
sample
{
2
,
2
},
sample
{
3
,
3
},
sample
{
5
,
5
}}),
NewListChunkSeriesFromSamples
(
labels
.
FromStrings
(
"bar"
,
"baz"
),
[]
tsdbutil
.
Sample
{
sample
{
4
,
4
},
sample
{
6
,
6
}}),
NewListChunkSeriesFromSamples
(
labels
.
FromStrings
(
"bar"
,
"baz"
),
[]
tsdbutil
.
Sample
{
sample
{
4
,
4
},
sample
{
6
,
6
6
}}),
NewListChunkSeriesFromSamples
(
labels
.
FromStrings
(
"bar"
,
"baz"
),
[]
tsdbutil
.
Sample
{
sample
{
6
,
6
},
sample
{
10
,
10
}}),
},
expected
:
NewListChunkSeriesFromSamples
(
labels
.
FromStrings
(
"bar"
,
"baz"
),
[]
tsdbutil
.
Sample
{
sample
{
1
,
1
},
sample
{
2
,
2
},
sample
{
3
,
3
},
sample
{
4
,
4
},
sample
{
5
,
5
},
sample
{
6
,
6
},
sample
{
10
,
10
}}),
expected
:
NewListChunkSeriesFromSamples
(
labels
.
FromStrings
(
"bar"
,
"baz"
),
[]
tsdbutil
.
Sample
{
sample
{
1
,
1
},
sample
{
2
,
2
},
sample
{
3
,
3
},
sample
{
4
,
4
},
sample
{
5
,
5
},
sample
{
6
,
6
6
},
sample
{
10
,
10
}}),
},
{
name
:
"three in chained overlap complex"
,
...
...
web/api/v1/api.go
浏览文件 @
a6ee1f85
...
...
@@ -603,7 +603,8 @@ func (api *API) series(r *http.Request) (result apiFuncResult) {
var
sets
[]
storage
.
SeriesSet
for
_
,
mset
:=
range
matcherSets
{
s
:=
q
.
Select
(
false
,
nil
,
mset
...
)
// We need to sort this select results to merge (deduplicate) the series sets later.
s
:=
q
.
Select
(
true
,
nil
,
mset
...
)
sets
=
append
(
sets
,
s
)
}
...
...
web/api/v1/api_test.go
浏览文件 @
a6ee1f85
...
...
@@ -303,6 +303,11 @@ func TestEndpoints(t *testing.T) {
test_metric1{foo="bar"} 0+100x100
test_metric1{foo="boo"} 1+0x100
test_metric2{foo="boo"} 1+0x100
test_metric3{foo="bar", dup="1"} 1+0x100
test_metric3{foo="boo", dup="1"} 1+0x100
test_metric4{foo="bar", dup="1"} 1+0x100
test_metric4{foo="boo", dup="1"} 1+0x100
test_metric4{foo="boo"} 1+0x100
`
)
testutil
.
Ok
(
t
,
err
)
defer
suite
.
Close
()
...
...
@@ -737,6 +742,18 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, testLabelAPI
labels
.
FromStrings
(
"__name__"
,
"test_metric1"
,
"foo"
,
"boo"
),
},
},
// Try to overlap the selected series set as much as possible to test the result de-duplication works well.
{
endpoint
:
api
.
series
,
query
:
url
.
Values
{
"match[]"
:
[]
string
{
`test_metric4{foo=~".+o$"}`
,
`test_metric4{dup=~"^1"}`
},
},
response
:
[]
labels
.
Labels
{
labels
.
FromStrings
(
"__name__"
,
"test_metric4"
,
"dup"
,
"1"
,
"foo"
,
"bar"
),
labels
.
FromStrings
(
"__name__"
,
"test_metric4"
,
"dup"
,
"1"
,
"foo"
,
"boo"
),
labels
.
FromStrings
(
"__name__"
,
"test_metric4"
,
"foo"
,
"boo"
),
},
},
{
endpoint
:
api
.
series
,
query
:
url
.
Values
{
...
...
@@ -1449,6 +1466,8 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, testLabelAPI
response
:
[]
string
{
"test_metric1"
,
"test_metric2"
,
"test_metric3"
,
"test_metric4"
,
},
},
{
...
...
@@ -1597,7 +1616,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, testLabelAPI
// Label names.
{
endpoint
:
api
.
labelNames
,
response
:
[]
string
{
"__name__"
,
"foo"
},
response
:
[]
string
{
"__name__"
,
"
dup"
,
"
foo"
},
},
// Start and end before Label names starts.
{
...
...
@@ -1615,7 +1634,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, testLabelAPI
"start"
:
[]
string
{
"1"
},
"end"
:
[]
string
{
"100"
},
},
response
:
[]
string
{
"__name__"
,
"foo"
},
response
:
[]
string
{
"__name__"
,
"
dup"
,
"
foo"
},
},
// Start before Label names, end within Label names.
{
...
...
@@ -1624,7 +1643,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, testLabelAPI
"start"
:
[]
string
{
"-1"
},
"end"
:
[]
string
{
"10"
},
},
response
:
[]
string
{
"__name__"
,
"foo"
},
response
:
[]
string
{
"__name__"
,
"
dup"
,
"
foo"
},
},
// Start before Label names starts, end after Label names ends.
...
...
@@ -1634,7 +1653,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, testLabelAPI
"start"
:
[]
string
{
"-1"
},
"end"
:
[]
string
{
"100000"
},
},
response
:
[]
string
{
"__name__"
,
"foo"
},
response
:
[]
string
{
"__name__"
,
"
dup"
,
"
foo"
},
},
// Start with bad data for Label names, end within Label names.
{
...
...
@@ -1652,7 +1671,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, testLabelAPI
"start"
:
[]
string
{
"1"
},
"end"
:
[]
string
{
"1000000006"
},
},
response
:
[]
string
{
"__name__"
,
"foo"
},
response
:
[]
string
{
"__name__"
,
"
dup"
,
"
foo"
},
},
// Start and end after Label names ends.
{
...
...
@@ -1669,7 +1688,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, testLabelAPI
query
:
url
.
Values
{
"start"
:
[]
string
{
"4"
},
},
response
:
[]
string
{
"__name__"
,
"foo"
},
response
:
[]
string
{
"__name__"
,
"
dup"
,
"
foo"
},
},
// Only provide End within Label names, don't provide a start time.
{
...
...
@@ -1677,7 +1696,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, testLabelAPI
query
:
url
.
Values
{
"end"
:
[]
string
{
"20"
},
},
response
:
[]
string
{
"__name__"
,
"foo"
},
response
:
[]
string
{
"__name__"
,
"
dup"
,
"
foo"
},
},
}
...
)
}
...
...
web/ui/react-app/src/pages/targets/TargetLabels.test.tsx
浏览文件 @
a6ee1f85
...
...
@@ -31,8 +31,10 @@ describe('targetLabels', () => {
it
(
'
wraps each label in a label badge
'
,
()
=>
{
const
l
:
{
[
key
:
string
]:
string
}
=
defaultProps
.
labels
;
Object
.
keys
(
l
).
forEach
((
labelName
:
string
):
void
=>
{
const
badge
=
targetLabels
.
find
(
Badge
).
filterWhere
(
badge
=>
badge
.
hasClass
(
labelName
));
expect
(
badge
.
children
().
text
()).
toEqual
(
`
${
labelName
}
="
${
l
[
labelName
]}
"`
);
const
badge
=
targetLabels
.
find
(
Badge
)
.
filterWhere
(
badge
=>
badge
.
children
().
text
()
===
`
${
labelName
}
="
${
l
[
labelName
]}
"`
);
expect
(
badge
).
toHaveLength
(
1
);
});
expect
(
targetLabels
.
find
(
Badge
)).
toHaveLength
(
3
);
});
...
...
web/ui/react-app/src/pages/targets/TargetLabels.tsx
浏览文件 @
a6ee1f85
...
...
@@ -27,7 +27,7 @@ const TargetLabels: FC<TargetLabelsProps> = ({ discoveredLabels, labels, idx, sc
<
div
id
=
{
id
}
className
=
"series-labels-container"
>
{
Object
.
keys
(
labels
).
map
(
labelName
=>
{
return
(
<
Badge
color
=
"primary"
className
=
{
`mr-1
${
labelName
}
`
}
key
=
{
labelName
}
>
<
Badge
color
=
"primary"
className
=
"mr-1"
key
=
{
labelName
}
>
{
`
${
labelName
}
="
${
labels
[
labelName
]}
"`
}
</
Badge
>
);
...
...
web/ui/react-app/src/pages/targets/__snapshots__/TargetLabels.test.tsx.snap
浏览文件 @
a6ee1f85
...
...
@@ -7,7 +7,7 @@ exports[`targetLabels renders discovered labels 1`] = `
id="series-labels-cortex/node-exporter_group/0-1"
>
<Badge
className="mr-1
instance
"
className="mr-1"
color="primary"
key="instance"
pill={false}
...
...
@@ -16,7 +16,7 @@ exports[`targetLabels renders discovered labels 1`] = `
instance="localhost:9100"
</Badge>
<Badge
className="mr-1
job
"
className="mr-1"
color="primary"
key="job"
pill={false}
...
...
@@ -25,7 +25,7 @@ exports[`targetLabels renders discovered labels 1`] = `
job="node_exporter"
</Badge>
<Badge
className="mr-1
foo
"
className="mr-1"
color="primary"
key="foo"
pill={false}
...
...
web/ui/templates/rules.html
浏览文件 @
a6ee1f85
...
...
@@ -10,8 +10,8 @@
<thead>
<tr>
<td
colspan=
"3"
><h2><a
href=
"#{{reReplaceAll "
([^
a-zA-Z0-9
])"
"$1"
.
Name
}}"
id=
"{{reReplaceAll "
([^
a-zA-Z0-9
])"
"$1"
.
Name
}}"
>
{{.Name}}
</a></h2></td>
<td><h2>
{{if .Get
EvaluationTimestamp.IsZero}}Never{{else}}{{since .GetEvaluationTimestamp
}} ago{{end}}
</h2></td>
<td><h2>
{{humanizeDuration .GetEvaluation
Duration
.Seconds}}
</h2></td>
<td><h2>
{{if .Get
LastEvaluation.IsZero}}Never{{else}}{{since .GetLastEvaluation
}} ago{{end}}
</h2></td>
<td><h2>
{{humanizeDuration .GetEvaluation
Time
.Seconds}}
</h2></td>
</tr>
</thead>
<tbody>
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录