aws-embedded-metrics-customink 0.6.0 → 0.8.0

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: b07c505a8d7790b89bff615c824567402f3e6b613287753ea5b7fe930614ce8b
4
- data.tar.gz: cd42f99bccbd143a40acdd8f7ec91e442d3fc2c6475397179561c78482e9a2de
3
+ metadata.gz: 1cc2867474c435e6c5de18f3c599aeffd9f589b0164e9659fecf4d26ecda8478
4
+ data.tar.gz: a5a7bd3e0c2f4bf710343e1f54707d69a79c889ecf38025ac9106b7fcac44cd0
5
5
  SHA512:
6
- metadata.gz: 8de84739de64092a2998196e7a5348ad2a8339282eb7fdc7dfbb0773096dd70fd8ef77e853e8a812075c3d6ef2cddd74fdb9cb629643bb0efabd9fe9a8168582
7
- data.tar.gz: 9892885a4debc5335e8c43cecc687e4107c8ac52efb046cb82b12c3d12c0529a40c23d73e4b9539ca51b94b6de6dfd805f417136f68a6a3551ddc684e85f72a9
6
+ metadata.gz: e4021d0eb717b34bd6f25421c4fc39ea65138570ace643fabdd2eac2551155314310eb2c44f7bd2755bd4a70ea51e6dde4d12e68c629b492a0e05ae9c1a87bea
7
+ data.tar.gz: d41ed4bf3b8ba2f0b3cbcb5d8eb5bef2b4e214cf41ce61deb151cefdb206db7a94eda3f6a3886dcff9d615a26a58be0901f6913bb7345151ddbb0c8943a0c98c
data/CHANGELOG.md CHANGED
@@ -3,6 +3,22 @@
3
3
 
4
4
  See this http://keepachangelog.com link for information on how we want this documented formatted.
5
5
 
6
+ ## v0.8.0
7
+
8
+ ### Added
9
+
10
+ - New TCP Sink.
11
+ - Support for `LogGroupName` and `LogStreamName`.
12
+ - New `Metrics::Units` constants.
13
+
14
+ ## v0.7.0
15
+
16
+ ### Added
17
+
18
+ - A new `Tcp` sink is added. The `Tcp` sink can send EMF messages to any valid TCP endpoint.
19
+ - `tcp-client` will be required at runtime if you use the `Tcp` sink. Originally a small hand-written TCP client was used but it proved unreliable and well outside the scope of this library.
20
+ - Added the new `Units` class for easy reference to the accepted metric units.
21
+
6
22
  ## v0.6.0
7
23
 
8
24
  ### Fixed
data/Gemfile CHANGED
@@ -8,4 +8,5 @@ gem 'rubocop'
8
8
  group :test do
9
9
  gem 'mocha'
10
10
  gem 'pry'
11
+ gem 'tcp-client'
11
12
  end
data/Gemfile.lock CHANGED
@@ -1,41 +1,46 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- aws-embedded-metrics-customink (0.6.0)
4
+ aws-embedded-metrics-customink (0.8.0)
5
5
  concurrent-ruby
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- ast (2.4.1)
10
+ ast (2.4.2)
11
11
  coderay (1.1.3)
12
- concurrent-ruby (1.1.7)
12
+ concurrent-ruby (1.1.10)
13
+ json (2.6.3)
13
14
  method_source (1.0.0)
14
- minitest (5.14.1)
15
- mocha (1.11.2)
16
- parallel (1.19.2)
17
- parser (2.7.1.4)
15
+ minitest (5.17.0)
16
+ mocha (2.0.2)
17
+ ruby2_keywords (>= 0.0.5)
18
+ parallel (1.22.1)
19
+ parser (3.2.0.0)
18
20
  ast (~> 2.4.1)
19
- pry (0.13.1)
21
+ pry (0.14.2)
20
22
  coderay (~> 1.1)
21
23
  method_source (~> 1.0)
