Refactor docs; Add 'ipng_source_tag', add udp listener for nginx-ipng-stats plugin
This commit is contained in:
@@ -21,14 +21,16 @@ const (
|
||||
CoarseEvery = 5 // fine ticks between coarse writes
|
||||
)
|
||||
|
||||
// Tuple6 is the aggregation key (website, prefix, URI, status, is_tor, asn).
|
||||
// Tuple6 is the aggregation key (website, prefix, URI, status, is_tor, asn, source_tag).
|
||||
// The name is kept for source-compat with older call sites; it now carries seven fields.
|
||||
type Tuple6 struct {
|
||||
Website string
|
||||
Prefix string
|
||||
URI string
|
||||
Status string
|
||||
IsTor bool
|
||||
ASN int32
|
||||
Website string
|
||||
Prefix string
|
||||
URI string
|
||||
Status string
|
||||
IsTor bool
|
||||
ASN int32
|
||||
SourceTag string
|
||||
}
|
||||
|
||||
// Entry is a labelled count used in snapshots and query results.
|
||||
@@ -85,12 +87,13 @@ func EncodeTuple(t Tuple6) string {
|
||||
if t.IsTor {
|
||||
tor = "1"
|
||||
}
|
||||
return t.Website + "\x00" + t.Prefix + "\x00" + t.URI + "\x00" + t.Status + "\x00" + tor + "\x00" + strconv.Itoa(int(t.ASN))
|
||||
return t.Website + "\x00" + t.Prefix + "\x00" + t.URI + "\x00" + t.Status + "\x00" + tor + "\x00" + strconv.Itoa(int(t.ASN)) + "\x00" + t.SourceTag
|
||||
}
|
||||
|
||||
// LabelTuple decodes a NUL-separated snapshot label back into a Tuple6.
|
||||
// Labels from older snapshots (6 fields) round-trip with SourceTag=="".
|
||||
func LabelTuple(label string) Tuple6 {
|
||||
parts := splitN(label, '\x00', 6)
|
||||
parts := splitN(label, '\x00', 7)
|
||||
if len(parts) < 4 {
|
||||
return Tuple6{}
|
||||
}
|
||||
@@ -98,11 +101,14 @@ func LabelTuple(label string) Tuple6 {
|
||||
if len(parts) >= 5 {
|
||||
t.IsTor = parts[4] == "1"
|
||||
}
|
||||
if len(parts) == 6 {
|
||||
if len(parts) >= 6 {
|
||||
if n, err := strconv.Atoi(parts[5]); err == nil {
|
||||
t.ASN = int32(n)
|
||||
}
|
||||
}
|
||||
if len(parts) == 7 {
|
||||
t.SourceTag = parts[6]
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
@@ -239,6 +245,9 @@ func MatchesFilter(t Tuple6, f *CompiledFilter) bool {
|
||||
if p.AsnNumber != nil && !matchesAsnOp(t.ASN, p.GetAsnNumber(), p.AsnOp) {
|
||||
return false
|
||||
}
|
||||
if p.IpngSourceTag != nil && t.SourceTag != p.GetIpngSourceTag() {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -299,6 +308,8 @@ func DimensionLabel(t Tuple6, g pb.GroupBy) string {
|
||||
return t.Status
|
||||
case pb.GroupBy_ASN_NUMBER:
|
||||
return strconv.Itoa(int(t.ASN))
|
||||
case pb.GroupBy_SOURCE_TAG:
|
||||
return t.SourceTag
|
||||
default:
|
||||
return t.Website
|
||||
}
|
||||
|
||||
@@ -335,3 +335,45 @@ func TestDimensionLabelASN(t *testing.T) {
|
||||
t.Errorf("DimensionLabel ASN: got %q, want %q", got, "12345")
|
||||
}
|
||||
}
|
||||
|
||||
// --- SourceTag label encoding, filtering, and DimensionLabel ---
|
||||
|
||||
func TestEncodeLabelTupleRoundtripWithSourceTag(t *testing.T) {
|
||||
for _, tag := range []string{"", "direct", "cdn", "tag with spaces"} {
|
||||
orig := Tuple6{Website: "a.com", Prefix: "1.2.3.0/24", URI: "/x", Status: "200", SourceTag: tag}
|
||||
got := LabelTuple(EncodeTuple(orig))
|
||||
if got != orig {
|
||||
t.Errorf("roundtrip mismatch for tag=%q: got %+v, want %+v", tag, got, orig)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLabelTupleBackwardCompatNoSourceTag(t *testing.T) {
|
||||
// 6-field label (pre-source_tag snapshot) decodes with SourceTag="".
|
||||
label := "a.com\x001.2.3.0/24\x00/x\x00200\x000\x0012345"
|
||||
got := LabelTuple(label)
|
||||
if got.SourceTag != "" {
|
||||
t.Errorf("expected empty SourceTag for 6-field label, got %q", got.SourceTag)
|
||||
}
|
||||
if got.ASN != 12345 {
|
||||
t.Errorf("expected ASN=12345, got %d", got.ASN)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatchesFilterSourceTag(t *testing.T) {
|
||||
tag := "cdn"
|
||||
cf := CompileFilter(&pb.Filter{IpngSourceTag: &tag})
|
||||
if !MatchesFilter(Tuple6{SourceTag: "cdn"}, cf) {
|
||||
t.Fatal("should match equal source_tag")
|
||||
}
|
||||
if MatchesFilter(Tuple6{SourceTag: "direct"}, cf) {
|
||||
t.Fatal("should not match different source_tag")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDimensionLabelSourceTag(t *testing.T) {
|
||||
got := DimensionLabel(Tuple6{SourceTag: "cdn"}, pb.GroupBy_SOURCE_TAG)
|
||||
if got != "cdn" {
|
||||
t.Errorf("DimensionLabel SOURCE_TAG: got %q, want %q", got, "cdn")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user