Skip to content

Martini Services Tracker Indexing Data

Martini provides an API for searching and storing data in the [Tracker search index][tracker]. This API allows you to customize how service calls appear in the Tracker interface and select data for indexing and future [searching][tracker-searching].

Logging HTTP calls

Within Martini, the trackers.xml configuration file is pivotal for determining the tracking of requests and responses. Located in the conf/ directory, its default structure is as follows:

1
2
3
4
5
6
<?xml version="1.0" encoding="UTF-8"?>
<trackers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns="http://www.torocloud.com/toro-martini/schema/trackers"
          xsi:schemaLocation="http://www.torocloud.com/toro-martini/schema/trackers trackers.xsd">
    <tracker pattern="/api/**" scope="none"/>
</trackers>

The <tracker> element above implies matching all requests beginning with /api/ while not tracking them due to the none scope. Altering the scope attribute by removing it:

1
<tracker pattern="/api/**"/>

enables tracking for these requests. The <tracker> element supports various attributes for customization:

Attribute Default Description
pattern (required) The URL or exact URL pattern to match
method all Comma-separated request methods (e.g., GET, POST) to match
scope all Logs the request, response, all, or none
internal-id (generated) Identifier for tracking a single request-response cycle
sender-id Client Addr Used as the Tracker document senderId
receiver-id Path Info Used as the Tracker document receiverId
document-type HTTP Tracker document type
More example Tracker configurations

Additional <tracker> configurations illustrate the flexibility in tracking specifications:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<trackers>
    <tracker pattern="/exact-match"/>
    <tracker pattern="/pattern/**"/>
    <tracker pattern="/by-post-method" method="POST"/>
    <tracker pattern="/by-post-or-put-method" method="POST,PUT"/>
    <tracker pattern="/scope/request-only" scope="request"/>
    <tracker pattern="/scope/response-only" scope="response"/>
    <tracker pattern="/scope/all" scope="all"/>
    <tracker pattern="/scope/none" scope="none"/>
    <tracker pattern="/custom-document"
             internal-id="harcoded-internal-id"
             sender-id="8888"
             receiver-id="09158888888"
             document-type="CustomType"/>
</trackers>

How granular should I get?

Tracking is invaluable for traceability but may not suit all cases, such as:

  • Avoiding sensitive information indexing.
  • Enhancing Martini's throughput by reducing Tracker's performance impact.

When configuring <tracker> elements, prioritize specificity at the top and generality at the bottom. Incorrect configurations can lead to inefficiencies, as shown:

1
2
3
4
<trackers>
    <tracker pattern="/api/**"/>
    <tracker pattern="/api/pets"/>
</trackers>

The correct configuration ensures specificity is prioritized:

1
2
3
4
<trackers>
    <tracker pattern="/api/pets"/>
    <tracker pattern="/api/**"/>
</trackers>

Restrictions

By default, tracking is limited to specific base URLs, including:

  • The api.rest.base-path in [application properties][application-properties] (default /api)
  • /soap
  • /invoke
  • /flux-api

Therefore, Tracker patterns must start with one of these bases.

Logging from HTTP Client Services

In Martini, logging HTTP requests made by invoking the io.toro.martini.HttpFunctions.http(...) service is streamlined through the configuration of the trackable input model. This model is accessible in the input section of the service's configuration interface when setting up an HTTP request. Among the fields of the trackable model, trackingScope plays a crucial role by defining the extent of logging for the HTTP request in question.

The trackable input model serves as a flexible mechanism for developers to specify exactly what aspects of the HTTP request should be tracked. This capability ensures that developers can maintain granular control over logging, which is essential for debugging, monitoring, and maintaining the security of the application. The trackingScope field, in particular, allows for customization of the logging level, enabling decisions on whether to log the request, response, both, or neither.

Configuring Tracking Scope

To adjust the tracking scope for an HTTP client service call, you would typically follow these steps:

  1. Select the HTTP request configuration: Access the configuration interface for the HTTP client service you are working with.

  2. Locate the trackable model: Within the input configuration, find the trackable model. This model is specifically designed to manage how the service call is logged by Martini.

  3. Set the trackingScope field: Modify the trackingScope field to one of the predefined values (request, response, all, or none) to match your logging requirements. Each option provides a different level of visibility into the service call, allowing you to tailor the logging to the needs of your application.

Best Practices for Logging HTTP Client Services

  • Security Considerations: Be mindful of logging sensitive information. Ensure that the tracking scope and logging configurations adhere to your application's security policies.
  • Performance Impact: Consider the performance implications of logging, especially in production environments. Extensive logging can impact application throughput and response times.
  • Diagnostic Utility: Utilize logging judiciously to aid in diagnosing issues and monitoring service health, while avoiding unnecessary log verbosity.

