fluent-plugin-jfrog-metrics 0.2.14 → 0.2.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a5d5ad46df6caec2199b42f521c9722ce27552d988fda9950d8f5dac659e40ed
4
- data.tar.gz: 4ec636b979f8cae25013c698d977d3b9021b68325b806b8c415f3fa356396593
3
+ metadata.gz: e129c6f7bc3ddd71533676e19f0684500cbceb9785db59e514d3e18a6d42a856
4
+ data.tar.gz: 1ae603b9e3ed77ed7d66ec8ba92eea76461b25b4b064f168d562b222c0d59234
5
5
  SHA512:
6
- metadata.gz: c0e1bc0f53fd024f6f200b27a4e0c39f98833b1412bf2fcaebbd24c743e7188dd8107c5a5f5e31c12cf8c0d9a88387ffe19bc5852e53c38afbe1b29dc18eebfa
7
- data.tar.gz: f1db053da0248b953b9c023d092b101bd22dbf8a2a7a7379efacc675d6fb3ca8e161ea1dc66d43f01483da9e898057b0f373b4961781efe924a38420a585643a
6
+ metadata.gz: 2338a45c27238e28b806916812acf7c33e64d7df4d1b8af67447e6b05ab0a7db5e58ada412dccd8ec4e95a27fe14037ec34f798cf0a4847ff3911980de2ef13a
7
+ data.tar.gz: f2ac0b3afca4d3301455ba5ae565e585f6eba3fcb930a34db5b488069fa83e3411c7bdb08892268ee632a4e9772889fcb4cce45956c6bd6ee4ea9f1da7b10c09
data/CHANGELOG.md ADDED
@@ -0,0 +1,24 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [0.2.15] - 2026-03-24
6
+
7
+ ### Fixed
8
+ - **JOBS-2011**: Fixed regex parsing issue that caused metrics shipping to fail when Artifactory emits metrics with nested curly braces in label values
9
+ - Changed regex from greedy `/(.*){(.*)}(.*)/i` to non-greedy `/(.*?){(.*)}(.*)/i` in all three parser files:
10
+ - `datadog_metrics_parser.rb`
11
+ - `splunk_metrics_parser.rb`
12
+ - `newrelic_metrics_parser.rb`
13
+ - This fix resolves the "no implicit conversion of nil into String" error when parsing metrics like:
14
+ ```
15
+ db_query_large_total{action="/artifactory/api/nuget/{repoKey}/Download/{packageId}/{packageVersion}",application="Artifactory"} 1.0
16
+ ```
17
+
18
+ ### Added
19
+ - Unit tests for metrics with nested curly braces to prevent regression
20
+
21
+ ## [0.2.14] - 2026-01-19
22
+
23
+ ### Previous Release
24
+ - See previous release notes for earlier changes
@@ -3,7 +3,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
4
  Gem::Specification.new do |spec|
5
5
  spec.name = 'fluent-plugin-jfrog-metrics'
6
- spec.version = '0.2.14'
6
+ spec.version = '0.2.15'
7
7
  spec.authors = ['MahithaB, BenHarosh']
8
8
  spec.email = ['cpe-support@jfrog.com']
9
9
 
@@ -13,12 +13,9 @@ Gem::Specification.new do |spec|
13
13
  spec.homepage = 'https://github.com/jfrog/jfrog-fluentd-plugins/tree/main/fluent-plugin-jfrog-metrics'
14
14
  spec.license = 'Apache-2.0'
15
15
 
16
- test_files, files = `git ls-files -z`.split("\x0").partition do |f|
17
- f.match(%r{^(test|spec|features)/})
18
- end
19
- spec.files = files
20
- spec.executables = files.grep(%r{^bin/}) { |f| File.basename(f) }
21
- spec.test_files = test_files
16
+ spec.files = Dir['lib/**/*', 'README.md', 'LICENSE', 'CHANGELOG.md', 'Gemfile', 'Rakefile', '*.gemspec']
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = Dir['test/**/*', 'spec/**/*']
22
19
  spec.require_paths = ['lib']
