JSON logging on GKE with various golang logging libraries.
This is just a simple http application which emits JSON strings to stdout/stderr from go using
For each log type, there is an endpoint to invoke them where the various handler will emit a JSON string:
{
"str": "foo",
"num": 100,
"bool": false,
"null": null,
"array": [
"foo",
"bar",
"baz"
],
"obj": {
"a": 1,
"b": 2
}
}
Using logging for your apps running on Kubernetes Engine
gcloud container clusters create cluster-1 --machine-type "n1-standard-2" \
--zone us-central1-a \
--num-nodes 2 --enable-ip-alias \
--cluster-version "1.19"
$ kubectl apply -f my-deployment.yaml -f my-srv.yaml
$ kubectl get po,svc
NAME READY STATUS RESTARTS AGE
pod/myapp-deployment-6fcc7f9df9-ddls6 1/1 Running 0 81s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.10.32.1 <none> 443/TCP 6d11h
service/myapp-srv-lb LoadBalancer 10.10.43.107 34.122.242.147 8080:30970/TCP 81s
Once a network loadbalancer is setup, configure a firewall rule to allow you to access te service
gcloud compute firewall-rules create allow-lb-requests \
--allow=tcp:8080 --network=default --source-ranges=0.0.0.0/0
Then invoke each endpoint
export L4=`kubectl get service/myapp-srv-lb -o jsonpath='{.status.loadBalancer.ingress[0].ip}'`
echo $L4
curl -s http://$L4:8080/fmt
curl -s http://$L4:8080/log
curl -s http://$L4:8080/glog
curl -s http://$L4:8080/logsrus
Creates JSON and parses it as structured:
Creates JSON and parses it as structured:
Creates JSON and but does NOT parse the inner json:
Creates JSON and but does NOT parse the inner json:
package main
import (
"flag"
"fmt"
"net/http"
"os"
"log"
"github.com/golang/glog"
"github.com/sirupsen/logrus"
"github.com/gorilla/mux"
"golang.org/x/net/http2"
)
var (
msg = flag.String("msg", `{"str": "foo","num": 100,"bool": false,"null": null,"array": ["foo", "bar", "baz"],"obj": { "a": 1, "b": 2 } }`, "message to print")
)
const ()
func defaulthandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "ok")
}
func fmtHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(os.Stdout, "%s\n", *msg)
fmt.Fprint(w, "ok")
}
func logHandler(w http.ResponseWriter, r *http.Request) {
log.SetFlags(0)
log.Printf("%s", *msg)
fmt.Fprint(w, "ok")
}
func glogHandler(w http.ResponseWriter, r *http.Request) {
glog.Infof("%s", *msg)
fmt.Fprint(w, "ok")
}
func logsRUsHandler(w http.ResponseWriter, r *http.Request) {
logrus.SetFormatter(&logrus.JSONFormatter{
DisableTimestamp: true,
FieldMap: logrus.FieldMap{
logrus.FieldKeyLevel: "severity",
},
})
logrus.SetOutput(os.Stdout)
logrus.SetLevel(logrus.InfoLevel)
logrus.Infof("%s", *msg)
fmt.Fprint(w, "ok")
}
func main() {
flag.Set("stderrthreshold", "INFO")
flag.Parse()
router := mux.NewRouter()
router.Methods(http.MethodGet).Path("/").HandlerFunc(defaulthandler)
router.Methods(http.MethodGet).Path("/fmt").HandlerFunc(fmtHandler)
router.Methods(http.MethodGet).Path("/log").HandlerFunc(logHandler)
router.Methods(http.MethodGet).Path("/glog").HandlerFunc(glogHandler)
router.Methods(http.MethodGet).Path("/logsrus").HandlerFunc(logsRUsHandler)
var server *http.Server
server = &http.Server{
Addr: ":8080",
Handler: router,
}
http2.ConfigureServer(server, &http2.Server{})
log.Printf("Starting Server..")
err := server.ListenAndServe()
log.Fatal("Unable to start Server %v", err)
}
FROM golang:1.13 as build
ENV GO111MODULE=on
WORKDIR /app
COPY . .
RUN go mod download
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build server.go
FROM gcr.io/distroless/base
COPY --from=build /app/server /
EXPOSE 8080
ENTRYPOINT ["/server"]
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
labels:
type: myapp-deployment-label
spec:
replicas: 1
selector:
matchLabels:
type: myapp
template:
metadata:
labels:
type: myapp
spec:
containers:
- name: frontend
image: salrashid123/gke_logs
imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: myapp-srv-lb
labels:
type: myapp-srv-lb
annotations:
cloud.google.com/app-protocols: '{"fe":"HTTP"}'
spec:
type: LoadBalancer
ports:
- name: fe
port: 8080
protocol: TCP
targetPort: 8080
selector:
type: myapp
This site supports webmentions. Send me a mention via this form.