Repository: kentik/ktranslate
Pull request #538 (2023-03-08 23:29:10)

Bump github.com/prometheus/client_golang from 1.11.0 to 1.11.1
Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.11.0 to 1.11.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/prometheus/client_golang/releases">github.com/prometheus/client_golang's releases</a>.</em></p>
<blockquote>
<h2>1.11.1 / 2022-02-15</h2>
<ul>
<li>[SECURITY FIX] promhttp: Check validity of method and code label values <a href="https://github-redirect.dependabot.com/prometheus/client_golang/pull/987">prometheus/client_golang#987</a> (Addressed <a href="https://github.com/prometheus/client_golang/security/advisories/GHSA-cg3q-j54f-5p7p"><code>CVE-2022-21698</code></a>)</li>
</ul>
<h2>What's Changed</h2>
<ul>
<li>promhttp: Check validity of method and code label values by <a href="https://github.com/bwplotka"><code>@​bwplotka</code></a> and <a href="https://github.com/kakkoyun"><code>@​kakkoyun</code></a> in  <a href="https://github-redirect.dependabot.com/prometheus/client_golang/pull/987">prometheus/client_golang#987</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/prometheus/client_golang/compare/v1.11.0...v1.11.1">https://github.com/prometheus/client_golang/compare/v1.11.0...v1.11.1</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md">github.com/prometheus/client_golang's changelog</a>.</em></p>
<blockquote>
<h2>Unreleased</h2>
<h2>1.14.0 / 2022-11-08</h2>
<ul>
<li>[FEATURE] Add Support for Native Histograms. <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/1150">#1150</a></li>
<li>[CHANGE] Extend <code>prometheus.Registry</code> to implement <code>prometheus.Collector</code> interface. <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/1103">#1103</a></li>
</ul>
<h2>1.13.1 / 2022-11-01</h2>
<ul>
<li>[BUGFIX] Fix race condition with Exemplar in Counter. <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/1146">#1146</a></li>
<li>[BUGFIX] Fix <code>CumulativeCount</code> value of <code>+Inf</code> bucket created from exemplar. <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/1148">#1148</a></li>
<li>[BUGFIX] Fix double-counting bug in <code>promhttp.InstrumentRoundTripperCounter</code>. <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/1118">#1118</a></li>
</ul>
<h2>1.13.0 / 2022-08-05</h2>
<ul>
<li>[CHANGE] Minimum required Go version is now 1.17 (we also test client_golang against new 1.19 version).</li>
<li>[ENHANCEMENT] Added <code>prometheus.TransactionalGatherer</code> interface for <code>promhttp.Handler</code> use which allows using low allocation update techniques for custom collectors. <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/989">#989</a></li>
<li>[ENHANCEMENT] Added exemplar support to <code>prometheus.NewConstHistogram</code>. See <a href="https://github.com/prometheus/client_golang/blob/main/prometheus/examples_test.go#L602"><code>ExampleNewConstHistogram_WithExemplar</code></a> example on how to use it. <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/986">#986</a></li>
<li>[ENHANCEMENT] <code>prometheus/push.Pusher</code> has now context aware methods that pass context to HTTP request. <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/1028">#1028</a></li>
<li>[ENHANCEMENT] <code>prometheus/push.Pusher</code> has now <code>Error</code> method that retrieve last error. <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/1075">#1075</a></li>
<li>[ENHANCEMENT] <code>testutil.GatherAndCompare</code> provides now readable diff on failed comparisons. <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/998">#998</a></li>
<li>[ENHANCEMENT] Query API now supports timeouts. <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/1014">#1014</a></li>
<li>[ENHANCEMENT] New <code>MetricVec</code> method <code>DeletePartialMatch(labels Labels)</code> for deleting all metrics that match provided labels. <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/1013">#1013</a></li>
<li>[ENHANCEMENT] <code>api.Config</code> now accepts passing custom <code>*http.Client</code>. <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/1025">#1025</a></li>
<li>[BUGFIX] Raise exemplar labels limit from 64 to 128 bytes as specified in OpenMetrics spec. <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/1091">#1091</a></li>
<li>[BUGFIX] Allow adding exemplar to +Inf bucket to const histograms. <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/1094">#1094</a></li>
<li>[ENHANCEMENT] Most <code>promhttp.Instrument*</code> middlewares now supports adding exemplars to metrics. This allows hooking those to your tracing middleware that retrieves trace ID and put it in exemplar if present. <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/1055">#1055</a></li>
<li>[ENHANCEMENT] Added <code>testutil.ScrapeAndCompare</code> method. <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/1043">#1043</a></li>
<li>[BUGFIX] Fixed <code>GopherJS</code> build support. <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/897">#897</a></li>
<li>[ENHANCEMENT] :warning: Added way to specify what <code>runtime/metrics</code>  <code>collectors.NewGoCollector</code> should use. See <a href="https://github.com/prometheus/client_golang/blob/main/prometheus/collectors/go_collector_latest_test.go#L263"><code>ExampleGoCollector_WithAdvancedGoMetrics</code></a>. <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/1102">#1102</a></li>
</ul>
<h2>1.12.2 / 2022-05-13</h2>
<ul>
<li>[CHANGE] Added <code>collectors.WithGoCollections</code> that allows to choose what collection of Go runtime metrics user wants: Equivalent of <a href="https://pkg.go.dev/runtime#MemStats"><code>MemStats</code> structure</a> configured using <code>GoRuntimeMemStatsCollection</code>, new based on dedicated <a href="https://pkg.go.dev/runtime/metrics">runtime/metrics</a> metrics represented by <code>GoRuntimeMetricsCollection</code> option, or both by specifying <code>GoRuntimeMemStatsCollection | GoRuntimeMetricsCollection</code> flag. <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/1031">#1031</a></li>
<li>[CHANGE] :warning: Change in <code>collectors.NewGoCollector</code> metrics: Reverting addition of new ~80 runtime metrics by default. You can enable this back with <code>GoRuntimeMetricsCollection</code> option or <code>GoRuntimeMemStatsCollection | GoRuntimeMetricsCollection</code> for smooth transition.</li>
<li>[BUGFIX] Fixed the bug that causes generated histogram metric names to end with <code>_total</code>. ⚠️ This changes 3 metric names in the new Go collector that was reverted from default in this release.
<ul>
<li><code>go_gc_heap_allocs_by_size_bytes_total</code> -&gt; <code>go_gc_heap_allocs_by_size_bytes</code>,</li>
<li><code>go_gc_heap_frees_by_size_bytes_total</code> -&gt; <code>go_gc_heap_allocs_by_size_bytes</code></li>
<li><code>go_gc_pauses_seconds_total</code> -&gt; <code>go_gc_pauses_seconds</code>.</li>
</ul>
</li>
<li>[CHANCE] Removed <code>-Inf</code> buckets from new Go Collector histograms.</li>
</ul>
<h2>1.12.1 / 2022-01-29</h2>
<ul>
<li>[BUGFIX] Make the Go 1.17 collector concurrency-safe <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/969">#969</a>
<ul>
<li>Use simpler locking in the Go 1.17 collector <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/975">#975</a></li>
</ul>
</li>
<li>[BUGFIX] Reduce granularity of histogram buckets for Go 1.17 collector <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/974">#974</a></li>
<li>[ENHANCEMENT] API client: make HTTP reads more efficient <a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/976">#976</a></li>
</ul>
<h2>1.12.0 / 2022-01-19</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/prometheus/client_golang/commit/989baa30fe956631907493ccee1f8e7708660d96"><code>989baa3</code></a> promhttp: Check validity of method and code label values (<a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/962">#962</a>) (<a href="https://github-redirect.dependabot.com/prometheus/client_golang/issues/987">#987</a>)</li>
<li>See full diff in <a href="https://github.com/prometheus/client_golang/compare/v1.11.0...v1.11.1">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/prometheus/client_golang&package-manager=go_modules&previous-version=1.11.0&new-version=1.11.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
- `@dependabot use these labels` will set the current labels as the default for future PRs for this repo and language
- `@dependabot use these reviewers` will set the current reviewers as the default for future PRs for this repo and language
- `@dependabot use these assignees` will set the current assignees as the default for future PRs for this repo and language
- `@dependabot use this milestone` will set the current milestone as the default for future PRs for this repo and language

