Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
doodoocoder
prometheus
提交
00f16d1a
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,体验更适合开发者的 AI 搜索 >>
未验证
提交
00f16d1a
编写于
11月 05, 2020
作者:
F
Frederic Branczyk
提交者:
GitHub
11月 05, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #8146 from brancz/cp-8104-8061
Cut v2.22.1
上级
f3da817d
8e0e326f
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
137 addition
and
16 deletion
+137
-16
CHANGELOG.md
CHANGELOG.md
+6
-0
VERSION
VERSION
+1
-1
scrape/scrape.go
scrape/scrape.go
+24
-15
tsdb/chunks/head_chunks.go
tsdb/chunks/head_chunks.go
+36
-0
tsdb/chunks/head_chunks_test.go
tsdb/chunks/head_chunks_test.go
+70
-0
未找到文件。
CHANGELOG.md
浏览文件 @
00f16d1a
## 2.22.1 / 2020-11-03
*
[BUGFIX] Fix potential "mmap: invalid argument" errors in loading the head chunks, after an unclean shutdown, by performing read repairs. #8061
*
[BUGFIX] Fix serving metrics and API when reloading scrape config. #8104
*
[BUGFIX] Fix head chunk size calculation for size based retention. #8139
## 2.22.0 / 2020-10-07
As announced in the 2.21.0 release notes, the experimental gRPC API v2 has been
...
...
VERSION
浏览文件 @
00f16d1a
2.22.
0
2.22.
1
scrape/scrape.go
浏览文件 @
00f16d1a
...
...
@@ -192,7 +192,13 @@ type scrapePool struct {
appendable
storage
.
Appendable
logger
log
.
Logger
mtx
sync
.
Mutex
// targetMtx protects activeTargets and droppedTargets from concurrent reads
// and writes. Only one of Sync/stop/reload may be called at once due to
// manager.mtxScrape so we only need to protect from concurrent reads from
// the ActiveTargets and DroppedTargets methods. This allows those two
// methods to always complete without having to wait on scrape loops to gracefull stop.
targetMtx
sync
.
Mutex
config
*
config
.
ScrapeConfig
client
*
http
.
Client
// Targets and loops must always be synchronized to have the same
...
...
@@ -273,8 +279,8 @@ func newScrapePool(cfg *config.ScrapeConfig, app storage.Appendable, jitterSeed
}
func
(
sp
*
scrapePool
)
ActiveTargets
()
[]
*
Target
{
sp
.
m
tx
.
Lock
()
defer
sp
.
m
tx
.
Unlock
()
sp
.
targetM
tx
.
Lock
()
defer
sp
.
targetM
tx
.
Unlock
()
var
tActive
[]
*
Target
for
_
,
t
:=
range
sp
.
activeTargets
{
...
...
@@ -284,8 +290,8 @@ func (sp *scrapePool) ActiveTargets() []*Target {
}
func
(
sp
*
scrapePool
)
DroppedTargets
()
[]
*
Target
{
sp
.
m
tx
.
Lock
()
defer
sp
.
m
tx
.
Unlock
()
sp
.
targetM
tx
.
Lock
()
defer
sp
.
targetM
tx
.
Unlock
()
return
sp
.
droppedTargets
}
...
...
@@ -294,8 +300,7 @@ func (sp *scrapePool) stop() {
sp
.
cancel
()
var
wg
sync
.
WaitGroup
sp
.
mtx
.
Lock
()
defer
sp
.
mtx
.
Unlock
()
sp
.
targetMtx
.
Lock
()
for
fp
,
l
:=
range
sp
.
loops
{
wg
.
Add
(
1
)
...
...
@@ -308,6 +313,9 @@ func (sp *scrapePool) stop() {
delete
(
sp
.
loops
,
fp
)
delete
(
sp
.
activeTargets
,
fp
)
}
sp
.
targetMtx
.
Unlock
()
wg
.
Wait
()
sp
.
client
.
CloseIdleConnections
()
...
...
@@ -326,9 +334,6 @@ func (sp *scrapePool) reload(cfg *config.ScrapeConfig) error {
targetScrapePoolReloads
.
Inc
()
start
:=
time
.
Now
()
sp
.
mtx
.
Lock
()
defer
sp
.
mtx
.
Unlock
()
client
,
err
:=
config_util
.
NewClientFromConfig
(
cfg
.
HTTPClientConfig
,
cfg
.
JobName
,
false
,
false
)
if
err
!=
nil
{
targetScrapePoolReloadsFailed
.
Inc
()
...
...
@@ -352,6 +357,8 @@ func (sp *scrapePool) reload(cfg *config.ScrapeConfig) error {
mrc
=
sp
.
config
.
MetricRelabelConfigs
)
sp
.
targetMtx
.
Lock
()
forcedErr
:=
sp
.
refreshTargetLimitErr
()
for
fp
,
oldLoop
:=
range
sp
.
loops
{
var
cache
*
scrapeCache
...
...
@@ -387,6 +394,8 @@ func (sp *scrapePool) reload(cfg *config.ScrapeConfig) error {
sp
.
loops
[
fp
]
=
newLoop
}
sp
.
targetMtx
.
Unlock
()
wg
.
Wait
()
oldClient
.
CloseIdleConnections
()
targetReloadIntervalLength
.
WithLabelValues
(
interval
.
String
())
.
Observe
(
...
...
@@ -398,11 +407,9 @@ func (sp *scrapePool) reload(cfg *config.ScrapeConfig) error {
// Sync converts target groups into actual scrape targets and synchronizes
// the currently running scraper with the resulting set and returns all scraped and dropped targets.
func
(
sp
*
scrapePool
)
Sync
(
tgs
[]
*
targetgroup
.
Group
)
{
sp
.
mtx
.
Lock
()
defer
sp
.
mtx
.
Unlock
()
start
:=
time
.
Now
()
sp
.
targetMtx
.
Lock
()
var
all
[]
*
Target
sp
.
droppedTargets
=
[]
*
Target
{}
for
_
,
tg
:=
range
tgs
{
...
...
@@ -419,6 +426,7 @@ func (sp *scrapePool) Sync(tgs []*targetgroup.Group) {
}
}
}
sp
.
targetMtx
.
Unlock
()
sp
.
sync
(
all
)
targetSyncIntervalLength
.
WithLabelValues
(
sp
.
config
.
JobName
)
.
Observe
(
...
...
@@ -431,7 +439,6 @@ func (sp *scrapePool) Sync(tgs []*targetgroup.Group) {
// scrape loops for new targets, and stops scrape loops for disappeared targets.
// It returns after all stopped scrape loops terminated.
func
(
sp
*
scrapePool
)
sync
(
targets
[]
*
Target
)
{
// This function expects that you have acquired the sp.mtx lock.
var
(
uniqueLoops
=
make
(
map
[
uint64
]
loop
)
interval
=
time
.
Duration
(
sp
.
config
.
ScrapeInterval
)
...
...
@@ -442,6 +449,7 @@ func (sp *scrapePool) sync(targets []*Target) {
mrc
=
sp
.
config
.
MetricRelabelConfigs
)
sp
.
targetMtx
.
Lock
()
for
_
,
t
:=
range
targets
{
hash
:=
t
.
hash
()
...
...
@@ -487,6 +495,8 @@ func (sp *scrapePool) sync(targets []*Target) {
}
}
sp
.
targetMtx
.
Unlock
()
targetScrapePoolTargetsAdded
.
WithLabelValues
(
sp
.
config
.
JobName
)
.
Set
(
float64
(
len
(
uniqueLoops
)))
forcedErr
:=
sp
.
refreshTargetLimitErr
()
for
_
,
l
:=
range
sp
.
loops
{
...
...
@@ -507,7 +517,6 @@ func (sp *scrapePool) sync(targets []*Target) {
// refreshTargetLimitErr returns an error that can be passed to the scrape loops
// if the number of targets exceeds the configured limit.
func
(
sp
*
scrapePool
)
refreshTargetLimitErr
()
error
{
// This function expects that you have acquired the sp.mtx lock.
if
sp
.
config
==
nil
||
sp
.
config
.
TargetLimit
==
0
&&
!
sp
.
targetLimitHit
{
return
nil
}
...
...
tsdb/chunks/head_chunks.go
浏览文件 @
00f16d1a
...
...
@@ -163,6 +163,11 @@ func (cdm *ChunkDiskMapper) openMMapFiles() (returnErr error) {
return
err
}
files
,
err
=
repairLastChunkFile
(
files
)
if
err
!=
nil
{
return
err
}
chkFileIndices
:=
make
([]
int
,
0
,
len
(
files
))
for
seq
,
fn
:=
range
files
{
f
,
err
:=
fileutil
.
OpenMmapFile
(
fn
)
...
...
@@ -218,9 +223,40 @@ func listChunkFiles(dir string) (map[int]string, error) {
}
res
[
int
(
seq
)]
=
filepath
.
Join
(
dir
,
fi
.
Name
())
}
return
res
,
nil
}
// repairLastChunkFile deletes the last file if it's empty.
// Because we don't fsync when creating these file, we could end
// up with an empty file at the end during an abrupt shutdown.
func
repairLastChunkFile
(
files
map
[
int
]
string
)
(
_
map
[
int
]
string
,
returnErr
error
)
{
lastFile
:=
-
1
for
seq
:=
range
files
{
if
seq
>
lastFile
{
lastFile
=
seq
}
}
if
lastFile
<=
0
{
return
files
,
nil
}
info
,
err
:=
os
.
Stat
(
files
[
lastFile
])
if
err
!=
nil
{
return
files
,
errors
.
Wrap
(
err
,
"file stat during last head chunk file repair"
)
}
if
info
.
Size
()
==
0
{
// Corrupt file, hence remove it.
if
err
:=
os
.
RemoveAll
(
files
[
lastFile
]);
err
!=
nil
{
return
files
,
errors
.
Wrap
(
err
,
"delete corrupted, empty head chunk file during last file repair"
)
}
delete
(
files
,
lastFile
)
}
return
files
,
nil
}
// WriteChunk writes the chunk to the disk.
// The returned chunk ref is the reference from where the chunk encoding starts for the chunk.
func
(
cdm
*
ChunkDiskMapper
)
WriteChunk
(
seriesRef
uint64
,
mint
,
maxt
int64
,
chk
chunkenc
.
Chunk
)
(
chkRef
uint64
,
err
error
)
{
...
...
tsdb/chunks/head_chunks_test.go
浏览文件 @
00f16d1a
...
...
@@ -19,6 +19,7 @@ import (
"io/ioutil"
"math/rand"
"os"
"strconv"
"testing"
"github.com/prometheus/prometheus/tsdb/chunkenc"
...
...
@@ -363,6 +364,75 @@ func TestHeadReadWriter_TruncateAfterFailedIterateChunks(t *testing.T) {
testutil
.
Ok
(
t
,
hrw
.
Truncate
(
2000
))
}
func
TestHeadReadWriter_ReadRepairOnEmptyLastFile
(
t
*
testing
.
T
)
{
hrw
:=
testHeadReadWriter
(
t
)
defer
func
()
{
testutil
.
Ok
(
t
,
hrw
.
Close
())
}()
timeRange
:=
0
addChunk
:=
func
()
{
step
:=
100
mint
,
maxt
:=
timeRange
+
1
,
timeRange
+
step
-
1
_
,
err
:=
hrw
.
WriteChunk
(
1
,
int64
(
mint
),
int64
(
maxt
),
randomChunk
(
t
))
testutil
.
Ok
(
t
,
err
)
timeRange
+=
step
}
nonEmptyFile
:=
func
()
{
testutil
.
Ok
(
t
,
hrw
.
CutNewFile
())
addChunk
()
}
addChunk
()
// 1. Created with the first chunk.
nonEmptyFile
()
// 2.
nonEmptyFile
()
// 3.
testutil
.
Equals
(
t
,
3
,
len
(
hrw
.
mmappedChunkFiles
))
lastFile
:=
0
for
idx
:=
range
hrw
.
mmappedChunkFiles
{
if
idx
>
lastFile
{
lastFile
=
idx
}
}
testutil
.
Equals
(
t
,
3
,
lastFile
)
dir
:=
hrw
.
dir
.
Name
()
testutil
.
Ok
(
t
,
hrw
.
Close
())
// Write an empty last file mimicking an abrupt shutdown on file creation.
emptyFileName
:=
segmentFile
(
dir
,
lastFile
+
1
)
f
,
err
:=
os
.
OpenFile
(
emptyFileName
,
os
.
O_WRONLY
|
os
.
O_CREATE
,
0666
)
testutil
.
Ok
(
t
,
err
)
testutil
.
Ok
(
t
,
f
.
Sync
())
stat
,
err
:=
f
.
Stat
()
testutil
.
Ok
(
t
,
err
)
testutil
.
Equals
(
t
,
int64
(
0
),
stat
.
Size
())
testutil
.
Ok
(
t
,
f
.
Close
())
// Open chunk disk mapper again, corrupt file should be removed.
hrw
,
err
=
NewChunkDiskMapper
(
dir
,
chunkenc
.
NewPool
())
testutil
.
Ok
(
t
,
err
)
testutil
.
Assert
(
t
,
!
hrw
.
fileMaxtSet
,
""
)
testutil
.
Ok
(
t
,
hrw
.
IterateAllChunks
(
func
(
_
,
_
uint64
,
_
,
_
int64
,
_
uint16
)
error
{
return
nil
}))
testutil
.
Assert
(
t
,
hrw
.
fileMaxtSet
,
""
)
// Removed from memory.
testutil
.
Equals
(
t
,
3
,
len
(
hrw
.
mmappedChunkFiles
))
for
idx
:=
range
hrw
.
mmappedChunkFiles
{
testutil
.
Assert
(
t
,
idx
<=
lastFile
,
"file index is bigger than previous last file"
)
}
// Removed even from disk.
files
,
err
:=
ioutil
.
ReadDir
(
dir
)
testutil
.
Ok
(
t
,
err
)
testutil
.
Equals
(
t
,
3
,
len
(
files
))
for
_
,
fi
:=
range
files
{
seq
,
err
:=
strconv
.
ParseUint
(
fi
.
Name
(),
10
,
64
)
testutil
.
Ok
(
t
,
err
)
testutil
.
Assert
(
t
,
seq
<=
uint64
(
lastFile
),
"file index on disk is bigger than previous last file"
)
}
}
func
testHeadReadWriter
(
t
*
testing
.
T
)
*
ChunkDiskMapper
{
tmpdir
,
err
:=
ioutil
.
TempDir
(
""
,
"data"
)
testutil
.
Ok
(
t
,
err
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录