Documentation forAppOptics

Instrumentation SDK (legacy agent)

The following content pertains to instrumentation SDK for the legacy AppOptics PHP Agent.

AppOptics agents are no long receiving updates. The new SolarWinds Observability libraries can send APM data in AppOptics and are regularly updated with new features and improvements. If you are still relying on the AppOptics agents and your components are supported by the new libraries, consider transitioning to the SolarWinds Observability libraries for your APM needs. For more information about the benefits of migrating to the SolarWinds Observability libraries. Alternatively, you can use SolarWinds Observability as your primary APM solution.

If you have already transitioned to the new SolarWinds Observability PHP Library, see the SolarWinds PHP Library documentation for instrumentation SDK information.

SolarWinds Observability libraries are not compatible with AppOptics agents. Do not use a mix of SolarWinds Observability libraries and AppOptics agents to instrument applications that are part of a distributed trace.

Looking to extend our out-of-the box instrumentation? The SDK enables custom tracing and metrics reporting.

Customization involves adding hooks from our public SDK to your code so that you can take advantage of additional filtering capabilities on the dashboard, change how requests are traced, or capture additional information during the trace.

Get started

The instrumentation customization SDK relies on methods defined in the extension. In order to make your code safe to run in all environments, you'll want to include the api.php stub file in your code. Using that, any instrumentation calls that you add will simply do nothing if the extension is not installed.

PHP custom spans

By default, the php instrumentation creates a ‘php' span, and then creates a span for each non-php service that it is instrumenting, e.g., php_mysql, memcache, phpredis, curl. If these spans don't provide enough visibility, you can further divide your code into sub-spans. How you segment your application into spans is entirely up to you. For example the out-of-box instrumentation might not recognize calls to external processes; or, maybe there's a discrete subsection of your code that is worth calling out on its own. In any case, a span is started by calling appoptics_log_entry() and ended by calling appoptics_log_exit(). Follow the links to the SDK documentation for complete syntax and usage information.

appoptics_log_entry('sayhello');
...
appoptics_log_exit('sayhello');

Add info events

There are two reasons you might want to create an info event: the first is to simply to attach any metadata that may be of interest to you during later analysis of a trace. The other reason is to take full advantage of AppOptics filtering capability. In short, you can classify extents by attaching a pre-defined set of specified key/value pairs as a third parameter. Then from AppOptics, you can filter for traces with that extent type.

To add info to an extent, call appoptics_log anywhere within it, as shown. You may do this at multiple points if necessary. The information events are displayed on the raw span data tab on the trace details page. If all of the key/value pairs for special interpretation are present, the extent type is reflected in the span details tab. Follow the link to the SDK documentation for complete syntax and usage information.

appoptics_log('span-name', 'info', array('key' => $variable));

Set custom transaction name

PHP instrumentation supports these frameworks. If we don’t support your framework you can set a custom transaction name for the traced request. Be aware of these restrictions:

  • a transaction name can only be set on active traces (e.g. between appoptics_start_trace() and appoptics_end_trace())
  • if set outside an active trace, call will be ignored
  • if multiple calls are made, only the last one takes effect
  • empty transaction names will be ignored
  • final transaction name is converted to lowercase, and might be truncated with invalid characters replaced
appoptics_set_transaction_name('my-controller/my-action');

Starting a trace

Traces are usually automatically started when a request is made. In certain cases it is desirable to start a trace manually, for example if you are only interested in tracing a specific area of your code. In order to achieve this you first disable auto-instrumentation by setting appoptics.use_custom_start_trace = 1. Then you surround your code with a call to appoptics_start_trace() and a call to appoptics_end_trace().

appoptics_start_trace('my-name');
// your code
appoptics_end_trace()

Enabling CLI tracing

By default Command Line Interface (CLI) tracing is disabled. Setting appoptics.enable_cli = 1 will enable CLI tracing.

Check if agent is ready