You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/kentik/ktranslate/network/alerts).

</details>


Patch:
diff --git a/.github/workflows/publish-kentik.yml b/.github/workflows/publish-kentik.yml
index c53bb08..6b42e1d 100644
--- a/.github/workflows/publish-kentik.yml
+++ b/.github/workflows/publish-kentik.yml
@@ -1,4 +1,5 @@
 name: Publish Kentik
+run-name: ${{ inputs.message }}
 
 on:
   push:
@@ -6,6 +7,9 @@ on:
       - kentik
 
   workflow_dispatch:
+    inputs:
+      message:
+        type: string
 
 jobs:
   deploy:
diff --git a/README.md b/README.md
index 7d2f93a..b7c6e8e 100644
--- a/README.md
+++ b/README.md
@@ -140,7 +140,7 @@ To get your own MaxMind key, visit [MaxMind](https://www.maxmind.com).
   -nr_estimate_only
     	If true, record size of inputs to NR but don't actually send anything
   -nr_region string
-    	NR Region to use. US|EU
+       NR Region to use. US|EU|GOV
   -olly_dataset string
     	Olly dataset name
   -olly_write_key string
diff --git a/config.go b/config.go
index ee6399f..8228d7c 100644
--- a/config.go
+++ b/config.go
@@ -13,6 +13,9 @@ const (
 	FlowDefaultFields = "TimeReceived,SamplingRate,Bytes,Packets,SrcAddr,DstAddr,Proto,SrcPort,DstPort,InIf,OutIf,SrcVlan,DstVlan,TCPFlags,SrcAS,DstAS,Type,SamplerAddress,FlowDirection"
 	// KentikAPITokenEnvVar is the environment variables used to get the Kentik API Token
 	KentikAPITokenEnvVar = "KENTIK_API_TOKEN"
+	// MaxNetflowsPerMessage is the maximum flowsets in a single netflow message
+	// Must be less than ( 65535[nf_max_size] - 16[nf_header_size] - 96(nf_template_flowset_size] ) / 128[nf_data_flowset_size]
+	MaxNetflowsPerMessage = 510
 )
 
 // NetflowFormatConfig is the config format for netflow
@@ -494,6 +497,10 @@ func LoadConfig(configPath string) (*Config, error) {
 		return nil, err
 	}
 
+	if cfg.Format == "netflow" && (cfg.MaxFlowsPerMessage <= 0 || cfg.MaxFlowsPerMessage > MaxNetflowsPerMessage) {
+		cfg.MaxFlowsPerMessage = MaxNetflowsPerMessage
+	}
+
 	return cfg, nil
 }
 
