# Introduction

Welcome to the Inspector developer documentation.

Inspector is a **Code Execution Monitoring** tool that helps software developers to identify bugs and bottlenecks in their application automatically. Before users stumble onto the problem.&#x20;

Installing our library you will be able to visualize what your application is doing on every execution cycle, and identify unexpected behavior at a glance.

![](/files/6ERpaX7WJ6CbtVRWO1h7)

This documentation will help you to start working with Inspector in just a few minutes, as well as support if you get stuck.

Below are the supported technologies. Choose the one your application is built with.

### Supported Platforms

{% content-ref url="/pages/-LuWcB8gWM5wptHOWiEF" %}
[Laravel / Lumen](/guides/laravel)
{% endcontent-ref %}

{% content-ref url="/pages/-MbG50kVKWT\_dmhrNUpX" %}
[Symfony](/guides/symfony)
{% endcontent-ref %}

{% content-ref url="/pages/GqQIK9NcYrhKhzY5acoB" %}
[CodeIgniter](/guides/codeigniter)
{% endcontent-ref %}

{% content-ref url="/pages/u2aisXfoYkJFTHoQsOcI" %}
[Broken mention](broken://pages/u2aisXfoYkJFTHoQsOcI)
{% endcontent-ref %}

{% content-ref url="/pages/-LuWUZySI5nmGZTcqyyK" %}
[PHP](/guides/raw-php)
{% endcontent-ref %}

{% content-ref url="/pages/sFz09Y2ifm3lLFM7iSEA" %}
[Slim](/guides/slim)
{% endcontent-ref %}

{% content-ref url="/pages/uqOsMUhOjGdNXKmHEtnE" %}
[Neuron AI](/guides/neuron-ai)
{% endcontent-ref %}

### Security and compliance

Inspector is committed to deliver a powerful and easy-to-use monitoring platform while keeping your data secure. The security of our systems is of the utmost importance and we consistently aim to improve our security posture by building it into every layer of our products.

#### Encryption of data

Inspector datastores and their client communications are encrypted throughout the Inspector platform both in transit and at rest.

#### At rest

Our storage and analysis infrastructure is not accessible from the public internet and data are encrypted at the sotrage level. This helps mitigate the risk of unintentional or malicious access to user data.

#### In transit

All connections with Inspector API are secured by an industry-standard 256-bit HTTPS Encryption.

### Performance

Inspector is designed to be completely transparent from your users point of view. It collects and sends data to our inspection API asynchronuosly. This means that it doesn't introduce any latency in your code execution.&#x20;

### Contcacts

* Email: <support@inspector.dev>
* Website: <https://www.inspector.dev>
* Blog: <https://www.inspector.dev/blog>
* GitHub organization: <https://github.com/inspector-apm>


# Metrics

How metrics are calculated and presented in the dashboard.

Inspector offers several ways to view and aggregate data: Execution time, Memory usage, Performance distribution.&#x20;

What do they do, and how should you use them?&#x20;

### Data aggregations

Data aggregation is when multiple values of a specific parameter are grouped together to give a single summary value. This is especially useful when you want to extract simple but meaningful information from your application data that consists of thousands, or even millions of measurements.

### Execution time & Memory Usage

These metrics are calculated using the 75th percentile. It is the value where 75% of all measurements are under it, and 25% of measurements are over it. It is [the percentile that Google research team recommends](https://web.dev/defining-core-web-vitals-thresholds/#choice-of-percentile) using when monitoring Web Vitals.

![](/files/ru6upgdabWqBPLI25PRx)

The chart above shows the page load histogram with all of the measurements below the 75th percentile coloured in blue.

#### Why use the 75th percentile

The 75th percentile is a good balance of representing the vast majority of measurements, and not being impacted by outliers. While not as stable as the median (50th pecentile), the 75th percentile is a good choice for seeing medium - to long term trends. We also think the 75th percentile is the best value to use when setting performance budgets.

### Performance Distribution

You can make a deeper investigation on specific transactions using the frequency distribution histogram.

That's a fancy way of describing a bar chart where the X (horizontal) axis shows the value of a measurement and the Y (vertical) axis shows the number of measurements that had that value.&#x20;

Take this chart for example:

![Performance Distribution Chart](/files/ImKOAQ3cYEO2eHVs3PYl)

The chart above shows clusters of execution times on the X axis. The height of the bars represents how many measurements had execution times that fell within each cluster. We can see that the majority of execution times were between 0 and 407 milliseconds, with a smaller number of execution times on either side.

Notice how there are many clusters to the right of the chart, but they all have a small number of measurements. This is called the "long tail" and represents the times the transaction had the worst performances.

{% hint style="info" %}
This particular chart is "**clickable**". So you can view and compare two samples of the transaction at different performance. One from a good performance cluster (left side of the chart), versus one from bad performance (right side of the chart).
{% endhint %}


# Notification Channels

Routes important alerts to your preferred communication services.

Inspector is able to detect a variety of events in your application for which you can be notified in Real-Time.

### What types of notifications can you receive?

| Name                        | Description                                 |
| --------------------------- | ------------------------------------------- |
| **New Error**               | When a brand new error is detected.         |
| **10^nth Error Occurrence** | When an error occurs 10, 100, 1000+ times.  |
| **Error Frequency**         | When the frequency of an error rears up.    |
| **Error Occurrence**        | Every time an error occurrence is detected. |
| **Transaction**             | When a brand new transaction is detected.   |
| **Alert**                   | On an alert threshold violation.            |

### Supported channels

Thanks to channels you can connect the monitoring system with your workspace sending notifications across a variety of tools, including E-mail, Slack, Webhooks, SMS, and others.

You can enable one or more channels for each application, distributing different notifications on different channels based on your preferences and priorities.

{% content-ref url="/pages/-M3p9fvPN7draqefFLkZ" %}
[Email](/concepts/notifications/email-channel)
{% endcontent-ref %}

{% content-ref url="/pages/-M3pCz3894RZuViftOVE" %}
[Slack](/concepts/notifications/slack-channel)
{% endcontent-ref %}

{% content-ref url="/pages/oBtkH2zaGs3pXFRVhe6h" %}
[Telegram](/concepts/notifications/telegram)
{% endcontent-ref %}

{% content-ref url="/pages/-MkgfDEhe3Dcn6vaM-YR" %}
[Microsoft Teams](/concepts/notifications/microsoft-teams)
{% endcontent-ref %}

{% content-ref url="/pages/J9VbLk9auy3Kk0yuee9A" %}
[Google Chat](/concepts/notifications/google-chat)
{% endcontent-ref %}

{% content-ref url="/pages/-M3pUtiPHuIO4QgTiSPj" %}
[Webhook](/concepts/notifications/webhook-channel)
{% endcontent-ref %}

{% content-ref url="/pages/-MkrfCaeT7f0qabz5pU0" %}
[Discord](/concepts/notifications/discord)
{% endcontent-ref %}

{% content-ref url="/pages/-M6iQqvaFfzLkLAZ3n37" %}
[Pushover](/concepts/notifications/pushover)
{% endcontent-ref %}

{% content-ref url="/pages/-M5IcEzDdNthJXWGbLKt" %}
[PagerDuty](/concepts/notifications/pagerduty)
{% endcontent-ref %}

{% content-ref url="/pages/-MRVFxfMHG9QZ\_\_EcyDR" %}
[Twilio - SMS](/concepts/notifications/twilio-sms)
{% endcontent-ref %}

### Limitations

Notification Channels are associated to each application. You can use a limited number of channels per application based on your subscription plan.


# Email

Send notifications to the users email addresses.

In Inspector, navigate to the project you want to activate email notifications.

* Click **Settings → Notifications Channels**

Email channel is activated by default when you create a new application so you'll find the channel in the "Active Channels" list.

* Click **Configure** in the E-Mail channel to open the configuration screen

You can simply add as many E-mail addresses you want to receive selected notifications. Separate each email address with a comma ( **,** ).

![](/files/-M3pCJba7i0yjApM_fuM)

{% hint style="info" %}
Remember to click "**Save**" after any change in the channel settings.
{% endhint %}

If you want to disable the channel click "**Disconnect**" and confirm your choise.


# Slack

Send notifications to your Slack workspace.

{% hint style="warning" %}
Slack has 1 message per second rate limiter. Sometimes the Slack API could allows more higher rate but in general Slack shouldn't be used for notifications with an high volume of messages (e.g. Error Occurrence).
{% endhint %}

Navigate to the project you want to integrate with Slack.

### 1) Connect

* Click **Settings → Notifications Channels**
* Click **Configure** in the Slack channel to open the configuration screen
* Click **Connect with Slack**
* Allow Inspector app to interact with your Slack account.

![Slask authorization screen](/files/-M3pj8-Lt6_NJLBZpffy)

### 2) Configure

Select the channel or group you wish to receive messages for, and select the notifications you want to receive.

![Slack channel settings](/files/-M3pjFjmNYUz5hDr6JYV)

Click **Save** to confirm your configuration.

### 3) Add the Inspector app to the channel

To start receiving messages from the Inspector bot you need to invite the app in the channel selected in the Notification channel settings. To do it follow this two simple steps:

* Go to the channel you want to add the app to
* Type a forward slash followed by the app's name (e.g., `/invite @appName`) to add it to the channel

Congrats!&#x20;

Slack is now integrated with Inspector and you'll receive monitoring notifications directly in your Slack workspace.

![](/files/WiufdP6MscdlNKySm9bh)

If you want to disable the channel click "**Disconnect**" and confirm your choice.

Learn more about the Inspector's privacy policy at this link: <https://www.inspector.dev/privacy-policy.pdf>


# Telegram

Send notifications to Telegram users.

In order to receive notifications directly in the Telegram app you need to accomplish two steps:

* Retrieve the Telegram ID of users that want to use this channel;
* Each user must start a chat with the Inspector bot. [Click here to start the chat. ](https://web.telegram.org/k/#@InspectorAlertBot)

### How to get the Telegram user ID?

The steps are the same for desktop and mobile apps. First, open your Telegram app. Then, type "**userinfobot"** in your contacts search bar. If you can't find this "profile", try adding an "@" in front of the search query. When you’ve located **@userinfobot**, click or tap it. Then, select **Start** at the bottom of the chat.

![How to search the user info bot.](/files/NHyHYwpbUCBSYaZK8IXb)

By clicking Start, you’ve automatically entered "**/start**." It will prompt the bot to display your user ID, as well as your selected first name, last name, and the language of choice.

![The response by the user bot.](/files/FYm7J3l7QMIcYwqirwkB)

Copy the value of the ID field and add it in the configuration of the notification channel.

![The Telegram channel configuration screen.](/files/tray5pPN0eETcnLNikWi)

Click **Save** or **Enable channel** in case of the first activation.

### Start a chat with the Inspector bot

In order to be able to send you messages in your telegram app there must be an active chat with the bot.

Open this link and click Start to start a chat: <https://web.telegram.org/k/#@InspectorAlertBot>

<figure><img src="/files/g42UpKhRMt9Lz7sKMr1n" alt=""><figcaption><p>The Start button to open a chat with Inspector bot.</p></figcaption></figure>


# Microsoft Teams

Send notifications to Microsoft Teams channels.

### How to create a webhook in Microsoft Teams

Incoming Webhook allows any external apps to share content in Teams channels. To add an Incoming Webhook to a Teams channel:

* Go to the channel where you want to add the webhook and select "•••" (More Options) from the top navigation bar;
* Select Connectors from the dropdown menu;
* Search for **Incoming Webhook** and select **Add**.

You can read more about incoming webhooks on the official Microsoft Teams documentation: <https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook>

### Attach the Microsoft Teams channel to your project

* Navigate to **Settings → Notifications Channels;**
* Click **Configure** in the Microsoft Teams channel to open the configuration screen;
* Paste the incoming webhook url generated by Microsoft Teams.

![](/files/-MkggDBHZep_ZVL62B-p)

{% hint style="info" %}
Remember to click "**Save**" after any change in the channel settings.
{% endhint %}

If you want to disable the channel click "**Disconnect**" and confirm your choise.


# Google Chat

Send notifications to your Google Chat space.

### How to create a webhook in Google Chat

Webhooks allow any external apps to share content in Google Chat spaces. To add a webhook to a Google Chat space follow the instructions below:

1. Go to the space where you want to add the webhook (or create a new space);
2. Click on the space title to expand the menu, and then click **Apps & Integrations;**
3. Click +**Add webhooks**;
4. In the Avatar URL field, enter: `https://app.inspector.dev/images/logo-square-black-background.png`
5. Click **Save**.

You can read more about webhooks on the official Google Chat documentation: <https://developers.google.com/chat/how-tos/webhooks#create_a_webhook>

### Install the Google Chat channel

1. Navigate to **Notifications Channels;**
2. Click **Configure** in the Google Chat channel to open the configuration screen;
3. Paste the incoming webhook url generated in the steps above;
4. Activate the type of notifications you want to forward to this channel;
5. Click Enable Channel, and confirm your choice.

<figure><img src="/files/4WWTZXahOkBTbg2tFEZa" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Remember to click "**Save**" after any change to make the channel settings effective.
{% endhint %}

If you want to disable the channel click "**Disconnect**" and confirm your choise.


# Webhook

Send http POST requests to specified endpoints.

### Configuration

In [Inspector](https://app.inspector.dev), navigate to the project for which you want to configure webhooks.

* Click **Settings → Notifications Channels;**
* Click **Configure** in the Webhook channel to open the configuration screen;
* Paste the url you want to point to in the input form;

![](/files/-MAjwmsMOVIs-NGBq0lh)

{% hint style="info" %}
Remember to click "**Save**" after any change in the channel settings.
{% endhint %}

If you want to disable the channel click "**Disconnect**" and confirm your choise.

## HTTP POST request format

When a request is fired against your endpoint it will contains specific information in its body and headers. Below you can understand the content delivered for each event.

## Headers

```
User-Agent: "Inspector-Notification-Channel"
X-Inspector-Key: "your-application-api-key"
```

## Body

### Alert

```
{
    event: "alert_violation_notification",
    
    application: {
        id: 12345,
        name: "Your App name",
        client_version: "4.7.22"
    },
    
    payload: {
        id: 25,
        title: "High system load",
        violated_at: "2020-06-26 09:03:54"
    }
}
```

### Error Occurrence

```
{
    event: "error_occurrence_detected_notification",
    
    application: {
        id: 12345,
        name: "Your App Name",
        client_version: "4.7.22"
    },
    
    payload: {
        timestamp: "2020-06-26 09:03:54",
        message: "Missing required parameters for [Route: home] [URI: /]",
        class: "ErrorException",
        file: "app/Http/Controllers/YourController.php",
        line: "17"
    }
}
```

### Error Group

```
{
    event: "error_group_detected_notification",
    
    application: {
        id: 12345,
        name: "Your App Name",
        client_version: "4.7.22"
    },
    
    payload: {
        last_seen_at: "2020-06-26 09:03:54",
        created_at: "2020-06-26 09:03:54",
        handled: false,
        message: "Missing required parameters for [Route: home] [URI: /]",
        class: "ErrorException",
        file: "app/Http/Controllers/YourController.php",
        line: "17"
    }
}
```

### Error Frequency Increasing

```
{
    event: "error_frequency_increasing_notification",
    
    application: {
        id: 12345,
        name: "Your App Name",
        client_version: "4.7.22"
    },
    
    payload: {
        last_seen_at: "2020-06-26 09:03:54",
        created_at: "2020-06-26 09:03:54",
        handled: false,
        message: "Missing required parameters for [Route: home] [URI: /]",
        class: "ErrorException",
        file: "app/Http/Controllers/YourController.php",
        line: "17"
    }
}
```

### 10^nth Error Occurrence

```
{
    event: "nth_error_notification",
    
    application: {
        id: 12345,
        name: "Your App Name",
        client_version: "4.7.22"
    },
    
    payload: {
        last_seen_at: "2020-06-26 09:03:54",
        created_at: "2020-06-26 09:03:54",
        handled: false,
        message: "Missing required parameters for [Route: home] [URI: /]",
        class: "ErrorException",
        file: "app/Http/Controllers/YourController.php",
        line: "17",
        nth: 100,
    }
}
```

### New Transaction

```
{
    event: "transaction_group_notification",
    
    application: {
        id: 12345,
        name: "Your App Name",
        client_version: "4.7.22"
    },
    
    payload: {
        created_at: "2020-06-26 09:03:54",
        name: "GET /bookings",
        type: "request",
        avg_duration: 354.01
    }
}
```


# Discord

Send notifications to your Discord channel.

### Creating a Discord Channel and Webhook

&#x20;Let's start by creating a new Discord channel. To do so, go to your Discord server and then click on the `+` next to the 'Text channels':

![](/files/-MkrfcNknTYe1wmoeC4P)

After that, set the channel to 'Text Channel', choose a channel name and choose if you want to have the channel private or not:

![](/files/-MkrfmEW5oWeL7q8rcxy)

Once you have your channel ready, click on edit `->` and then go to the `Integrations` tab `->` and in there click on the `Create Webhook` button.

In there, type `Inspector Bot` as webhook name and copy the Webhook URL:

![](/files/-MkrjXEGl0JtOA51Vp8w)

Copy the Webhook URL as we will use it in the next step when we set up the notification channel!

You can use our square logo as Bot icon:&#x20;

![](/files/-Mkrg6fYMG6nI0uA5cTJ)

### Attach the Discord Notification Channel to your project

* Navigate to the project **Settings → Notifications Channels** screen;
* Click **Configure** in the Discord channel to open the configuration screen;
* Paste the webhook url in the `Webhook` field;
* Activate the notifications you want forward via this channel.

![](/files/-MkriJe--BEoivQ2uQhD)

Click **Save** to start receiving notifications:

![](/files/-MkrjiwCDzlvnhNoFU6o)

If you want to disable the channel click "**Disconnect**" and confirm your choise.


# Pushover

Send notifications to your Pushover mobile application.

Navigate to the application you want to integrate with Pushover.

* Click **Settings → Notifications Channels**
* Click **Configure** in the Pushover channel to open the configuration screen
* Click **Connect with Pushover**

Confirm your integration in the Pushover integration view:

![](/files/-M6iW6DwuKB0ceUAFjJ7)

* Select the device you want to connect
* Select the default notification sound
* Click on **Subscribe Me**, than you'll be redirected to Inspector
* Select the notifications you want receive in your Pushover app

![](/files/-M6iVjCA4S_KmLu8Iqyn)

* Click **Save**

Congrats! Pushover is now integrated with Inspector and you'll receive important notifications directly in your smartphone.

![](/files/-M6iX2rumj_rmqE5j8vR)

{% hint style="info" %}
Remember to click "**Save**" after any change in the channel settings.
{% endhint %}

If you want to disable the channel click "**Disconnect**" and confirm your choise.


# PagerDuty

Send notifications to your PagerDuty service.

Navigate to the application you want to integrate with PagerDuty.

* Click **Settings → Notifications Channels**
* Click **Configure** in the PagerDuty channel to open the configuration screen
* Click **Connect with PagerDuty**

Confirm your integration in the PagerDuty integration view:

![PagerDuty integration confirm](/files/-M5Icxcs_Q4v6Hu_Y8GB)

* Select the service
* Select the notifications you want receive in your PagerDuty dashboard

![Inspector PagerDuty integration configuration](/files/uxGlvIrgSjmcN2KjKXUN)

* Click **Save**

Congrats! PagerDuty is now integrated with Inspector and you'll receive important notifications directly in your PagerDuty dashboard.

![](/files/-M5IdfTbjJtLrLR6-JtE)

{% hint style="info" %}
Remember to click "**Save**" after any change in the channel settings.
{% endhint %}

If you want to disable the channel click "**Disconnect**" and confirm your choise.


# Twilio - SMS

Send SMS notifications through your Twilio account.

Inspector will send SMS notifications using your Twilio account, so first you need to configure your Twilio account keys to allow Inspector to connect to Twilio API on your behalf.

In Inspector, navigate to the project you want to activate SMS notifications.

* Click **Settings → Notifications Channels**
* Click **Configure** in the "**Twilio - SMS**" channel to open the configuration screen

### Twilio Configuration

You need three mandatory parameters from your Twilio console:

* Account SID
* Auth Token
* From number

![](/files/-MRVINiwVR2U2sQI8IlP)

{% hint style="info" %}
You can find these information directly in your Twilio console: [**https://www.twilio.com/console**](https://www.twilio.com/console)
{% endhint %}

### Recipients

You can add as many phone numbers you want to receive selected notifications. Separate each number with a comma ( **,** ).

{% hint style="warning" %}
Each number will receive a separate SMS, so each of them contributes to the consumption of your Twilio credit.
{% endhint %}

{% hint style="info" %}
Remember to click "**Save**" after any change in the channel settings.
{% endhint %}

If you want to disable the channel click "**Disconnect**" and confirm your choise.


# Filtering Syntax

Apply filters with an intuitive, human-friendly search.

Inspector filter is designed for human-entered text. Filter queries can be saved and reused with a click so understand how to search in your transactions stream could give you a lot of free time later.

### Why use filters

You can visualize performance statistics of a sub-part of your system and not only for the whole application. Applying a filtering logic to your `Monitoring` dashboard you can create a custom view to keep specific parts of your app under control.

Let me show you a real world example.

Suppose to have a list of transactions executed by your application.

![](/files/00HG6Vzt87zkUs0x9gnm)

We want isolate the "console commands" to understand if the background work done by your application is going in the right way.

Type `"artisan"` in the filter box and push enter.

### Simple Text

By default the text used as query will filter the transactions list by name.

Remeber to use double quotes:

```
"my text query"
```

### Wildcard

Inspector supports single and multiple character wildcard searches within single terms (not within phrase queries).

To perform a single character wildcard search use the "?" symbol.

```
"/api/platform?/details"
```

To perform a multiple character wildcard search use the "\*" symbol.

```
"/api/platforms/*/group"
```

### Operators

Boolean operators allow terms to be combined through logic operators. AND, OR, NOT operators are supported (Note: **operators must be ALL CAPS**).

#### OR

The OR operator is the default conjunction operator. This means that if there is no Boolean operator between two terms, the OR operator is used.

To search for transactions that contain either "GET /" or just "GET" use the query:

```
"GET /" GET
```

Or

```
"GET /" OR GET
```

#### AND

The AND operator matches records where both terms exist in the event fields.

```
GET AND "/api"
```

#### NOT

The NOT operator excludes documents that contain the term after NOT.

```
"/*" NOT POST
```

### Range

You can filter both numeric and string value using range:

```
# Filter by transaction duration
duration:[800 TO *]

# Filter by transaction memory_peak
memory_peak:[40 TO 50]
```

### Escaping Special Characters

You need to consider special characters all the items that could be interfere with syntax:

* :
* \*
* ?
* (
* )

To escape these character use the \ before the character. For example to search for `route:list` use the query:

```
route\:list
```


# Alerts

Create alerts to monitor your application processes.

### Introduction

Alerts empowers developers to catch complications before they develop into problems, and helps you preserve high availability and deliver high quality of service.

It also assists you in making informed decisions about the present and the future, serves as input to automation of infrastructures and, most importantly, is an indispensable learning tool.

![Alerts list](/files/JH4O1PMGfFvzGpC054Lh)

### Create an alert

The most important part of the alert creation form is "Query & Metric".

![Alert form](/files/YhZakCJnEoTOQ5GyTypz)

### Query

Define what resource you want monitor (Transactions or Segments) and the query you want perform to identify the target items.

### Metric

As a metric you can choose from a various analytic functions like count, min, max, or the average value.  The execution time or memory consume are the available metrics. You could limit this value directly in the metric so in that case you should select the count option to match the number of events within the condition specified in the query.

### Threshold

Threshold represents **when** you want receive an alert. Different conditions allows you to detect different anomalous behaviors. For any type of threshold you can read a short description of their typical use cases.

{% hint style="warning" %}
**Note**

You need to turn on **Alert** notifications in your notification channels, in order to be notified for threshold violations.
{% endhint %}


# Grouping Patterns

How to customize the transactions and errors grouping strategy

### Introduction

Grouping patterns are custom rules to help you group similar items together overcoming the limitations of the Inspector's standard grouping strategy. You can create custom patterns for both Transactions and Errors, so you have maximum flexibility on the way data are reported in your dashboard.

### Errors Settings

With grouping patterns you can register custom rules to group similar errors together. The typical use case is errors that repeat themselves with only small differences within the message, such as a date, an ID, but the occurrences always refers to the exact same error.

The dynamic part of the error's message must be delimited by curly brackets {...}. You can also use multiple slots to parametrize multiple parts of the error message:

```
Invalid datetime format: 1292 Incorrect date value: {date} for column {column_name}_at
```

#### Add an Error Pattern

Navigate in the `App -> Settings -> Errors Settings` section. In the top right corner of the transactions list you'll find the orange button to open the grouping pattern form.

<figure><img src="/files/aAI2ZJv2pHYyk0aRg0dw" alt=""><figcaption></figcaption></figure>

Type your desired pattern in the form and click Save.

<figure><img src="/files/XUbs1tz41Ofj5wuB2uq8" alt=""><figcaption></figcaption></figure>

### Transaction Settings

Since it is not always possible to identify the original signature of the endpoints within the application, you may see a different transaction generated for each URL parameter in the endpoint. Take a look at the example below:

* GET /api/users/123/profile
* GET /api/users/56/profile
* GET /api/users/824/profile

It is actually the same endpoint where only the user ID changes.

Creating the pattern **`GET /api/users/{user_id}/profile`** you can instruct Inspector to group all these transactions together.

The dynamic part of the transaction's name must be delimited by curly brackets ({...}), such as **`{user_id}`** in the example above.&#x20;

You can also use multiple parameters inthe same string like:

&#x20;**`GET`` ``/api/users/{user_id}/projects/{project_id}`**.

#### Add a Transaction pattern

Navigate in the `App -> Settings -> Transactions Settings` section. In the top right corner of the transactions list you'll find the orange button to open the grouping pattern form.

![](/files/Yg0fNY3Vcq2ZX44Cf6uZ)

Type your desired pattern in the form and click Save.

![](/files/QcD5ZzGbOEMjkiouc6Iz)

It can require some minutes to become active. Checkout your transactions list to verify if Inspector start grouping transactions as you expect.


# Custom Segments

Monitor custom code blocks inside your application.

Inspector automatically creates a basic timeline to see what happen inside your application. It will report many type of statements by default.&#x20;

Segments give you the opportunity to "monitor" specific code bloks that you consider relevant for your app to create a more complete picture of what's happening on any execution cycle.

### What are segments?

Segments represents tasks performed during an execution cycle, like:

* Http call to external services (webhooks, integration, etc.)
* Functions that deal with files (pdf, excel, images)
* Data manipulation processes (import/export, data aggregation, etc.)

Below you can see an example of how custom segments will appear in the timeline:

![A new segment in the timeline](/files/-LuWgbN9J5ftiM5TDO2T)

You can learn how to add custom segments from the code examples below:

{% content-ref url="/pages/-McFYez8BNvP8qjYxvXw" %}
[Custom Segments](/guides/raw-php/custom-segments)
{% endcontent-ref %}


# Billing

Inspector pricing was designed for transparency and scalability.

### Overview

Inspector offers a scalable, pay-as-you-grow plan model, which means you'll never have to over-provision resources while building your application. We offer five base data tiers: `Developer`, `Team`, `Scale`, and `Enterprise`.

You can find the complete list of plan offerings [in the next section](#inspector-plans).

Inspector charges on three factors:

* **Transactions**: Number of execution cycles in your application;
* **Users**: Colleagues or collaborators who access your account;
* **Notification Channels**: Number of delivery channels for alerts and notification for each application.

### Subscription plans

Inspector applies billing plans at the **Organization level**. You can connect unlimited applications under one Organization.&#x20;

We offer five pre-packaged data tiers options, summarized below:

<table><thead><tr><th width="208"> </th><th>Beginner</th><th>Developer</th><th>Team</th><th>Scale</th><th>Enterprise</th></tr></thead><tbody><tr><td><strong>Monthly Charge</strong></td><td>15€</td><td>39€</td><td>69€</td><td>99€</td><td>169€</td></tr><tr><td><strong>Transactions</strong></td><td>300K</td><td>800K</td><td>1.5 million</td><td>3 million</td><td>6 million</td></tr><tr><td><strong>Users</strong></td><td>Unlimited</td><td>Unlimited</td><td>Unlimited</td><td>Unlimited</td><td>Unlimited</td></tr><tr><td><strong>Notification Channels</strong></td><td>Unlimited</td><td>Unlimited</td><td>Unlimited</td><td>Unlimited</td><td>Unlimited</td></tr><tr><td><strong>REST APIs</strong></td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr><tr><td><strong>AI Bug Fixer</strong></td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr><tr><td><strong>Usage-Based fee (every 50K trasnactions)</strong></td><td><mark style="color:blue;">*</mark> 2.5€</td><td><mark style="color:blue;">*</mark> 2.25€</td><td><mark style="color:blue;">*</mark> 2€</td><td><mark style="color:blue;">*</mark> 1.65€</td><td><mark style="color:blue;">*</mark> 1.4€</td></tr></tbody></table>

*<mark style="color:blue;">\* The fee refers to every slot of 50K transactions</mark>*

### Usage Based Billing

Normally, when your account reaches the maximum number of transactions included in your plan, Inspector simply ignores data that your application send to us, until the start of the next  monthly cycle.

With `usage-based-billing` you can keep your monitoring system on for a small fee for transactions monitored beyond the default quotas included in your tier.

You can think of `usage-based-billing` as a way to have a smoother transition to higher subscription plans, or a tool to cover some transitory spike in traffic.

The fee associated with data beyond quotas depends on your subscription plan. It decreases as your account grows. It starts as €3 for the free tier, down to €1.4 for enterprise plans, **for every slot of 50K transactions**.

Go to the billing section from the link below.

{% embed url="<https://app.inspector.dev/billing>" %}

### Do you need higher volumes?

If your organization structurally exceeds the highest quota included in the Enterprise plan, you should contact our technical support at <support@inspector.dev> to get a price estimate based on the amount of transactions expected to be monitored for your Organization.

We don't charge any extra fee for a custom tiers, in fact, you will be able to access even more advantageous conditions.

Eventually a dedicated cluster is required to manage large amounts of data and provides many benefits:

* **Fully managed** - No technical effort is required by your side. Free your team to focus on your business' core competencies instead of spend time installing and configuring complex tools in your infrastructure. Inspector easily scale with your needs and it's always ready to provide you with fast and effective technical support.
* **Scalability & Performance** - Continue to deliver metrics and alerts to your collaborators in real-time without any additional effort, using our platform at scale.
* **Data isolation** - Your data will be stored in a database completely separate from the data of other companies. This ensures better compliance with the most stringent regulations and high performance in the processing of monitoring metrics.

{% hint style="info" %}
Contact our techcnical support to get an estimate based on your historical data: <support@inspector.dev>
{% endhint %}


# AI Bug Fix

Real-Time bug fix proposals to immediately get solutions from emerging errors.

Inspector can automatically generates code change proposals to fix application errors detected in real-time. You will receive the first bug fix solution without having to ask your collaborators for time, or wait to be in front of the desk to analyze the problem manually.

To enable AI Bug Fixer you should connect your Inspector account with the source control providers where you host your source code.

### Connect to source control providers

Navigate to the [**Source Control**](https://app.inspector.dev/organization/vcs) section in the Organization menu.

<figure><img src="/files/zbWqAOqjvUvHhFvNBEzb" alt=""><figcaption></figcaption></figure>

Click on the connect button to follow the installation process. Make sure to grant the Inspector app access to the repositories you want to connect to. You will be redirected to this page.

### Configure the AI Bug Fixer

Once you enabled the connection with the source control provider, you should associate a specific repository to the application you want to enable the AI Bug Fix.

Go into the ***Application Settings -> AI Bug Fixer*** section.

<figure><img src="/files/519Gug1LBlR9mQS9ACBx" alt=""><figcaption></figcaption></figure>

Here are the configurations you need:

* The **repository** to connect from the source control provider;
* The default **branch** you want Inspector to connect to;
* The **root path** of the application on your production server;

#### How to find the root path on the server

SSH into your server and go to the directory where your application is located:

```sh
> cd app-directory/
```

Execute the [pwd](https://en.wikipedia.org/wiki/Pwd) command to see the full root path on the server:

```
> pwd
```

Paste the output into the input field in the configuration form.

Click **Save** to activate the integration.

### Zero Downtime Deployment

If you use zero downtime deployment as release strategy, the real path of the application on your server will change on any deploy. As you know zero downtime deployment will create a new directory on every release.

In this case you need to use the wildcard character "\*" to map the release directory. See the example below:

```bash
# The final directory will change on every release
/var/www/html/public_html/releases/382758329/

# This is how you should configure the root server path on Inspector
/var/www/html/public_html/releases/*/
```

### Receive Bug Fix Proposals

Once an error is detected, Inspector will use the gathered information to generate a solution starting from your original source code that may fix the error immediately.

If Inspector successfully generates a bug fix, you will see the "source code" icon in the errors list colored in orange.

<figure><img src="/files/NFI19xPFOTj2ccmMiMYl" alt=""><figcaption><p>Inspector Errors List</p></figcaption></figure>

And you will be able to read the entire fix proposal automatically created for you.

<figure><img src="/files/DNwVjASQYm768pu3jkuY" alt=""><figcaption><p>Inspector Ai Bug Fix</p></figcaption></figure>


# MCP Server

Let AI coding agents access your application monitoring data to help them debug your application.

The rise of AI coding agents like [Claude Code](https://docs.anthropic.com/en/docs/claude-code), [OpenCode](https://opencode.ai/), [Cursor](https://cursor.com/), and [GitHub Copilot](https://github.com/features/copilot) has transformed how developers write code. These tools can generate entire features, debug complex issues, and refactor code at unprecedented speed - but their effectiveness depends heavily on how well they understand your issues.

Inspector MCP server allows AI clients to consume your application monitoring data, helping them spotlight the exact code changes needed to fix bugs and improve application performance.

### What the Inspector MCP Server Actually Does

The MCP server creates a bridge between AI code assistant and your Inspector monitoring data. Your AI assistant gains access to performance metrics, error analyses, database queries, and application health indicators.

They can investigate slow transactions, the execution timeline and performance data of everything happen into your application while running the actual production environment.

Rather than switching between multiple tools, you maintain a single conversation thread where coding questions and production monitoring blend seamlessly.

{% embed url="<https://www.youtube.com/watch?v=Z_BNykUXGb8>" %}

### Local CLI Agents

The communication between your coding agent and Inspector needs authentication. Before moving forward you need to create an [**API key**](https://app.inspector.dev/account/api).

Navigate to your **Application Settings** in the Inspector dashboard to copy the proper configuration. Here are ready to use configurations for most commomn ai coding asisstant.

#### Claude Code

```
claude mcp add --transport http inspector https://app.inspector.dev/mcp?app=xxxx --header "Authorization: Bearer YOUR_API_KEY"
```

#### VS Code

```json
{
    "mcp": {
        "servers": {
            "inspector": {
                "type": "http",
                "url": "https://app.inspector.dev/mcp?app=xxxx",
                "headers": {
                    "Authorization": "Bearer YOUR_API_KEY"
                }
            }
        }
    }
}
```

#### Cursor

```json
{
  "mcpServers": {
    "inspector": {
      "url": "https://app.inspector.dev/mcp?app=xxxx",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}
```

If you need to configure the MCP connection in other agent you need to setup two mandatory parameters:

* URL with the APP you want to connect (e.g. <https://app.inspector.dev/mcp?app=9583>)
* Authorization token

Verify the connection with a simple prompt, like: “*Are there errors in the app production environment?*”

Once connected, your AI assistant gains access to comprehensive monitoring data, including performance metrics, errors, bug fix suggestions, database query analysis, and more.

### Web Chat AI Assistant

Using an AI Assistant on a web interfaceit's different. They authenticate external MCP servers through OAuth, the login-and-approve flow you already know from connecting Slack or Google Drive to some other tool, not through a secret you copy and paste.&#x20;

Here is the actual flow, using Claude as the example, because it’s the client I use most. ChatGPT and other web based agents follow the same pattern under different menu names.

#### Step 1: add the connector with just a URL

In Claude, open Settings and go to the Connectors section, then choose to add a custom connector. You give it a name, Inspector, and paste the server URL, which you’ll find in your application settings inside the Inspector dashboard. It looks like this, with your own application ID at the end:

```
https://app.inspector.dev/mcp?app=YOUR_APP_ID
```

That’s it. You don’t need to touch “Advanced settings”, and there is no field asking you for an authorization token, because the server now negotiates that part on its own.

<figure><img src="/files/xOJ3ytktzJwWMawv3lL5" alt=""><figcaption></figcaption></figure>

#### Step 2: authorize the connection on Inspector

As soon as you connect, you’re redirected to Inspector, where you’ll see a plain authorization screen telling you which application is asking for access and what it will be able to do. In this case, Claude requesting permission to use the MCP server. You log in with the Inspector account you already have, click Authorize, and the handshake completes behind the scenes.

<figure><img src="/files/WGidynAJ77FMqIw3hhiv" alt=""><figcaption></figcaption></figure>

#### Step 3: check the tools you just gave your assistant

You land back in Claude with a confirmation that you’re connected, and the connector page now shows the tools the Inspector MCP server exposes, along with a permission switch for each one. You’ll see the ability to analyze a specific error, pull recent errors from your production environment, list recent transactions, inspect the details of a single transaction, and get the ten worst performing transactions in your application.

<figure><img src="/files/igomsHMSCLPbJy5qihY4" alt=""><figcaption></figcaption></figure>


# Agentic Integration

Connect the documentation to coding agents for AI Assisted Development

#### Introduction <a href="#introduction" id="introduction"></a>

This documentation is also available and searchable as a Model Context Protocol (MCP) server.

This allows AI assistants to access Neuron AI documentation content directly, making it easy for tools like Claude Code, Cursor, and VS Code extensions reliably understand what Inspector client library can do, its configurations, how to use it.

The MCP server is available at: [https://docs.inspector.dev/\~gitbook/mcp](https://docs.neuron-ai.dev/neuron-v2/~gitbook/mcp)

#### Claude Code <a href="#claude-code" id="claude-code"></a>

```
claude mcp add --transport http inspector-lib-doc https://docs.inspector.dev/~gitbook/mcp
```

#### VS Code <a href="#vs-code" id="vs-code"></a>

```json
"mcp": {
    "servers": {
        "inspector-lib-doc": {
            "type": "http",
            "url": "https://docs.inspector.dev/~gitbook/mcp"
        }
    }
}
```

#### Cursor <a href="#cursor" id="cursor"></a>

```json
{
  "mcpServers": {
    "inspector-lib-doc": {
        "url": "https://docs.inspector.dev/~gitbook/mcp"
    }
  }
}
```

#### Windsurf <a href="#windsurf" id="windsurf"></a>

```json
{
  "mcpServers": {
    "inspector-lib-doc": {
      "serverUrl": "https://docs.inspectori.dev/~gitbook/mcp"
    }
  }
}
```

#### OpenCode <a href="#opencode" id="opencode"></a>

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "inspector-lib-doc": {
      "type": "remote",
      "url": "https://docs.inspector.dev/~gitbook/mcp",
      "enabled": true
    }
  }
}
```


# Access control

Explore roles, permissions, and access control options at an organization and application level.

### Organization access control

When you set up your Inspector account, an **Organization** is automatically created.

An organization is essentially a container for your applications, settings, and team members.

Within the organization, you can add members and assign them different roles and permissions. This document covers the different roles and the ways you can assign permissions.

### Application Permissions

You can restrict the developers access to your Inspector organization by limiting access to one or more applications without being able to access organization data.

Our authorization system give you the ability to limit the access of your collaborator to specific projects they are responsible for.

![](/files/-LuX7Cj6UXv6dZYNc3Aq)

Here is a short video about “*per-app*” authorization: <https://www.youtube.com/watch?v=ZOn8SD3pWzw>

### Admin

If you want to share full control of your organization data with other team members you can assign them the `Admin` role.

![](/files/-LuX7WycyfMRPccCGC8u)

{% hint style="danger" %}
"Admin" permission allows users to view/delete organization's projects and to access and modify organization informations (billing, subscription plan, users, etc...).
{% endhint %}


# Two-factor authentication

Enable multi-factor authentication (MFA) to keep your Inspector account secure.

### Overview

Two-factor authentication (2FA) provides better safety for your account and prevents unauthorized access to your data. MFA strengthens security by requiring two or more methods *(i.e. authentication factors)* to verify your identity.

Inspector allows users logging in with an email address and password to set 2FA as a requirement for logging into the user account.

### Authentication provider

Inspector supports login with a unique *time-based one-time password (TOTP)* that is generated for your user account by using the Google Authenticator mobile app.

You have to download the app on your smartphone before proceed.

### Enable 2FA

You can enable 2FA for your user account under your user account menu.

<figure><img src="/files/bxlFSnDk2SAvpFo7O3cQ" alt=""><figcaption><p>User menu to open MFA configuration page.</p></figcaption></figure>

Clicking the **Enable** button you will be redirected to the activaton screen.

<figure><img src="/files/zx6wkuBfSycefcp7Ju6v" alt=""><figcaption><p>Screen with QR code</p></figcaption></figure>

Scan the QR Code with the Google Authenticator app. If the new Inspector entry appears in your smartphone you can confirm the contol checkbox and click **Next**.

### Log-in with Two-factor authentication

Once you've enabled 2FA in your Inspector user account, the next time you login, you'll be prompted to enter your two-factor authentication (2FA) code.

* Use the **OTP code** generated by your Google Authenticator app to login to your Inspector account.

### Recovery

You must contact our [support team](mailto:support@inspector.dev) to regain access to your account in the event that you lose the device that generates your authentication codes.

### Disable 2FA

{% hint style="warning" %}
We strongly recommend that you do not disable MFA to avoid unauthorized access to your user account.
{% endhint %}

{% hint style="info" %}
**Effects of disabling 2FA:**

* Any devices setup with the QR code for your account will no longer be able to produce valid OTP tokens.
  {% endhint %}

You have to enter your current password to disable two-factor authentication.

<figure><img src="/files/ehx25gxrKW8zEU47RSaH" alt=""><figcaption><p>2FA disable screen.</p></figcaption></figure>

Type your password and click **Disable**.


# PHP

Code Execution Monitoring for PHP scripts and applications.

### Introduction

The Inspector PHP package sends performance metrics and errors to your Inspector account. It has  a simple API which allows you to instrument any application or PHP script.

### How does the package works?

The package can be used to wrap your application execution cycles to measure their duration and metadata (like the DB statements), as well as HTTP related information (like the URL, parameters, headers, etc).

These events, called Transactions and Segments, are sent to our ingestion API. Our data ingestion system  converts and store them to provides you with insights into latency issues and error culprits within your application.

{% hint style="info" %}
This package can be used as dependency to develop frameworks' specific integration as we did for [Symfony](/guides/symfony) and [Laravel](/guides/laravel).
{% endhint %}

### Useful Links

* Website: <https://www.inspector.dev>
* Blog: <https://www.inspector.dev/blog>
* GitHub repository: <https://github.com/inspector-apm/inspector-php>


# Installation & Set Up

Connect your application with Inspector.

### Server requirements

* PHP >= 8.1

### Install

You can install Inspector using composer:

```bash
composer require inspector-apm/inspector-php
```

### Create an Inspector instance

Be sure to include the composer autoload in your application. The first step is to create an instance of the **`Configuration`** class using the Ingestion Key.

```php
<?php

use Inspector\Inspector;

require __DIR__ . '/../vendor/autoload.php';

$inspector = Inspector::create('YOUR_INGESTION_KEY');
```

{% hint style="info" %}
&#x20;Get a new Ingestion Key by signing up for Inspector (<https://app.inspector.dev/register>) and creating a new application.
{% endhint %}

### Transactions

All start with a `transaction`. A Transaction represents an execution cycle and it can contains one or hundreds of segments (database queries, internal functions, etc.).

You need to start a new Transaction as soon as possible in your application execution cycle to better represent the time your script takes to fulfill an HTTP request.

Typically the transaction should be started in the entry point of your application e.g. **`index.php`**

```php
$pathInfo = explode('?', $_SERVER["REQUEST_URI"]);
$path = array_shift($pathInfo);


/*
 * A transaction should start as soon as possible, 
 * typically in the "index.php" file of your application.
 */
$inspector->startTransaction($path)
    ->markAsRequest();


// Continue with the script...
```

### Set the Transaction result

When your application return a response back to the client you can setup the result of the transaction using the HTTP code:

```php
$inspector->transaction()->setResult(200);
```

### Add Context

Each transaction can be enriched with additional information to have a more complete picture of the process execution context.

You can use the `addCotext` method to attach new tabs to the current Transaction:

```php
$inspector->transaction()?->addContext('label', ['foo' => 'bar']);
```

Contextual information will be reported as additional tabs in the Transaction view. This code example creates a new tab "Label" in the Transaction details as showed in the image below:

<figure><img src="/files/-MUVVqCY1H7-N13XiubW" alt=""><figcaption></figcaption></figure>

The context is designed to help developers easily collect custom data during an execution cycle.

### Make Inspector available in your application globally

If you want to use the current Inspector instance inside your code to add contexual information or new segments, you need a way to make the Inspector instance available everywhere in your application.&#x20;

Use an IoC container like [PHP-DI](https://php-di.org/) is a common way to distribute internal services inside an application. If your application has one, or implement other similar strategies, you could put the Inspector instance in the registry:

```php
$container->set('inspector', $inspector);
```

in order to use it later inside your application (e.g. add segments):

```php
class UserController extends BaseController
{
    /**
     * Example of how to get the Inspector instance from a container.
     */
    public function action()
    {
        // Get the instance from the container.
        $inspector = $container->get('inspector');
    
        // Add a new segment to monitor an action.
        return $inspector->addSegment(function () {
            
            return $this->someService->action();
        
        }, 'someService', 'action');
    }
}
```

### Register callbacks

Using the `beforeFlush()` static method you can register a list of callbacks that will be executed just before data are sent out of your application.

This method provides a simple hook to interact with your monitoring data at the end of the transaction execution.

```php
Inspector::beforeFlush(function (\Inspector\Inspector $inspector) {
    // Do something
});
```

You can also register multiple callbacks that will be executed in the same order:

```php
// First
Inspector::beforeFlush(function (\Inspector\Inspector $inspector) {
    // Do something
});

// Second
Inspector::beforeFlush(function (\Inspector\Inspector $inspector) {
    // Do something
});

// Last
Inspector::beforeFlush(function (\Inspector\Inspector $inspector) {
    // Do something
});
```

By explicitly returning `FALSE` from a callback, the current transaction will not be sent to the remote platform, regardless of the value returned by other callbacks:

```php
Inspector::beforeFlush(function (\Inspector\Inspector $inspector) {
    if ($inspector->transaction()->name === 'GET /api') {
        return false; // <- Do not send data to the remote platform.
    }
});
```


# Custom Segments

Monitor custom code blocks inside your application.

### Add Segments (short form)

This is the most easy way to wrap a code block into a segment:

```php
$inspector->addSegment(function () {
    
    // Code block that you want add to the transaction timeline.
    // DB queries, http calls, etc.
    
}, 'type', 'label');
```

The code block inside the callback will be transparently executed, and your script will continue its execution normally. Inspector will works under the hood to profile execution performance.

Here is an example of how the segment will appear in the timeline:

![A new segment in the transaction's timeline](/files/-LuWgbN9J5ftiM5TDO2T)

As showed in the code example above a new segment is built with two input parameters:

| Parameter | Required | Description                                                                                                             |
| --------- | -------- | ----------------------------------------------------------------------------------------------------------------------- |
| type      | YES      | This is the master category of your segment                                                                             |
| label     | NO       | Human readable label or specific task's name that will be used as label during visualization. Otherwise `type` is used. |

Think about how database queries is reported. There is one master category like `mysql` but each query has its own custom label that simply is an extract of the sql code.

* **mysql**: master type
* **select \* from table**: task label

In this way you can mark toghether statements related to the same topic or service, using something like `mysql` as type parameter and use the `specific query string` as label for a better timeline visualization.

This also increase your ability to filter data in the dashboard.

### Get return

What you return from the callback will be returned back by `addSegment()` method:

```php
// $response will contain "true"
$response = $inspector->addSegment(function () {
    
    // Your code block here
    return true;
    
}, 'type', 'label');
```

### Add Segments (extended code)

You can use `startSegment()` method on the Inspector instance to manually control the monitoring of a code block:

```php
/* 
 * Create a new "segment" that will be automatically attached 
 * to the current transaction.
 */
$segment = $inspector->startSegment('type', 'label');

try {

    /*
     * Here is your code
     */

} catch(UnauthorizedException $exception) {

    /*
     * Report the exception to Inspector for diagnosis purpose.
     */
    $inspector->reportException($exception);
    
} finally {
    /*
     * Close the code block with end() method to stop monitoring.
     */
    $segment->end();
}
```

As you can see in the example above we use `try/catch/finally` to be sure that your code block is monitored in a consistent way.

Or you can use the `addSegment()` method that implements this strategy for you as seen above:

```php
$inspector->addSegment(function () {
    
    /*
     * Write here your code block
     */
     
}, 'type', 'label');
```

![](/files/-LuWgbN9J5ftiM5TDO2T)

## Segments tips and tricks

It may happen that you aren't able to wrap directly a specific statement, so it might be useful to add a segment after the task has been executed. Like the hook to listen the execution of database queries by an ORM.&#x20;

When you hook the **saved** event, the query has already been executed.

In this case you can create the segment later passing the start time in the `start()` method, and the duration in the `end()` method, as shown in the example below:

```php
/*
 * Http call to an external url has been perfromed with this result.
 */
$url = 'https://www.inspector.dev';
$duration_ms = 10; // Duration in milliseconds

/** 
 * -----------------------------------------
 * Create the segment manually setting timing information after the execution.
 * -----------------------------------------
 */

// convert duration in seconds
$timespamp_start = microtime(true) - ($duration_ms/1000) 

$inspector->startSegment('api', $url)
    ->start($timespamp_start)
    ->end($duration_ms);
```

### Access the Inspector instance

If you are using a framework like Laravel or Symfony, you have to access the current Inspector instance to call the `addSegment()` method. Check it out on their specific documetation:

* [**Laravel**](https://docs.inspector.dev/guides/laravel/installation#access-the-inspector-instance)
* [**Symfony**](https://docs.inspector.dev/symfony/intallation#access-the-inspector-instance)
* [**CodeIgniter**](https://docs.inspector.dev/guides/codeigniter/configuration#access-the-inspector-instance)


# Exceptions Monitoring

Catch a real-time diagnosis of your application's exceptions.

### Manual reporting

Inspector allows you to report exceptions manually if you want be aware of it but you don't want to block the execution of your code:

```php
try {

    /*
     * Your dangerous code here.
     */

} catch (\Exception $exception) {
    // Report an exception intentionally to collect diagnostics data
    $inspector->reportException($exception);
}
```

If something goes wrong in your code you will be alerted in real time in your inbox and the exception will be monitored for all subsequent occurrences.

### Use PHP global handler

In alternative you can use the PHP global exceptions handler to be sure that any unhandled exception will be reported in your Inspector dashboard:

```php
set_exception_handler(function (Throwable $exception) use ($inspector) {
    
    // Other exception management tasks...
    
    $inspector->reportException($exception);
    
});
```

### Exception monitoring

When an exception is detected you can read the code inside the stacktrace, and monitor its occurrences frequency for a better investigation:

![Exception details](/files/-MAWEXMt8Tg2LQs0RmAB)

{% hint style="success" %}
Activate the AI Bug Fix to receive code change proposals for faster resolution: <https://docs.inspector.dev/concepts/ai-bug-fixer>
{% endhint %}


# Configuration

Customize the package behaviour.

As you could see in installation instructions, our package include a `Configuration` class that contains the options to customize the package's behaviour.

```php
// Create a configuration instance.
$configuration = new Configuration('YOUR_INGESTION_KEY');

// Pass the configuration to the Inspector constructor.
$inspector = new Inspector($configuration);
```

You can use the following variables to determine how Inspector will collect information in your application:

| Option         | Type     | Default | Description                                                                                 |
| -------------- | -------- | ------- | ------------------------------------------------------------------------------------------- |
| ingestion\_key | string   |         | Your application key to identify your project in Inspector.                                 |
| enabled        | boolean  | true    | Enable/Disable data transfer from your app to the inspection API.                           |
| max\_items     | integter | 100     | How many segments could be included in a single transaction. More segments will be ignored. |

```php
$configuration = new Configuration('YOUR_INGESTION_KEY');
$configuration->setEnabled(true);
$configuration->setMaxItems(500);
```


# Laravel / Lumen

Code Execution Monitoring for Laravel applications.

### Introduction

This package automatically instruments a Laravel application and records performance metrics about HTTP requests, DB queries, Jobs, Commands and more. It also has  a simple API which allows you to monitor any code block in your application.

### How does the package works?

The package wraps application execution cycles to measure their duration and metadata (like the DB statements), as well as HTTP-related information (like the URL, parameters, headers, etc).

These events, called Transactions and Segments, are sent to our ingestion API where they will be processed and stored to provide you with insights into latency issues and error culprits within your application.

The first step is to install the Inspector Laravel package:

{% content-ref url="/pages/-LuWkBbdtWOmvSwaKx3X" %}
[Installation & Set-up](/guides/laravel/installation)
{% endcontent-ref %}

### Resources

* Website: <https://www.inspector.dev>
* Blog: <https://www.inspector.dev/blog>
* GitHub repository: <https://github.com/inspector-apm/inspector-laravel>


# Upgrade Guide

Upgrading to 4.0 from 2.x or 3.x

**Estimated Upgrade Time: Five Minutes**

{% hint style="warning" %}
We attempt to document every possible breaking change. Since some of these breaking changes are in hidden parts of the library only a portion of these changes may actually affect your application.
{% endhint %}

### Updating dependencies

Update your `inspector-apm/inspector-laravel` dependency to `^4.4` in your `composer.json` file.

Update packages in your application by:

```
composer update
```

### Change Inspector URL

The url of Inspetor ingestion system was changed a few month ago, so if you have published the `inspector.php` configuration file in the config directory be sure that the `url` parameter is set to: **<https://ingest.inspector.dev>**

**Change the env viariable name**

In the previous package version you have installed the KEY to enable data transfer from your server to Inspector API in the application's environment file:

```
INSPECTOR_API_KEY=xxx
```

The name of this environment variable was changed as `INSPECTOR_INGESTION_KEY`, so be sure to change the `.env` file as below:

```
INSPECTOR_INGESTION_KEY=xxx
```

### What's new

* [**A redesigned version of our Middleware**](/guides/laravel/http-requests-monitoring#ignore-web-requests) to provide better support for http requests ignoring.
* [**Ignore Jobs**](https://docs.inspector.dev/platforms/laravel/configuration#ignore-transactions-command-url-jobs)


# Installation & Set-up

Connect your Laravel application with Inspector.

### Server requirements

* PHP >= 8.1
* Laravel >= 9.0

To verify what version of PHP is installed on your server run this command in your terminal:

```
php -v
```

To know what is the Laravel version behind your application run this command in your application's main directory:

```
php artisan --version
```

### Clear the Laravel configuration

Before installing the package you should clear your Laravel configuration&#x20;to avoid unexpected error loading the default package config file.

Run the command below to clear your cached configuration:

```
php artisan config:clear
```

### Install

Type the command below in your terminal to install the latest version of the package:

```
composer require inspector-apm/inspector-laravel
```

### For Lumen

If your application is based on Lumen you need to manually register the `InspectorServiceProvider`:

```php
$app->register(\Inspector\Laravel\InspectorServiceProvider::class);
```

If you wish to use the `\Inspector\Laravel\Facades\Inspector` facade, you should also enable facades if you did not already by uncommenting the `withFacades()` call in `bootstrap/app.php`:

```php
$app->withFacades();
```

### Configure the Ingestion Key

Get a new Ingestion Key by signing up for Inspector (<https://app.inspector.dev/register>) and creating a new application.

Put the Inspector Ingestion Key in your environment file:

```
INSPECTOR_INGESTION_KEY=[ingestion key]
```

### Test everything is working

Execute the test command to check if your app can send data to inspector correctly:

```php
php artisan inspector:test
```

Go to [`https://app.inspector.dev`](https://app.inspector.dev/home) to explore your data.

By default Inspector will monitor everything executed in background:

* Queued Jobs
* Artisan commands
* Unhandled Exceptions

{% hint style="info" %}
If you want learn more about background jobs monitoring take a look on our article: <https://www.inspector.dev/laravel-background-jobs-commands-monitoring-with-inspector/>
{% endhint %}

Go the [Http Request Monitoring](/guides/laravel/http-requests-monitoring) section to understand how to trace your application when it's executed due to an incoming http request.

### Reporting Out Of Memory Errors

When your app runs out of memory, it needs to temporarily increase the PHP memory limit to ensure Inspector can report the current transaction. To do this, a “bootstrapper” class must be registered in both the `app/Http/Kernel.php` and `app/Console/Kernel.php` files:

```php
protected function bootstrappers()
{
    return array_merge(
        [\Inspector\Laravel\OutOfMemoryBootstrapper::class],
        parent::bootstrappers(),
    );
}
```

The `OutOfMemoryBootstrapper` must be the first registered bootstrapper, or it may not be called before the out of memory exception crashes your app.

### Scheduled Jobs

Laravel allows you to execute jobs as cron tasks. Here is an example of an entry in the Laravel scheduler:

```php
$schedule->job(ProcessAudioFiles::class)->everyFifteenMinutes();
```

To allow Inspector to correctly monitor the scheduled job you must be sure that the job class implements the `Illuminate\Contracts\Queue\ShouldQueue` interface:

```php
namespace App\Jobs;

use Illuminate\Contracts\Queue\ShouldQueue;

class ProcessAudioFiles implements ShouldQueue 
{
    ...
}
```

Since Laravel internally runs a closure to dispatch the job onto the queue, you need to add the class name of the job in the `ignore_commands` configuration property in the `inspector.php` configuration file to filter out the execution of this closure from the monitoring dashboard.

```php
/*
|--------------------------------------------------------------------------
| Artisan command to ignore
|--------------------------------------------------------------------------
|
| Add at this list all command signature that you don't want monitoring
| in your Inspector dashboard.
|
*/

'ignore_commands' => [
    ...,
    \App\Jobs\ProcessAudioFiles::class,
],
```

### Before flush callback

The package allows you to register a callback before data are sent to the remote platform. Paste the code below in the `boot` method of your `AppServiceProvider`:

```php
use Inspector\Laravel\Facades\Inspector as InspectorFacade;
use Inspector\Inspector;

InspectorFacade::beforeFlush(function (Inspector $inspector) {
    // Do something before data are sent.
});
```

The callback will receive the current Inspector instance as parameter.

For more detailed instruction on how to use the beforeFlush method take a look at the [**PHP documentation**](https://docs.inspector.dev/guides/raw-php/installation#register-callbacks).

#### Sampling a specific transaction

The most common use case for `beforeFlush` method is sampling. If your application execute a specific transaction for a huge number of times every hour, it could be useful to sample this transasction to mitigate the quota consumption still guaranteeing a good level of detail of the metrics.

In the example below we report only the 70% of the `GET /healthceck` endpoint calls:

```php
<?php

namespace App\Providers;

use App\Jobs\ExampleJob;
use Illuminate\Support\ServiceProvider;
use Inspector\Laravel\Facades\Inspector;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Inspector::beforeFlush(function ($inspector) {
            if ($inspector->transaction()->name === 'GET /healthceck') {
                $prob = mt_rand(0, mt_getrandmax() - 1) / mt_getrandmax();
                
                return $prob < 0.7; // Report 70% of the times
            }
        });
    }
}
```

You can do the same with Jobs using the fully qualified class name of the job in the IF statement:

```php
if ($inspector->transaction()->name === ExampleJob::class) {
    $prob = mt_rand(0, mt_getrandmax() - 1) / mt_getrandmax();
               
    return $prob < 0.7; // Report 70% of the times
}
```

#### Set a custom service name

If your application runs in Kubernetes cluster or use "auto-scaling" you could see a bit of mess in your charts. It is probably due to the constant turnover of servers to handle the application load dynamically.

It may be useful to monitor each autoscaling group with the same name regardless of the hostnames of the servers that are continuously turned on and off.

Using the `beforeFlush()` method you can group your monitoring data by services (API, workers, web app, etc) instead by hostnames:

```php
<?php

namespace App\Providers;

use App\Jobs\ExampleJob;
use Illuminate\Support\ServiceProvider;
use Inspector\Laravel\Facades\Inspector;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Inspector::beforeFlush(function ($inspector) {
            $inspector->transaction()
                ->host
                ->hostname = config('app.service_name')??'rest-api'
        });
    }
}
```

In the example above you can get your service name by a custom configuration property, or alternatively you could create an environment variable. You are free to configure it based also on your CI/CD pipelines.

### Access the Inspector instance

You can get the current Inspector instance using the helper function or the Facade:

```php
/*
 * Using the helper function
 */
inspector()->addSegment(function () {
    // Do something
}, 'label');



/*
 * Using the Facade
 */
\Inspector\Laravel\Facades\Inspector::addSegment(function () {
    // Do something
}, 'label');
```

The current Inspector instance is binded in the Laravel service container. In your controller, you can type-hint an argument with the Inspector's class name.

```php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Inspector\Laravel\Inspector;

class HomeController extends Controller
{
    /**
     * Show the application dashboard.
     *
     * @return \Illuminate\Contracts\Support\Renderable
     */
    public function index(Inspector $inspector)
    {
        return view('home');
    }
}
```


# Http Requests Monitoring

Monitor your application behaviour during incoming http requests.

### Introduction

To activate inspection when your application is executed by an incoming http request you can use the `WebRequestMonitoring` middleware.&#x20;

Thanks to the middleware you are free to decide on which routes you want activate monitoring, based on your routes configuration or on your personal monitoring preferences.  `WebRequestMonitoring` middleware works like any other Laravel middleware you are familiar to.

{% hint style="info" %}
If you use Laravel Octane to serve your application you should use the specialized middleware instead. [**Go to the Octane integration guide**](/guides/laravel/laravel-octane).
{% endhint %}

### Option 1 - Append to the middleware groups (recommended)

#### Laravel >=11

You should append the Inspector middleware in the `bootstrap/app.php` file for `web` and `api` middleware groups, so in two lines of code you'll intercept all incoming http requests:

{% code title="boostrap/app.php" lineNumbers="true" %}

```php
use \Inspector\Laravel\Middleware\WebRequestMonitoring;

return Application::configure(basePath: dirname(__DIR__))
    ->withMiddleware(function (Middleware $middleware) {
        // Append the middleware
        $middleware->appendToGroup('web', WebRequestMonitoring::class)
            ->appendToGroup('api', WebRequestMonitoring::class);
    })
    ->create();
```

{% endcode %}

#### Previous Laravel versions (<= 10)

For previous Laravel version up to 10 you should append the Inspector middleware to the middleware gourps in the `App\Http\Kernel` class:

{% code title="" %}

```php
/**
 * The application's route middleware groups.
 *
 * @var  array
 */
protected $middlewareGroups = [
    'web' => [
        ...,
        \Inspector\Laravel\Middleware\WebRequestMonitoring::class,
    ],

    'api' => [
        ...,
        \Inspector\Laravel\Middleware\WebRequestMonitoring::class,
    ]
]
```

{% endcode %}

### Option 2 - Assigning middleware to routes

In alternative you can assign the middleware to specific routes or group:

```php
/*
 * Attach the "inspector" middleware in your routes
 */
Route::middleware(\Inspector\Laravel\Middleware\WebRequestMonitoring::class)
    ->group(function () {
        // Monitored routes here
    });
```

### Ignore Http Requests

{% hint style="info" %}
Basic ignoring logic is supported by default via a simple configuration parameter. [**Learn more here**](https://docs.inspector.dev/guides/laravel/configuration#ignore-urls).
{% endhint %}

If you need to implement a custom logic to ignore requests, the middleware is also designed to be extended.

Overwriting the `shouldRecorded()` method, you can implement a custom condition to decide which routes should be ignored by Inspector.&#x20;

Run the artisan command below to create a new middleware class:

```php
php artisan make:middleware InspectorMonitoringMiddleware
```

In the new middleware class extend the Inspector middleware and override the `shouldRecorded()` method to implement your condition. Return back a boolean value to enable or disable monitoring:

```php
use \Inspector\Laravel\Middleware\WebRequestMonitoring;

class InspectorMonitoringMiddleware extends WebRequestMonitoring
{
    /**
     * Determine if Inspector should record current request.
     *
     * @param \Illuminate\Http\Request $request
     * @return bool
     */
    protected function shouldRecorded($request): bool
    {
        // Only requests from your IP addresses should be recorded
        return in_array($request->ip(), ['xxx.xxx.xxx.xxx']);
    }
}
```

Returning `true` the current http request will be recorded in your dashboard, returning `false` the transaction will be completely ignored.

The last step is to use this new custom middleware instead of the original Inspector middleware.

#### Laravel >=11

{% code title="bootstrap/app.php" %}

```php
use App\Http\Middleware\InspectorMonitoringMiddleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        // routes
    )
    ->withMiddleware(function (Middleware $middleware) {
        // Append the custom middleware
        $middleware->appendToGroup('web', InspectorMonitoringMiddleware::class)
            ->appendToGroup('api', InspectorMonitoringMiddleware::class);
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();
```

{% endcode %}

#### Previosu Laravel version (<= 10)

{% code title="app/Http/Kernel.php" %}

```php
use App\Http\Middleware\InspectorMonitoringMiddleware;

/**
 * The application's route middleware groups.
 *
 * @var  array
 */
protected $middlewareGroups = [
    'web' => [
        ...,
        //\Inspector\Laravel\Middleware\WebRequestMonitoring::class,
        InspectorMonitoringMiddleware::class,
    ],

    'api' => [
        ...,
        //\Inspector\Laravel\Middleware\WebRequestMonitoring::class,
        InspectorMonitoringMiddleware::class,
    ]
]
```

{% endcode %}

### Hide sensible contents

You may hide sensible data from HTTP requests body and Headers like passwords, authorization token, etc. Inspector is able to detect that parameters in your request's content masking them with "\*\*\*\*\*\*".

Simply add fields to the `hidden_parameters` array in the in inspector config file:

```php
'hidden_parameters' => [
    'password',
    'password_confirmation',
    'Authorization',
    
    // Other fields here...
],
```

You can specify nested fields using the dot notation like `user.password`

### MCP server monitoring

If you are exposing an MCP server to make AI Agents able to interact with it, you could be interested in measuring it's usage and performance. To do this you can use the `MCPRequestMonitoring` middleware that capture the underlying MCP object the client is requesting allowing you to have full visbility into your MCP server operations.

Use the middleware in the `routes/ai.php` file on the MCP servers you are exposing:

```php
<?php

use Inspector\Laravel\Middleware\McpRequestMonitoring;
use App\Mcp\MyServer;
use Laravel\Mcp\Facades\Mcp;

/*
 * Provide monitoring data to coding agents.
 */
Mcp::web('/mcp', MyServer::class)
    ->middleware([
        'auth:api',
        'throttle:mcp',
        McpRequestMonitoring::class, // <-- The monitoring middleware here
    ]);
```


# Configuration

Customize the monitoring strategy in your Laravel application.

If you want full control of the package behaviour publish the configuration file:

```
php artisan vendor:publish --provider="Inspector\Laravel\InspectorServiceProvider"
```

This comand will create the `config/inspector.php` file.

### Environment Variables

You can use the following environment variables to determine how Inspector will collect information for your application:

<table><thead><tr><th>Variable</th><th>Type</th><th width="138">Default</th><th>Description</th></tr></thead><tbody><tr><td>INSPECTOR_API_KEY</td><td>string</td><td></td><td>Your application key to identify uniquely your application in Inspector.</td></tr><tr><td>INSPECTOR_ENABLE</td><td>boolean</td><td>true</td><td>Enable/Disable data transfer from your app to Inspection API.</td></tr><tr><td>INSPECTOR_TRANSPORT</td><td>string</td><td>async</td><td>Tha way the package sends data to the inspection API. <code>sync</code> (using php curl extension), <code>async</code> (in a background process)</td></tr><tr><td>INSPECTOR_MAX_ITEMS</td><td>integer</td><td>100</td><td>Max numebr of items recorded during an execution cycle.</td></tr><tr><td>INSPECTOR_QUERY</td><td>boolean</td><td>true</td><td>Determine if you want to report database queries.</td></tr><tr><td>INSPECTOR_QUERY_BINDINGS</td><td>boolean</td><td>false</td><td>Determine if you want to report binding values for queries.</td></tr><tr><td>INSPECTOR_USER</td><td>boolean</td><td>true</td><td>Determine if you want to attach user information in your events.</td></tr><tr><td>INSPECTOR_EMAIL</td><td>boolean</td><td>true</td><td>Determine if you want to report emails.</td></tr><tr><td>INSPECTOR_NOTIFICATIONS</td><td>boolean</td><td>true</td><td>Determine if you want to report notifications.</td></tr><tr><td>INSPECTOR_JOB</td><td>boolean</td><td>true</td><td>Determine if you want to report queued jobs execution.</td></tr><tr><td>INSPECTOR_JOB_DATA</td><td>boolean</td><td>true</td><td>Determine if you want to report the data field of the job payload.</td></tr><tr><td>INSPECTOR_VIEWS</td><td>boolean</td><td>true</td><td>Determine if you want to report views rendering stats.</td></tr><tr><td>INSPECTOR_UNHANDLED_EXCEPTIONS</td><td>boolean</td><td>true</td><td>Determine if you want to report unhandled exception fired in your application.</td></tr><tr><td>INSPECTOR_REDIS</td><td>boolean</td><td>true</td><td>Determine if you want to report redis command.</td></tr><tr><td>INSPECTOR_HTTP_CLIENT</td><td>boolean</td><td>true</td><td>Determine if you want to report Http requests done using the Laravel Http Client</td></tr><tr><td>INSPECTOR_<em>HTTP_</em>CLIENT_BODY</td><td>boolean</td><td>true</td><td>Determine if you want to report Http client response body</td></tr></tbody></table>

### Master Switch

If desired, you may disable data transfer setting to `false` the `enable` configuration option:

```
'enable' => env('INSPECTOR_ENABLE', true),
```

## Ignore Urls, Commands, Jobs

Not all transactions need to be monitored in your application. Think about a Laravel Nova admin panel that is built for internal use and aren't reachable by users. Or the Livewire internal HTTP requests that arent related to your business logic.

You have many options to keep off the noise and only monitor what metter.

{% hint style="info" %}
To add these customizations, you need to publish the `inspector.php` configuration file. You can do it with the command below:&#x20;

`php artisan vendor:publish --provider="Inspector\Laravel\InspectorServiceProvider"`
{% endhint %}

### Ignore URLs

It could be necessary to turn off monitoring based on **url.** Think about paths like `/nova`, `/telescope`, or other parts of your app that don't affect the user experience.

You can also use the wildcard character `*` to exclude all sub-paths.

```php
/*
 |---------------------------------------------------------------------
 | Web request url to ignore
 |---------------------------------------------------------------------
 |
 | Add at this list the url schemes that you don't want monitoring
 | in your Inspector dashboard. You can also use wildcard expression (*).
 |
 */
 
'ignore_url' => [
    'telescope*',
    'vendor/telescope*',
    'horizon*',
    'vendor/horizon*',
],

```

### Ignore Commands

You can ignore artisan commands by adding the command signature to the `ignore_commands` parameter in the `config/inspector.php` configuration file.

```php
/*
 |---------------------------------------------------------------------
 | Artisan command to ignore
 |---------------------------------------------------------------------
 |
 | Add at this list all command signature that you don't want monitoring
 | in your Inspector dashboard.
 |
 */
 
'ignore_commands' => [
    'migrate:rollback',
    'migrate:fresh',
    'migrate:reset',
    'migrate:install',
    'package:discover',
    'queue:listen',
    'queue:work',
    'horizon',
    'horizon:work',
    'horizon:supervisor',
],
```

### Ignore Jobs

You can also ignore **background jobs** adding classes to the `ignore_jobs` property:

```php
/*
|--------------------------------------------------------------------------
| Job classes to ignore
|--------------------------------------------------------------------------
|
| Add at this list the job classes that you don't want monitor.
|
*/

'ignore_jobs' => [
    //\App\Jobs\MyJob::class
],
```


# Exception Monitoring

Laravel error tracking

{% hint style="info" %}
**By default, every unhandled exception will be reported automatically to be sure you'll be alerted for unpredictable errors in real time.**
{% endhint %}

Inspector allows you to report exceptions manually if you want to be aware of it, but you don't want to block the execution of your code:

```php
try {

    // Your code statements here...

} catch(LogicException $exception) {
    // Report an exception intentionally to collect diagnostics data
    inspector()->reportException($exception);
}
```

If something goes wrong in your code you will be alerted in real time in your inbox and the exception will be monitored for all subsequent occurrences.

### Exception monitoring

When an exception is detected you can read the code inside the stacktrace, and monitor its occurrences frequency for a better investigation:

![Exception details](/files/-MAWEXMt8Tg2LQs0RmAB)

{% hint style="success" %}
Activate the AI Bug Fix to receive code change proposals for faster resolution: <https://docs.inspector.dev/concepts/ai-bug-fixer>
{% endhint %}


# Livewire

Monitor Livewire components execution and state

### Requirements

* Livewire 3.x

### The Problem

Livewire is a full-stack framework in Laravel that makes it easy to create reactive interfaces without writing any Javascript, just using PHP.

After the initial rendering of the page containing the Livewire component, Livewire binds some javascript event listeners to its components and watches for every action. Each action is sent to the server as an asynchronous API request.

<figure><img src="/files/QgDfRQVXpF2MaddhWdeh" alt=""><figcaption></figcaption></figure>

When the user clicks on a button in the UI, Livewire makes a network request to the server to interact with the PHP component associated. Take a look at the example below that implement a simple counter:

{% code title="resources/views/livewire/counter.blade.php" %}

```html
<div>
    <h1>{{ $count }}</h1>
 
    <button wire:click="increment">+</button>
 
    <button wire:click="decrement">-</button>
</div>
```

{% endcode %}

{% code title="app/Livewire/Counter.php" %}

```php
class Counter extends Component
{
    public $count = 1;

    public function increment() {
        $this->count++;
    }

    public function decrement() {
        $this->count--;
    }

    public function render()
    {
        return view('livewire.counter');
    }
}
```

{% endcode %}

Every click on the counter button generates an HTTP request handled by the associated PHP component. And this happen for all UI component you have in the user interface.&#x20;

All these HTTP requests are routed to the default Livewire URL: `/livewire/update`

That's why you see tons of requests to the endpoint **"POST /livewire/update"** in your Inspector monitoring dashboard. So, everything under `/livewire/update` it's like a grey area, because you don't have any clue of what component is behing executed, what is its state, etc.

### Inspector Configuration

To solve this problem the Inspector Laravel package includes a specifc configuration to monitor Livewire components.

When the user interact with Livewire components a dedicated transaction category, *livewire*, will now appear in the Inspector dashboard:

<figure><img src="/files/IAzPMqtK1lteP9sOprcZ" alt=""><figcaption></figcaption></figure>

As you can see, the transaction name is the name of the component class. This way, you'll have all the components monitored individually.

From the individual component's detail page, you can access the history of every time that component has been run. Any exceptions will also be attached to the component's transaction, so everything remains clear.

### Ignore Components

You can exclude components from being reported on Inspector listing the component classes in the `inspector.livewire.ignore_components` configuiration property:

```php
'livewire' => [
    ...
    'ignore_components' => [
        // \App\Livewire\MyComponent::class
    ],
],
```

### Livewire Path

In order to make Inspector able to recognize the execution of livewire components instead of normal HTTP requests you should keep in sync the Livewire URL with the Inspector configuration. The Livewire URL is customizable, so if you use a custom path instead of the default one, you should change the Inspector configuration accordingly:

```php
'livewire' => [
    ...
    'path' => env('INSPECTOR_LIVEWIRE_PATH', '/livewire/update'),
    ...
],
```


# Laravel Vapor

How to make Inspector works on Laravel Vapor.

{% hint style="warning" %}
When using Vapor you have to enable the "**serverless**" flag in the Application Settings.
{% endhint %}

### Use the default Vapor runtime

Behind the scene, Inspector uses `curl` to send data from your application to the monitoring system. In the default Vapor runtime curl is available in custom path, so you need to let the package know this path to properly build the curl command to send the data.

The package has an option for this configuration. You just need to publish the Inspector configuration file using the command below:

```
php artisan vendor:publish --provider="Inspector\Laravel\InspectorServiceProvider"
```

After publishing the `config/inspector.php` file you can customize the curlPath field in the "options" property:

```php
/*
 |--------------------------------------------------------------------------
 | Custom transport options
 |--------------------------------------------------------------------------
 |
 | This is where you can set the transport option settings you'd like us to use when
 | communicating with Inspector.
 |
 */

'options' => [
    'curlPath' => '/opt/bin/curl --cacert /opt/lib/curl/cert.pem',
],
```

#### Test and Deploy

You can run the test command to verify everything is well configured before deploy in production:

```sh
php artisan inspector:test
```

### Use Docker runtime

Docker based runtimes offer much more control over the execution environment, so you can deploy applications up to 10GB in size and allow you to install additional PHP extensions or libraries.

In order to use a Docker image instead of the Vapor native runtimes, set the `runtime` configuration option to `docker` within your `vapor.yml` file:

{% code lineNumbers="true" %}

```yaml
id: 2
name: vapor-laravel-app
environments:
    production:
        runtime: docker # Use docker as runtime environment
        build:
            - 'composer install --no-dev'
```

{% endcode %}

{% hint style="info" %}
Learn more about [Docker runtime](https://docs.vapor.build/1.0/projects/environments.html#docker-runtimes) in Vapor.
{% endhint %}

To make Inspector works you must be sure that the current PHP installation in the Docker image has *proc\_open*, and *proc\_close* native functions enabled.

The default Docker runtime should have these functions enabled by default. In alternative you need to create a custom `php.ini` file in your project root directory with these two functions not listed in the *disable\_functions* parameter:

{% code title="php.ini" %}

```ini
disable_functions=exec,passthru,shell_exec,system,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
```

{% endcode %}

Add the entry below in your environment `.Dockerfile` to override the default `php.ini` configuration:

{% code title="environment.Dockerfile" %}

```docker

# Update the `php.ini` file...
# Requires a `php.ini` file at the root of your project...
COPY ./php.ini /usr/local/etc/php/conf.d/overrides.ini

```

{% endcode %}

Now you can continue installing the library as usual: <https://docs.inspector.dev/guides/laravel/installation>

### Increase ulimits

Ulimit is a Unix property used to set the number of open file descriptors for each process. It is also used to set restrictions on the resources used by a process. If the load on your application starts to increase due to background jobs, commands, or requests you could easily hit this limit for the underlying docker container behind your Vapor environment.

To increase this limit you can add `ulimits` section to the `vapor.yml` file for both production and staging environments.

```yaml
services:
  frontend:
    build:
      context: .
      ulimits:
        nproc: 65535
        nofile:
          soft: 65535
```

Following this documentation on the docker <https://docs.docker.com/reference/compose-file/build/#ulimits>


# Laravel Octane

Monitor a Laravel application served by Octane

By defaults Inspector registers a shutdown function to transfer data from your application to Inspector at the end of each request lifecycle.

Since Octane runs your application in a long-running process, the data transfer must be performed at the end of the HTTP request life cycle.

So instead of using the normal `WebRequestMonitoring` middleware, you should attach to your routes the Octane specialized middleware.

### Configure the Octane middleware

Register the `InspectorOctaneMiddleware` class instead of `WebRequestMonitoring`:

#### Laravel 11

```php
use \Inspector\Laravel\Middleware\InspectorOctaneMiddleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        // routes
    )
    ->withMiddleware(function (Middleware $middleware) {
        // Append the middleware
        $middleware->appendToGroup('web', InspectorOctaneMiddleware::class)
            ->appendToGroup('api', InspectorOctaneMiddleware::class);
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();
```

#### Laravel <= 10

```php
/**
 * The application's route middleware groups.
 *
 * @var array
 */
protected $middlewareGroups = [
    'web' => [
        ...,
        //\Inspector\Laravel\Middleware\WebRequestMonitoring::class,
        \Inspector\Laravel\Middleware\InspectorOctaneMiddleware::class,
    ],
    
    'api' => [
        ...,
        //\Inspector\Laravel\Middleware\WebRequestMonitoring::class,
        \Inspector\Laravel\Middleware\InspectorOctaneMiddleware::class,
    ],
]
```

Now Inspector is able to recognize the end of an HTTP requests and monitor your application properly.

{% hint style="info" %}

#### No configuration is needed for artisan commands and background jobs. They will continue to be monitored as usual.

{% endhint %}


# Laravel Nova Tool

Direct link to the Inspector dashboard in your Laravel Nova administration panel.

Based on the API key configured in your *.env* file it lookups your application and open your Inspector dashboard in another tab.

![](/files/n8KDWwv1BHFc5qMfA9hL)

### Install

Install the latest version using composer:

```
composer require inspector-apm/inspector-nova-link
```

### Register the tool

&#x20;Register the tool in your `app/Providers/NovaServiceProvider`:

```php
public function tools()
{
    return [
        ...,
        
        new \Inspector\Nova\InspectorNovaLink,
    ];
}
```

{% hint style="info" %}
Visit the official Nova package page: <https://novapackages.com/packages/inspector-apm/inspector-nova-link>
{% endhint %}


# Group by service name

Monitor your Laravel application by service name instead of single hostname.

Inspector segments metrics by hostnames. So as the number of underlying hosts increase it could create a bit of clutter in the charts.

It may be more clear to use a human friendly **service name** to represent all your servers inside the same logical group.

<figure><img src="/files/MTlewxkYjZda4qXZ7eYE" alt=""><figcaption></figcaption></figure>

We can use the Inspector library to programmatically change the hostname just before the transaction is sent out of your server and set the same for related instances. It will make your dashboard more clear and understandable.

<figure><img src="/files/Lpy7bRa6i7nkupnz58TA" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Read the step by step guide on our blog: <https://inspector.dev/how-to-monitor-your-laravel-application-by-services-not-by-hostnames/>
{% endhint %}


# Symfony

Code Execution Monitoring for Symfony applications.

### Introduction

The package automatically instrument a Symfony application and records performance metrics about HTTP requests, DB queries, Commands and more. It also has  a simple API which allows you to monitor custom code blocks in your application.

### How does the bundle works?

The bundle wrap your application execution cycles to measure their duration and metadata (like the DB statements), as well as HTTP related information (like the URL, parameters, headers, etc).

These events, called Transactions and Segments, are sent to our ingestion API where they will be processed and stored to provides you insights into latency issues and error culprits within your application.

The first step is to install the Inspector Symfony package:

{% content-ref url="/pages/-MbG5C\_\_wh0oXTXftA8D" %}
[Installation](/guides/symfony/installation)
{% endcontent-ref %}

### Resources

* Website: <https://www.inspector.dev>
* Blog: <https://www.inspector.dev/blog>
* GitHub repository: <https://github.com/inspector-apm/inspector-symfony>


# Installation

Connect your Symfony application to Inspector.

### Requirements

* PHP >= 8.1
* Symfony ^6.0 | ^7.0 | ^8.0

### Install

Type the command below in your terminal to install the latest version of the bundle:

```
composer require inspector-apm/inspector-symfony
```

### Configure the Ingestion Key

Create the `inspector.yaml` configuration file in your `config/packages` directory, and put the `ingestion_key` field inside:

```yaml
inspector:
    ingestion_key: '%env(INSPECTOR_INGESTION_KEY)%'
```

Add the new variable in your production env file:

```bash
INSPECTOR_INGESTION_KEY=xxxxxxxxxxxxxxxxxxx
```

You can obtain the `ingestion_key` creating a new project in your [Inspector](https://app.inspector.dev) dashboard.

{% hint style="info" %}
To learn more about environment variables configuration you can check the [Symfony documentation](https://symfony.com/doc/current/configuration.html#overriding-environment-values-via-env-local).
{% endhint %}

### Test & Deploy

Execute the Symfony command below to check if your app is properly configured and can send data to inspector:

```bash
php bin/console inspector:test
```

Go to [`https://app.inspector.dev/`](https://app.inspector.dev) to explore your data.

Inspector will monitor many components by default:

* HTTP requests
* Console commands
* SQL queries
* Twig views rendering
* Messenger Background Processes

But you have several configuration parameters to customize its behavior. Learn more in the next section.

## Access the Inspector instance

Inspector instance is binded in the Symfony service container. In your controller, you can type-hint an argument with the Inspector's class name to get a concrete Inspector instance.

```php
namespace App\Controller;

use Inspector\Inspector;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;

class ProductController
{
    /**
     * @Route("/invoice")
     */
    public function generateInvoice(Inspector $inspector, Request $request): Response
    {
        $pdf = $inspector->addSegment(function () {
            return $this->createPDF();
        }, 'file', 'Create Invoice PDF');

        return $pdf;
    }
}
```


# Configuration

Customize the monitoring strategy in your Symfony application.

Here is the list of bundle options you can use to customize how Inspector collects data within your application.

### Master Switch

Turn on/off monitoring in your application:

```yaml
inspector:
    ingestion_key: '%env(INSPECTOR_INGESTION_KEY)%'
    
    # True by default
    enabled: false
```

### Track Unhandled Exceptions

Turn on/off the unhandled exceptions reporting:

```yaml
inspector:
    ingestion_key: '%env(INSPECTOR_INGESTION_KEY)%'
    
    # True by default
    unhandled_exceptions: false
```

### Database Query Monitoring

Turn on/off monitoring of database statements:

```yaml
inspector:
    ingestion_key: '%env(INSPECTOR_INGESTION_KEY)%'
    
    # True by default
    query: false
    query_bindings: false
```

`query_bindings` option allows you to collect the content of the parameters binded to a query.

### Symfony Messenger Monitoring

Turn on/off the monitoring of asynchronous jobs scheduled by the Symfony Messenger component:

```yaml
inspector:
    ingestion_key: '%env(INSPECTOR_INGESTION_KEY)%'
    
    # True by default
    messenger: false
```

## Ignore Transactions

There may be parts of the application that you are not interested in monitoring. Maybe they were created for internal use, or for application maintenance, and have no impact on the user experience in production.

Inspector provides you several options to keep off the noise, and only monitor what matters.

### Ignore Routes

You can turn off monitoring based on url. Add the `ignore_routes` option into the `config/packages/inspector.yaml` file to define routes you don't want to monitor:

```yaml
inspector:
    ingestion_key: '%env(INSPECTOR_INGESTION_KEY)%'
    
    ignore_routes:
        - '/admin*' # Also with wildcard
```

### Ignore Commands

You can ignore commands adding the command *defaultName* to the `ignore_commands` collection in the `config/packages/inspector.yaml` file.

```yaml
inspector:
    ingestion_key: '%env(INSPECTOR_INGESTION_KEY)%'
    
    ignore_commands:
        - 'app:create-user'
        - 'app:internal*' # Also with wildcard
```

### Ignore Messenger Messages

You can ignore messages processed in background by adding the message's class to the `ignore_messages` collection in the `config/packages/inspector.yaml` file.

```yaml
inspector:
    ingestion_key: '%env(INSPECTOR_INGESTION_KEY)%'
    
    ignore_messages:
        - 'App\Messenger\Messages\SmsNotification'
        - 'App\Messenger\Messages\EmailInternal*' # Also with wildcard
```

### Transport

Inspector supports two type of strategies to send data from your application to the remote Inspection APIs: `sync` and `async`.

The async strategy is default one, and it basically process data sending in a process completely independent by your application lifecycle so your application will have zero impact in terms of performance.

The async transport requires two PHP native functions enabled: `proc_open`, and `proc_close`.

Sometimes in local environmet you don't have these functions enabled, so you can switch to the sync transport with a simple configuration property:&#x20;

```yaml
inspector:
    ingestion_key: '%env(INSPECTOR_INGESTION_KEY)%'
    
    transport: 'sync'
```


# Exception Monitoring

Symfony error tracking

{% hint style="info" %}
**By default every Unhandled exception will be reported automatically to be sure you'll be alerted for unpredictable errors in real time.**
{% endhint %}

Inspector allows you to report an exception manually if you want to be aware of it, but you don't want to block the execution of your code:

```php
try {

    // Your code statements here...

} catch(LogicException $exception) {
    // Report an exception intentionally to collect diagnostics data
    $inspector->reportException($exception);
}
```

If something goes wrong in your code you will be alerted in real time in your inbox and the exception will be monitored for all subsequent occurrences.

{% hint style="info" %}
For more information about access the Inspector instance in your application take al look on this section: [**Access the Inspector instance**](https://docs.inspector.dev/symfony/intallation#access-the-inspector-instance)
{% endhint %}

### Exception monitoring

When an exception is detected you can read the code inside the stacktrace, and monitor its occurrences frequency for a better investigation:

![Exception details](/files/-MAWEXMt8Tg2LQs0RmAB)

{% hint style="success" %}
Activate the AI Bug Fix to receive code change proposals for faster resolution: <https://docs.inspector.dev/concepts/ai-bug-fixer>
{% endhint %}


# Tempest

Code Execution Monitoring for Tempest applications

### Requirements

* PHP ^8.5
* Tempest ^3.0

## Install

Install the latest version by:

```bash
composer require inspector-apm/inspector-tempest
```

Tempest will automatically discover the package provider and other library components.

### Configure the Ingestion Key

You just need to put the Ingestion Key in your environment file:

```
INSPECTOR_INGESTION_KEY=[ingestion key]
```

You can obtain an `INSPECTOR_INGESTION_KEY` creating a new project in your [Inspector](https://inspector.dev) account.

### Test everything is working

Run the command below:

```bash
vendor/bin/tempest inspector:test
```

Go to <https://app.inspector.dev> to explore your data.

### Agentic Integration

You can connect the Inspector library documentation to your coding assistant as a Model Context Protocol (MCP) server.

It makes it easy for tools like Claude Code, Cursor, and VS Code extensions reliably understand what Inspector client library can do, its configurations, how to use it.

[AI Assisted Integration](https://docs.inspector.dev/concepts/agentic-integration)

## Publish Configuration

If you want to take full control over the Inspector client behaviour you need to install the inspector assets on your project directory.

The command below will add the `app/inspector.config.php` file providing the `InspectorConfig` instance:

```shellscript
php tempest install inspector    
```

### Ignore Urls

It could be necessary to turn off monitoring based on url. Think about parts of your app that don't affect the user experience.&#x20;

You can also use the wildcard character \* to exclude all sub-paths.

{% code title="inspector.config.php" %}

```php
return new InspectorConfig(
    ...,
    ignoreUrls: [
        '/admin/*'
    ],
);
```

{% endcode %}

### Ignore Commands

You can ignore artisan commands by adding the command name to the `ignoreCommands` argument in the `InspectorConfig` configuration class:

{% code title="inspector.config.php" %}

```php
return new InspectorConfig(
    ...,
    ignoreCommands: [
        'discovery:generate'
    ],
);
```

{% endcode %}


# CodeIgniter

Code Execution Monitoring for CodeIgniter applications.

### Introduction

The package automatically instrument a CodeIgniter v4 application and records performance metrics about HTTP requests, DB queries, and Unhandled Exceptions. It also has  a simple API which allows you to monitor custom code blocks in your application.

### How does the library works?

The library wrap your application execution cycles to measure their duration and metadata (like the DB statements), as well as HTTP related information (like the URL, parameters, headers, etc).

These events, called Transactions and Segments, are sent to the ingestion API where they will be processed and stored to provides you with insights into latency issues and error culprits within your application.

The first step is to install the Inspector CodeIgniter package:

{% content-ref url="/pages/M5N56UUIHZ5mtkgicCNW" %}
[Installation](/guides/codeigniter/installation)
{% endcontent-ref %}

### Resources

* Website: <https://www.inspector.dev>
* Blog: <https://www.inspector.dev/blog>
* GitHub repository: <https://github.com/inspector-apm/inspector-codeigniter>


# Installation

How to connect your CodeIgniter application to Inspector.

### Requirements

* PHP >= 7.4
* CodeIgniter >= 4

### Installation

Install the latest version using the composer command below:

```bash
composer require inspector-apm/inspector-codeigniter
```

Run the install command to publish the `Inspector.php` configuration file in your application `app/Config` directory:

```bash
php spark inspector:install
```

### Configure The Ingestion Key

Add the environment variable below to your `.env` file in order to make your application able to send data to your dashboard. You can get a new Ingestion Key by creating a new app in your account: [https://app.inspector.dev](https://app.inspector.dev/)

```
#--------------------------------------------------------------------
# INSPECTOR
#--------------------------------------------------------------------

inspector.ingestionKey = '974yn8c34ync8xxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
```

### Add The Exception Handler

In your `app/Config/Exceptions.php` add the line of code below in the `handle` method to enable exception tracking:

```php
/**
 * Setup how the exception handler works.
 */
class Exceptions extends BaseConfig
{
    ...

    public function handler(int $statusCode, Throwable $exception): ExceptionHandlerInterface
    {
        InspectorExceptionHandler::handle($statusCode, $exception);

        return new ExceptionHandler($this);
    }
}

```

### HTTP Request Monitoring

The package provides your application with the `inspector` filter that you can use to monitor incoming HTTP requests.

**We highly recommend** to add `inspector` to the global filters in your `app/Config/Filter.php` configuration class in order to monitor all HTTP requests:

```php
class Filters extends BaseFilters
{

    /**
     * List of filter aliases that are always
     * applied before and after every request.
     *
     * @var array
     */
    public array $globals = [
        'before' => [
            ...,
            'inspector',
        ],
        'after' => [
           ...,
           'inspector',
        ],
    ];

}
```

{% hint style="info" %}
You can eventually turn off monitoring using the `ignoreRoutes` configuration property: <https://docs.inspector.dev/guides/codeigniter/configuration#ignore-routes>
{% endhint %}

### Verify And Deploy

Run the command below to check if your system is properly configured. If all checks are green you can deploy in your production environment.

```bash
php spark inspector:test
```

If everything is "green" you can release the update in your production environment.

By default Inspector will monitor:

* Http Requests
* Spark Commands
* Database queries
* Unhandled Exceptions

In the next sections you can learn how to further customize the library behaviour.

### Helper

**We highly recommend** adding the helper in the `Config/Autoload.php` configuration class to make it available globally into the application:

```php
class Autoload extends AutoloadConfig
{
    ...
    
    /**
     * -------------------------------------------------------------------
     * Helpers
     * -------------------------------------------------------------------
     * Prototype:
     *   $helpers = [
     *       'form',
     *   ];
     *
     * @var list<string>
     */
    public $helpers = ['inspector'];
}
```

The helper provides a shortcut to the inspector instance to monitor custom code blocks or manually report specific exceptions.

```php
// Load the helper if you haven't added it to Autoload.php
helper('inspector');

// Monitor custom code blocks
$json = inspector()->addSegment(function () {
    return file_get_contents('auth.json');
}, 'http', 'READ auth.json');

// Report an exception
inspector()->reportException(new \Exception("Whoops there's an error here."));
```

{% hint style="info" %}
Learn more about custom Segments here: <https://docs.inspector.dev/guides/raw-php/custom-segments>
{% endhint %}


# Configuration

Fine tune the CodeInginter monitoring strategy on your needs.

The Ingestion Key  is the only required configuration parameter, but the Inspector package is designed to help you deeply customize the monitoring strategy based on your application needs.

### Ignore Routes

It could be needed to turn off monitoring based on **url.** Think about paths like `/backend`, or other parts of your app that has nothing to do with the user experience.

You can easily ignore these path listing them into the `ignoreRoutes` array of `app/Config/Inspector.php` configuration file.

```php
class Inspector extends BaseConfig
{
    ...
    
    /**
     * List the path you don't want to monitor (Support for wildcard "*").
     *
     * @var array
     */
    public $ignoreRoutes = [
        'backend*'
    ];
    
    ...
}
```

{% hint style="warning" %}
You can also use the wildcard character **`*`** to exclude all sub-paths.
{% endhint %}

### Ignore Commands

You can ignore spark commands adding the command name to the `ignoreCommands` property in the `app/Config/Inspector.php` configuration file.

```php
class Inspector extends BaseConfig
{
    ...
    
    /**
     * List the commands you don't want to monitor (Support for wildcard "*").
     *
     * @var array
     */
    public $ignoreCommands = [
        'inspector:install',
        'serve',
        'make:*',
        'db:*',
        'migrate',
    ];
    
    ...
}
```

### Access the Inspector instance

You can get the current Inspector instance using the helper function:

```php
// Load the helper
helper('inspector');

// Use the inspector() function
inspector()->addSegment(function () {
    // Your code here...
}, 'type', 'label');
```


# Exception Monitoring

CodeIgniter error tracking

{% hint style="info" %}
**By default every Unhandled exception will be reported automatically to be sure you'll be alerted for unpredictable errors in real time.**
{% endhint %}

Inspector also allows you to report an exception manually if you want to be aware of it, but you don't want to block the execution of your code:

```php
helper('inspector'); // You don't need this if you autoload inspector globally

try {

    // Your code statements here...

} catch(LogicException $exception) {
    // Report an exception intentionally to collect diagnostics data
    inspector()->reportException($exception);
}
```

If something goes wrong in your code you will be alerted in real time in your inbox and the exception will be monitored for all subsequent occurrences.

{% hint style="info" %}
For more information about access the Inspector instance in your application take al look on this section: [**Access the Inspector instance**](https://docs.inspector.dev/guides/codeigniter/configuration#access-the-inspector-instance)
{% endhint %}

### Exception monitoring

When an exception is detected you can read the code inside the stacktrace, and monitor its occurrences frequency for a better investigation:

<figure><img src="/files/9JC1LTwo0ggQrrrMsIAB" alt=""><figcaption></figcaption></figure>

{% hint style="success" %}
Activate the AI Bug Fix to receive code change proposals for faster resolution: <https://docs.inspector.dev/concepts/ai-bug-fixer>
{% endhint %}


# Drupal

Connect Drupal instances to the Inspector monitoring dashboard.

### Requirements

* Drupal: 9.x | 10.x | 11.x

### Introduction

The package automatically instrument a Drupal instance and records performance metrics about HTTP requests, DB queries, and Unhandled Exceptions. It also has  a simple API which allows you to monitor custom code blocks in your application.

### Resources

* Website: <https://www.inspector.dev>
* Blog: <https://www.inspector.dev/blog>
* Drupal official page: <https://www.drupal.org/project/inspector_monitoring>

### Installation

Run the command below in your terminal to install the latest version:

```bash
composer require drupal/inspector_monitoring
```

### Configure the Ingestion Key

{% hint style="info" %}
To get a new Ingestion Key sign up for Inspector (<https://app.inspector.dev/register>) and creating a new application.
{% endhint %}

The Inspector Drupal module includes a form to makes you able to configure the monitoring system in a convenient web page.

To access the configuration page navigate to:

```
Admin >> Configuration >> Development >> Inspector Monitoring
```

Paste the Ingestion Key into the input form and click "Save".

### Test & Deploy

Once you have configured the Ingestion Key, try to navigate your website to see the first data flowing into the dashboard.

If everything works well, you are ready to release this integration into the production environment.

Inspector automatically reports:

* HTTP traffic
* Database queries
* Unhandled exceptions

You will be alerted for any error in your application and the [AI Bug Fix](https://docs.inspector.dev/concepts/ai-bug-fixer) will provides you with a ready to use solution in real-time.

<figure><img src="/files/OniWB7Iak21xvD14PJLh" alt=""><figcaption></figcaption></figure>

### Transport

The transport method refers to the way Inspector sends monitoring data collected into your Drupal installation to the remote platform. We suggest to use `sync` for development or local environments, and `async` for production environment.

* **SYNC -** dev or local environment
* **ASYNC -** prod environment

### Query Logging

By default the module automatically monitors the internal database queries generated from your code, or other modules code. It will help you understand what is going on behind the scene, and immediately identify slow statements that can impact your user experience.

<figure><img src="/files/FRVckf4ku1Kcol4SJ7Rv" alt=""><figcaption></figcaption></figure>

You can eventually enable/disable this monitoring component from the configuration page as per your needs.

### Exception Monitoring

{% hint style="info" %}
**By default every unhandled exception will be reported automatically to be sure you'll be alerted for unpredictable errors in real time.**
{% endhint %}

When an exception is detected you can read the code inside the stacktrace, and monitor its occurrences frequency for a better investigation:

<figure><img src="/files/b70vnaOAmadHroqPCrCy" alt=""><figcaption></figcaption></figure>

{% hint style="success" %}
Activate the AI Bug Fix to receive code change proposals for faster resolution: <https://docs.inspector.dev/concepts/ai-bug-fixer>
{% endhint %}


# Slim

Code Execution Monitoring for Slim based applications.

### Server requirements

* PHP >= 7.2
* Slim >= 4.x

### Install

Install the latest package version by:

```
composer require inspector-apm/inspector-slim
```

### Register On Container

First you have to register the Inspector instance inside the application container in order to make the monitoring agent available within the application.

Consider to use [environment variables](https://github.com/vlucas/phpdotenv) to store your project's INGESTION KEY:

```php
$container->set('inspector', function () {
    $configuration = new \Inspector\Slim\Configuration('INSPECTOR_INGESTION_KEY');
	
    return new \Inspector\Inspector($configuration);
});
```

If you are using a Slim 4 skeleton you can add a new container definition in `app/dependencies.php` file:

```php
use DI\ContainerBuilder;
use Psr\Container\ContainerInterface;

return function (ContainerBuilder $containerBuilder) {
    $containerBuilder->addDefinitions([
    
        // Other services definitions...
    
        'inspector' => function (ContainerInterface $container) {
            $configuration = new \Inspector\Slim\Configuration('INSPECTOR_INGESTION_KEY');
            return new \Inspector\Inspector($configuration);
        }
        
    ]);
}
```

You can get an `INSPECTOR_INGESTION_KEY` creating a new project in your [Inspector](https://www.inspector.dev/) account.

### Attach the middleware

To monitor all the incoming HTTP traffic you can attach the middleware globally:

```php
$app->add(\Inspector\Slim\WebRequestMonitoring::class);
```

Or in specific routes:

```php
$app->get('/home', function () {
    
    // do something...
    
})->add(\Inspector\Slim\WebRequestMonitoring::class);
```

### Test that everything works

Create a test route and open it in the browser <http://localhost:8080>

```php
$app->get('/test', function () {
    
    throw new \Exception('My First Exception.');
    
});
```

You should receive your first notification in a few seconds.

### Add Segments

You can add segments to the transaction's timeline from route functions:

```php
$app->get('/', function (Request $request, Response $response) {
    /*
     * Retrieve the inspector instance from the container.
     */
    $this->get('inspector')->addSegment(function () {
        
        // your code here...
        sleep(1);
        
    }, 'sleep');
        
    return $response;
});
```

If your routes are organized using controllers you need to inject the container in the controller constructor in order to retrieve the inspector agent later during execution:

```php
namespace App\Controllers;


use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;

class TestRouteController
{
    protected $container;
    
    /**
     * Inject the container to retrieve the inspector instance later.
     */
    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    public function __invoke(Request $request, Response $response)
    {
        // Use the inspector instance from the container.
        $this->container->get('inspector')->addSegment(function () {
        
            // your code here...
            sleep(1);
            
        }, 'sleep');

        $response->getBody()->write('Test route.');

        return $response;
    }
}
```

{% hint style="info" %}

### **Learn more about** [**custom segments**](/concepts/custom-segments)**.**

{% endhint %}


# Neuron AI

Monitor your AI Agents, RAGs, and Workflows in real-time.

### The Problem With AI Systems <a href="#the-problem-with-ai-systems" id="the-problem-with-ai-systems"></a>

Integrating AI Agents into your application you're not working only with functions and deterministic code, you program your agent also influencing probability distributions. Same input ≠ output. That means reproducibility, versioning, and debugging become real problems.

Many of the Agents you build with Neuron will contain multiple steps with multiple invocations of LLM calls, tool usage, access to external memories, etc. As these applications get more and more complex, it becomes crucial to be able to inspect what exactly your agent is doing and why.

Why is the model making certain decisions? What data is the model reacting to? Prompting is not programming in the common sense. No static types, small changes break output, long prompts cost latency, and no two models behave exactly the same with the same prompt.

### Install

You need to install the Inspector PHP package only if you are not already using other inspector libraries like `inspector-laravel`, `inspector-symfony`, and others.

```shellscript
composer require inspector-apm/inspector-php
```

If you are building with Neuron AI inside a web framework, we strongly recommend to use the framework specific package in order to have a complete integration.

### Get Started <a href="#get-started-with-inspector" id="get-started-with-inspector"></a>

First add the `INSPECTOR_INGESTION_KEY` variable in your application environment file. Authenticate on [app.inspector.dev](https://app.inspector.dev/register) to create a new one.

{% code title=".env" %}

```
INSPECTOR_INGESTION_KEY=nwse877auxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

{% endcode %}

The second step is to register the `InspectorObserver` in your Agent, RAG, or Workflow. You can do it in the constructor:

```php
use Inspector\Neuron\InspectorObserver;

class MyAgent extends Agent
{
    public function __construct()
    {
        parent::__construct();
        
        // Register the InspectorObserver
        $this->observe(InspectorObserver::instance());
    }
    
    ...
}
```

When your agents are being executed, you will see the details of their inference steps, tool calls, and more.

<figure><img src="/files/SB3noPtYTg0LVupAxcop" alt=""><figcaption></figcaption></figure>

#### Create An Ingestion Key <a href="#create-an-ingestion-key" id="create-an-ingestion-key"></a>

To create an Ingestion key head to the [**Inspector dashboard**](https://app.inspector.dev/register) and create a new app.

{% hint style="success" %}
For any additional support drop in a live chat in the dashboard. We are happy to listen from your experience, find new possible improvements, and make the tool better overtime.
{% endhint %}

### Configure Observer

If your application already works with environment files, it is very likely that Neuron can automatically instrument itself if you add the `INSPECTOR_INGESTION_KEY` . If you have no access to environment variables, or you just want to customize the `InspectorObserver` configuration you can register it manually in your agent.&#x20;

```php
use Inspector\Neuron\InspectorObserver;

class MyAgent extends Agent
{
    public function __construct()
    {
        parent::__construct();
        
        // Register the InspectorObserver
        $this->observe(
            InspectorObserver::instance('INSPECTOR_INGESTION_KEY')
        );
    }

    ...
}
```

### Background Workers

If you are running your agent into a long running process like a queue worker or systems like Swoole, or Roadrunner, you need to explicitly configure the auto-flush of events:

```php
// Register Inspector
$this->observe(
    InspectorObserver::instance(
        key: 'INSPECTOR_INGESTION_KEY',
        autoFlush: true
    )
);
```

### Add The Framework Specific Package

If you are integrating Neuron in an already existing application built on top of a framework like Laravel, Symfony, or simialr, we strongly recommend to add the framework specific package for a better data collection.

It's not required, just recommended. You can continue to monitor Neuron without the framework specific package.&#x20;

{% content-ref url="/pages/-LuWcB8gWM5wptHOWiEF" %}
[Laravel / Lumen](/guides/laravel)
{% endcontent-ref %}

{% content-ref url="/pages/-MbG50kVKWT\_dmhrNUpX" %}
[Symfony](/guides/symfony)
{% endcontent-ref %}

{% content-ref url="/pages/GqQIK9NcYrhKhzY5acoB" %}
[CodeIgniter](/guides/codeigniter)
{% endcontent-ref %}

{% content-ref url="/pages/sFz09Y2ifm3lLFM7iSEA" %}
[Slim](/guides/slim)
{% endcontent-ref %}


# Authentication

### Base Endpoint

Inspector APIs are hosted on the following base URI:

```
https://app.inspector.dev/api
```

### Include the key

In order to use the API you should authenticate your request by including your API key as a bearer token value in the request's headers:

```
Authorization: Bearer API_KEY_HERE
```

{% hint style="info" %}
If you don't have an API key, you can create a new one in just a few clicks: <https://app.inspector.dev/account/api>
{% endhint %}

### Recommended Headers

Make sure you have the following content type headers set on every request:

```
Accept: application/json 
Content-Type: application/json
```

### Error codes

Inspector uses conventional HTTP response codes to indicate the success or failure of an API request. The table below contains a summary of the typical response codes:

| Code    | Description                                                            |
| ------- | ---------------------------------------------------------------------- |
| **200** | Everything is ok.                                                      |
| **401** | No valid API Key was given.                                            |
| **404** | The request resource could not be found.                               |
| **422** | The payload has missing required parameters or invalid data was given. |
| **429** | Too many attempts.                                                     |
| **500** | Request failed due to an internal error in Inspector.                  |


# Apps

Create and retrieve Projects is needed to get the ingestion key.

## List Apps

<mark style="color:blue;">`GET`</mark> `https://app.inspector.dev/api/apps`

#### Headers

| Name                                             | Type   | Description |
| ------------------------------------------------ | ------ | ----------- |
| Authentication<mark style="color:red;">\*</mark> | string | API key.    |

{% tabs %}
{% tab title="200 " %}

```json
[
    {
        "id": 123,
        "name": "App Demo",
        "favorite": false,
        "client_version": "4.7.33",
        "key": "xxxxxxxxxxxxxxxxx",
        "serverless": false,
        "weekly_report": true,
        "platform": {
            "id": 1,
            "name": "Laravel",
            "language": "PHP"
        },
        "users": [1, 2],
        "created_at": "2024-03-01 10:52",
        "updated_at": "2024-03-01 10:52"
    },
    {
        "id": 456,
        "name": "Demo 2",
        "favorite": false,
        "key": "xxxxxxxxxxxxxxxxx",
        
        ...
    }
]
```

{% endtab %}
{% endtabs %}

## App Details

<mark style="color:blue;">`GET`</mark> `https://app.inspector.dev/api/apps/:id`

#### Path Parameters

| Name                                 | Type    | Description |
| ------------------------------------ | ------- | ----------- |
| id<mark style="color:red;">\*</mark> | integer | App's ID    |

#### Headers

| Name                                             | Type   | Description |
| ------------------------------------------------ | ------ | ----------- |
| Authentication<mark style="color:red;">\*</mark> | string | API key     |

{% tabs %}
{% tab title="200 " %}

```json
{
    "id": 123,
    "name": "App Demo",
    "favorite": false,
    "client_version": "4.7.33",
    "key": "xxxxxxxxxxxxxxxxx",
    "serverless": false,
    "weekly_report": true,
    "platform": {
        "id": 1,
        "name": "Laravel",
        "language": "PHP"
    },
    "users": [1, 2],
    "created_at": "2024-03-01 10:52",
    "updated_at": "2024-03-01 10:52"
}
```

{% endtab %}

{% tab title="404 " %}

```
{
    "message": "Resource not found."
}
```

{% endtab %}
{% endtabs %}

## Create App

<mark style="color:green;">`POST`</mark> `https://app.inspector.dev/api/apps`

Create a new project will generate a new ingestion key.

#### Headers

| Name                                             | Type   | Description |
| ------------------------------------------------ | ------ | ----------- |
| Authentication<mark style="color:red;">\*</mark> | string | API key     |

#### Request Body

| Name                                           | Type    | Description                                         |
| ---------------------------------------------- | ------- | --------------------------------------------------- |
| name<mark style="color:red;">\*</mark>         | string  | The name of the project                             |
| platform\_id<mark style="color:red;">\*</mark> | integer | The ID of the technology stack used for the project |

{% tabs %}
{% tab title="200 " %}

```json
{
    "id": 123,
    "name": "App Demo",
    "favorite": false,
    "client_version": "4.7.33",
    "key": "xxxxxxxxxxxxxxxxx",
    "serverless": false,
    "weekly_report": true,
    "platform": {
        "id": 1,
        "name": "Laravel",
        "language": "PHP"
    },
    "users": [1, 2],
    "created_at": "2024-03-01 10:52",
    "updated_at": "2024-03-01 10:52"
}
```

{% endtab %}

{% tab title="422 If some data is incorrect." %}

```json
{
    "message": "The given data are incorrect",
    "errors": {
        "name": [
            "The name field is required",
            "The name field should contains more than 3 characters"
        ]
    }
}
```

{% endtab %}
{% endtabs %}

## Update App

<mark style="color:orange;">`PUT`</mark> `https://app.inspector.dev/api/apps/:id`

#### Path Parameters

| Name                                 | Type    | Description |
| ------------------------------------ | ------- | ----------- |
| id<mark style="color:red;">\*</mark> | integer | App's ID    |

#### Headers

| Name                                             | Type   | Description |
| ------------------------------------------------ | ------ | ----------- |
| Authentication<mark style="color:red;">\*</mark> | string | API key     |

#### Request Body

| Name                                           | Type    | Description                                                    |
| ---------------------------------------------- | ------- | -------------------------------------------------------------- |
| weekly\_report                                 | boolean | Determine if you want to receive the weekly summary via email. |
| platform\_id<mark style="color:red;">\*</mark> | integer | The tech stack.                                                |
| name<mark style="color:red;">\*</mark>         | string  | Name of the project                                            |

{% tabs %}
{% tab title="200 " %}

```json
{
    "id": 123,
    "name": "App Demo",
    "favorite": false,
    "client_version": "4.7.33",
    "key": "xxxxxxxxxxxxxxxxx",
    "serverless": false,
    "weekly_report": true,
    "platform": {
        "id": 1,
        "name": "Laravel",
        "language": "PHP"
    },
    "users": [1, 2],
    "created_at": "2024-03-01 10:52",
    "updated_at": "2024-03-01 10:52"
}
```

{% endtab %}
{% endtabs %}

## Delete App

<mark style="color:red;">`DELETE`</mark> `https://app.inspector.dev/api/apps/:id`

#### Path Parameters

| Name                                 | Type    | Description |
| ------------------------------------ | ------- | ----------- |
| id<mark style="color:red;">\*</mark> | integer | App's ID    |

#### Headers

| Name                                            | Type   | Description |
| ----------------------------------------------- | ------ | ----------- |
| Authorization<mark style="color:red;">\*</mark> | string | API key     |

{% tabs %}
{% tab title="200 " %}

```json
{
    "id": 123,
    "name": "App Demo",
    "favorite": false,
    "client_version": "4.7.33",
    "key": "xxxxxxxxxxxxxxxxx",
    "serverless": false,
    "weekly_report": true,
    "platform": {
        "id": 1,
        "name": "Laravel",
        "language": "PHP"
    },
    "users": [1, 2],
    "created_at": "2024-03-01 10:52",
    "updated_at": "2024-03-01 10:52"
}
```

{% endtab %}
{% endtabs %}

## Enable/Disable Data Transfer

<mark style="color:green;">`POST`</mark> `/https://app.inspector.dev/api/apps/:id/lock`

The endpoint works as a toggle. To know if your application is currently locked or not you can check the `locked_at` field in the app object. If it exists that means the application monitoring is currently off, and the next call to the lock endpoint will turn it on.

**Headers**

| Name          | Value              |
| ------------- | ------------------ |
| Content-Type  | `application/json` |
| Authorization | `Bearer <token>`   |

**Response**

{% tabs %}
{% tab title="200" %}

```json
{
  "id": 123,
    "name": "App Demo",
    "favorite": false,
    "client_version": "4.7.33",
    "key": "xxxxxxxxxxxxxxxxx",
    "serverless": false,
    "weekly_report": true,
    "platform": {
        "id": 1,
        "name": "Laravel",
        "language": "PHP"
    },
    "users": [1, 2],
    "locked_at": "2025-01-29 11:53",
    "created_at": "2024-03-01 10:52",
    "updated_at": "2024-03-01 10:52"
}
```

{% endtab %}

{% tab title="401" %}

```json
{
  "error": "Unauthorized action."
}
```

{% endtab %}
{% endtabs %}


# Platforms

## List Platforms

<mark style="color:blue;">`GET`</mark> `https://app.inspector.dev/api/platforms`

This endpoint allows you to list the supported platforms.

#### Headers

| Name           | Type   | Description |
| -------------- | ------ | ----------- |
| Authentication | string | API key.    |

{% tabs %}
{% tab title="200 " %}

```json
[
    {
        "id": 1,
        "name": "Laravel",
        "language": "php",
        "client_version": "4.6.21"
    },
    {
        "id": 2,
        "name": "PHP",
        "language": "php",
        "client_version": "3.5.17"
    },
    {
        "id": 3,
        "name": "NodeJs",
        "language": "javascript",
        "client_version": "1.9.4"
    },
    {
        "id": 3,
        "name": "ExpressJs",
        "language": "javascript",
        "client_version": "1.9.4"
    },
    {
        "id": 3,
        "name": "Fastify",
        "language": "javascript",
        "client_version": "1.9.4"
    }
]
```

{% endtab %}
{% endtabs %}


# Transactions

Access transactions metrics.

Transactions metrics are always related to an App. This means that all endpoints have the same root so it could be helpful to wrap your api call under the same base URI:

&#x20;`https://app.inspector.dev`**`/api/apps/:id`**

## Transactions List

<mark style="color:green;">`POST`</mark> `/api/apps/:id/transactions`

Get the list of transactions in the given interval.

#### Path Parameters

| Name                                 | Type    | Description      |
| ------------------------------------ | ------- | ---------------- |
| id<mark style="color:red;">\*</mark> | Integer | App's identifier |

#### Headers

| Name          | Value              |
| ------------- | ------------------ |
| Content-Type  | `application/json` |
| Authorization | `Bearer <token>`   |

#### Request Body

| Name                                           | Type   | Description                             |
| ---------------------------------------------- | ------ | --------------------------------------- |
| filter.start<mark style="color:red;">\*</mark> | String | ISO-8601 date format                    |
| filter.end                                     | String | ISO-8601 date format                    |
| filter.hosts                                   | Array  | Filter the transactions list by servers |
| filter.query\_string                           | String | Filter by transaction's name            |

{% tabs %}
{% tab title="200 " %}

```
[
    {
        name: "request",
        transactions: [
            {
                type: "request",
                duration: 42.8,
                group_hash: "4fbb4fa36bad346bbe8a26827a244e70",
                hash: "37d6f2a1bd370759ff46cc63266603b81b60da4774bfa9a72af7bf26ba3d4fb1",
                host: {hostname: "307510.cloudwaysapps.com", ip: "127.0.0.1"},
                memory_peak: 16.98,
                name: "GET /api",
                project_id: 389,
                result: "success",
                timestamp: "2024-10-04 16:52:02",
                doc_count: 60,
                performance: [
                    {label: "2021-02-03 16:00", value: 38, doc_count: 61},
                    {label: "2021-02-03 17:00", value: 5, doc_count: 63},
                    {label: "2021-02-03 18:00", value: 65, doc_count: 123},
                    {label: "2021-02-03 19:00", value: 34, doc_count: 11},
                    {label: "2021-02-03 20:00", value: 43, doc_count: 110},
                    {label: "2021-02-03 21:00", value: 2, doc_count: 123},
                    ...
                ]
            },
            
            {...},
        ],
    },
    
    {
        name: "command",
        transactions: [...],
    },
    
    {...}
]
```

{% endtab %}
{% endtabs %}

## Transaction occurrences

<mark style="color:green;">`POST`</mark> `/api/apps/:id/transactions/:group_hash/occurrences`

Get the last occurrences of a specific transaction.

#### Path Parameters

| Name                                          | Type    | Description                        |
| --------------------------------------------- | ------- | ---------------------------------- |
| id<mark style="color:red;">\*</mark>          | Integer | Project's Identifier               |
| group\_hash<mark style="color:red;">\*</mark> | String  | The transaction group's identifier |

#### Query Parameters

| Name                                           | Type    | Description                                                                                              |
| ---------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------- |
| filter.start<mark style="color:red;">\*</mark> | Date    | ISO-8601 date format                                                                                     |
| filter.end                                     | Date    | ISO-8601 date format                                                                                     |
| filter.from                                    | Integer | The results are paginated 25 elements at a time. Use **from** to advance the starting point of the list. |

#### Headers

| Name                                             | Type   | Description |
| ------------------------------------------------ | ------ | ----------- |
| Authentication<mark style="color:red;">\*</mark> | String | API key     |

{% tabs %}
{% tab title="200: OK An array of items." %}

```javascript
[
    {
        duration: 164.22,
        group_hash: "7d8647ff14a84a458b0f6xxxxxxxxxxxx",
        memory_peak: 19.09,
        name: "GET /api/users",
        result: "success",
        timestamp: "2022-04-19 14:10:04",
        type: "process"
    },
    {
        ...
    },
]
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
You can get the **group\_hash** value of a specific transaction in the address bar of your browser navigating the detail page of the transaction of your interest.
{% endhint %}

![](/files/I20PgTiWcz2NGDnjaRnL)


# Segments

Access Segments metrics

Transactions metrics are always related to an App. This means that all endpoints have the same root so it could be helpful to wrap your api call under the same base URI:

&#x20;`https://app.inspector.dev`**`/api/apps/:id`**

## Segments List

<mark style="color:green;">`GET`</mark> `/api/apps/:id/segments`

Get the list of Segments in the given interval.

#### Path Parameters

| Name                                 | Type    | Description      |
| ------------------------------------ | ------- | ---------------- |
| id<mark style="color:red;">\*</mark> | Integer | App's identifier |

**Headers**

| Name          | Value              |
| ------------- | ------------------ |
| Content-Type  | `application/json` |
| Authorization | `Bearer <token>`   |

**Body**

| Name                                              | Type   | Description                             |
| ------------------------------------------------- | ------ | --------------------------------------- |
| `filter.start`<mark style="color:red;">`*`</mark> | string | ISO-8601 date format                    |
| `filter.end`                                      | string | ISO-8601 date format                    |
| `filter.types`                                    | array  | Filter the transactions list by servers |
| `filter.query_string`                             | string | Filter by Segment's label               |

**Response**

{% tabs %}
{% tab title="200" %}

```json
[
    {
        type: "mysql",
        segments: [
            {
                type: "mysql",
                start: 123,
                duration: 42.8,
                group_hash: "4fbb4fa36bad346bbe8a26827a244e70",
                hash: "37d6f2a1bd370759ff46cc63266603b81b60da4774bfa9a72af7bf26ba3d4fb1",
                memory_peak: 16.98,
                label: "SELECT * FROM users",
                app_id: 389,
                timestamp: "2024-10-04 16:52:02",
                hits: 60,
            },
            
            ...,
        ],
    },
    
    ...,
]
```

{% endtab %}
{% endtabs %}


# Analytics

Analytics are always related to a project. This means that all endpoints have the same root:

&#x20;`https:://app.inspector.dev`**`/api/apps/:id`**

## Get Hosts

<mark style="color:green;">`POST`</mark> `https://app.inspector.dev/api/apps/:id/hosts`

The list of hosts (servers) where the application runs on.

#### Path Parameters

| Name | Type   | Description  |
| ---- | ------ | ------------ |
| id   | string | Project's ID |

#### Headers

| Name           | Type   | Description |
| -------------- | ------ | ----------- |
| Authentication | string | API key     |

#### Request Body

| Name   | Type   | Description                                                                                                                                                                                                                                   |
| ------ | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| filter | object | <p>This object should contains "<strong>start</strong>" and "<strong>end</strong>" dates (ISO8601) to define the period you would analyze.<br><br>You can also provide the <strong>types</strong> field as an array of transaction types.</p> |

{% tabs %}
{% tab title="200 " %}

```json
[
    {
        "hostname": "server-useast-2",
        "transactions": 2320,
        "memory_peak": 25,
        "median": 168.3
    },
    {
        "hostname": "server-useast-1",
        "transactions": 2320,
        "memory_peak": 25,
        "median": 168.3
    }
]
```

{% endtab %}
{% endtabs %}

## Types

<mark style="color:green;">`POST`</mark> `/users`

The list of transaction types the application runs (request, command, job, etc).

**Headers**

| Name          | Value              |
| ------------- | ------------------ |
| Content-Type  | `application/json` |
| Authorization | `Bearer <token>`   |

**Request Body**

| Name   | Type   | Description                                                                                                   |
| ------ | ------ | ------------------------------------------------------------------------------------------------------------- |
| filter | object | This object should contains "**start**" and "**end**" dates (ISO8601) to define the period you would analyze. |

**Response**

{% tabs %}
{% tab title="200" %}

```json
[
    {
        "type": "request",
        "transactions": 2320,
        "memory_peak": 9,
        "median": 36.3
    },
    {
        "type": "command",
        "transactions": 532,
        "memory_peak": 25,
        "median": 168.3
    }
]
```

{% endtab %}

{% tab title="400" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}

## Performance

<mark style="color:green;">`POST`</mark> `https://app.inspector.dev/api/apps/:id/performance`

#### Path Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id   | integer | Project's ID |

#### Headers

| Name           | Type   | Description |
| -------------- | ------ | ----------- |
| Authentication | string | API key     |

#### Request Body

| Name   | Type   | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| ------ | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| filter | object | <p>This object should contains "<strong>start</strong>" and "<strong>end</strong>" dates (ISO 8601) to define the period you would analyze. <br><br>You can attach the "<strong>hosts</strong>" field as an array of hostnames to filter your performance report by servers.<br><br>You can include the "<strong>query\_string</strong>" parameter to filter by transactions name.</p><p></p><p>Furthermore you can include the <strong>group\_hash</strong> field to get insights for a specific process.</p> |

{% tabs %}
{% tab title="200 " %}

```json
[
    {
        "type": "request",
        "performance": [
            {
                "date": "2020-10-10 12:54",
                "count": 4,
                "p50": 5.37,
                "p95": 6.56,
                "memory_average": 4.52
            },
            {
                "date": "2020-10-10 13:54",
                "count": 4,
                "p50": 5.37,
                "p95": 6.56,
                "memory_average": 4.52
            }
        ]
    },
    
    {
        "type": "command",
        "performance": [
            {
                "date": "2020-10-10 12:54",
                "count": 4,
                "p50": 5.37,
                "p95": 6.56,
                "memory_average": 3.77
            },
            {
                "date": "2020-10-10 13:54",
                "count": 4,
                "p50": 5.37,
                "p95": 6.56,
                "memory_average": 3.77
            }
        ]
    }
]
```

{% endtab %}
{% endtabs %}

## Errors

<mark style="color:blue;">`GET`</mark> `https://app.inspector.dev/api/projects/:id/errors`

Retrieve the list of the error detected in the given application.

#### Path Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id   | integer | Project's ID |

#### Headers

| Name           | Type   | Description |
| -------------- | ------ | ----------- |
| Authentication | string | API Key     |

{% tabs %}
{% tab title="200 " %}

```json
[
    {
        "id": 24,
        "message": "First Exception detected",
        "handled": true,
        "muted": false,
        "class": "Exception",
        "file": "C:\\xampp\\htdocs\\crongenius\\vendor\\inspector-apm\\inspector-laravel\\src\\Commands\\TestCommand.php",
        "line": 71,
        "hash": "287366827414d79f8f4775c5a99e0d05",
        "last_seen_at": "2020-10-09 14:05:41",
        "created_at": "2020-10-08 14:48:55",
        "histogram_day": {
            "2020-10-15 07:00": 0,
            "2020-10-15 08:00": 1,
            "2020-10-15 09:00": 1,
            "2020-10-15 10:00": 7,
            "2020-10-15 11:00": 0,
            "2020-10-15 12:00": 0,
            "2020-10-15 13:00": 1,
            "2020-10-15 14:00": 1,
            "2020-10-15 15:00": 3,
            "2020-10-15 16:00": 0,
            "2020-10-15 17:00": 0,
            "2020-10-15 18:00": 21,
            "2020-10-15 19:00": 6,
            "2020-10-15 20:00": 0,
            "2020-10-15 21:00": 0,
            "2020-10-15 22:00": 16,
            "2020-10-15 23:00": 0,
            "2020-10-16 00:00": 0,
            "2020-10-16 01:00": 0,
            "2020-10-16 02:00": 0,
            "2020-10-16 03:00": 0,
            "2020-10-16 04:00": 0,
            "2020-10-16 05:00": 0,
            "2020-10-16 06:00": 0,
            "2020-10-16 07:00": 0
        },
        "histogram_month": {
            "2020-09-16 07:00": 0,
            "2020-09-17 07:00": 0,
            "2020-09-18 07:00": 0,
            "2020-09-19 07:00": 0,
            "2020-09-20 07:00": 0,
            "2020-09-21 07:00": 0,
            "2020-09-22 07:00": 0,
            "2020-09-23 07:00": 0,
            "2020-09-24 07:00": 5,
            "2020-09-25 07:00": 0,
            "2020-09-26 07:00": 0,
            "2020-09-27 07:00": 0,
            "2020-09-28 07:00": 0,
            "2020-09-29 07:00": 0,
            "2020-09-30 07:00": 0,
            "2020-10-01 07:00": 0,
            "2020-10-02 07:00": 21,
            "2020-10-03 07:00": 8,
            "2020-10-04 07:00": 0,
            "2020-10-05 07:00": 0,
            "2020-10-06 07:00": 0,
            "2020-10-07 07:00": 0,
            "2020-10-08 07:00": 0,
            "2020-10-09 07:00": 4,
            "2020-10-10 07:00": 0,
            "2020-10-11 07:00": 0,
            "2020-10-12 07:00": 4,
            "2020-10-13 07:00": 0,
            "2020-10-14 07:00": 0,
            "2020-10-15 07:00": 2,
            "2020-10-16 07:00": 127
        },
        "histogram_hour": {
            "2020-10-16 06:36": 0,
            "2020-10-16 06:38": 0,
            "2020-10-16 06:40": 0,
            "2020-10-16 06:42": 0,
            "2020-10-16 06:44": 0,
            "2020-10-16 06:46": 0,
            "2020-10-16 06:48": 4,
            "2020-10-16 06:50": 27,
            "2020-10-16 06:52": 25,
            "2020-10-16 06:54": 0,
            "2020-10-16 06:56": 3,
            "2020-10-16 06:58": 0,
            "2020-10-16 07:00": 0,
            "2020-10-16 07:02": 5,
            "2020-10-16 07:04": 6,
            "2020-10-16 07:06": 6,
            "2020-10-16 07:08": 0,
            "2020-10-16 07:10": 0,
            "2020-10-16 07:12": 0,
            "2020-10-16 07:14": 0,
            "2020-10-16 07:16": 0,
            "2020-10-16 07:18": 19,
            "2020-10-16 07:20": 0,
            "2020-10-16 07:22": 0,
            "2020-10-16 07:24": 0,
            "2020-10-16 07:26": 0,
            "2020-10-16 07:28": 0,
            "2020-10-16 07:30": 0,
            "2020-10-16 07:32": 5,
            "2020-10-16 07:34": 30,
            "2020-10-16 07:36": 0
        },
        "total": 4
    }
]
```

{% endtab %}
{% endtabs %}

## Errors Trend

<mark style="color:blue;">`GET`</mark> `https://app.inspector.dev/api/apps/:id/errors/trend`

Retrieve the daily errors trend inthe last 30 days.

#### Path Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id   | integer | Project's ID |

#### Headers

| Name           | Type   | Description |
| -------------- | ------ | ----------- |
| Authentication | string | API key     |

{% tabs %}
{% tab title="200 " %}

```json
[
  {
    "date": 1617494400000,
    "num": 0
  },
  {
    "date": 1617580800000,
    "num": 0
  },
  {
    "date": 1617667200000,
    "num": 0
  },
  {
    "date": 1617753600000,
    "num": 0
  },
  {
    "date": 1617840000000,
    "num": 0
  },
  {
    "date": 1617926400000,
    "num": 1
  },
  {
    "date": 1618012800000,
    "num": 0
  },
  {
    "date": 1618099200000,
    "num": 0
  },
  {
    "date": 1618185600000,
    "num": 0
  },
  {
    "date": 1618272000000,
    "num": 0
  },
  {
    "date": 1618358400000,
    "num": 0
  },
  {
    "date": 1618444800000,
    "num": 0
  },
  {
    "date": 1618531200000,
    "num": 0
  },
  {
    "date": 1618617600000,
    "num": 0
  },
  {
    "date": 1618704000000,
    "num": 0
  },
  {
    "date": 1618790400000,
    "num": 0
  },
  {
    "date": 1618876800000,
    "num": 0
  },
  {
    "date": 1618963200000,
    "num": 0
  },
  {
    "date": 1619049600000,
    "num": 0
  },
  {
    "date": 1619136000000,
    "num": 0
  },
  {
    "date": 1619222400000,
    "num": 0
  },
  {
    "date": 1619308800000,
    "num": 0
  },
  {
    "date": 1619395200000,
    "num": 0
  },
  {
    "date": 1619481600000,
    "num": 0
  },
  {
    "date": 1619568000000,
    "num": 0
  },
  {
    "date": 1619654400000,
    "num": 0
  },
  {
    "date": 1619740800000,
    "num": 0
  },
  {
    "date": 1619827200000,
    "num": 0
  },
  {
    "date": 1619913600000,
    "num": 0
  },
  {
    "date": 1620000000000,
    "num": 0
  },
  {
    "date": 1620086400000,
    "num": 0
  }
]
```

{% endtab %}
{% endtabs %}


