[[api]] == Public API Although most usage is covered automatically, Elastic APM also has a public API that allows custom usage. [float] [[agent-life-cycle]] === Agent life cycle Controlling when the agent starts and stops. [float] [[api-agent-start]] ==== `ElasticAPM.start` To create and start an ElasticAPM agent use `ElasticAPM.start`: [source,ruby] ---- ElasticAPM.start(server_url: 'http://localhost:8200') ---- * `config`: An optional hash or `ElasticAPM::Config` instance with configuration options. See <>. If you are using <> this is done automatically for you. If not see <>. [float] [[api-agent-stop]] ==== `ElasticAPM.stop` Stop the currently running agent. Use this inside `at_exit` in your <> to gracefully shut down. [float] [[api-agent-running]] ==== `ElasticAPM.running?` Returns whether the ElasticAPM Agent is currently running. [float] [[api-agent-agent]] ==== `ElasticAPM.agent` Returns the currently running agent or nil. [float] === Instrumentation [float] [[api-agent-current-transaction]] ==== `ElasticAPM.current_transaction` Returns the current `ElasticAPM::Transaction` or nil. [float] [[api-agent-transaction]] ==== `ElasticAPM.transaction` Start a _transaction_ eg. a web request or background job. If called without a block you are expected to end the transaction yourself. If given a block, the code inside will be wrapped in a transaction. You need to submit it yourself with `transaction.submit(status)`. [source,ruby] ---- # call with block transaction = ElasticAPM.transaction('Do things') do do_work # ... end # .done is called when block ends transaction.submit(200) # without block transaction = ElasticAPM.transaction('Do things') do_work transaction.submit(200) # .submit(result) will also .done(result) ---- Arguments: * `name`: A name for your transaction. Transactions are grouped by name. **Required**. * `type`: A `type` for your transaction eg. `db.postgresql.sql`. * `context:`: An optional <> used to enrich the transaction with information about the current request. * `&block`: An optional block to wrap with the transaction. The block is passed the transaction as an optional argument. Returns the transaction. [float] [[api-agent-span]] ==== `ElasticAPM.span` Most transactions have nested spans signifying work of a specific sort eg. database queries or external web requests. If given a block, wrap the code inside in a span. If not you are expected to close the span yourself with `span.done(result)`. [source,ruby] ---- ElasticAPM.transaction 'Do things' do ElasticAPM.span 'Do one of the things' do Database.query # ... end end ---- Arguments: * `name`: A name for your span. **Required**. * `type`: The type of work eg. `db.postgresql.query`. * `context`: An instance of `Span::Context`. * `include_stacktrace`: Whether or not to collect a Stacktrace. * `&block`: An optional block to wrap with the span. The block is passed the span as an optional argument. Return the span or the return value of the given block. [float] [[api-agent-build-context]] ==== `ElasticAPM.build_context` Build a new _Context_ from a Rack `env`. A context provides information about the current request, response, user and more. Arguments: * `rack_env`: An instance of Rack::Env Returns the built context. [float] === Errors [float] [[api-agent-report]] ==== `ElasticAPM.report` Send an `Exception` to Elastic APM. If reported inside a transaction, the context from that will be added. [source,ruby] ---- begin do_a_thing_and_fail rescue Exception => e ElasticAPM.report(e) end ---- Arguments: * `exception`: An instance of `Exception`. **Required**. * `handled`: Whether the error was _handled_ eg. wasn't rescued and was represented to the user. Default: `true`. Returns `[ElasticAPM::Error]`. [float] [[api-agent-report-message]] ==== `ElasticAPM.report_message` Send a custom message to Elastic APM. If reported inside a transaction, the context from that will be added. [source,ruby] ---- ElasticAPM.report_message('This should probably never happen?!') ---- Arguments: * `message`: A custom error string. **Required**. Returns `[ElasticAPM::Error]`. [float] === Context [float] [[api-agent-set-tag]] ==== `ElasticAPM.set_tag` Add a tag to the current transaction. Tags are basic key-value pairs that are indexed in your Elasticsearch database and therefore searchable. [source,ruby] ---- before_action do ElasticAPM.set_tag(:company_id, current_user.company.id) end ---- Arguments: * `key`: A string key. * `value`: A string value. Returns the set `value`. WARNING: Be aware that tags are indexed in Elasticsearch. Using too many unique keys will result in *https://www.elastic.co/blog/found-crash-elasticsearch#mapping-explosion[Mapping explosion]*. [float] [[api-agent-set-custom-context]] ==== `ElasticAPM.set_custom_context` Add custom context to the current transaction. Use this to further specify a context that will help you track or diagnose what's going on inside your app. If called several times during a transaction the custom context will be destructively merged with `merge!`. [source,ruby] ---- before_action do ElasticAPM.set_custom_context(company: current_user.company.to_h) end ---- Arguments: * `context`: A hash of JSON-compatible key-values. Can be nested. Returns current custom context. [float] [[api-agent-set-user]] ==== `ElasticAPM.set_user` Add the current user to the current transaction's context. Arguments: * `user`: An object representing the user Returns the given user [float] === Data [float] [[api-agent-add-filter]] ==== `ElasticAPM.add_filter` Provide a filter to transform payloads before sending. Arguments: * `key`: A unique key identifying the filter * `callable`: An object or proc (responds to `.call(payload)`) Return the altered payload. If `nil` is returned all subsequent filters will be skipped and the post request cancelled. Example: [source,ruby] ---- ElasticAPM.add_filter(:filter_pings) do |payload| payload[:transactions]&.reject! do |t| t[:name] == 'PingsController#index' end payload end ---- [float] [[api-transaction]] === Transaction `ElasticAPM.transaction` returns a `Transaction` (if the agent is running). [float] ==== Properties - `name`: String - `type`: String [float] [[api-transaction-release]] ==== `#release` Makes sure the transaction is no longer `ElasticAPM.current_transaction`. [float] [[api-transaction-done]] ==== `#done(result)` *Args:* - `result`: String result of transaction, eg. `success`. Default: `nil`. Ends the transaction, settings its `duration` to µs since it began and sets its result. Returns `self`. [float] [[api-transaction-done_]] ==== `#done?` Returns whether the transaction is done. [float] [[api-transaction-submit]] ==== `#submit(result, status:, headers:)` *Args:* - `result`: String result of transaction, eg. `success`. Default: `nil`. - `status`: HTTP status code (for request transactions). Default: `nil`. - `headers`: HTTP headers (for request transactions). Default: `{}`. Ends transaction with done, adds HTTP request information, releases it and submits it to the queue of transactions waiting to be sent to APM Server. Returns `self`. [float] [[api-transaction-sampled_]] ==== #sampled? Whether the transaction is _sampled_ eg. it includes stacktraces for its spans. [float] [[api-span]] === Span [float] ==== Properties - `name`: String - `type`: String [float] [[api-context]] === Context A `Context` provides more information to transactions. Build one with `ElasticAPM.build_context`.