diff --git a/go.mod b/go.mod
index 710ea52..0808995 100644
--- a/go.mod
+++ b/go.mod
@@ -14,6 +14,7 @@ require (
 	github.com/aws/aws-sdk-go v1.41.19
 	github.com/dchest/siphash v1.2.2
 	github.com/elliotchance/orderedmap v1.4.0
+	github.com/fsnotify/fsnotify v1.6.0
 	github.com/go-openapi/runtime v0.24.1
 	github.com/go-ping/ping v0.0.0-20211014180314-6e2b003bffdd
 	github.com/google/uuid v1.3.0
@@ -34,7 +35,7 @@ require (
 	github.com/netsampler/goflow2 v1.1.1-0.20220818030102-fc42020d1b73
 	github.com/oschwald/geoip2-golang v1.5.0
 	github.com/pkg/errors v0.9.1
-	github.com/prometheus/client_golang v1.11.0
+	github.com/prometheus/client_golang v1.11.1
 	github.com/sasha-s/go-hll v0.0.0-20180522065212-c6eb27aee351
 	github.com/segmentio/kafka-go v0.4.23
 	github.com/stretchr/testify v1.7.1
@@ -67,7 +68,6 @@ require (
 	github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a // indirect
 	github.com/facebookgo/limitgroup v0.0.0-20150612190941-6abd8d71ec01 // indirect
 	github.com/facebookgo/muster v0.0.0-20150708232844-fd3d7953fd52 // indirect
-	github.com/fsnotify/fsnotify v1.6.0 // indirect
 	github.com/go-openapi/analysis v0.21.2 // indirect
 	github.com/go-openapi/errors v0.20.2 // indirect
 	github.com/go-openapi/jsonpointer v0.19.5 // indirect
@@ -123,7 +123,7 @@ require (
 	golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a // indirect
 	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
 	golang.org/x/sys v0.2.0 // indirect
-	golang.org/x/text v0.3.7 // indirect
+	golang.org/x/text v0.3.8 // indirect
 	golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
 	google.golang.org/api v0.74.0 // indirect
 	google.golang.org/appengine v1.6.7 // indirect
diff --git a/go.sum b/go.sum
index 57e02b0..03e4722 100644
--- a/go.sum
+++ b/go.sum
@@ -169,8 +169,6 @@ github.com/frankban/quicktest v1.13.0 h1:yNZif1OkDfNoDfb9zZa9aXIpejNR4F23Wely0c+
 github.com/frankban/quicktest v1.13.0/go.mod h1:qLE0fzW0VuyUAJgPU19zByoIr0HtCHN/r/VLSOOIySU=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
-github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
-github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
 github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
 github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
@@ -490,8 +488,9 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
 github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
 github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
-github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
 github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
+github.com/prometheus/client_golang v1.11.1 h1:+4eQaD7vAZ6DsfsxB15hbE0odUjGI5ARs9yskGu1v4s=
+github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
 github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -797,7 +796,6 @@ golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
@@ -814,8 +812,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
+golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
diff --git a/pkg/formats/netflow/netflow.go b/pkg/formats/netflow/netflow.go
index cf43fe6..518ea6c 100644
--- a/pkg/formats/netflow/netflow.go
+++ b/pkg/formats/netflow/netflow.go
@@ -58,6 +58,7 @@ const (
 	IPV6_DST_ADDR             = 28
 	SRC_MAC                   = 56
 	DST_MAC                   = 80
+	OBSERVATION_POINT_ID      = 138
 	FLOW_START_SECONDS        = 150
 	FLOW_END_SECONDS          = 151
 )
@@ -92,6 +93,7 @@ var fields = []Field{
 	{OUT_BYTES, 8},
 	{IN_PKTS, 8},
 	{OUT_PKTS, 8},
+	{OBSERVATION_POINT_ID, 8}, // uint64
 	{FLOW_START_SECONDS, 4}, // uint32
 	{FLOW_END_SECONDS, 4},
 }
@@ -434,6 +436,8 @@ func encodeFlow(flow *kt.JCHF) (*bytes.Buffer, error) {
 			value = uint64(flow.InPkts)
 		case OUT_PKTS:
 			value = uint64(flow.OutPkts)
+		case OBSERVATION_POINT_ID:
+			value = uint64(flow.CompanyId&0xffff)<<32 + uint64(flow.DeviceId)
 		case FLOW_START_SECONDS:
 			value = uint32(flow.Timestamp)
 		case FLOW_END_SECONDS: // Assume that each flow is 60 sec long.
diff --git a/pkg/inputs/snmp/metadata/poll.go b/pkg/inputs/snmp/metadata/poll.go
index 12d3caa..f00b2a0 100644
--- a/pkg/inputs/snmp/metadata/poll.go
+++ b/pkg/inputs/snmp/metadata/poll.go
@@ -260,8 +260,9 @@ func (p *Poller) toFlows(dd *kt.DeviceData) ([]*kt.JCHF, error) {
 	for k, v := range cs {
 		if strings.HasPrefix(v, TagValuePrefix) { // See if we can find this value in the MDS instead.
 			for tag, value := range dst.CustomStr {
-				if tag == v[len(TagValuePrefix):] {
+				if len(v) > len(TagValuePrefix) && tag == v[len(TagValuePrefix):] {
 					v = value
+					break // Once we find a match, break out and don't try comparing to anything else any more.
 				}
 			}
 		}
diff --git a/pkg/inputs/snmp/metrics/poll.go b/pkg/inputs/snmp/metrics/poll.go
index dda9fc1..32ac54a 100644
--- a/pkg/inputs/snmp/metrics/poll.go
+++ b/pkg/inputs/snmp/metrics/poll.go
@@ -26,6 +26,7 @@ type Poller struct {
 	jchfChan         chan []*kt.JCHF
 	metrics          *kt.SnmpDeviceMetric
 	counterTimeSec   int
+	jitterTimeSec    int
 	dropIfOutside    bool
 	pinger           *ping.Pinger
 	extension        extension.Extension
@@ -45,6 +46,11 @@ func NewPoller(server *gosnmp.GoSNMP, gconf *kt.SnmpGlobalConfig, conf *kt.SnmpD
 		counterTimeSec = 30
 	}
 
+	jitterTimeSec := 15 // This is how long to spead the polling load out across.
+	if gconf.JitterTimeSec > 0 {
+		jitterTimeSec = gconf.JitterTimeSec
+	}
+
 	// Default is not not drop.
 	dropIfOutside := false
 	if gconf != nil && gconf.PollTimeSec > 0 {
@@ -70,6 +76,7 @@ func NewPoller(server *gosnmp.GoSNMP, gconf *kt.SnmpGlobalConfig, conf *kt.SnmpD
 		interfaceMetrics: NewInterfaceMetrics(gconf, conf, metrics, interfaceMetricMibs, profile, counterTimeSec, log),
 		deviceMetrics:    NewDeviceMetrics(gconf, conf, metrics, deviceMetricMibs, profile, log),
 		counterTimeSec:   counterTimeSec,
+		jitterTimeSec:    jitterTimeSec,
 		dropIfOutside:    dropIfOutside,
 	}
 
@@ -99,6 +106,11 @@ func NewPollerForPing(gconf *kt.SnmpGlobalConfig, conf *kt.SnmpDeviceConfig, jch
 		counterTimeSec = 30
 	}
 
+	jitterTimeSec := 15 // This is how long to spead the polling load out across.
+	if gconf.JitterTimeSec > 0 {
+		jitterTimeSec = gconf.JitterTimeSec
+	}
+
 	pingSec := conf.PingSec
 	if pingSec == 0 { // If not per device, try per global.
 		pingSec = gconf.PingSec
@@ -112,6 +124,7 @@ func NewPollerForPing(gconf *kt.SnmpGlobalConfig, conf *kt.SnmpDeviceConfig, jch
 		log:            log,
 		metrics:        metrics,
 		counterTimeSec: counterTimeSec,
+		jitterTimeSec:  jitterTimeSec,
 		deviceMetrics:  NewDeviceMetrics(gconf, conf, metrics, nil, profile, log),
 	}
 
@@ -140,11 +153,17 @@ func NewPollerForExtention(gconf *kt.SnmpGlobalConfig, conf *kt.SnmpDeviceConfig
 		counterTimeSec = 30
 	}
 
+	jitterTimeSec := 15 // This is how long to spead the polling load out across.
+	if gconf.JitterTimeSec > 0 {
+		jitterTimeSec = gconf.JitterTimeSec
+	}
+
 	poller := Poller{
 		jchfChan:       jchfChan,
 		log:            log,
 		metrics:        metrics,
 		counterTimeSec: counterTimeSec,
+		jitterTimeSec:  jitterTimeSec,
 		deviceMetrics:  NewDeviceMetrics(gconf, conf, metrics, nil, profile, log),
 	}
 
@@ -167,7 +186,7 @@ func (p *Poller) StartLoop(ctx context.Context) {
 	// to jitter the devices, and the rest of the five-minute chunk to actually do the counter-polling.  For any device whose counters we can walk
 	// in less than (5 minutes - jitter period), we should be able to guarantee exactly one datapoint per aligned five-minute chunk.
 	counterAlignment := time.Duration(p.counterTimeSec) * time.Second
-	jitterWindow := 15 * time.Second
+	jitterWindow := time.Duration(p.jitterTimeSec) * time.Second
 	firstCollection := time.Now().Truncate(counterAlignment).Add(counterAlignment).Add(time.Duration(rand.Int63n(int64(jitterWindow))))
 	counterCheck := tick.NewFixedTimer(firstCollection, counterAlignment)
 	statusCheck := time.NewTicker(STATUS_CHECK_TIME)
@@ -278,7 +297,7 @@ func (p *Poller) StartPingOnlyLoop(ctx context.Context) {
 	// to jitter the devices, and the rest of the five-minute chunk to actually do the counter-polling.  For any device whose counters we can walk
 	// in less than (5 minutes - jitter period), we should be able to guarantee exactly one datapoint per aligned five-minute chunk.
 	counterAlignment := time.Duration(p.counterTimeSec) * time.Second
-	jitterWindow := 15 * time.Second
+	jitterWindow := time.Duration(p.jitterTimeSec) * time.Second
 	firstCollection := time.Now().Truncate(counterAlignment).Add(counterAlignment).Add(time.Duration(rand.Int63n(int64(jitterWindow))))
 	counterCheck := tick.NewFixedTimer(firstCollection, counterAlignment)
 	p.deviceMetrics.ResetPingStats() // Initialize to 0 sent and recieved.
diff --git a/pkg/kt/snmp.go b/pkg/kt/snmp.go
index 08484c3..23ea393 100644
--- a/pkg/kt/snmp.go
+++ b/pkg/kt/snmp.go
@@ -270,6 +270,7 @@ type SnmpGlobalConfig struct {
 	UserTags              map[string]string      `yaml:"user_tags"`
 	MatchAttr             map[string]string      `yaml:"match_attributes"`
 	ProviderMap           map[string]ProviderMap `yaml:"providers"`
+	JitterTimeSec         int                    `yaml:"jitter_time_sec"`
 }
 
 type SnmpConfig struct {


Test patch:
diff --git a/pkg/inputs/snmp/metadata/poll_test.go b/pkg/inputs/snmp/metadata/poll_test.go
index 8c71f43..22d2a47 100644
--- a/pkg/inputs/snmp/metadata/poll_test.go
+++ b/pkg/inputs/snmp/metadata/poll_test.go
@@ -40,3 +40,37 @@ func TestGetDeviceManufacturer(t *testing.T) {
 		}
 	}
 }
+
+func TestToFlows(t *testing.T) {
+	l := lt.NewTestContextL(logger.NilContext, t)
+	conf := &kt.SnmpDeviceConfig{
+		Provider: "foo",
+		UserTags: map[string]string{
+			"foo": "$foo",
+			"aaa": "$SysContact",
+		},
+	}
+	conf.InitUserTags("service")
+
+	p := &Poller{
+		log:  l,
+		conf: conf,
+	}
+
+	input := kt.DeviceData{
+		Manufacturer: "man",
+		DeviceMetricsMetadata: &kt.DeviceMetricsMetadata{
+			SysContact: "ddd",
+			Customs: map[string]string{
+				"foo": "",
+				"bar": "",
+			},
+		},
+	}
+	res, err := p.toFlows(&input)
+	assert.NotNil(t, res)
+	assert.Nil(t, err)
+	assert.Equal(t, 1, len(res))
+	assert.Equal(t, "ddd", res[0].CustomStr["tags.aaa"])
+	assert.Equal(t, "", res[0].CustomStr["tags.foo"]) // Empty string match for tag here.
+}