23
20
 
24
21
  spec.add_development_dependency 'bundler', '~> 1.14'
@@ -19,7 +19,7 @@ class DatadogMetricsParser < BaseMetricsParser
19
19
  point = {}
20
20
  points = []
21
21
  if interim_data =~ /{/ && interim_data =~ /}/
22
- metric_name, additional_dims, metric_val_and_time = interim_data.match(/(.*){(.*)}(.*)/i).captures
22
+ metric_name, additional_dims, metric_val_and_time = interim_data.match(/(.*?){(.*)}(.*)/i).captures
23
23
  additional_dims.split("\",").each do |interim_data|
24
24
  pair_data = interim_data.gsub("\"", "").gsub("{", "").gsub("}", "")
25
25
  interim_data_value = pair_data.split("=", 2)[1]
@@ -17,7 +17,7 @@ class NewRelicMetricsParser < BaseMetricsParser
17
17
  metrics_hash = {}
18
18
  if interim_data =~ /{/ && interim_data =~ /}/
19
19
  attributes = {}
20
- metric_name, additional_dims, metric_val_and_time = interim_data.match(/(.*){(.*)}(.*)/i).captures
20
+ metric_name, additional_dims, metric_val_and_time = interim_data.match(/(.*?){(.*)}(.*)/i).captures
21
21
  additional_dims.split("\",").each do |interim_data|
22
22
  pair_data = interim_data.gsub("\"", "").gsub("{", "").gsub("}", "")
23
23
  interim_data_value = pair_data.split("=", 2)[1]
@@ -20,7 +20,7 @@ class SplunkMetricsParser < BaseMetricsParser
20
20
  def generate_hash_from_data(data = '', prefix = '', separator = '')
21
21
  metrics_hash = {}
22
22
  if data =~ /{/ && data =~ /}/
23
- metric_name, additional_dims, metric_val_and_time = data.match(/(.*){(.*)}(.*)/i).captures
23
+ metric_name, additional_dims, metric_val_and_time = data.match(/(.*?){(.*)}(.*)/i).captures
24
24
  if metric_val_and_time =~ / /
25
25
  metrics_hash['metric_name'] = prefix + separator + metric_name
26
26
  metrics_hash['value'] =