The agent initializes and maintains a connection to an AppOptics server, and also receives settings used for making tracing decisions. This process can take up to a few seconds depending on the connection. If the application receives requests before initialization has completed, these requests will not be traced. While this is not critical for long-running server processes (e.g. Apache), it might be a problem for short-running apps such as cron jobs or CLI apps. A call to this method allows the app to block until initialization has completed and the agent is ready for tracing. The method takes an optional timeout value in milliseconds which tells the agent how long to wait for getting ready. The default timeout is 0, which means no blocking. The return value indicates whether the agent is ready to receive traces (true) or not (false).

appoptics_is_ready(1000);

Report errors and exceptions

Errors automatically generate error events in a trace if the appoptics.enable_error_callback ini setting is not set to zero. When enabled, the default error handling is further configured by the appoptics.report_suppressed_errors and appoptics.use_error_reporting ini settings. If you disable the default appoptics error callback handler then you're probably providing your own error handler. Whatever the case, if you want to manually record an error in a trace then you’ll need to call appoptics_log_error() as shown, where ‘E_NOTICE’ is the php error code. Follow the link to the SDK documentation for complete syntax and usage information.

appoptics_log_error('span-name', 'something is wrong', E_NOTICE);

Like errors, exceptions are automatically recorded in a trace if the appoptics.enable_error_callback ini setting is not set to zero. Otherwise you'll need to manually create an exception error event using a call to appoptics_log_exception() (see PHP SDK reference). Here the exception object is passed instead of an error message, and additional key values are passed in a hashtable. Also, stack trace from the exception object is explicitly passed so the agent reports that as the error backtrace rather than the default stack trace taken from the exception handler.

appoptics_log_exception('myexcept', $e, array('test' => 'tripleInteger($int)', 'result' => 'InvalidArgumentException generated'), $e->getTrace());

Add php data objects instrumentation

PDO instrumentation enables you to collect performance data relating to query and database usage in php applications.

  1. Explicitly enable the pdo instrumentation by adding this line to your php.ini settings. Alternatively, you might find it more convenient to add this line to the appoptics-specific ini settings, which are in appoptics.ini. On debian/ubuntu appoptics.ini is in /etc/php5/conf.d/; on rhel/centos it's in /etc/php.d/.

    appoptics.enable_wrap_pdo = 1
  2. Verify that this ini value has been successfully set, you can run php -i or call phpinfo().

PHP SDK reference

<?php
/**
* AppOptics SDK API for PHP
*
* This can be used for autocompletion in many major PHP editors
* provides documentation for the code
* and can be used on systems where the appoptics extension is not loaded
* to provide no-op versions of functionality
*/

