appsignal 4.8.1-java → 4.8.3-java

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: 43b923f86f68b59e5398b10394ecbab0e020644aa52ac3d115f648c7600676a1
4
- data.tar.gz: 8fff3cc2fe093c596164b50309bf88aa72ee84fb036310d542f43dc1bf5bd938
3
+ metadata.gz: cd64c501f9026dc4658364532b105f9a866c21533fd510bf2c0abea321c2d513
4
+ data.tar.gz: ff044b5dda35caaeeb9eb51789100937122db57a2d28f798c037b99b74367f01
5
5
  SHA512:
6
- metadata.gz: faa0243f4174d6ace6df6e39585b5484917f5efa9453b352cc74d816c7d12084c13cc2e6052cd05247bdffa180110e542125a17c5aea8384a4a03da8cb8b927f
7
- data.tar.gz: 9edbcb359dbfb4414ffbfd83b00d4c9dc3424aeab0a6f1bf0eb10eee5c0887b43a185b48fdea30e98e7ec1b11ac3aedc735e6bbab69ac387fe2173db4a740878
6
+ metadata.gz: c7d95a9271fd861afb88e398f9db80288870114d26a6719517a6a9f5654e40b0b6f332d3432e2cfebe29d061d1fb75247587ce7e36757da630f119e990c13171
7
+ data.tar.gz: 6c4c27891167d520cfa0d86f1ce6771fe8b9c3a24189ed4b05a43a124fd1be41667628182c08bd6baed443de81089c77197e31cf25b1193ffd07d2b8be46fd5c
data/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # AppSignal for Ruby gem Changelog
2
2
 