@@ -0,0 +1,12 @@
1
+ # HELP db_query_large_total Total large queries
2
+ # UPDATED db_query_large_total 1711100784000
3
+ # TYPE db_query_large_total counter
4
+ db_query_large_total{action="/artifactory/api/nuget/{repoKey}/Download/{packageId}/{packageVersion}",application="Artifactory",group="download",package="nuget"} 2.0 1711100784000
5
+ # HELP db_query_large_total_alt Alternative large queries with different template
6
+ # UPDATED db_query_large_total_alt 1711100784000
7
+ # TYPE db_query_large_total_alt counter
8
+ db_query_large_total{action="/artifactory/api/artifactproperties{name:(/[^/]+?)?}",application="Artifactory",group="",package=""} 1.0 1711100784000
9
+ # HELP jfrt_http_connections_available_total Available HTTP Connections
10
+ # UPDATED jfrt_http_connections_available_total 1711100784000
11
+ # TYPE jfrt_http_connections_available_total gauge
12
+ jfrt_http_connections_available_total{instance="node1",port="8081"} 50 1711100784000
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+ [
3
+ File.join(File.dirname(__FILE__), '..'),
4
+ File.join(File.dirname(__FILE__), '..', 'lib/fluent/plugin'),
5
+ File.join(File.dirname(__FILE__), '..', 'spec'),
6
+ ].each do |dir|
7
+ $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir)
8
+ end
9
+
10
+ require 'datadog_metrics_parser'
11
+ require 'date'
12
+ require 'rspec'
13
+
14
+
15
+ RSpec.describe DatadogMetricsParser do
16
+ describe "#emit_parsed_metrics" do
17
+ it 'should read sample Artifactory metrics data and verify the size of parsed data > 1' do
18
+ platform_metrics = File.read('./spec/fixtures/files/sample_artifactory_metrics.txt')
19
+ expect(platform_metrics.size).to be > 1
20
+
21
+ parser = DatadogMetricsParser.new('jfrog.artifactory', '', 'jfrog.artifactory.metrics')
22
+
23
+ normalized_data = parser.normalise_data(platform_metrics)
24
+ expect(normalized_data.size).to be > 1
25
+
26
+ cleaned_data = parser.clean_data(normalized_data)
27
+ expect(cleaned_data.size).to be > 1
28
+
29
+ hash_data_array = parser.format_data(cleaned_data, 'jfrog.artifactory', '.')
30
+ expect(hash_data_array.size).to be 1
31
+
32
+ serialized_data = parser.serialize_data(hash_data_array)
33
+ expect(serialized_data.size).to be 1
34
+ end
35
+
36
+ it 'should read sample Xray metrics data and verify the size of parsed data > 1' do
37
+ platform_metrics = File.read('./spec/fixtures/files/sample_xray_metrics.txt')
38
+ expect(platform_metrics.size).to be > 1
39
+
40
+ parser = DatadogMetricsParser.new('jfrog.xray', '', 'jfrog.xray.metrics')
41
+
42
+ normalized_data = parser.normalise_data(platform_metrics)
43
+ expect(normalized_data.size).to be > 1
44
+
45
+ cleaned_data = parser.clean_data(normalized_data)
46
+ expect(cleaned_data.size).to be > 1
47
+
48
+ hash_data_array = parser.format_data(cleaned_data, 'jfrog.xray', '.')
49
+ expect(hash_data_array.size).to be 1
50
+
51
+ serialized_data = parser.serialize_data(hash_data_array)
52
+ expect(serialized_data.size).to be 1
53
+ end
54
+
55
+ it 'should correctly parse metrics with nested curly braces in labels (JOBS-2011)' do
56
+ platform_metrics = File.read('./spec/fixtures/files/sample_metrics_with_nested_braces.txt')
57
+ expect(platform_metrics.size).to be > 1
58
+
59
+ parser = DatadogMetricsParser.new('jfrog.artifactory', '', 'jfrog.artifactory.metrics')
60
+
61
+ normalized_data = parser.normalise_data(platform_metrics)
62
+ expect(normalized_data.size).to be > 1
63
+
64
+ cleaned_data = parser.clean_data(normalized_data)
65
+ expect(cleaned_data.size).to be > 1
66
+
67
+ hash_data_array = parser.format_data(cleaned_data, 'jfrog.artifactory', '.')
68
+ expect(hash_data_array.size).to be 1
69
+
70
+ series_array = hash_data_array[0]['series']
71
+ expect(series_array.size).to be > 1
72
+
73
+ series_array.each do |metric|
74
+ expect(metric['metric']).to start_with('jfrog.artifactory.')
75
+ expect(metric['metric']).not_to include('{')
76
+ expect(metric['points']).not_to be_nil
77
+ expect(metric['points'].size).to be >= 1
78
+ end
79
+ end
80
+
81
+ it 'should parse single metric with nested braces correctly' do
82
+ metric_line = 'db_query_large_total{action="/artifactory/api/nuget/{repoKey}/Download/{packageId}/{packageVersion}",application="Artifactory",group="download",package="nuget"} 2.0 1711100784000'
83
+
84
+ parser = DatadogMetricsParser.new('jfrog.artifactory', '', 'jfrog.artifactory.metrics')
85
+ result = parser.format_data([metric_line], 'jfrog.artifactory', '.')
86
+
87
+ expect(result.size).to eq(1)
88
+ series = result[0]['series']
89
+ expect(series.size).to eq(1)
90
+ expect(series[0]['metric']).to eq('jfrog.artifactory.db_query_large_total')
91
+ expect(series[0]['points'][0]['value']).to eq(2.0)
92
+ expect(series[0]['tags']).to include('action:/artifactory/api/nuget/{repoKey}/Download/{packageId}/{packageVersion}')
93
+ expect(series[0]['tags']).to include('application:Artifactory')
94
+ end
95
+
96
+ it 'should not crash with nil values when parsing nested braces (regression test)' do
97
+ metric_with_complex_braces = 'db_query_large_total{action="/artifactory/api/artifactproperties{name:(/[^/]+?)?}",application="Artifactory",group="",package=""} 1.0 1711100784000'
98
+
99
+ parser = DatadogMetricsParser.new('jfrog.artifactory', '', 'jfrog.artifactory.metrics')
100
+
101
+ expect {
102
+ result = parser.format_data([metric_with_complex_braces], 'jfrog.artifactory', '.')
103
+ expect(result[0]['series'][0]['metric']).to eq('jfrog.artifactory.db_query_large_total')
104
+ }.not_to raise_error
105
+ end
106
+ end
107
+ end
@@ -51,5 +51,45 @@ RSpec.describe NewRelicMetricsParser do
51
51
  serialized_data = parser.serialize_data(hash_data_array)
