first commit
هذا الالتزام موجود في:
8
q1-deploy-monitor/app/.dockerignore
Normal file
8
q1-deploy-monitor/app/.dockerignore
Normal file
@@ -0,0 +1,8 @@
|
||||
.git
|
||||
.gitignore
|
||||
.env
|
||||
.env.*
|
||||
README.md
|
||||
Dockerfile
|
||||
.dockerignore
|
||||
dashboard
|
||||
34
q1-deploy-monitor/app/Dockerfile
Normal file
34
q1-deploy-monitor/app/Dockerfile
Normal file
@@ -0,0 +1,34 @@
|
||||
# Build stage
|
||||
FROM golang:1.26-alpine AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy dependency files first to leverage Docker cache
|
||||
COPY go.mod ./
|
||||
|
||||
# Copy source code
|
||||
COPY . .
|
||||
|
||||
# Build the application
|
||||
RUN go build -o server .
|
||||
|
||||
|
||||
# Runtime stage
|
||||
FROM alpine:3.20
|
||||
|
||||
# Create a non-root user
|
||||
RUN adduser -D appuser
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy the compiled binary
|
||||
COPY --from=builder /app/server .
|
||||
|
||||
# Run as non-root user
|
||||
USER appuser
|
||||
|
||||
# Document the application port
|
||||
EXPOSE 8080
|
||||
|
||||
# Start the application
|
||||
CMD ["./server"]
|
||||
3
q1-deploy-monitor/app/go.mod
Normal file
3
q1-deploy-monitor/app/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module q1-deploy-monitor
|
||||
|
||||
go 1.26.5
|
||||
95
q1-deploy-monitor/app/main.go
Normal file
95
q1-deploy-monitor/app/main.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// Stores the total number of API requests.
|
||||
var requestCount uint64
|
||||
|
||||
func main() {
|
||||
// Register API endpoints
|
||||
http.HandleFunc("/", requestCounter(helloHandler))
|
||||
http.HandleFunc("/health", requestCounter(healthHandler))
|
||||
http.HandleFunc("/metrics", metricsHandler)
|
||||
|
||||
// Start server on port 8080
|
||||
fmt.Println("Server is running on port 8080")
|
||||
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||
}
|
||||
|
||||
// Middleware that counts API requests.
|
||||
// The /metrics endpoint is not wrapped with this middleware,
|
||||
// so requests to /metrics are not included in the counter.
|
||||
func requestCounter(next http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
atomic.AddUint64(&requestCount, 1)
|
||||
next(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
// Adds CORS headers to allow the dashboard to access the API.
|
||||
func enableCORS(w http.ResponseWriter) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
|
||||
}
|
||||
|
||||
// Root endpoint
|
||||
func helloHandler(w http.ResponseWriter, r *http.Request) {
|
||||
enableCORS(w)
|
||||
|
||||
// Handle browser CORS preflight requests
|
||||
if r.Method == http.MethodOptions {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
json.NewEncoder(w).Encode(map[string]string{
|
||||
"message": "Hello, World!",
|
||||
})
|
||||
}
|
||||
|
||||
// Health check endpoint
|
||||
func healthHandler(w http.ResponseWriter, r *http.Request) {
|
||||
enableCORS(w)
|
||||
|
||||
// Handle browser CORS preflight requests
|
||||
if r.Method == http.MethodOptions {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
json.NewEncoder(w).Encode(map[string]string{
|
||||
"status": "healthy",
|
||||
})
|
||||
}
|
||||
|
||||
// Metrics endpoint
|
||||
// This endpoint does NOT increment the request counter.
|
||||
func metricsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
enableCORS(w)
|
||||
|
||||
// Handle browser CORS preflight requests
|
||||
if r.Method == http.MethodOptions {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
json.NewEncoder(w).Encode(map[string]uint64{
|
||||
"requests": atomic.LoadUint64(&requestCount),
|
||||
})
|
||||
}
|
||||
المرجع في مشكلة جديدة
حظر مستخدم