Use AWS CSM to monitoring the api call in your service

Enable the aws CSM for application specific the following Environment Variables

1export AWS_CSM_ENABLED=true # or config the `~/.aws/config` include `csm_enabled = true`
2export AWS_CSM_HOST=10.0.0.1 # to send message to udp host
3export AWS_CSM_PORT=31000 # the CSM host port to listener
4export AWS_CSM_CLIENT_ID=appName # to set an identifier to differentiate multiple processes you might have configured to send to the same listener.

Receive the message from client in local testing

1nc -luv localhost 31000

Receive the message from client use go code

 1package main
 2
 3import (
 4	"encoding/json"
 5	"fmt"
 6	"log"
 7	"net"
 8	"os"
 9	"os/signal"
10	"runtime"
11	"strconv"
12	"strings"
13	"syscall"
14)
15
16// ActionMessage is a struct representing a message from CSM
17type ActionMessage struct {
18	Version             int    `json:"Version"`
19	ClientID            string `json:"ClientId"`
20	Type                string `json:"Type"`
21	Service             string `json:"Service"`
22	Action              string `json:"Api"`
23	Timestamp           int    `json:"Timestamp"`
24	AttemptLatency      int    `json:"AttemptLatency"`
25	Fqdn                string `json:"Fqdn"`
26	UserAgent           string `json:"UserAgent"`
27	AccessKey           string `json:"AccessKey"`
28	Region              string `json:"Region"`
29	HTTPStatusCode      int    `json:"HttpStatusCode"`
30	FinalHTTPStatusCode int    `json:"FinalHttpStatusCode"`
31	XAmzRequestID       string `json:"XAmzRequestId"`
32	XAmzID2             string `json:"XAmzId2"`
33}
34
35func listen(connection *net.UDPConn, quit chan struct{}) {
36	buffer := make([]byte, 4096)
37	n, _, err := 0, new(net.UDPAddr), error(nil)
38	var message ActionMessage
39	for err == nil {
40		n, _, err = connection.ReadFromUDP(buffer)
41		err := json.Unmarshal(buffer[:n], &message)
42		if err != nil {
43			log.Println(err)
44		}
45		//Each action taken sends two json messages. The first has a type of "ApiCallAttempt" this filters for the API call itself
46		if message.Type == "ApiCall" {
47			fmt.Println(strings.ToLower(message.Service) + ":" + message.Action)
48		}
49	}
50	fmt.Println("listener failed - ", err)
51	quit <- struct{}{}
52}
53
54//SetupCloseHandler Displays a message when the user closes the program
55func SetupCloseHandler() {
56	c := make(chan os.Signal)
57	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
58	go func() {
59		<-c
60		fmt.Println("\rCtrl+C pressed, Stopping...")
61		os.Exit(0)
62	}()
63}
64
65func main() {
66
67	var port = 31000
68	var err error
69	var addr = net.UDPAddr{
70		Port: port,
71		IP:   net.IP{127, 0, 0, 1},
72	}
73	if os.Getenv("AWS_CSM_PORT") != "" {
74		port, err = strconv.Atoi(os.Getenv("AWS_CSM_PORT"))
75		if err != nil {
76			fmt.Println("Could not parse value of AWS_CSM_PORT Exiting...")
77			os.Exit(1)
78		}
79	}
80	if os.Getenv("IN_DOCKER") == "True" {
81		addr = net.UDPAddr{
82			Port: port,
83			IP:   net.IP{0, 0, 0, 0},
84		}
85	}
86	connection, err := net.ListenUDP("udp", &addr)
87	if err != nil {
88		fmt.Println("Could not start Action hero on the specified port, Exiting...")
89		os.Exit(1)
90	}
91	fmt.Println("Action Hero Starting...")
92	SetupCloseHandler()
93	quit := make(chan struct{})
94	for i := 0; i < runtime.NumCPU(); i++ {
95		go listen(connection, quit)
96	}
97	<-quit // hang until an error
98}

Make a dockerfile

1FROM scratch
2COPY actionhero /
3EXPOSE 31000/udp
4ENTRYPOINT ["/actionhero"]

Health check for udp

 1#!/usr/local/bin/python
 2
 3import enet
 4import random
 5import sys
 6import os
 7import signal
 8
 9udp_socket_port=int(os.environ.get('UDP_SOCKET_PORT'))
10udp_socket_ip=os.environ.get('UDP_SOCKET_IP').encode('utf-8')
11print("checking health of udp endpoint %s %s" %(udp_socket_ip,udp_socket_port))
12
13host = enet.Host(None, 1, 0, 0)
14addr=enet.Address(udp_socket_ip,udp_socket_port)
15peer = host.connect(addr,1)
16if peer:
17    print("%s:" % peer)
18    event = host.service(1000)
19    if event.type == enet.EVENT_TYPE_CONNECT:
20        print("%s: CONNECT" % event.peer.address)
21    elif event.type == enet.EVENT_TYPE_DISCONNECT:
22        print("%s: DISCONNECT" % event.peer.address)
23        os.system("while true; do pkill nginx;sleep 1;done")
24        print ("sidecar NGINX process stopped successfully")

Reference