52
52
  expect(serialized_data.size).to be 1
53
53
  end
54
+
55
+ it 'should correctly parse metrics with nested curly braces in labels (JOBS-2011)' do
56
+ platform_metrics = File.read('./spec/fixtures/files/sample_metrics_with_nested_braces.txt')
57
+ expect(platform_metrics.size).to be > 1
58
+
59
+ parser = NewRelicMetricsParser.new('jfrog.artifactory', '', 'jfrog.artifactory.metrics')
60
+
61
+ normalized_data = parser.normalise_data(platform_metrics)
62
+ expect(normalized_data.size).to be > 1
63
+
64
+ cleaned_data = parser.clean_data(normalized_data)
65
+ expect(cleaned_data.size).to be > 1
66
+
67
+ hash_data_array = parser.format_data(cleaned_data, 'jfrog.artifactory', '.')
68
+ expect(hash_data_array.size).to be 1
69
+
70
+ metrics_array = hash_data_array[0]['metrics']
71
+ expect(metrics_array.size).to be > 1
72
+
73
+ metrics_array.each do |metric|
74
+ expect(metric['name']).to start_with('jfrog.artifactory.')
75
+ expect(metric['name']).not_to include('{')
76
+ expect(metric['value']).not_to be_nil
77
+ end
78
+ end
79
+
80
+ it 'should parse single metric with nested braces correctly' do
81
+ metric_line = 'db_query_large_total{action="/artifactory/api/nuget/{repoKey}/Download/{packageId}/{packageVersion}",application="Artifactory",group="download",package="nuget"} 2.0 1711100784000'
82
+
83
+ parser = NewRelicMetricsParser.new('jfrog.artifactory', '', 'jfrog.artifactory.metrics')
84
+ result = parser.format_data([metric_line], 'jfrog.artifactory', '.')
85
+
86
+ expect(result.size).to eq(1)
87
+ metrics = result[0]['metrics']
88
+ expect(metrics.size).to eq(1)
89
+ expect(metrics[0]['name']).to eq('jfrog.artifactory.db_query_large_total')
90
+ expect(metrics[0]['value']).to eq(2.0)
91
+ expect(metrics[0]['attributes']['action']).to eq('/artifactory/api/nuget/{repoKey}/Download/{packageId}/{packageVersion}')
92
+ expect(metrics[0]['attributes']['application']).to eq('Artifactory')
93
+ end
54
94
  end
55
95
  end
@@ -51,5 +51,39 @@ RSpec.describe SplunkMetricsParser do
51
51
  serialized_data = parser.serialize_data(hash_data_array)
52
52
  expect(serialized_data.size).to be > 1
53
53
  end