By following these guidelines and effectively configuring the trackable model, developers can harness the power of Martini's logging capabilities to enhance the observability and reliability of their HTTP client services.

Logging from Flux

The Flux engine facilitates automatic tracking by creating a Tracker document whenever a Flux service executes. This document captures various states throughout the execution lifecycle, providing a comprehensive log that's invaluable for debugging and monitoring. The key scenarios logged include:

  • Start of Execution: Logs the context of the Flux service at the start, encapsulating it within a JSON file.
  • Execution of a State: Each state's execution context is logged, also in JSON format.
  • Exception Occurrence: In case of an exception, the document includes the stack trace extracted from the {stateName}-error.log file.
  • End of Execution: Marks the completion of the service execution.

Limitations on Tracking

Flux invocations executed through debugging or within the IDE environment are exempt from logging to Tracker, focusing the tracking on production or live test executions.

Configuring Tracking for Flux Executions

To enable tracking for Flux executions, especially those initiated via REST API, the trackers.xml file must be configured accordingly. By setting the base path to /flux-api, all associated executions are tracked:

1
2
3
4
<?xml version="1.0" encoding="UTF-8"?>
<trackers>
    <tracker pattern="/flux-api/**" document-type="FluxExecution"/>
</trackers>

For more granular tracking, such as per-package monitoring, the configuration can specify package names:

1
2
3
4
5
<?xml version="1.0" encoding="UTF-8"?>
<trackers>
    <!-- Specifying 'examples' as the package name -->
    <tracker pattern="/flux-api/examples/**" document-type="FluxExecution"/>
</trackers>

Custom Document Types

Although the document-type attribute defaults to HTTP, customizing this value enhances document searchability and filtering. It's advisable to assign a meaningful, distinct value tailored to the specific logging context, such as "FluxExecution" for Flux service executions.

Including Flux States in Tracker Documents

To capture detailed logs that include Flux states within the Tracker document, additional configuration is needed:

  • Flux Service Configuration: Incorporate a custom input property, named $trackerId, within your Flux service. This identifier is pivotal for linking the service execution to its corresponding Tracker document.

  • Tracker Document Updates: Utilize the TrackerMethods API to update the Tracker document dynamically during execution. The $trackerId property serves as a reference for these updates, ensuring that all related states and transitions are accurately logged.

This approach not only logs the request-response lifecycle but also enriches the Tracker document with detailed Flux states, providing deeper insights into the execution flow.

Logging from Martini Endpoints

Logging activities within Martini endpoints to the Tracker is an essential practice for monitoring and analyzing the data flow through your services. This functionality is especially crucial for maintaining visibility into the processing performed by these endpoints, aiding in debugging and operational insights. Here's how to configure logging for Martini endpoints:

Enabling Logging for an Endpoint

To ensure that data processed by a Martini endpoint is tracked and indexed by the Tracker, you must enable the logging property within the endpoint's configuration settings. This property can be found and modified in the Endpoint configuration editor, accessible during both the creation and configuration phases of an endpoint's lifecycle.

Steps to Enable Logging:

  1. Access Endpoint Configuration: Navigate to the Endpoint configuration editor within your Martini application environment. This can be done either when you are creating a new endpoint or modifying the settings of an existing one.

  2. Locate the Logging Property: Within the configuration settings, find the property or checkbox labeled as "Logging" or similar. This property directly controls whether the data processed by the endpoint will be logged and indexed.

  3. Enable Logging: Check or activate the Logging property. By doing so, you instruct Martini to track and index data processed by this endpoint, making it searchable and retrievable via the Tracker.

  4. Save Changes: After enabling the logging property, ensure you save your changes to apply the new configuration.

Disabling Logging

If for any reason you decide that logging for a specific endpoint is unnecessary, or if you wish to exclude certain data from being indexed due to privacy or performance considerations, you can disable logging:

  • Uncheck the Logging Property: In the Endpoint configuration editor, simply uncheck or deactivate the Logging property for the endpoint in question. This action will exclude data processed by the endpoint from being tracked and indexed.

Considerations

  • Performance Impact: Be mindful of the potential performance implications of logging, especially for endpoints with high traffic or sensitive data. While logging provides valuable insights, it can also introduce overhead.

  • Security and Compliance: Ensure that enabling logging for endpoints aligns with your application's security policies and compliance requirements, particularly when handling personal or sensitive data.

  • Operational Monitoring: Regularly review the logged data from your endpoints to monitor for anomalies, performance issues, or errors. This proactive approach can help in early detection and resolution of issues.

By following these guidelines, you can effectively manage logging for your Martini endpoints, leveraging the Tracker for enhanced monitoring, debugging, and operational insight into your application's data processing activities.

Programmatic Logging

