diff --git a/CHANGELOG.md b/CHANGELOG.md index 917dc9c2..b3bc254e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,57 @@ ## CHANGELOG +### `v1.31` + +A big release after a long time dormant! + +#### Notable changes +* Use Elixir Logger as the default agent logger [#455](https://github.com/newrelic/elixir_agent/pull/455) + - Changes where internal New Relic agent logs will go by default +* Use logger primary filter to hook into error reporting [#466](https://github.com/newrelic/elixir_agent/pull/466) + - No longer need to add `ErrorLogger` to your `:logger` `:backend` config +* Finch Instrumentation [#469](https://github.com/newrelic/elixir_agent/pull/469) + - No longer need to `@trace` with `category: :external` to instrument Finch based HTTP requests + +#### Features +* Make Distributed Tracing configurable [#457](https://github.com/newrelic/elixir_agent/pull/457) +* Support ignoring web transaction paths via configuration [#451](https://github.com/newrelic/elixir_agent/pull/451) +* Support host display name [#464](https://github.com/newrelic/elixir_agent/pull/464) +* Oban Instrumentation [#463](https://github.com/newrelic/elixir_agent/pull/463) +* Absinthe Instrumentation [#471](https://github.com/newrelic/elixir_agent/pull/471) +* Added `NewRelic.notice_error` to report rescued exceptions [#470](https://github.com/newrelic/elixir_agent/pull/470) +* Added `NewRelic.add_span_attributes` [#478](https://github.com/newrelic/elixir_agent/pull/478) +* Added `NewRelic.span` macro [#471](https://github.com/newrelic/elixir_agent/pull/471) + +#### Tweaks +* Doc improvements [#453](https://github.com/newrelic/elixir_agent/pull/453) Thanks @axelson! +* Performance refactor to use map_reduce [#423](https://github.com/newrelic/elixir_agent/pull/423) Thanks @bradhanks! +* Handle binary attribute values better [#458](https://github.com/newrelic/elixir_agent/pull/458) +* Safer math in Process sampler [#461](https://github.com/newrelic/elixir_agent/pull/461) +* Speed up BackoffSampler with counters [#460](https://github.com/newrelic/elixir_agent/pull/460) +* Conditional compilation to address warnings [#456](https://github.com/newrelic/elixir_agent/pull/456) +* Add spansaction for regular DT [#467](https://github.com/newrelic/elixir_agent/pull/467) +* Only start telemetry handlers when agent is enabled [#474](https://github.com/newrelic/elixir_agent/pull/474) +* Only start os_mon when agent enabled [#473](https://github.com/newrelic/elixir_agent/pull/473) +* Add extended attributes for function tracers, make extended attributes configurable [#479](https://github.com/newrelic/elixir_agent/pull/479) + +#### Fixes +* Handle when Bandit telemetry doesn't include the conn [#449](https://github.com/newrelic/elixir_agent/pull/449) +* Fix a few Bandit attributes [#480](https://github.com/newrelic/elixir_agent/pull/480) +* Enable Logger calls to be compile time purgable [#402](https://github.com/newrelic/elixir_agent/pull/402) Thanks @TylerWitt! +* Tracer - Create a proper list when tail of list is ignored [#465](https://github.com/newrelic/elixir_agent/pull/465) +* Add bandit optional dependency [#472](https://github.com/newrelic/elixir_agent/pull/472) + +------ + ### `v1.30` +Features * adjust metadata_reporter :transaction report_error [#443](https://github.com/newrelic/elixir_agent/pull/443) * Identify Phoenix LiveView metrics [#424](https://github.com/newrelic/elixir_agent/pull/424) * Add Bandit HTTP server support [#445](https://github.com/newrelic/elixir_agent/pull/445) +------ + ### `v1.29` Features @@ -16,6 +62,7 @@ Features [#427](https://github.com/newrelic/elixir_agent/pull/427). Thank you so much @tmaszk and @XiXiaPdx! +------ ### `v1.28` @@ -25,6 +72,7 @@ Features * Add support for [Dimensional Metrics](https://docs.newrelic.com/docs/query-your-data/nrql-new-relic-query-language/nrql-query-tutorials/query-infrastructure-dimensional-metrics-nrql/). [#408](https://github.com/newrelic/elixir_agent/pull/408) Thanks @XiXiaPdx! +------ ### `v1.27.8` diff --git a/README.md b/README.md index 8a641eda..f3ea2123 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ You can also configure these attributes via `ENV` vars, which helps keep secrets #### HTTP Client Settings -httpc client settings can be overridden if needed. For example, the HTTP connect timeout can be increased which can help alleviate errors related to timeouts connecting to New Relic: +`httpc` client settings can be overridden if needed. For example, the HTTP connect timeout can be increased which can help alleviate errors related to timeouts connecting to New Relic: ```elixir config :new_relic_agent, @@ -81,6 +81,8 @@ Some common Elixir packages are auto-instrumented via [`telemetry`](https://gith * [`Ecto`](https://github.com/elixir-ecto/ecto): See [NewRelic.Telemetry.Ecto](https://hexdocs.pm/new_relic_agent/NewRelic.Telemetry.Ecto.html) for details. * [`Redix`](https://github.com/whatyouhide/redix): See [NewRelic.Telemetry.Redix](https://hexdocs.pm/new_relic_agent/NewRelic.Telemetry.Redix.html) for details. * [`Finch`](https://github.com/sneako/finch): See [NewRelic.Telemetry.Finch](https://hexdocs.pm/new_relic_agent/NewRelic.Telemetry.Finch.html) for details. +* [`Oban`](https://github.com/oban-bg/oban): See [NewRelic.Telemetry.Oban](https://hexdocs.pm/new_relic_agent/NewRelic.Telemetry.Oban.html) for details. +* [`Absinthe`](https://github.com/absinthe-graphql/absinthe): See [NewRelic.Telemetry.Absinthe](https://hexdocs.pm/new_relic_agent/NewRelic.Telemetry.Absinthe.html) for details. ## Agent features @@ -98,6 +100,8 @@ The `Plug` and `Phoenix` instrumentation automatically report a Transaction for These Transactions will follow across any process spawned and linked (ex: `Task.async`), but will _not_ follow a process that isn't linked (ex: `Task.Supervisor.async_nolink`). +--- + To manually connect a Transaction to an unlinked process, you can use `NewRelic.get_transaction` and `NewRelic.connect_to_transaction`. See the docs for those functions for further details. ```elixir @@ -109,6 +113,37 @@ spawn(fn -> end) ``` +--- + +To exclude a process from the Transaction: + +```elixir +Task.async(fn -> + NewRelic.exclude_from_transaction() + Work.wont_be_tracked() +end) +``` + +--- + +To prevent reporting an individual transaction: + +```elixir +NewRelic.ignore_transaction() +``` + +You can configure some paths to be automatically ignored: + +```elixir +config :new_relic_agent, + ignore_paths: [ + "/health", + ~r/longpoll/ + ] +``` + +--- + If you are using a `Task` to spawn work, you can use the pre-instrumented `NewRelic.Instrumented.Task` convenience module to make this easier. Just `alias` it in your module and all your Tasks will be instrumented. You may also use the functions directly. ```elixir @@ -134,6 +169,23 @@ defmodule MyModule do end ``` +If you want to trace a sub-set of a function, you can use the `NewRelic.span` macro. + +```elixir +defmodule MyModule do + use NewRelic.Tracer + + def work do + # Do some stuff.. + + NewRelic.span "do.some_work", user_id: "abc123" do + # Will report as `do.some_work` + # Will return the result of the block + end + end +end +``` + #### Distributed Tracing Requests to other services can be connected with an additional outgoing header. @@ -166,16 +218,16 @@ end You may start an "Other" Transaction for non-HTTP related work. This could used be while consuming from a message queue, for example. -To start an Other Transaction: - ```elixir -NewRelic.start_transaction(category, name) -``` - -And to stop the Transaction within the same process: +defmodule Worker do + use NewRelic.Tracer -```elixir -NewRelic.stop_transaction() + def process_messages do + NewRelic.other_transaction("Worker", "ProcessMessages") do + # ... + end + end +end ``` #### Adapters diff --git a/VERSION b/VERSION index 034552a8..34aae156 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.30.0 +1.31.0 diff --git a/lib/new_relic.ex b/lib/new_relic.ex index 9e894639..91d75eb6 100644 --- a/lib/new_relic.ex +++ b/lib/new_relic.ex @@ -241,7 +241,7 @@ defmodule NewRelic do @spec distributed_trace_headers(:http) :: [{key :: String.t(), value :: String.t()}] defdelegate distributed_trace_headers(type), to: NewRelic.DistributedTrace - @type name :: binary() | {primary_name :: binary(), secondary_name :: binary()} + @type name :: String.t() | {primary_name :: String.t(), secondary_name :: String.t()} @doc """ Record a "Span" within the given block. The return value of the block is returned. diff --git a/lib/new_relic/config.ex b/lib/new_relic/config.ex index 702b6b35..27cd4881 100644 --- a/lib/new_relic/config.ex +++ b/lib/new_relic/config.ex @@ -77,7 +77,7 @@ defmodule NewRelic.Config do Example: - ``` + ```elixir config :new_relic_agent, automatic_attributes: [ environment: {:system, "APP_ENV"}, @@ -115,7 +115,7 @@ defmodule NewRelic.Config do * Ignore Phoenix longpoll http requests: `"/live/longpoll"` Example: - ``` + ```elixir config :new_relic_agent, ignore_paths: [ "/health", @@ -127,47 +127,40 @@ defmodule NewRelic.Config do do: get(:ignore_paths) @doc """ - Some Agent features can be toggled via configuration. + Some Agent features can be toggled via configuration. These all default to `true`, but can be configured in two ways: + * Environment variables: `NEW_RELIC_ERROR_COLLECTOR_ENABLED=false` + * Application config: `config :new_relic_agent, error_collector_enabled: false` + + ### Built-in features + + * `:distributed_tracing` + * Toggles reading of incoming distributed tracing headers + * `:request_queuing_metrics_enabled` + * Toggles collection of request queuing metrics + * `:extended_attributes` + * Toggles reporting extended per-source attributes for datastore, external and function traces ### Security - * `:error_collector_enabled` (default `true`) + * `:error_collector_enabled` * Toggles collection of any Error traces or metrics - * `:db_query_collection_enabled` (default `true`) - * Toggles collection of Database query strings - * `function_argument_collection_enabled` (default `true`) + * `:query_collection_enabled` + * Toggles collection of any kind of query string + * `:function_argument_collection_enabled` * Toggles collection of traced function arguments - ### Instrumentation + ### Common library instrumentation Opting out of Instrumentation means that `:telemetry` handlers will not be attached, reducing the performance impact to zero. - * `:plug_instrumentation_enabled` (default `true`) - * Controls all Plug instrumentation - * `:distributed_tracing` (default `true`) - * Controls Distributed Tracking - * `:ecto_instrumentation_enabled` (default `true`) - * Controls all Ecto instrumentation - * `:redix_instrumentation_enabled` (default `true`) - * Controls all Redix instrumentation - * `:oban_instrumentation_enabled` (default `true`) - * Controls all Oban instrumentation - * `:finch_instrumentation_enabled` (default `true`) - * Controls all Finch instrumentation - * `:absinthe_instrumentation_enabled` (default `true`) - * Controls all Absinthe instrumentation - * `:request_queuing_metrics_enabled` - * Controls collection of request queuing metrics - * `:extended_attributes` (default `true`) - * Controls reporting extended per-source attributes for datastore, external and function traces - - - ### Configuration - - Each of these features can be configured in two ways, for example: - * Environment variables: `NEW_RELIC_ERROR_COLLECTOR_ENABLED=false` - * Application config: `config :new_relic_agent, error_collector_enabled: false` + * `:plug_instrumentation_enabled` + * `:phoenix_instrumentation_enabled` + * `:ecto_instrumentation_enabled` + * `:redix_instrumentation_enabled` + * `:oban_instrumentation_enabled` + * `:finch_instrumentation_enabled` + * `:absinthe_instrumentation_enabled` """ def feature?(toggleable_agent_feature) @@ -175,8 +168,8 @@ defmodule NewRelic.Config do get(:features, :error_collector) end - def feature?(:db_query_collection) do - get(:features, :db_query_collection) + def feature?(:query_collection) do + get(:features, :query_collection) end def feature?(:distributed_tracing) do diff --git a/lib/new_relic/init.ex b/lib/new_relic/init.ex index f59120ba..a2007aba 100644 --- a/lib/new_relic/init.ex +++ b/lib/new_relic/init.ex @@ -63,7 +63,7 @@ defmodule NewRelic.Init do "NEW_RELIC_ERROR_COLLECTOR_ENABLED", :error_collector_enabled ), - db_query_collection: + query_collection: determine_feature( "NEW_RELIC_SQL_COLLECTION_ENABLED", :sql_collection_enabled, @@ -71,7 +71,12 @@ defmodule NewRelic.Init do ) || determine_feature( "NEW_RELIC_DB_QUERY_COLLECTION_ENABLED", - :db_query_collection_enabled + :db_query_collection_enabled, + false + ) || + determine_feature( + "NEW_RELIC_QUERY_COLLECTION_ENABLED", + :query_collection_enabled ), distributed_tracing: determine_feature( diff --git a/lib/new_relic/telemetry/absinthe.ex b/lib/new_relic/telemetry/absinthe.ex index db268171..6c1f9f97 100644 --- a/lib/new_relic/telemetry/absinthe.ex +++ b/lib/new_relic/telemetry/absinthe.ex @@ -9,8 +9,9 @@ defmodule NewRelic.Telemetry.Absinthe do * Transaction name * Distributed Trace span events - You can opt-out of this instrumentation as a whole and specifically of - query collection via configuration. See `NewRelic.Config` for details. + You can opt-out of this instrumentation as a whole with `:absinthe_instrumentation_enabled` + and specifically of query collection with `:query_collection_enabled` via configuration. + See `NewRelic.Config` for details. """ @doc false @@ -37,7 +38,7 @@ defmodule NewRelic.Telemetry.Absinthe do def init(enabled: true) do config = %{ handler_id: {:new_relic, :absinthe}, - collect_query?: NewRelic.Config.feature?(:db_query_collection), + collect_query?: NewRelic.Config.feature?(:query_collection), collect_args?: NewRelic.Config.feature?(:function_argument_collection) } diff --git a/lib/new_relic/telemetry/ecto.ex b/lib/new_relic/telemetry/ecto.ex index d964e052..6d18259f 100644 --- a/lib/new_relic/telemetry/ecto.ex +++ b/lib/new_relic/telemetry/ecto.ex @@ -14,15 +14,16 @@ defmodule NewRelic.Telemetry.Ecto do * Transaction datastore attributes * Distributed Trace span events - You can opt-out of this instrumentation as a whole and specifically of - SQL query collection via configuration. See `NewRelic.Config` for details. + You can opt-out of this instrumentation as a whole with `:ecto_instrumentation_enabled` + and specifically of query collection with `:query_collection_enabled` via configuration. + See `NewRelic.Config` for details. """ @doc false def start_link(repo: repo, opts: opts) do config = %{ enabled?: NewRelic.Config.feature?(:ecto_instrumentation), - collect_db_query?: NewRelic.Config.feature?(:db_query_collection), + collect_db_query?: NewRelic.Config.feature?(:query_collection), handler_id: {:new_relic_ecto, repo}, event: opts[:telemetry_prefix] ++ [:query], opts: opts diff --git a/lib/new_relic/telemetry/finch.ex b/lib/new_relic/telemetry/finch.ex index 4638d0bb..7c652595 100644 --- a/lib/new_relic/telemetry/finch.ex +++ b/lib/new_relic/telemetry/finch.ex @@ -12,7 +12,8 @@ defmodule NewRelic.Telemetry.Finch do * External metrics * External spans - You can opt-out of this instrumentation via configuration. See `NewRelic.Config` for details. + You can opt-out of this instrumentation with `:finch_instrumentation_enabled` via configuration. + See `NewRelic.Config` for details. """ def start_link(_) do config = %{ diff --git a/lib/new_relic/telemetry/oban.ex b/lib/new_relic/telemetry/oban.ex index 79cfeb5e..41196d09 100644 --- a/lib/new_relic/telemetry/oban.ex +++ b/lib/new_relic/telemetry/oban.ex @@ -12,7 +12,8 @@ defmodule NewRelic.Telemetry.Oban do * Transaction Traces * Distributed Traces - You can opt-out of this instrumentation via configuration. See `NewRelic.Config` for details. + You can opt-out of this instrumentation with `:oban_instrumentation_enabled` via configuration. + See `NewRelic.Config` for details. """ alias NewRelic.Transaction diff --git a/lib/new_relic/telemetry/phoenix.ex b/lib/new_relic/telemetry/phoenix.ex index 3207e896..ecbc22ba 100644 --- a/lib/new_relic/telemetry/phoenix.ex +++ b/lib/new_relic/telemetry/phoenix.ex @@ -6,6 +6,9 @@ defmodule NewRelic.Telemetry.Phoenix do This instrumentation adds extra Phoenix specific instrumentation on top of the base `NewRelic.Telemetry.Plug` instrumentation. + + You can opt-out of this instrumentation with `:phoenix_instrumentation_enabled` via configuration. + See `NewRelic.Config` for details. """ def start_link(_) do config = %{ diff --git a/lib/new_relic/telemetry/plug.ex b/lib/new_relic/telemetry/plug.ex index dfd28790..562e5c22 100644 --- a/lib/new_relic/telemetry/plug.ex +++ b/lib/new_relic/telemetry/plug.ex @@ -12,30 +12,8 @@ defmodule NewRelic.Telemetry.Plug do * Transaction Traces * Distributed Traces - You can opt-out of this instrumentation via configuration. See `NewRelic.Config` for details. - - ---- - - To prevent reporting an individual transaction: - - ```elixir - NewRelic.ignore_transaction() - ``` - - ---- - - Inside a Transaction, the agent will track work across processes that are spawned and linked. - You can signal to the agent not to track work done inside a spawned process, which will - exclude it from the current Transaction. - - To exclude a process from the Transaction: - - ```elixir - Task.async(fn -> - NewRelic.exclude_from_transaction() - Work.wont_be_tracked() - end) - ``` + You can opt-out of this instrumentation with `:plug_instrumentation_enabled` via configuration. + See `NewRelic.Config` for details. """ alias NewRelic.{Transaction, DistributedTrace, Util} diff --git a/lib/new_relic/telemetry/redix.ex b/lib/new_relic/telemetry/redix.ex index 21584091..a1459ee9 100644 --- a/lib/new_relic/telemetry/redix.ex +++ b/lib/new_relic/telemetry/redix.ex @@ -13,8 +13,9 @@ defmodule NewRelic.Telemetry.Redix do * Transaction datastore attributes * Distributed Trace span events - You can opt-out of this instrumentation as a whole and specifically of - query collection via configuration. See `NewRelic.Config` for details. + You can opt-out of this instrumentation as a whole with `:redix_instrumentation_enabled` + and specifically of query collection with `:query_collection_enabled` via configuration. + See `NewRelic.Config` for details. """ @doc false @@ -36,7 +37,7 @@ defmodule NewRelic.Telemetry.Redix do config = %{ handler_id: {:new_relic, :redix}, connections: %{}, - collect_db_query?: NewRelic.Config.feature?(:db_query_collection) + collect_db_query?: NewRelic.Config.feature?(:query_collection) } :telemetry.attach_many(