if(!extension_loaded('appoptics') && !function_exists('appoptics_set_context')) {

  /**
   * Get string representation of current global context (X-trace) being used
   * if request is not tracing, will return false
   *
   * @return string|false
   */
  function appoptics_get_context() {
    return false;
  }
  
  /**
   * Set a string value for the current global context (X-trace) being used
   * will not start a trace, but will set the context to use for tracing even
   * if not currently tracing
   *
   * @return bool true for valid set, false for invalid x-trace sent
   */
  function appoptics_set_context($context) {
    return true;
  }

  /**
   * Check if AppOptics is ready for receiving traces and optionally wait for a given
   * time. 'Ready' here means AppOptics has connected to the collector and has
   * successfully received settings.
   * Note: The ini config option 'appoptics.max_ready_wait_time' can set this on the
   * global application level.
   *
   * @param int timeout (optional) to wait for becoming ready (in milli seconds).
   *      A value of 0 will turn off waiting for timeout.
   *
   * @return bool true if ready, false otherwise
   */
  function appoptics_is_ready($timeout = 0) {
    return true;
  }

  /**
   * Attempts to start a new trace
   * Uses appoptics and feeds in optional incoming xtrace edge
   * xmeta header, and PHP set sample mode or sample rate if applicable
   *
   * If it returns false then tracing is not started
   *
   * if context is set before a trace is started the context provided will be used
   * otherwise a new random context is generated
   *
   * Will throw a PHP Notice if start trace has already been called or autotracing is on
   *
   * @param string layer name for custom tracing
   * @param string xtrace (optional) incoming xtrace edge (default = null)
   * @param mixed info (optional) if arrayaccess (array or object with hashtable) is sent then the items in the key
   *       value pairs that aren't reserved are sent with the beginning trace
   * @param mixed backtrace (optional) if arrayaccess (array or object with hashtable) that is used as a backtrace
   *        if true is passed PHP generated backtrace is sent, if false
   *        is passed then no backtrace is sent
   *
   * @return array('sample_rate' => value
   *        'sample_source' => value) or false
   */
  function appoptics_start_trace($layer, $xtrace = null, $info = null, $backtrace = true) {
    return false;
  }

  /**
   * Stops a trace
   *
   * If it returns false then tracing was never started or an error occurred
   *
   * @param mixed info (optional) if arrayaccess (array or object with hashtable) is sent then the items in the key
   *       value pairs that aren't reserved are sent with the beginning trace
   * @param mixed backtrace (optional) if arrayaccess (array or object with hashtable) that is used as a backtrace
   *        if true is passed PHP generated backtrace is sent, if false
   *        is passed then no backtrace is sent
   * @param mixed edge (optional) if arrayaccess (array or object with hashtable) is sent then the items are treated
   *       as additional edges to add, if it's a single string the string is added
   * @param string transaction_name (optional) the transaction name to be set for this trace
   *
   * @return boolean (true on success, false on failure)
   */
  function appoptics_end_trace($info = null, $backtrace = true, $edge = null, $transaction_name = null) {
    return false;
  }

  /**
   * Sets a custom transaction name
   * Can only be called on an active trace (e.g. between appoptics_start_trace() and appoptics_end_trace(),
   * or when autotracing is on)
   *
   * @param string transaction_name the transaction name to be set for this trace
   *
   * @return boolean (true on success, false on failure (e.g. empty $transaction_name passed in))
   */
  function appoptics_set_transaction_name($transaction_name) {
    return false;
  }
  
  /**
   * Is this request/script currently tracing
   *
   * @return boolean (true on success, false on failure)
   */
  function appoptics_is_tracing() {
    return false;
  }
  
  /**
   * Has tracing been started? either by normal means (when use_custom_start_trace is off) or a call to appoptics_start_trace
   *
   * @return boolean (true on success, false on failure)
   */
  function appoptics_trace_started() {
    return false;
  }

  /**
   * Creates an event
   *
   * @param string layer (optional) layer name to use (may be null)
   * @param string label label name to trace (entry, exit, info, etc)
   * @param mixed info (optional) if arrayaccess (array or object with hashtable) is sent then the items in the key
   *       value pairs that aren't reserved are sent with the beginning trace
   * @param mixed backtrace (optional) if arrayaccess (array or object with hashtable) that is used as a backtrace
   *        if true is passed PHP generated backtrace is sent, if false
   *        is passed then no backtrace is sent
   * @param mixed edge (optional) if arrayaccess (array or object with hashtable) is sent then the items are treated
   *       as additional edges to add, if it's a single string the string is added
   * @return boolean (true on success, false on failure)
   */
  function appoptics_log($layer, $label, $info = null, $backtrace = true, $edge = null) {
    return false;
  }
  
  /**
   * Creates a new entry event
   *
   * @param string layer layer name to use
   * @param mixed info (optional) if arrayaccess (array or object with hashtable) is sent then the items in the key
   *       value pairs that aren't reserved are sent with the beginning trace
   * @param mixed backtrace (optional) if arrayaccess (array or object with hashtable) that is used as a backtrace
   *        if true is passed PHP generated backtrace is sent, if false
   *        is passed then no backtrace is sent
   *
   * @return boolean (true on success, false on failure)
   */
  function appoptics_log_entry($layer, $info = null, $backtrace = true) {
    return false;
  }
  
  /**
   * Creates a new exit event
   *
   * @param string layer layer name to use
   * @param mixed info (optional) if arrayaccess (array or object with hashtable) is sent then the items in the key
   *       value pairs that aren't reserved are sent with the beginning trace
   * @param mixed backtrace (optional) if arrayaccess (array or object with hashtable) that is used as a backtrace
   *        if true is passed PHP generated backtrace is sent, if false
   *        is passed then no backtrace is sent
   * @param mixed edge (optional) if arrayaccess (array or object with hashtable) is sent then the items are treated
   *       as additional edges to add, if it's a single string the string is added
   * @return boolean (true on success, false on failure)
   */
  function appoptics_log_exit($layer, $info = null, $backtrace = true, $edge = null) {
    return false;
  }
  
  /**
  * Creates an error event
  *
  * @param string layer layer name to use
  * @param string message error message
  * @param int PHP error code
  * @param mixed info (optional) if arrayaccess (array or object with hashtable) is sent then the items in the key
  *       value pairs that aren't reserved are sent with the beginning trace
  * @param mixed backtrace (optional) if arrayaccess (array or object with hashtable) that is used as a backtrace
  * @param mixed edge (optional) if arrayaccess (array or object with hashtable) is sent then the items are treated
  *       as additional edges to add, if it's a single string the string is added
  * @return boolean (true on success, false on failure)
  */
  function appoptics_log_error($layer, $message, $code, $info = null, $backtrace = null, $edge = null) {
    return false;
  }
  
  /**
   * Creates an event from a PHP exception
   * 
   * @param string layer layer name to use
   * @param object instanceof Exception exception
   * @param mixed info (optional) if arrayaccess (array or object with hashtable) is sent then the items in the key
   *       value pairs that aren't reserved are sent with the beginning trace
   * @param mixed backtrace (optional) if arrayaccess (array or object with hashtable) that is used as a backtrace
   * @param mixed edge (optional) if arrayaccess (array or object with hashtable) is sent then the items are treated
   *       as additional edges to add, if it's a single string the string is added
   * @return boolean (true on success, false on failure)
   */
  function appoptics_log_exception($layer, Exception $e, $info = null, $backtrace = null, $edge = null) {
    return false;
  }

  /**
   * Creates a new or adds to an existing Summary Metric
   *
   * @param string name the name of the metrics, a part of the "metric key"
   * @param float value a value to be recorded associated with this "metric key"
   * @param int count (optional) default as 1
   * @param boolean host_tag (optional) default as false, whether host information should be included
   * @param string service_name (optional) default as empty, custom service name
   * @param array tags (optional) default as empty, a part of the "metric key"
   *       (e.g. array("region"=>"us-west", "name"=>"web-prod-3", "db"=>"db-prod-1"))
   * @return boolean (true on success, false on failure)
   */
  function appoptics_metric_summary($name, $value, $count = 1, $host_tag = false, $service_name = null, $tags = null) {
    return false;
  }
  
  /**
   * Creates a new or adds to an existing Increment Metric
   * 
   * @param string name the name of the metrics, a part of the "metric key"
   * @param int count (optional) default as 1
   * @param boolean host_tag (optional) default as false, whether host information should be included
   * @param string service_name (optional) default as empty, custom service name
   * @param array tags (optional) default as empty, a part of the "metric key"
   *       (e.g. array("region"=>"us-west", "name"=>"web-prod-3", "db"=>"db-prod-1"))
   * @return boolean (true on success, false on failure)
   */
  function appoptics_metric_increment($name, $count = 1, $host_tag = false, $service_name = null, $tags = null) {
    return false;
  }
  
  /**
   * Get the Trace ID with the sample flag ('-0' for not sampled, '-1' for sampled) of the currently running request.
   * This is the Trace ID appended to log messages if the INI option 'appoptics.log_trace_id' is enabled.
   *
   * @return trace id with sample flag
   */
  function appoptics_get_log_trace_id() {
    return "0000000000000000000000000000000000000000-0";
  }
}

The scripts are not supported under any SolarWinds support program or service. The scripts are provided AS IS without warranty of any kind. SolarWinds further disclaims all warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose. The risk arising out of the use or performance of the scripts and documentation stays with you. In no event shall SolarWinds or anyone else involved in the creation, production, or delivery of the scripts be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability to use the scripts or documentation.