Martini offers developers the capability to manually interact with the Tracker search index, allowing for the creation and updating of Tracker documents programmatically. This functionality is facilitated through the use of services provided by the TrackerMethods class. Located within the core package, these services are accessible under the services/io/toro/martini directory.

Utilizing TrackerMethods

The TrackerMethods class provides a suite of services that enable direct manipulation of Tracker documents. These services are instrumental for developers who need to customize the logging and tracking behavior beyond the automatic tracking Martini performs for service invocations and endpoint activities.

Updating Tracker Documents

To modify a Tracker document, you must have access to its internalId, a unique identifier that Martini uses to track each document within the search index. For activities already being tracked by Martini, the internalId can be further utilized to append or modify data within the Tracker document. This is typically achieved by integrating the following within your services:

  • For Martini Services: Declare a string input property named $trackerId. This property acts as a reference to the Tracker document's internalId, enabling you to update the document as needed.

  • Incorporation in Code: When developing services, including this property allows the TrackerMethods services to identify and modify the corresponding Tracker document programmatically.

Best Practices

  • Selective Logging: Use programmatic logging judiciously, focusing on significant events or data points that contribute to operational insights and debugging.

  • Security and Privacy: Ensure that logged information complies with data protection regulations and application security policies, especially when logging sensitive information.

  • Performance Considerations: Be aware of the potential impact on application performance when frequently updating Tracker documents, particularly in high-volume environments.

By leveraging the TrackerMethods class for programmatic logging, developers gain finer control over how and what information is logged to the Tracker. This advanced capability enables tailored logging strategies that align with specific application requirements and operational objectives.

Discrepancies

When examining Tracker documents across various service exposures in Martini, notable discrepancies emerge. These differences are crucial for understanding how Martini logs and tracks service executions, influencing how developers might interpret and utilize Tracker data for monitoring, debugging, and analytics purposes.

Examples of Discrepancies

To illustrate the distinctions, consider the following JSON examples, which highlight Tracker documents generated by different service types:

Groovy Service Example

A typical Tracker document generated from a Groovy service might look like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
{
  "internalId": "fa30f599-6030-4ad5-836e-2a18926ee1a6",
  "externalId": "1534393691669",
  "type": {
    "id": "hello",
    "name": "hello"
  },
  "stateName": "Processed",
  "senderId": "0:0:0:0:0:0:0:1",
  "receiverId": "/api/hello/world",
  "username": "Anonymous",
  "timestamp": 1534393691629,
  "logs": [],
  "properties": [
    {
      "key": "Martini_Server",
      "value": "Martini@TORO-MM64:8080 (fe80:0:0:0:42cd:e074:a3d4:4fdc%utun0)"
    },
    {
      "key": "Duration(ms)",
      "value": "29"
    }
  ],
  "states": [
    {
      "id": 1,
      "name": "Received",
      "timeReceived": 1534393691629,
      "canBeResubmitted": false,
      "contentFileName": "request.xml",
      "contentSize": 5347
    },
    {
      "id": 2,
      "name": "Processed",
      "timeReceived": 1534393691793,
      "canBeResubmitted": false,
      "contentFileName": "response.txt",
      "contentSize": 13
    }
  ]
}

Martini Endpoint Example

Contrastingly, a document from a Martini endpoint might present as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
{
  "internalId": "97bdc10b-237f-4c27-97f9-867145ee7ad7",
  "externalId": "1534400984618",
  "type": {
    "id": "Scheduler",
    "name": "Scheduler"
  },
  "stateName": "Processed",
  "senderId": "SendScheduledEmail",
  "receiverId": "gloop:endpointServices.gloop.schedulerExamples.SendScheduledEmail/endpointServices.gloop.schedulerExamples.SendScheduledEmail",
  "username": "",
  "timestamp": 1534400984618,
  "logs": [],
  "properties": [
    {
      "key": "Duration(ms)",
      "value": "6350"
    }
  ],
  "states": [
    {
      "id": 7,
      "name": "Started",
      "timeReceived": 1534400984618,
      "canBeResubmitted": false,
      "contentFileName": "",
      "contentSize": 0
    },
    {
      "id": 8,
      "name": "Processed",
      "timeReceived": 1534400990995,
      "canBeResubmitted": false,
      "contentFileName": "",
      "contentSize": 0
    }
  ]
}

Key Discrepancies Noted

  • Type Identification: The type attribute, including id and name, typically follows the URL mapping leading path for identification. For instance, endpoints following the /hello/{name} pattern would have "hello" as both the id and name.

  • Sender and Receiver IDs: The senderId commonly represents the IP address from which the request originates. Meanwhile, the receiverId details the URL mapping at which the request was received.

Martini Endpoint Specifics

For Martini endpoints: - The initial state is usually named "Started" rather than "Received." - The senderId reflects the endpoint's name itself. - The receiverId includes the fully qualified name of the endpoint's service.