aws-embedded-metrics-customink 0.6.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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: []