ThingWorx Observability > OpenTelemetry Support for Logging in ThingWorx Platform > Custom Log Retrieval Strategy for External Logs
Custom Log Retrieval Strategy for External Logs
Overview
In ThingWorx Platform, log observability is supported through various third-party logging applications. These applications provide multiple methods to push and retrieve logs. You can use a custom log retrieval strategy to display logs from third-party logging applications. OpenTelemetry pushes logs to these applications, and ThingWorx Platform retrieves them for display. You can view these logs in Composer > Monitoring > Logs.
ThingWorx Platform provides the following:
DefaultLogRetrievalStrategyThing — Retrieves logs from ThingWorx file logs or Sumo Logic based on the configuration.
* 
DefaultLogRetrievalStrategyThing is a system object. You can update its configuration but cannot use it as a template for custom log retrieval strategies.
Extension SDK — Enables the development of a custom log retrieval strategy.
RetrieveLogs Service
The RetrieveLogs service available with the DefaultLogRetrievalStrategyThing handles log retrieval.
Log retrieval is determined by the following:
If file logging is disabled (DisableFileLogging is set to true), and OpenTelemetry is enabled (EnableOpenTelemetryForLogging is set to true), logs are retrieved from Sumo Logic.
In all other cases, logs are retrieved from ThingWorx file logs.
You can implement the RetrieveLogs service in one of the following ways:
Through Composer Using a JavaScript Service
a. Create a Thing in Composer using the LogRetrievalStrategy base template.
b. Click Services and override the RetriveLogs service.
c. Enter JavaScript code to retrieve logs from the external logging provider application.
Use Content Loader or similar functions to communicate with third-party systems.
By Creating an Extension Using the Extension SDK
a. Create an extension in Eclipse using the latest SDK version.
b. Create a Thing Template (Java class) with the LogRetrievalStrategy base template.
Your class should extend LogRetrievalStrategy class.
c. Override the Retrieve Logs Java method, and implement your custom code to retrieve logs from the external logging provider application.
d. You can update the metadata.xml file of the extension and create a Thing. Or, you can create the Thing later in Composer after importing the extension.
e. Build the extension, and import it into ThingWorx Composer.
In both cases, after you create the Thing, set it as the LogRetrievalStrategy Thing in the Logging Subsystem.
Prerequisites
Before you begin, ensure you:
Understand how to build a ThingWorx Platform extension.
Have the Extension SDK (version 9.6.0 or later), which includes the LogRetrievalStrategy Thing Template.
Know how to build and import an extension into the ThingWorx Platform.
Implementing a Custom Log Retrieval Strategy
To create a custom log retrieval strategy in Java, do the following:
1. Create a strategy Thing Template. This Thing Template serves as the code base for the Java-based algorithm. The class definition for the Thing Template is as follows:
@ThingworxBaseTemplateDefinition(name = "LogRetrievalStrategy")
public class CustomLogRetrievalStrategy extends LogRetrievalStrategy{
2. Implement and override the RetrieveLogs method.
@ThingworxServiceDefinition(
name = LoggingConstants.RETRIEVE_LOGS_STRATEGY_SERVICE_NAME,
isAllowOverride = true,
description = "Retrieve Logs from the given source",
category = "Queries")
@ThingworxServiceResult(name = "result", description = "Table entries", baseType = "INFOTABLE", aspects = { "dataShape:LogEntry" })
@Override
public InfoTable RetrieveLogs(
@ThingworxServiceParameter(
name = LoggingConstants.MAX_ITEMS,
description = "Maximum number of items to return",
baseType = "NUMBER",
aspects = { "defaultValue:" + RESTAPIConstants.DEFAULT_ITEM_COUNT }) Double maxItems,
@ThingworxServiceParameter(
name = LoggingConstants.START_DATE,
description = "Start time",
baseType = "DATETIME") DateTime startDate,
@ThingworxServiceParameter(
name = LoggingConstants.END_DATE,
description = "End time",
baseType = "DATETIME") DateTime endDate,
@ThingworxServiceParameter(
name = LoggingConstants.FROM_LOG_LEVEL,
description = "From log level",
baseType = "STRING") String fromLogLevel,
@ThingworxServiceParameter(
name = LoggingConstants.TO_LOG_LEVEL,
description = "To log level",
baseType = "STRING") String toLogLevel,
@ThingworxServiceParameter(
name = LoggingConstants.USER,
description = "Log messages for a specific user",
baseType = "USERNAME") String user,
@ThingworxServiceParameter(
name = LoggingConstants.THREAD,
description = "Log messages for a specific thread",
baseType = "STRING") String thread,
@ThingworxServiceParameter(
name = LoggingConstants.PLATFORM_ID,
description = "Log message from a specific instance",
baseType = "STRING") String platformId,
@ThingworxServiceParameter(
name = LoggingConstants.ORIGIN,
description = "Specific class or log source",
baseType = "STRING") String origin,
@ThingworxServiceParameter(
name = LoggingConstants.INSTANCE,
description = "Specific class or log source",
baseType = "STRING") String instance,
@ThingworxServiceParameter(
name = LoggingConstants.SEARCH_EXPRESSION,
description = "Keywords to search content",
baseType = "STRING") String searchExpression,
@ThingworxServiceParameter(
name = LoggingConstants.SORT_FIELD_NAME,
description = "Sort field name",
baseType = "STRING") String sortFieldName,
@ThingworxServiceParameter(
name = LoggingConstants.ASCENDING_SEARCH,
description = "Ascending search indicator (true = ascending, false = descending)",
baseType = "BOOLEAN") Boolean ascendingSearch,
@ThingworxServiceParameter(
name = LoggingConstants.OLDEST_FIRST,
description = "Search/sort from oldest to newest",
baseType = "BOOLEAN") Boolean oldestFirst,
@ThingworxServiceParameter(
name = LoggingConstants.IS_REGEX,
description = "The Search expression should be treated as REGEX",
baseType = "BOOLEAN",
aspects = { "defaultValue:" + false }) Boolean isRegex,
@ThingworxServiceParameter(
name = "logName",
description = "Keywords to search content",
baseType = "STRING",
aspects = { Aspects.ASPECT_ISREQUIRED + ":true", Aspects.ASPECT_SELECTOPTIONS +
":ApplicationLog:ApplicationLog|CommunicationLog:CommunicationLog|" +
"ConfigurationLog:ConfigurationLog|ScriptLog:ScriptLog|SecurityLog:SecurityLog" }) String logName)
throws Exception {


// Create InfoTable to hold results
InfoTable logEntriesTable = new InfoTable();

// Add Field Definitions to InfoTable.
logEntriesTable.addField(new FieldDefinition(LoggingConstants.CONTENT, BaseTypes.STRING));
logEntriesTable.addField(new FieldDefinition(LoggingConstants.USER, BaseTypes.STRING));
logEntriesTable.addField(new FieldDefinition(LoggingConstants.THREAD, BaseTypes.STRING));
logEntriesTable.addField(new FieldDefinition(LoggingConstants.PLATFORM_ID, BaseTypes.STRING));
logEntriesTable.addField(new FieldDefinition(LoggingConstants.ORIGIN, BaseTypes.STRING));
logEntriesTable.addField(new FieldDefinition(LoggingConstants.INSTANCE, BaseTypes.STRING));

// TODO: Custom Log Retrieval Strategy implementation here. Add each log entry as row to logEntriesTable

return logEntriesTable;
3. Create a Strategy Thing in the metadata.xml file of your extension.
<Things>
<Thing
enabled="true"
name="CustomLogRetrievalStrategyThing"
published="true"
thingTemplate="CustomLogRetrievalStrategy">
</Thing>
</Things>
4. Package and build an extension. For more information, see Path B: Packaging and Deploying Solutions as Extensions
5. Import the extension into ThingWorx Composer.
6. Create a Thing from the CustomLogRetrievalStrategy Thing Template.
7. Click LoggingSubsystem > Configuration.
8. Select the Thing created in step 6 as Log Retrieval Strategy.
9. Click Composer > Monitoring > ApplicationLog and verify if the logs are being retrieved from the external source.
Related Topics
Was this helpful?