Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
doodoocoder
prometheus
提交
ff54c5c1
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,发现更多精彩内容 >>
提交
ff54c5c1
编写于
7月 25, 2017
作者:
E
emluque
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
2831 Add Healthy and Ready endpoints
上级
4b868113
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
144 addition
and
21 deletion
+144
-21
cmd/prometheus/main.go
cmd/prometheus/main.go
+5
-2
web/web.go
web/web.go
+60
-19
web/web_test.go
web/web_test.go
+79
-0
未找到文件。
cmd/prometheus/main.go
浏览文件 @
ff54c5c1
...
@@ -153,6 +153,7 @@ func Main() int {
...
@@ -153,6 +153,7 @@ func Main() int {
})
})
webHandler
:=
web
.
New
(
&
cfg
.
web
)
webHandler
:=
web
.
New
(
&
cfg
.
web
)
go
webHandler
.
Run
()
reloadables
=
append
(
reloadables
,
targetManager
,
ruleManager
,
webHandler
,
notifier
)
reloadables
=
append
(
reloadables
,
targetManager
,
ruleManager
,
webHandler
,
notifier
)
...
@@ -222,11 +223,13 @@ func Main() int {
...
@@ -222,11 +223,13 @@ func Main() int {
// to be canceled and ensures a quick shutdown of the rule manager.
// to be canceled and ensures a quick shutdown of the rule manager.
defer
cancelCtx
()
defer
cancelCtx
()
go
webHandler
.
Run
()
// Wait for reload or termination signals.
// Wait for reload or termination signals.
close
(
hupReady
)
// Unblock SIGHUP handler.
close
(
hupReady
)
// Unblock SIGHUP handler.
// Set web server to ready.
webHandler
.
Ready
()
log
.
Info
(
"Server is Ready to receive requests."
)
term
:=
make
(
chan
os
.
Signal
)
term
:=
make
(
chan
os
.
Signal
)
signal
.
Notify
(
term
,
os
.
Interrupt
,
syscall
.
SIGTERM
)
signal
.
Notify
(
term
,
os
.
Interrupt
,
syscall
.
SIGTERM
)
select
{
select
{
...
...
web/web.go
浏览文件 @
ff54c5c1
...
@@ -28,6 +28,7 @@ import (
...
@@ -28,6 +28,7 @@ import (
"sort"
"sort"
"strings"
"strings"
"sync"
"sync"
"sync/atomic"
"time"
"time"
pprof_runtime
"runtime/pprof"
pprof_runtime
"runtime/pprof"
...
@@ -81,6 +82,8 @@ type Handler struct {
...
@@ -81,6 +82,8 @@ type Handler struct {
externalLabels
model
.
LabelSet
externalLabels
model
.
LabelSet
mtx
sync
.
RWMutex
mtx
sync
.
RWMutex
now
func
()
model
.
Time
now
func
()
model
.
Time
ready
uint32
// ready is uint32 rather than boolean to be able to use atomic functions.
}
}
// ApplyConfig updates the status state as the new config requires.
// ApplyConfig updates the status state as the new config requires.
...
@@ -157,6 +160,8 @@ func New(o *Options) *Handler {
...
@@ -157,6 +160,8 @@ func New(o *Options) *Handler {
apiV1
:
api_v1
.
NewAPI
(
o
.
QueryEngine
,
o
.
Storage
,
o
.
TargetManager
,
o
.
Notifier
),
apiV1
:
api_v1
.
NewAPI
(
o
.
QueryEngine
,
o
.
Storage
,
o
.
TargetManager
,
o
.
Notifier
),
now
:
model
.
Now
,
now
:
model
.
Now
,
ready
:
0
,
}
}
if
o
.
RoutePrefix
!=
"/"
{
if
o
.
RoutePrefix
!=
"/"
{
...
@@ -169,50 +174,60 @@ func New(o *Options) *Handler {
...
@@ -169,50 +174,60 @@ func New(o *Options) *Handler {
instrh
:=
prometheus
.
InstrumentHandler
instrh
:=
prometheus
.
InstrumentHandler
instrf
:=
prometheus
.
InstrumentHandlerFunc
instrf
:=
prometheus
.
InstrumentHandlerFunc
readyf
:=
h
.
testReady
router
.
Get
(
"/"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
router
.
Get
(
"/"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
http
.
Redirect
(
w
,
r
,
path
.
Join
(
o
.
ExternalURL
.
Path
,
"/graph"
),
http
.
StatusFound
)
http
.
Redirect
(
w
,
r
,
path
.
Join
(
o
.
ExternalURL
.
Path
,
"/graph"
),
http
.
StatusFound
)
})
})
router
.
Get
(
"/alerts"
,
instrf
(
"alerts"
,
h
.
alerts
))
router
.
Get
(
"/alerts"
,
readyf
(
instrf
(
"alerts"
,
h
.
alerts
)
))
router
.
Get
(
"/graph"
,
instrf
(
"graph"
,
h
.
graph
))
router
.
Get
(
"/graph"
,
readyf
(
instrf
(
"graph"
,
h
.
graph
)
))
router
.
Get
(
"/status"
,
instrf
(
"status"
,
h
.
status
))
router
.
Get
(
"/status"
,
readyf
(
instrf
(
"status"
,
h
.
status
)
))
router
.
Get
(
"/flags"
,
instrf
(
"flags"
,
h
.
flags
))
router
.
Get
(
"/flags"
,
readyf
(
instrf
(
"flags"
,
h
.
flags
)
))
router
.
Get
(
"/config"
,
instrf
(
"config"
,
h
.
config
))
router
.
Get
(
"/config"
,
readyf
(
instrf
(
"config"
,
h
.
config
)
))
router
.
Get
(
"/rules"
,
instrf
(
"rules"
,
h
.
rules
))
router
.
Get
(
"/rules"
,
readyf
(
instrf
(
"rules"
,
h
.
rules
)
))
router
.
Get
(
"/targets"
,
instrf
(
"targets"
,
h
.
targets
))
router
.
Get
(
"/targets"
,
readyf
(
instrf
(
"targets"
,
h
.
targets
)
))
router
.
Get
(
"/version"
,
instrf
(
"version"
,
h
.
version
))
router
.
Get
(
"/version"
,
readyf
(
instrf
(
"version"
,
h
.
version
)
))
router
.
Get
(
"/heap"
,
instrf
(
"heap"
,
dumpHeap
))
router
.
Get
(
"/heap"
,
readyf
(
instrf
(
"heap"
,
dumpHeap
)
))
router
.
Get
(
o
.
MetricsPath
,
prometheus
.
Handler
()
.
ServeHTTP
)
router
.
Get
(
o
.
MetricsPath
,
readyf
(
prometheus
.
Handler
()
.
ServeHTTP
)
)
router
.
Get
(
"/federate"
,
instrh
(
"federate"
,
httputil
.
CompressionHandler
{
router
.
Get
(
"/federate"
,
readyf
(
instrh
(
"federate"
,
httputil
.
CompressionHandler
{
Handler
:
http
.
HandlerFunc
(
h
.
federation
),
Handler
:
http
.
HandlerFunc
(
h
.
federation
),
}))
}))
)
h
.
apiV1
.
Register
(
router
.
WithPrefix
(
"/api/v1"
))
h
.
apiV1
.
Register
(
router
.
WithPrefix
(
"/api/v1"
))
router
.
Get
(
"/consoles/*filepath"
,
instrf
(
"consoles"
,
h
.
consoles
))
router
.
Get
(
"/consoles/*filepath"
,
readyf
(
instrf
(
"consoles"
,
h
.
consoles
)
))
router
.
Get
(
"/static/*filepath"
,
instrf
(
"static"
,
serveStaticAsset
))
router
.
Get
(
"/static/*filepath"
,
readyf
(
instrf
(
"static"
,
serveStaticAsset
)
))
if
o
.
UserAssetsPath
!=
""
{
if
o
.
UserAssetsPath
!=
""
{
router
.
Get
(
"/user/*filepath"
,
instrf
(
"user"
,
route
.
FileServe
(
o
.
UserAssetsPath
)))
router
.
Get
(
"/user/*filepath"
,
readyf
(
instrf
(
"user"
,
route
.
FileServe
(
o
.
UserAssetsPath
)
)))
}
}
if
o
.
EnableQuit
{
if
o
.
EnableQuit
{
router
.
Post
(
"/-/quit"
,
h
.
quit
)
router
.
Post
(
"/-/quit"
,
readyf
(
h
.
quit
)
)
}
}
router
.
Post
(
"/-/reload"
,
h
.
reload
)
router
.
Post
(
"/-/reload"
,
readyf
(
h
.
reload
)
)
router
.
Get
(
"/-/reload"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
router
.
Get
(
"/-/reload"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
w
.
WriteHeader
(
http
.
StatusMethodNotAllowed
)
w
.
WriteHeader
(
http
.
StatusMethodNotAllowed
)
fmt
.
Fprintf
(
w
,
"This endpoint requires a POST request.
\n
"
)
fmt
.
Fprintf
(
w
,
"This endpoint requires a POST request.
\n
"
)
})
})
router
.
Get
(
"/debug/*subpath"
,
http
.
DefaultServeMux
.
ServeHTTP
)
router
.
Get
(
"/debug/*subpath"
,
readyf
(
http
.
DefaultServeMux
.
ServeHTTP
))
router
.
Post
(
"/debug/*subpath"
,
http
.
DefaultServeMux
.
ServeHTTP
)
router
.
Post
(
"/debug/*subpath"
,
readyf
(
http
.
DefaultServeMux
.
ServeHTTP
))
router
.
Get
(
"/-/healthy"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
w
.
WriteHeader
(
http
.
StatusOK
)
fmt
.
Fprintf
(
w
,
"Prometheus is Healthy.
\n
"
)
})
router
.
Get
(
"/-/ready"
,
readyf
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
w
.
WriteHeader
(
http
.
StatusOK
)
fmt
.
Fprintf
(
w
,
"Prometheus is Ready.
\n
"
)
}))
return
h
return
h
}
}
...
@@ -239,6 +254,32 @@ func serveStaticAsset(w http.ResponseWriter, req *http.Request) {
...
@@ -239,6 +254,32 @@ func serveStaticAsset(w http.ResponseWriter, req *http.Request) {
http
.
ServeContent
(
w
,
req
,
info
.
Name
(),
info
.
ModTime
(),
bytes
.
NewReader
(
file
))
http
.
ServeContent
(
w
,
req
,
info
.
Name
(),
info
.
ModTime
(),
bytes
.
NewReader
(
file
))
}
}
// Ready sets Handler to be ready.
func
(
h
*
Handler
)
Ready
()
{
atomic
.
StoreUint32
(
&
h
.
ready
,
1
)
}
// Verifies whether the server is ready or not.
func
(
h
*
Handler
)
isReady
()
bool
{
ready
:=
atomic
.
LoadUint32
(
&
h
.
ready
)
if
ready
==
0
{
return
false
}
return
true
}
// Checks if server is ready, calls f if it is, returns 503 if it is not.
func
(
h
*
Handler
)
testReady
(
f
http
.
HandlerFunc
)
http
.
HandlerFunc
{
return
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
if
h
.
isReady
()
{
f
(
w
,
r
)
}
else
{
w
.
WriteHeader
(
http
.
StatusServiceUnavailable
)
fmt
.
Fprintf
(
w
,
"Service Unavailable"
)
}
}
}
// ListenError returns the receive-only channel that signals errors while starting the web server.
// ListenError returns the receive-only channel that signals errors while starting the web server.
func
(
h
*
Handler
)
ListenError
()
<-
chan
error
{
func
(
h
*
Handler
)
ListenError
()
<-
chan
error
{
return
h
.
listenErrCh
return
h
.
listenErrCh
...
...
web/web_test.go
浏览文件 @
ff54c5c1
...
@@ -14,8 +14,10 @@
...
@@ -14,8 +14,10 @@
package
web
package
web
import
(
import
(
"net/http"
"net/url"
"net/url"
"testing"
"testing"
"time"
)
)
func
TestGlobalURL
(
t
*
testing
.
T
)
{
func
TestGlobalURL
(
t
*
testing
.
T
)
{
...
@@ -67,3 +69,80 @@ func TestGlobalURL(t *testing.T) {
...
@@ -67,3 +69,80 @@ func TestGlobalURL(t *testing.T) {
}
}
}
}
}
}
func
TestReadyAndHealthy
(
t
*
testing
.
T
)
{
opts
:=
&
Options
{
ListenAddress
:
":9090"
,
ReadTimeout
:
30
*
time
.
Second
,
MaxConnections
:
512
,
Context
:
nil
,
Storage
:
nil
,
QueryEngine
:
nil
,
TargetManager
:
nil
,
RuleManager
:
nil
,
Notifier
:
nil
,
RoutePrefix
:
"/"
,
MetricsPath
:
"/metrics/"
,
}
opts
.
Flags
=
map
[
string
]
string
{}
webHandler
:=
New
(
opts
)
go
webHandler
.
Run
()
// Give some time for the web goroutine to run since we need the server
// to be up before starting tests.
time
.
Sleep
(
5
*
time
.
Second
)
resp
,
err
:=
http
.
Get
(
"http://localhost:9090/-/healthy"
)
if
err
!=
nil
{
t
.
Fatalf
(
"Unexpected HTTP error %s"
,
err
)
}
if
resp
.
StatusCode
!=
http
.
StatusOK
{
t
.
Fatalf
(
"Path /-/healthy with server unready test, Expected status 200 got: %s"
,
resp
.
Status
)
}
resp
,
err
=
http
.
Get
(
"http://localhost:9090/-/ready"
)
if
err
!=
nil
{
t
.
Fatalf
(
"Unexpected HTTP error %s"
,
err
)
}
if
resp
.
StatusCode
!=
http
.
StatusServiceUnavailable
{
t
.
Fatalf
(
"Path /-/ready with server unready test, Expected status 503 got: %s"
,
resp
.
Status
)
}
resp
,
err
=
http
.
Get
(
"http://localhost:9090/version"
)
if
err
!=
nil
{
t
.
Fatalf
(
"Unexpected HTTP error %s"
,
err
)
}
if
resp
.
StatusCode
!=
http
.
StatusServiceUnavailable
{
t
.
Fatalf
(
"Path /version with server unready test, Expected status 503 got: %s"
,
resp
.
Status
)
}
// Set to ready.
webHandler
.
Ready
()
resp
,
err
=
http
.
Get
(
"http://localhost:9090/-/healthy"
)
if
err
!=
nil
{
t
.
Fatalf
(
"Unexpected HTTP error %s"
,
err
)
}
if
resp
.
StatusCode
!=
http
.
StatusOK
{
t
.
Fatalf
(
"Path /-/healthy with server ready test, Expected status 200 got: %s"
,
resp
.
Status
)
}
resp
,
err
=
http
.
Get
(
"http://localhost:9090/-/ready"
)
if
err
!=
nil
{
t
.
Fatalf
(
"Unexpected HTTP error %s"
,
err
)
}
if
resp
.
StatusCode
!=
http
.
StatusOK
{
t
.
Fatalf
(
"Path /-/ready with server ready test, Expected status 200 got: %s"
,
resp
.
Status
)
}
resp
,
err
=
http
.
Get
(
"http://localhost:9090/version"
)
if
err
!=
nil
{
t
.
Fatalf
(
"Unexpected HTTP error %s"
,
err
)
}
if
resp
.
StatusCode
!=
http
.
StatusOK
{
t
.
Fatalf
(
"Path /version with server ready test, Expected status 200 got: %s"
,
resp
.
Status
)
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录