3
+ ## 4.8.3
4
+
5
+ _Published on 2026-02-17._
6
+
7
+ ### Added
8
+
9
+ - Add a `default_tags` configuration option. Tags set in this configuration option will be set for all transactions. (patch [3b9d9f48](https://github.com/appsignal/appsignal-ruby/commit/3b9d9f4844295d3c8f94fe750509f69f579cb372))
10
+
11
+ ## 4.8.2
12
+
13
+ _Published on 2026-02-05._
14
+
15
+ ### Added
16
+
17
+ - Log where `Appsignal.configure` is called. When a warning is emitted about `Appsignal.configure` being called from an application where `config/appsignal.yml` or `config/appsignal.rb` exist, log the location from which `Appsignal.configure` was called alongside the location of the configuration file. (patch [a9097107](https://github.com/appsignal/appsignal-ruby/commit/a90971075370bcf1d37f568d934dd8aeb71c1223))
18
+
19
+ ### Fixed
20
+
21
+ - Fix the `bundle exec appsignal install` CLI command on Ruby 4 by removing the dependency on the `ostruct` gem, which is no longer part of the standard library. (patch [d3bd5198](https://github.com/appsignal/appsignal-ruby/commit/d3bd5198486a762353bfbd7807f4d042a85a9d3d))
22
+
3
23
  ## 4.8.1
4
24
 
5
25
  _Published on 2025-12-16._
data/build_matrix.yml CHANGED
@@ -118,8 +118,7 @@ matrix:
118
118
  - "rails-8.1"
119
119
 
120
120
  ruby:
121
- - ruby: "4.0.0-preview2"
122
- - ruby: "3.5.0-preview1"
121
+ - ruby: "4.0.0"
123
122
  - ruby: "3.4.1"
124
123
  - ruby: "3.3.4"
125
124
  - ruby: "3.2.5"
@@ -145,8 +144,7 @@ matrix:
145
144
  - gem: "dry-monitor"
146
145
  only:
147
146
  ruby:
148
- - "4.0.0-preview2"
149
- - "3.5.0-preview1"
147
+ - "4.0.0"
150
148
  - "3.4.1"
151
149
  - "3.3.4"
152
150
  - "3.2.5"
@@ -156,7 +154,6 @@ matrix:
156
154
  - gem: "hanami-2.0"
157
155
  only:
158
156
  ruby:
159
- - "3.5.0-preview1"
160
157
  - "3.4.1"
161
158
  - "3.3.4"
162
159
  - "3.2.5"
@@ -165,7 +162,6 @@ matrix:
165
162
  - gem: "hanami-2.1"
166
163
  only:
167
164
  ruby:
168
- - "3.5.0-preview1"
169
165
  - "3.4.1"
170
166
  - "3.3.4"
171
167
  - "3.2.5"
@@ -174,7 +170,6 @@ matrix:
174
170
  - gem: "hanami-2.2"
175
171
  only:
176
172
  ruby:
177
- - "3.5.0-preview1"
178
173
  - "3.4.1"
179
174
  - "3.3.4"
180
175
  - "3.2.5"
@@ -184,12 +179,11 @@ matrix:
184
179
  - gem: "padrino"
185
180
  exclude:
186
181
  ruby:
187
- - "4.0.0-preview2"
182
+ - "4.0.0"
188
183
  - gem: "psych-3"
189
184
  only:
190
185
  ruby:
191
- - "4.0.0-preview2"
192
- - "3.5.0-preview1"
186
+ - "4.0.0"
193
187
  - "3.4.1"
194
188
  - "3.3.4"
195
189
  - "3.2.5"
@@ -199,8 +193,7 @@ matrix:
199
193
  - gem: "psych-4"
200
194
  only:
201
195
  ruby:
202
- - "4.0.0-preview2"
203
- - "3.5.0-preview1"
196
+ - "4.0.0"
204
197
  - "3.4.1"
205
198
  - "3.3.4"
206
199
  - "3.2.5"
@@ -227,8 +220,7 @@ matrix:
227
220
  - gem: "rails-7.0"
228
221
  only:
229
222
  ruby:
230
- - "4.0.0-preview2"
231
- - "3.5.0-preview1"
223
+ - "4.0.0"
232
224
  - "3.4.1"
233
225
  - "3.3.4"
234
226
  - "3.2.5"
@@ -239,8 +231,7 @@ matrix:
239
231
  - gem: "rails-7.1"
240
232
  only:
241
233
  ruby:
242
- - "4.0.0-preview2"
243
- - "3.5.0-preview1"
234
+ - "4.0.0"
244
235
  - "3.4.1"
245
236
  - "3.3.4"
246
237
  - "3.2.5"
@@ -250,8 +241,7 @@ matrix:
250
241
  - gem: "rails-7.2"
251
242
  only:
252
243
  ruby:
253
- - "4.0.0-preview2"
254
- - "3.5.0-preview1"
244
+ - "4.0.0"
255
245
  - "3.4.1"
256
246
  - "3.3.4"
257
247
  - "3.2.5"
@@ -260,15 +250,13 @@ matrix:
260
250
  - gem: "rails-8.0"
261
251
  only:
262
252
  ruby:
263
- - "4.0.0-preview2"
264
- - "3.5.0-preview1"
253
+ - "4.0.0"
265
254
  - "3.4.1"
266
255
  - "3.3.4"
267
256
  - "3.2.5"
268
257
  - gem: "rails-8.1"
269
258
  only:
270
259
  ruby:
271
- - "3.5.0-preview1"
272
260
  - "3.4.1"
273
261
  - "3.3.4"
274
262
  - "3.2.5"
@@ -280,12 +268,10 @@ matrix:
280
268
  - gem: "sidekiq-7"
281
269
  only:
282
270
  ruby:
283
- - "4.0.0-preview2"
284
- - "3.5.0-preview1"
271
+ - "4.0.0"
285
272
  - "3.4.1"
286
273
  - gem: "sidekiq-8"
287
274
  only:
288
275
  ruby:
289
- - "4.0.0-preview2"
290
- - "3.5.0-preview1"
276
+ - "4.0.0"
291
277
  - "3.4.1"
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "erb"
4
- require "ostruct"
5
4
  require "io/console"
6
5
  require "appsignal/demo"
7
6
 
@@ -366,7 +365,7 @@ module Appsignal
366
365
  def write_config_file(template_path, path, data)
367
366
  file_contents = File.read(template_path)
368
367
  template = ERB.new(file_contents, :trim_mode => "-")
369
- config = template.result(OpenStruct.new(data).instance_eval { binding })
368
+ config = template.result_with_hash(data)
370
369
 
371
370
  FileUtils.mkdir_p(File.join(Dir.pwd, "config"))
372
371
  File.write(path, config)
@@ -132,7 +132,8 @@ module Appsignal
132
132
  :send_environment_metadata => true,
133
133
  :send_params => true,
134
134
  :send_session_data => true,
135
- :sidekiq_report_errors => "all"
135
+ :sidekiq_report_errors => "all",
136
+ :default_tags => {}
136
137
  }.freeze
137
138
 
138
139
  # @!visibility private
@@ -221,6 +222,11 @@ module Appsignal
221
222
  :cpu_count => "APPSIGNAL_CPU_COUNT"
222
223
  }.freeze
223
224
 
225
+ # @!visibility private
226
+ HASH_OPTIONS = {
227
+ :default_tags => "APPSIGNAL_DEFAULT_TAGS"
228
+ }.freeze
229
+
224
230
  # @!visibility private
225
231
  attr_reader :root_path, :env, :config_hash
226
232
 
@@ -639,9 +645,34 @@ module Appsignal
639
645
  config[option] = env_var.to_f
640
646
  end
641
647
 
648
+ # Configuration with hash type
649
+ HASH_OPTIONS.each do |option, env_key|
650
+ env_var = ENV.fetch(env_key, nil)
651
+ next unless env_var
652
+
653
+ config[option] = parse_tags_from_env(env_var)
654
+ end
655
+
642
656
  config
643
657
  end
644
658
 
659
+ # Parse tags from environment variable string format "foo=bar,baz=quux"
660
+ # @param env_var [String] the environment variable value
661
+ # @return [Hash] parsed tags with string keys and values
662
+ # @api private
663
+ def parse_tags_from_env(env_var)
664
+ return {} if env_var.nil? || env_var.strip.empty?
665
+
666
+ env_var.split(",").each_with_object({}) do |pair, hash|
667
+ key, value = pair.split("=", 2)
668
+
669
+ # Skip malformed pairs (no key, no value, or missing "=")
670
+ next unless key && value && !key.strip.empty? && !value.strip.empty?
671
+
672
+ hash[key.strip] = value.strip
673
+ end
674
+ end
675
+
645
676
  # Set config options based on the final user config. Fix any conflicting
646
677
  # config.
647
678
  def determine_overrides
@@ -891,6 +922,24 @@ module Appsignal
891
922
  end
892
923
  end
893
924
 
925
+ # @!group Hash Configuration Options
926
+
927
+ # @!attribute [rw] default_tags
928
+ # @return [Hash] Default tags to set on all transactions
929
+
930
+ # @!endgroup
931
+
932
+ # Custom getter for default_tags to ensure consistent format
933
+ def default_tags
934
+ fetch_option(:default_tags) || {}
935
+ end
936
+
937
+ # Custom setter for default_tags with validation
938
+ def default_tags=(value)
939
+ parsed_tags = parse_and_validate_tags(value)
940
+ update_option(:default_tags, parsed_tags)
941
+ end
942
+
894
943
  private
895
944
 
896
945
  def fetch_option(key)
@@ -904,6 +953,48 @@ module Appsignal
904
953
  def update_option(key, value)
905
954
  @dsl_options[key] = value
906
955
  end
956
+
957
+ # Parse tags from various input formats and validate values
958
+ # @param value [Hash, nil] input tags
959
+ # @return [Hash] validated tags with string keys
960
+ # @api private
961
+ def parse_and_validate_tags(value)
962
+ case value
963
+ when Hash
964
+ validate_tag_values(value)
965
+ when nil
966
+ {}
967
+ else
968
+ Appsignal.internal_logger.warn(
969
+ "Invalid value for 'default_tags' config option: #{value.class}. " \
970
+ "The 'default_tags' config option must be a Hash."
971
+ )
972
+ {}
973
+ end
974
+ end
975
+
976
+ # Validate tag values are allowed types, log errors for invalid types
977
+ # @param tags [Hash] tags to validate
978
+ # @return [Hash] tags with only valid values
979
+ # @api private
980
+ def validate_tag_values(tags)
981
+ tags.each_with_object({}) do |(key, value), valid_tags|
982
+ # Convert keys to strings for consistency
983
+ string_key = key.to_s
984
+
985
+ # Check if value is an allowed type
986
+ if [Symbol, String, Integer, TrueClass, FalseClass].any? { |type| value.is_a?(type) }
987
+ valid_tags[string_key] = value
988
+ else
989
+ Appsignal.internal_logger.warn(
990
+ "Ignored tag '#{string_key}' in 'default_tags' config option because of " \
991
+ "invalid value type: #{value.class}. " \
992
+ "Tags in the 'default_tags' config option must have values of type " \
993
+ "String, Symbol, Integer, or Boolean."
994
+ )
995
+ end
996
+ end
997
+ end
907
998
  end
908
999
  end
909
1000
  end
@@ -897,7 +897,18 @@ module Appsignal
897
897
  #
898
898
  # @see https://docs.appsignal.com/ruby/instrumentation/tagging.html
899
899
  def sanitized_tags
900
- @tags.select do |key, value|
900
+ # Start with config default_tags as base (if config is available)
901
+ base_tags = if Appsignal.config
902
+ Appsignal.config[:default_tags] || {}
903
+ else
904
+ {}
905
+ end
906
+
907
+ # Merge transaction tags on top (transaction tags take priority)
908
+ all_tags = base_tags.merge(@tags)
909
+
910
+ # Apply existing sanitization filter
911
+ all_tags.select do |key, value|
901
912
  ALLOWED_TAG_KEY_TYPES.any? { |type| key.is_a? type } &&
902
913
  ALLOWED_TAG_VALUE_TYPES.any? { |type| value.is_a? type }
903
914
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Appsignal
4
4
  # @return [String]
5
- VERSION = "4.8.1"
5
+ VERSION = "4.8.3"
6
6
  end
data/lib/appsignal.rb CHANGED
@@ -184,12 +184,14 @@ module Appsignal
184
184
  if config
185
185
  # When calling `Appsignal.configure` from an app, not the
186
186
  # `config/appsignal.rb` file, with also a Ruby config file present.
187
+ caller_location = external_caller_location
187
188
  message = "The `Appsignal.configure` helper is called from within an " \
188
189
  "app while a `#{context.dsl_config_file}` file is present. " \
189
190
  "The `config/appsignal.rb` file is ignored when the " \
190
191
  "config is loaded with `Appsignal.configure` from within an app. " \
191
192
  "We recommend moving all config to the `config/appsignal.rb` file " \
192
193
  "or the `Appsignal.configure` helper in the app."
194
+ message += "\n Called from: #{caller_location}" if caller_location
193
195
  Appsignal::Utils::StdoutAndLoggerMessage.warning(message)
194
196
  else
195
197
  # Load it when no config is present
@@ -340,6 +342,7 @@ module Appsignal
340
342
  # When calling `Appsignal.configure` from a Rails initializer and a YAML
341
343
  # file is present. We will not load the YAML file in the future.
342
344
  if !config_file_context? && config.yml_config_file?
345
+ caller_location = external_caller_location
343
346
  message = "The `Appsignal.configure` helper is called while a " \
344
347
  "`config/appsignal.yml` file is present. In future versions the " \
345
348
  "`config/appsignal.yml` file will be ignored when loading the " \
@@ -347,6 +350,7 @@ module Appsignal
347
350
  "`config/appsignal.rb` file, or the `Appsignal.configure` helper " \
348
351
  "in Rails initializer file, and remove the " \
349
352
  "`config/appsignal.yml` file."
353
+ message += "\n Called from: #{caller_location}" if caller_location
350
354
  Appsignal::Utils::StdoutAndLoggerMessage.warning(message)
351
355
  end
352
356
 
@@ -616,6 +620,26 @@ module Appsignal
616
620
  end
617
621
  Appsignal::Environment.report_supported_gems
618
622
  end
623
+
624
+ # Returns a formatted string with the file and line number where
625
+ # Appsignal.configure was called from, excluding internal AppSignal frames.
626
+ #
627
+ # @return [String, nil] Formatted caller location or nil if not found
628
+ def external_caller_location
629
+ # Get the call stack, skipping this method itself
630
+ locations = caller_locations(1)
631
+ return unless locations
632
+
633
+ # Find the first location outside the AppSignal gem's lib directory
634
+ appsignal_lib_path = File.expand_path(__dir__)
635
+ external_location = locations.find do |location|
636
+ !location.path.start_with?(appsignal_lib_path)
637
+ end
638
+
639
+ return unless external_location
640
+
641
+ "#{external_location.path}:#{external_location.lineno}"
642
+ end
619
643
  end
620
644
 
621
645
  # @!visibility private
data/sig/appsignal.rbi CHANGED
@@ -8,7 +8,7 @@
8
8
  module Appsignal
9
9
  extend Appsignal::Helpers::Metrics
10
10
  extend Appsignal::Helpers::Instrumentation
11
- VERSION = T.let("4.8.1", T.untyped)
11
+ VERSION = T.let("4.8.3", T.untyped)
12
12
 
13
13
  class << self
14
14
  # The loaded AppSignal configuration.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appsignal
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.8.1
4
+ version: 4.8.3
5
5
  platform: java
6
6
  authors:
7
7
  - Robert Beekman