22
- rainbow (3.0.0)
23
- rake (13.0.1)
24
- regexp_parser (1.7.1)
25
- rexml (3.2.3)
26
- rubocop (0.88.0)
24
+ rainbow (3.1.1)
25
+ rake (13.0.6)
26
+ regexp_parser (2.6.1)
27
+ rexml (3.2.5)
28
+ rubocop (1.43.0)
29
+ json (~> 2.3)
27
30
  parallel (~> 1.10)
28
- parser (>= 2.7.1.1)
31
+ parser (>= 3.2.0.0)
29
32
  rainbow (>= 2.2.2, < 4.0)
30
- regexp_parser (>= 1.7)
31
- rexml
32
- rubocop-ast (>= 0.1.0, < 1.0)
33
+ regexp_parser (>= 1.8, < 3.0)
34
+ rexml (>= 3.2.5, < 4.0)
35
+ rubocop-ast (>= 1.24.1, < 2.0)
33
36
  ruby-progressbar (~> 1.7)
34
- unicode-display_width (>= 1.4.0, < 2.0)
35
- rubocop-ast (0.2.0)
36
- parser (>= 2.7.0.1)
37
- ruby-progressbar (1.10.1)
38
- unicode-display_width (1.7.0)
37
+ unicode-display_width (>= 2.4.0, < 3.0)
38
+ rubocop-ast (1.24.1)
39
+ parser (>= 3.1.1.0)
40
+ ruby-progressbar (1.11.0)
41
+ ruby2_keywords (0.0.5)
42
+ tcp-client (0.11.4)
43
+ unicode-display_width (2.4.2)
39
44
 
40
45
  PLATFORMS
41
46
  ruby
@@ -47,6 +52,7 @@ DEPENDENCIES
47
52
  pry
48
53
  rake
49
54
  rubocop
55
+ tcp-client
50
56
 
51
57
  BUNDLED WITH
