Skip to content

Commit 2422118

Browse files
authored
Adding in gigamon input (#633)
* Adding in gigamon input * Adding a http.remote_ip flag to allow override of dockers remote ip handling * Adding in more pageload values
1 parent c631ea8 commit 2422118

File tree

4 files changed

+163
-35
lines changed

4 files changed

+163
-35
lines changed

cmd/ktranslate/main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,8 @@ func applyFlags(cfg *ktranslate.Config) error {
400400
return
401401
}
402402
cfg.EnableHTTPInput = v
403+
case "http.remote_ip":
404+
cfg.HttpRemoteIp = val
403405
case "enricher":
404406
if _, err := os.Stat(val); err == nil { // If this is a file on disk, run as a script.
405407
cfg.EnricherScript = val

config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ type Config struct {
254254
TagMapType string
255255
EnableTeeLogs bool
256256
EnableHTTPInput bool
257+
HttpRemoteIp string
257258
EnricherURL string
258259
EnricherSource string
259260
EnricherScript string

pkg/formats/nrm/nrm.go

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -332,40 +332,52 @@ func (f *NRMFormat) fromSnmpMetadata(in *kt.JCHF) []NRMetric {
332332

333333
var (
334334
synthWLAttr = map[string]bool{
335-
"agent_id": true,
336-
"agent_name": true,
337-
"dst_addr": true,
338-
"dst_cdn_int": true,
339-
"dst_geo": true,
340-
"provider": true,
341-
"src_addr": true,
342-
"src_cdn_int": true,
343-
"src_as_name": true,
344-
"src_geo": true,
345-
"test_id": true,
346-
"test_name": true,
347-
"test_type": true,
348-
"test_url": true,
349-
"src_host": true,
350-
"dst_host": true,
351-
"src_cloud_region": true,
352-
"src_cloud_provider": true,
353-
"src_site": true,
354-
"dst_cloud_region": true,
355-
"dst_cloud_provider": true,
356-
"dst_site": true,
357-
"statusMessage": true,
358-
"statusEncoding": true,
359-
"https_validity": true,
360-
"https_expiry_timestamp": true,
361-
"dest_ip": true,
362-
}
363-
364-
synthAttrKeys = []string{
365-
"statusMessage",
366-
"statusEncoding",
367-
"https_validity",
368-
"https_expiry_timestamp",
335+
"agent_id": true,
336+
"agent_name": true,
337+
"dst_addr": true,
338+
"dst_cdn_int": true,
339+
"dst_geo": true,
340+
"provider": true,
341+
"src_addr": true,
342+
"src_cdn_int": true,
343+
"src_as_name": true,
344+
"src_geo": true,
345+
"test_id": true,
346+
"test_name": true,
347+
"test_type": true,
348+
"test_url": true,
349+
"src_host": true,
350+
"dst_host": true,
351+
"src_cloud_region": true,
352+
"src_cloud_provider": true,
353+
"src_site": true,
354+
"dst_cloud_region": true,
355+
"dst_cloud_provider": true,
356+
"dst_site": true,
357+
"https_validity": true,
358+
"https_expiry_timestamp": true,
359+
"dest_ip": true,
360+
"statusMessage": true,
361+
"statusEncoding": true,
362+
"connectEnd": true,
363+
"connectStart": true,
364+
"decodedBodySize": true,
365+
"domComplete": true,
366+
"domContentLoadedEventEnd": true,
367+
"domContentLoadedEventStart": true,
368+
"domInteractive": true,
369+
"domainLookupEnd": true,
370+
"domainLookupStart": true,
371+
"duration": true,
372+
"fetchStart": true,
373+
"loadEventEnd": true,
374+
"loadEventStart": true,
375+
"redirectCount": true,
376+
"requestStart": true,
377+
"responseEnd": true,
378+
"responseStart": true,
379+
"secureConnectionStart": true,
380+
"tlsProtocol": true,
369381
}
370382
)
371383

@@ -436,7 +448,7 @@ func (f *NRMFormat) fromKSynth(in *kt.JCHF) []NRMetric {
436448
if len(strData) > 0 {
437449
switch sd := strData[0].(type) {
438450
case map[string]interface{}:
439-
for _, key := range synthAttrKeys {
451+
for key, _ := range synthWLAttr {
440452
if val, ok := sd[key]; ok {
441453
attr[key] = val
442454
}

pkg/inputs/http/http.go

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ package http
33
import (
44
"compress/gzip"
55
"context"
6+
"flag"
67
"fmt"
8+
"net"
79
"net/http"
810
"strings"
911
"time"
@@ -14,6 +16,7 @@ import (
1416
"github.com/kentik/ktranslate/pkg/eggs/kmux"
1517
"github.com/kentik/ktranslate/pkg/eggs/logger"
1618
"github.com/kentik/ktranslate/pkg/kt"
19+
"github.com/kentik/ktranslate/pkg/util/ic"
1720
)
1821

1922
type KentikHttpListener struct {
@@ -35,6 +38,14 @@ const (
3538
Listen = "/input"
3639
)
3740

41+
var (
42+
useAsRemoteIP string
43+
)
44+
45+
func init() {
46+
flag.StringVar(&useAsRemoteIP, "http.remote_ip", "", "If set, ignore actual remote IP and use this for device mapping.")
47+
}
48+
3849
func NewHttpListener(ctx context.Context, host string, log logger.Underlying, registry go_metrics.Registry, jchfChan chan []*kt.JCHF, apic *api.KentikApi) (*KentikHttpListener, error) {
3950
ks := KentikHttpListener{
4051
ContextL: logger.NewContextLFromUnderlying(logger.SContext{S: "Http"}, log),
@@ -55,6 +66,105 @@ func (ks *KentikHttpListener) RegisterRoutes(r *kmux.Router) {
5566
r.HandleFunc(Listen+"/telegraf/standard", ks.wrap(ks.readStandard))
5667
r.HandleFunc(Listen+"/telegraf/batch", ks.wrap(ks.readBatch))
5768
r.HandleFunc(Listen+"/ktranslate/jchf", ks.wrap(ks.readJCHF))
69+
r.HandleFunc(Listen+"/gigamon/batch", ks.wrap(ks.readGigaBatch))
70+
}
71+
72+
type gigaEvent struct {
73+
Timestamp string `json:"ts"`
74+
Vendor string `json:"vendor"`
75+
Version string `json:"version"`
76+
Generator string `json:"generator"`
77+
SrcIP net.IP `json:"src_ip"`
78+
DstIP net.IP `json:"dst_ip"`
79+
Protocol int `json:"protocol,string"`
80+
SrcPort int `json:"src_port,string"`
81+
DstPort int `json:"dst_port,string"`
82+
SslCommonName string `json:"ssl_common_name"`
83+
SslIssuer string `json:"ssl_issuer"`
84+
SslValidityNotBefore string `json:"ssl_validity_not_before"`
85+
SslValidityNotAdter string `json:"ssl_validity_not_after"`
86+
SslExtSigAlgorithumScheme int `json:"ssl_ext_sig_algorithm_scheme,string"`
87+
SslExtSigAlgorithumHash int `json:"ssl_ext_sig_algorithm_hash,string"`
88+
SslExtSigAlgorithumSig int `json:"ssl_ext_sig_algorithm_sig,string"`
89+
AppId int `json:"app_id,string"`
90+
SrcPackets int `json:"src_packets,string"`
91+
DstPackets int `json:"dst_packets,string"`
92+
AppName string `json:"app_name"`
93+
SrcBytes int `json:"src_bytes,string"`
94+
DstBytes int `json:"dst_bytes,string"`
95+
Id string `json:"id"`
96+
SeqNum int `json:"seq_num,string"`
97+
}
98+
99+
func (ks *KentikHttpListener) readGigaBatch(w http.ResponseWriter, r *http.Request) {
100+
var wrap []gigaEvent
101+
102+
// Decode body in gzip format if the request header is set this way.
103+
body := r.Body
104+
if r.Header.Get("Content-Encoding") == "gzip" {
105+
z, err := gzip.NewReader(r.Body)
106+
if err != nil {
107+
panic(http.StatusInternalServerError)
108+
}
109+
body = z
110+
}
111+
defer body.Close()
112+
113+
if err := json.NewDecoder(body).Decode(&wrap); err != nil {
114+
ks.Infof("Cannot decode input: %v", err)
115+
panic(http.StatusInternalServerError)
116+
}
117+
w.WriteHeader(http.StatusOK)
118+
119+
remoteIP := getIP(r)
120+
out := make([]*kt.JCHF, len(wrap))
121+
for i, m := range wrap {
122+
out[i] = ks.getGigaJCHF(&m, remoteIP)
123+
}
124+
125+
ks.metrics.Messages.Mark(int64(len(out)))
126+
ks.jchfChan <- out
127+
}
128+
129+
func (ks *KentikHttpListener) getGigaJCHF(event *gigaEvent, remoteIP string) *kt.JCHF {
130+
in := kt.NewJCHF()
131+
in.Timestamp = time.Now().Unix()
132+
in.CustomStr = map[string]string{
133+
"timestamp": event.Timestamp,
134+
"vendor": event.Vendor,
135+
"version": event.Version,
136+
"generator": event.Generator,
137+
"app_name": event.AppName,
138+
"id": event.Id,
139+
"ssl_common_name": event.SslCommonName,
140+
}
141+
in.CustomInt = map[string]int32{
142+
"app_id": int32(event.AppId),
143+
}
144+
in.CustomBigInt = map[string]int64{
145+
"seq_num": int64(event.SeqNum),
146+
}
147+
in.EventType = event.Vendor
148+
in.Provider = kt.ProviderHttpDevice
149+
in.SrcAddr = event.SrcIP.String()
150+
in.DstAddr = event.DstIP.String()
151+
in.Protocol = ic.PROTO_NAMES[uint16(event.Protocol)]
152+
in.L4SrcPort = uint32(event.SrcPort)
153+
in.L4DstPort = uint32(event.DstPort)
154+
in.InPkts = uint64(event.SrcPackets)
155+
in.OutPkts = uint64(event.DstPackets)
156+
in.InBytes = uint64(event.SrcBytes)
157+
in.OutBytes = uint64(event.DstBytes)
158+
159+
if dev, ok := ks.devices[remoteIP]; ok {
160+
in.DeviceName = dev.Name // Copy in any of these info we get
161+
in.DeviceId = dev.ID
162+
in.CompanyId = dev.CompanyID
163+
in.SampleRate = dev.SampleRate
164+
dev.SetUserTags(in.CustomStr)
165+
}
166+
167+
return in
58168
}
59169

60170
type basic struct {
@@ -219,6 +329,9 @@ type handler func(http.ResponseWriter, *http.Request)
219329
func getIP(r *http.Request) string {
220330
res := r.Header.Get("X-FORWARDED-FOR")
221331
if res == "" {
332+
if useAsRemoteIP != "" {
333+
return useAsRemoteIP
334+
}
222335
res = r.RemoteAddr
223336
}
224337
pts := strings.SplitN(res, ":", 2)

0 commit comments

Comments
 (0)