54
+
55
+ it 'should correctly parse metrics with nested curly braces in labels (JOBS-2011)' do
56
+ platform_metrics = File.read('./spec/fixtures/files/sample_metrics_with_nested_braces.txt')
57
+ expect(platform_metrics.size).to be > 1
58
+
59
+ parser = SplunkMetricsParser.new('jfrog.artifactory', '', 'jfrog.artifactory.metrics')
60
+
61
+ normalized_data = parser.normalise_data(platform_metrics)
62
+ expect(normalized_data.size).to be > 1
63
+
64
+ cleaned_data = parser.clean_data(normalized_data)
65
+ expect(cleaned_data.size).to be > 1
66
+
67
+ hash_data_array = parser.format_data(cleaned_data, 'jfrog.artifactory', '.')
68
+ expect(hash_data_array.size).to be > 1
69
+
70
+ hash_data_array.each do |metric_hash|
71
+ expect(metric_hash['metric_name']).to start_with('jfrog.artifactory.')
72
+ expect(metric_hash['metric_name']).not_to include('{')
73
+ expect(metric_hash['value']).not_to be_nil
74
+ end
75
+ end
76
+
77
+ it 'should parse single metric with nested braces correctly' do
78
+ metric_line = 'db_query_large_total{action="/artifactory/api/nuget/{repoKey}/Download/{packageId}/{packageVersion}",application="Artifactory",group="download",package="nuget"} 2.0 1711100784000'
79
+
80
+ parser = SplunkMetricsParser.new('jfrog.artifactory', '', 'jfrog.artifactory.metrics')
81
+ result = parser.generate_hash_from_data(metric_line, 'jfrog.artifactory', '.')
82
+
83
+ expect(result['metric_name']).to eq('jfrog.artifactory.db_query_large_total')
84
+ expect(result['value']).to eq(2.0)
85
+ expect(result['action']).to eq('/artifactory/api/nuget/{repoKey}/Download/{packageId}/{packageVersion}')
86
+ expect(result['application']).to eq('Artifactory')
87
+ end
54
88
  end
55
89
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-jfrog-metrics
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.14
4
+ version: 0.2.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - MahithaB, BenHarosh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-01-19 00:00:00.000000000 Z
11
+ date: 2026-03-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -109,10 +109,8 @@ executables: []
109
109
  extensions: []
110
110
  extra_rdoc_files: []
111
111
  files:
112
- - ".gitignore"
113
- - ".rspec"
112
+ - CHANGELOG.md
114
113
  - Gemfile
115
- - Gemfile.lock
116
114
  - LICENSE
117
115
  - README.md
118
116
  - Rakefile
@@ -126,7 +124,9 @@ files:
126
124
  - lib/fluent/plugin/splunk_metrics_parser.rb
127
125
  - spec/fixtures/files/creds.rb
128
126
  - spec/fixtures/files/sample_artifactory_metrics.txt
127
+ - spec/fixtures/files/sample_metrics_with_nested_braces.txt
129
128
  - spec/fixtures/files/sample_xray_metrics.txt
129
+ - spec/lib/datadog_metrics_parser_spec.rb
130
130
  - spec/lib/metrics_helper_spec.rb
131
131
  - spec/lib/newrelic_metrics_parser_spec.rb
132
132
  - spec/lib/splunk_metrics_parser_spec.rb
@@ -159,12 +159,14 @@ summary: Fluentd Plugin for converting JFrog Artifactory, Xray generated metrics
159
159
  Exposition Format) to target observability platform format (Splunk HEC, New Relic,
160
160
  DataDog)
161
161
  test_files:
162
- - spec/fixtures/files/creds.rb
163
- - spec/fixtures/files/sample_artifactory_metrics.txt
164
- - spec/fixtures/files/sample_xray_metrics.txt
165
- - spec/lib/metrics_helper_spec.rb
166
- - spec/lib/newrelic_metrics_parser_spec.rb
167
- - spec/lib/splunk_metrics_parser_spec.rb
168
- - spec/spec_helper.rb
169
162
  - test/helper.rb
170
163
  - test/plugin/test_in_jfrog_metrics.rb
