Skip to content

Commit

Permalink
feat: add healthcheck command
Browse files Browse the repository at this point in the history
  • Loading branch information
acouvreur committed Oct 23, 2024
1 parent ed357e3 commit 39abad4
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 7 deletions.
10 changes: 7 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ WORKDIR /go/mimic

# Download go modules
COPY go.mod .
COPY go.sum .
RUN GO111MODULE=on GOPROXY=https://proxy.golang.org go mod download
# COPY go.sum .
# RUN GO111MODULE=on GOPROXY=https://proxy.golang.org go mod download

COPY . .

Expand All @@ -21,4 +21,8 @@ COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=builder /go/mimic/mimic .

ENTRYPOINT ["/mimic"]
EXPOSE 80
EXPOSE 80

# Shell-less healthcheck are not working: https://github.com/docker/cli/issues/3719
# HEALTHCHECK --start-period=10s --start-interval=1 --interval=1s --timeout=3s --retries=50 \
# CMD /mimic healthcheck || exit 1
45 changes: 41 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,15 @@ func init() {
}

func main() {
os.Exit(run())
if len(os.Args) < 2 {
os.Exit(run())
}
switch os.Args[1] {
case "healthcheck":
os.Exit(healthcheck())
default:
os.Exit(run())
}
}

func run() int {
Expand All @@ -55,6 +63,12 @@ func server() {

log.Printf("Starting up on port %s (started in %.0f seconds)", *port, time.Since(startingTime).Seconds())

if *healthy {
log.Printf("Application is started... Should be healthy in %.0f seconds.", healthyAfter.Seconds())
} else {
log.Print("Application is started... Will be unhealthy because -healthy=false.")
}

log.Fatal(http.ListenAndServe(":"+*port, mux))
}

Expand All @@ -80,34 +94,57 @@ func hello(rw http.ResponseWriter, _ *http.Request) {
func health(rw http.ResponseWriter, _ *http.Request) {
// Starting
if *healthy && time.Since(startingTime) < *healthyAfter {
rw.WriteHeader(http.StatusServiceUnavailable)
_, err := rw.Write([]byte("starting"))
if err != nil {
http.Error(rw, err.Error(), http.StatusInternalServerError)
return
}
rw.WriteHeader(http.StatusOK)
return
}

// healthy
if *healthy && time.Since(startingTime) > *healthyAfter {
rw.WriteHeader(http.StatusOK)
_, err := rw.Write([]byte("healthy"))
if err != nil {
http.Error(rw, err.Error(), http.StatusInternalServerError)
return
}
rw.WriteHeader(http.StatusOK)
return
}

// Unhealthy
if !*healthy {
rw.WriteHeader(http.StatusServiceUnavailable)
_, err := rw.Write([]byte("unhealthy"))
if err != nil {
http.Error(rw, err.Error(), http.StatusInternalServerError)
return
}
rw.WriteHeader(http.StatusServiceUnavailable)
return
}
}

func healthcheck() int {
request, err := http.NewRequest("GET", "http://localhost:"+*port+"/health", http.NoBody)
if err != nil {
log.Printf("Error creating request: %v", err)
return 1
}

response, err := http.DefaultClient.Do(request)
if err != nil {
log.Printf("Error making request: %v", err)
return 1
}
defer response.Body.Close()

if response.StatusCode != http.StatusOK {
log.Printf("Bad healthcheck status: %s", response.Status)
return 1
}

log.Printf("Good healthcheck status: %s", response.Status)
return 0
}

0 comments on commit 39abad4

Please sign in to comment.