52
- 2.1.2
58
+ 2.3.5
data/README.md CHANGED
@@ -13,10 +13,8 @@ Pulled from these two projects using the [Embedded Metric Format Specification](
13
13
 
14
14
  However, unlike these projects, we differ in the following ways. Again, contributions are very much welcome if you want to see more or change this.
15
15
 
16
- * Initial focus on Lambda. No other sinks.
17
- * As such, no default Dimensions or Configuraiton for:
18
- - `LogGroupName`
19
- - `LogStreamName`
16
+ * Initial focus on Lambda. A TCP sink has been added, but no UDP sink exists.
17
+ * No default Dimensions or Configuration for:
20
18
  - `ServiceName`
21
19
  - `ServiceType`
22
20
 
@@ -29,11 +27,19 @@ gem 'aws-embedded-metrics-customink'
29
27
  ```
30
28
  ## Usage
31
29
 
30
+ If using outside of Rails, require the gem:
31
+ ```ruby
32
+ require 'aws-embedded-metrics-customink'
33
+ ```
34
+
32
35
  Simple configuration:
33
36
 
34
37
  ```ruby
35
38
  Aws::Embedded::Metrics.configure do |c|
36
39
  c.namespace = 'MyApplication'
40
+ # Optional
41
+ c.log_group_name = 'MyLogGroup'
42
+ c.log_stream_name = 'MyLogStream-UniqueID'
37
43
  end
38
44
  ```
39
45
 
@@ -45,6 +51,15 @@ Aws::Embedded::Metrics.configure do |c|
45
51
  end
46
52
  ```
47
53
 
54
+ Using the `Tcp` sink to write over a network:
55
+
56
+ ```ruby
57
+ Aws::Embedded::Metrics.configure do |c|
58
+ c.sink = Aws::Embedded::Metrics::Sinks::Tcp.new(conn_str: "tcp://localhost:25888",
59
+ logger: Rails.logger)
60
+ end
61
+ ```
62
+
48
63
  Usage is in a scope block. All metrics are flushed afterward
49
64
 
50
65
  ```ruby
@@ -22,7 +22,10 @@ module Aws
22
22
 
23
23
  class Configuration
24
24
 
25
- attr_writer :namespace, :sink
25
+ attr_writer :log_group_name,
26
+ :log_stream_name,
27
+ :namespace,
28
+ :sink
26
29
 
27
30
  def reconfigure
28
31
  instance_variables.each { |var| instance_variable_set var, nil }
@@ -30,16 +33,27 @@ module Aws
30
33
  self
31
34
  end
32
35
 
36
+ def log_group_name
37
+ return @log_group_name if defined?(@log_group_name)
38
+
39
+ ENV.fetch('AWS_EMF_LOG_GROUP_NAME', nil)
40
+ end
41
+
42
+ def log_stream_name
43
+ return @log_stream_name if defined?(@log_stream_name)
44
+
45
+ ENV.fetch('AWS_EMF_LOG_STREAM_NAME', nil)
46
+ end
47
+
33
48
  def namespace
34
49
  return @namespace if defined?(@namespace)
35
50
 
36
- ENV['AWS_EMF_NAMESPACE'] || 'aws-embedded-metrics'
51
+ ENV.fetch('AWS_EMF_NAMESPACE', 'aws-embedded-metrics')
37
52
  end
38
53
 
39
54
  def sink
40
55
  @sink ||= DEFAULT_SINK.new
41
56
  end
42
-
43
57
  end
44
58
  end
45
59
  end
@@ -5,6 +5,8 @@ module Aws
5
5
 
6
6
  def initialize(sink = Config.config.sink)
7
7
  @sink = sink
8
+ @log_group_name = Config.config.log_group_name
9
+ @log_stream_name = Config.config.log_stream_name
8
10
  @namespace = Config.config.namespace
9
11
  @dimensions = Concurrent::Array.new
10
12
  @metrics = Concurrent::Array.new
@@ -50,17 +52,20 @@ module Aws
50
52
  end
51
53
 
52
54
  def message
55
+ aws = {
56
+ 'Timestamp' => timestamp,
57
+ 'CloudWatchMetrics' => [{
58
+ 'Namespace' => @namespace,
59
+ 'Dimensions' => [@dimensions.map(&:keys).flatten],
60
+ 'Metrics' => @metrics
61
+ }]
62
+ }
63
+
64
+ aws['LogGroupName'] = @log_group_name if @log_group_name
65
+ aws['LogStreamName'] = @log_stream_name if @log_stream_name
66
+
53
67
  {
54
- '_aws' => {
55
- 'Timestamp' => timestamp,
56
- 'CloudWatchMetrics' => [
57
- {
58
- 'Namespace' => @namespace,
59
- 'Dimensions' => [@dimensions.map(&:keys).flatten],
60
- 'Metrics' => @metrics
61
- }
62
- ]
63
- }
68
+ '_aws' => aws
64
69
  }.tap do |m|
65
70
  @dimensions.each { |dim| m.merge!(dim) }
66
71
  m.merge!(@properties)
@@ -0,0 +1,9 @@
1
+ module Aws
2
+ module Embedded
3
+ module Metrics
4
+ module Sinks
5
+ class Error < StandardError; end
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ gem 'tcp-client'
4
+ require 'tcp-client'
5
+
6
+ module Aws
7
+ module Embedded
8
+ module Metrics
9
+ module Sinks
10
+ #
11
+ # Create a sink that will communicate to a CloudWatch Log Agent over a TCP connection.
12
+ #
13
+ # See https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Generation_CloudWatch_Agent.html
14
+ # for configuration information
15
+ class Tcp
16
+ AWS_EMF_AGENT_ENDPOINT_ENV_VAR = 'AWS_EMF_AGENT_ENDPOINT'
17
+ attr_reader :queue
18
+ attr :client_opts
19
+
20
+ #
21
+ # Create a new TCP sink. It will use the +AWS_EMF_AGENT_ENDPOINT+ environment variable by default to
22
+ # connect to a CloudWatch Metric Agent.
23
+ #
24
+ # @param conn_str [String] A connection string, formatted like 'tcp://127.0.0.1:25888'.
25
+ # @param conn_timeout_secs [Numeric] The number of seconds before timing out the connection to the agent.
26
+ # @param write_timeout_secs [Numeric] The number of seconds to wait before timing out a write.
27
+ # @param logger [Logger] A standard Ruby logger to propagate warnings and errors.
28
+ # Suggested to use Rails.logger.
29
+ def initialize(conn_str: ENV.fetch(AWS_EMF_AGENT_ENDPOINT_ENV_VAR, nil),
30
+ conn_timeout_secs: 10,
31
+ write_timeout_secs: 10,
32
+ logger: nil)
33
+ if conn_str.nil?
34
+ raise Sinks::Error, "Must specify a connection string or set environment variable #{AWS_EMF_AGENT_ENDPOINT_ENV_VAR}"
35
+ end
36
+
37
+ @logger = logger
38
+ @cw_agent_uri = URI.parse(conn_str)
39
+ if @cw_agent_uri.scheme != 'tcp' || !@cw_agent_uri.host || !@cw_agent_uri.port
40
+ raise Sinks::Error, "Expected connection string to be in format tcp://<host>:<port>, got '#{conn_str}'"
41
+ end
42
+
43
+ @client_opts = TCPClient::Configuration.create(
44
+ buffered: true,
45
+ keep_alive: true,
46
+ reverse_lookup: true,
47
+ connect_timeout: conn_timeout_secs,
48
+ write_timeout: write_timeout_secs
49
+ )
50
+ @conn = nil
51
+ end
52
+
53
+ def log_warn(msg)
54
+ @logger&.warn(msg)
55
+ end
56
+
57
+ def log_err(msg)
58
+ @logger&.error(msg)
59
+ end
60
+
61
+ def create_conn(host, port, opts)
62
+ TCPClient.open("#{host}:#{port}", opts)
63
+ end
64
+
65
+ def connection
66
+ @conn = create_conn(@cw_agent_uri.host, @cw_agent_uri.port, @client_opts) if @conn.nil? || @conn.closed?
67
+ @conn
68
+ end
69
+
70
+ def send_message(message)
71
+ retries = 2
72
+ conn = nil
73
+ begin
74
+ conn = connection
75
+ conn.write(message)
76
+ rescue Errno::ECONNREFUSED
77
+ conn.close unless conn.nil? || conn.closed?
78
+ log_warn("Could not connect to CloudWatch Agent at #{@cw_agent_uri.scheme}://#{@cw_agent_uri.host}:#{@cw_agent_uri.port}")
79
+ retries -= 1
80
+ retry if retries >= 0
81
+ rescue StandardError => e
82
+ log_err("#{e.class}: #{e.message}: #{e.backtrace.join("\n")}")
83
+ end
84
+ end
85
+
86
+ def accept(message)
87
+ send_message("#{JSON.dump(message)}\n")
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -1,2 +1,5 @@
1
1
  require 'aws-embedded-metrics-customink/sinks/logger'
2
2
  require 'aws-embedded-metrics-customink/sinks/stdout'
3
+ require 'aws-embedded-metrics-customink/sinks/tcp'
4
+
5
+ require 'aws-embedded-metrics-customink/sinks/sink_error'
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module Embedded
5
+ module Metrics
6
+ class Units
7
+ # Time
8
+ SECONDS = 'Seconds'
9
+ MICROSECONDS = 'Microseconds'
10
+ MILLISECONDS = 'Milliseconds'
11
+
12
+ # Size
13
+ BYTES = 'Bytes'
14
+ KILOBYTES = 'Kilobytes'
15
+ MEGABYTES = 'Megabytes'
16
+ GIGABYTES = 'Gigabytes'
17
+ TERABYTES = 'Terabytes'
18
+
19
+ BITS = 'Bits'
20
+ KILOBITS = 'Kilobits'
21
+ MEGABITS = 'Megabits'
22
+ GIGABITS = 'Gigabits'
23
+ TERABITS = 'Terabits'
24
+
25
+ # Simple units
26
+ PERCENT = 'Percent'
27
+ COUNT = 'Count'
28
+
29
+ # Size over time
30
+ BYTES_SECOND = "#{BYTES}/Second"
31
+ KILOBYTES_SECOND = "#{KILOBYTES}/Second"
32
+ MEGABYTES_SECOND = "#{MEGABYTES}/Second"
33
+ GIGABYTES_SECOND = "#{GIGABYTES}/Second"
34
+ TERABYTES_SECOND = "#{TERABYTES}/Second"
35
+
36
+ BITS_SECOND = "#{BITS}/Second"
37
+ KILOBITS_SECOND = "#{KILOBITS}/Second"
38
+ MEGABITS_SECOND = "#{MEGABITS}/Second"
39
+ GIGABITS_SECOND = "#{GIGABITS}/Second"
40
+ TERABITS_SECOND = "#{TERABITS}/Second"
41
+
42
+ COUNT_SECOND = "#{COUNT}/Second"
43
+
44
+ # Unit-less
45
+ NONE = 'None'
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,7 +1,7 @@
1
1
  module Aws
2
2
  module Embedded
3
3
  module Metrics
4
- VERSION = '0.6.0'.freeze
4
+ VERSION = '0.8.0'.freeze
5
5
  end
6
6
  end
7
7
  end
@@ -6,6 +6,7 @@ require 'aws-embedded-metrics-customink/version'
6
6
  require 'aws-embedded-metrics-customink/sinks'
7
7
  require 'aws-embedded-metrics-customink/config'
8
8
  require 'aws-embedded-metrics-customink/logger'
9
+ require 'aws-embedded-metrics-customink/units'
9
10
  require 'aws-embedded-metrics-customink/instance' if defined?(Rails)
10
11
 
11
12
  module Aws
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aws-embedded-metrics-customink
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ken Collins
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-08-22 00:00:00.000000000 Z
11
+ date: 2023-04-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -54,7 +54,10 @@ files:
54
54
  - lib/aws-embedded-metrics-customink/logger.rb
55
55
  - lib/aws-embedded-metrics-customink/sinks.rb
56
56
  - lib/aws-embedded-metrics-customink/sinks/logger.rb
57
+ - lib/aws-embedded-metrics-customink/sinks/sink_error.rb
57
58
  - lib/aws-embedded-metrics-customink/sinks/stdout.rb
59
+ - lib/aws-embedded-metrics-customink/sinks/tcp.rb
60
+ - lib/aws-embedded-metrics-customink/units.rb
58
61
  - lib/aws-embedded-metrics-customink/version.rb
59
62
  homepage: https://github.com/customink/aws-embedded-metrics-customink
60
63
  licenses:
@@ -63,7 +66,7 @@ metadata:
63
66
  homepage_uri: https://github.com/customink/aws-embedded-metrics-customink
64
67
  source_code_uri: https://github.com/customink/aws-embedded-metrics-customink
65
68
  changelog_uri: https://github.com/customink/aws-embedded-metrics-customink/blob/master/CHANGELOG.md
66
- post_install_message:
69
+ post_install_message:
67
70
  rdoc_options: []
68
71
  require_paths:
69
72
  - lib
@@ -78,8 +81,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
78
81
  - !ruby/object:Gem::Version
79
82
  version: '0'
80
83
  requirements: []
81
- rubygems_version: 3.1.2
82
- signing_key:
84
+ rubygems_version: 3.4.7
85
+ signing_key:
83
86
  specification_version: 4
84
87
  summary: Amazon CloudWatch Embedded Metric Format Client Library
85
88
  test_files: []