164
+ - spec/spec_helper.rb
165
+ - spec/lib/datadog_metrics_parser_spec.rb
166
+ - spec/lib/splunk_metrics_parser_spec.rb
167
+ - spec/lib/metrics_helper_spec.rb
168
+ - spec/lib/newrelic_metrics_parser_spec.rb
169
+ - spec/fixtures/files/sample_xray_metrics.txt
170
+ - spec/fixtures/files/sample_metrics_with_nested_braces.txt
171
+ - spec/fixtures/files/creds.rb
172
+ - spec/fixtures/files/sample_artifactory_metrics.txt
data/.gitignore DELETED
@@ -1,3 +0,0 @@
1
- .DS_Store
2
- fluent-plugin-jfrog-metrics-*.gem
3
- fluent-plugin-jfrog-metrics.iml
data/.rspec DELETED
@@ -1 +0,0 @@
1
- --require spec_helper
data/Gemfile.lock DELETED
@@ -1,81 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- fluent-plugin-jfrog-metrics (0.2.13)
5
- fluentd (>= 0.14.10, < 2)
6
- rest-client (~> 2.1.0)
7
-
8
- GEM
9
- remote: https://rubygems.org/
10
- specs:
11
- ansi (1.5.0)
12
- builder (3.2.4)
13
- concurrent-ruby (1.2.2)
14
- cool.io (1.7.1)
15
- domain_name (0.5.20190701)
16
- unf (>= 0.0.5, < 1.0.0)
17
- fluentd (1.16.1)
18
- bundler
19
- cool.io (>= 1.4.5, < 2.0.0)
20
- http_parser.rb (>= 0.5.1, < 0.9.0)
21
- msgpack (>= 1.3.1, < 2.0.0)
22
- serverengine (>= 2.3.2, < 3.0.0)
23
- sigdump (~> 0.2.2)
24
- strptime (>= 0.2.4, < 1.0.0)
25
- tzinfo (>= 1.0, < 3.0)
26
- tzinfo-data (~> 1.0)
27
- webrick (~> 1.4)
28
- yajl-ruby (~> 1.0)
29
- http-accept (1.7.0)
30
- http-cookie (1.0.4)
31
- domain_name (~> 0.5)
32
- http_parser.rb (0.8.0)
33
- mime-types (3.4.1)
34
- mime-types-data (~> 3.2015)
35
- mime-types-data (3.2021.1115)
36
- minitest (5.14.4)
37
- minitest-reporters (1.4.3)
38
- ansi
39
- builder
40
- minitest (>= 5.0)
41
- ruby-progressbar
42
- msgpack (1.7.1)
43
- netrc (0.11.0)
44
- power_assert (2.0.1)
45
- rake (12.3.3)
46
- rest-client (2.1.0)
47
- http-accept (>= 1.7.0, < 2.0)
48
- http-cookie (>= 1.0.2, < 2.0)
49
- mime-types (>= 1.16, < 4.0)
50
- netrc (~> 0.8)
51
- ruby-progressbar (1.11.0)
52
- serverengine (2.3.2)
53
- sigdump (~> 0.2.2)
54
- sigdump (0.2.4)
55
- strptime (0.2.5)
56
- test-unit (3.5.0)
57
- power_assert
58
- tzinfo (2.0.6)
59
- concurrent-ruby (~> 1.0)
60
- tzinfo-data (1.2023.3)
61
- tzinfo (>= 1.0.0)
62
- unf (0.1.4)
63
- unf_ext
64
- unf_ext (0.0.8)
65
- webrick (1.8.1)
66
- yajl-ruby (1.4.3)
67
-
68
- PLATFORMS
69
- ruby
70
-
71
- DEPENDENCIES
72
- bundler (~> 1.14)
73
- fluent-plugin-jfrog-metrics!
74
- minitest
75
- minitest-reporters (>= 0.5.0)
76
- rake (~> 12.0)
77
- rest-client (>= 2.1.0)
78
- test-unit (~> 3.0)
79
-
80
- BUNDLED WITH
81
- 1.17.3