.. _snippet-framework: ################ |FRAMEWORK_NAME| ################ ********************** The Collection Factory ********************** You can think of the framework as a factory assembly line. SL1 takes input from Dynamic Applications, credentials, and discovered devices and delivers them to the factory as raw materials and work orders. During production, the framework takes the work orders and materials and determines the sequence of |STEP_NAME_PLURAL| and machines that will result in the requested finished product. The line supervisor and station technicians watch for errors and ensure that any issues are handled or reported. Finally, SL1 picks up the finished product for delivery to the customer. .. image:: ../diagrams/framework_assembly_line.png In the assembly line analogy, the supervisors do not limit the type of products that can be produced or the way in which they can be assembled. The role of the framework is to arrange the |STEP_NAME| and |STEP_NAME_PLURAL| according to the work orders, move the materials through the stages, handle routine reporting tasks, and deliver the finished items. **************************** The Framework for Collection **************************** A software framework is an abstraction that provides the ability for user-written code to customize and plug into general functionality in a controlled way to accomplish specific tasks. Your role as a |FRAMEWORK_NAME| developer is to define the |STEP_NAME_PLURAL| that will do the work, the order in which they will execute, and any customizations needed. The |FRAMEWORK_NAME| handles the basic tasks and responsibilities of collection applications, so that you can focus on the specifics of what to request and how to process it. In other words, you get to spend more time thinking about the data you want to collect, display, and act on, rather than spending time understanding snippet variables, the order of operations, and routine collection tasks like parsing and conversion of data types. The framework takes as input the configuration of SL1, the snippet argument, custom snippet functions, and any custom libraries, and then it assembles the collection sequence of events, executes that sequence, and finally returns the results to the snippet for storage in SL1. This diagram shows these responsibilities at a high level: .. image:: ../diagrams/low_code_overview.png The orange entities indicate the parts that a |FRAMEWORK_NAME| developer needs to be concerned with. The rest are handled by SL1, built-in |STEP_NAME_PLURAL|, or the framework. The following sections describe from simple to more complex, the ways in which a |FRAMEWORK_NAME| developer can customize collection. .. _low-code-snippet-arguments: ************************** |FRAMEWORK_NAME| Arguments ************************** As a user of the |FRAMEWORK_NAME|, your main method for customizing collection is the snippet argument. The *snippet_arg* is a text field that is provided as input for the collection object when the snippet executes. For a general snippet, this text field can contain anything useful to the snippet for identifying or working with the object. For a snippet, this field contains a |FRAMEWORK_NAME| specification for: * the protocol to use for device communication * a resource to request from the device * transformations to apply to the response Combined with the built-in |STEP_NAME_PLURAL| in the framework, the snippet argument allows a |FRAMEWORK_NAME| developer to solve most collection problems without any traditional programming language knowledge. .. _low-code-snippet-functions: ************************** |FRAMEWORK_NAME| Functions ************************** The snippet argument allows you to specify what values should be collected and how they should be processed using built-in |STEP_NAME_CAPITAL|, but sometimes those built-in |STEP_NAME_CAPITAL| will not be sufficient for special cases and you will need some Python code. In this case you can use or create custom |STEP_NAME_CAPITAL| in the snippet. These |STEP_NAME_PLURAL| can be added to the framework's execution |STEP_NAME| to customize the collection objects as the framework moves through each |STEP_NAME|. ***************************************** |FRAMEWORK_NAME| |STEP_NAME_CAPITAL| ***************************************** The |FRAMEWORK_NAME| executes reusable code blocks known as |STEP_NAME_PLURAL|. A |STEP_NAME| would only have a single purpose (e.g. parse string to JSON, select a value from a dict, etc). |STEP_NAME_PLURAL_CAPITAL| are chained together during execution to collect, process, and select the correct values with little to no coding required. A valid |STEP_NAME| can be a class or function, depending on where the |STEP_NAME| is registered. Execution of a |STEP_NAME| is referred as an |ACTION| and an |ACTION_ARGUMENT| is the configuration parameters for the |STEP_NAME|. If neither the snippet argument's |FRAMEWORK_NAME| syntax nor a |STEP_NAME_CAPITAL| defined in the snippet offer enough flexibility to solve a problem, you can create your own |STEP_NAME_CAPITAL| to include and reuse in a ScienceLogic Library. As a developer of |FRAMEWORK_NAME| |STEP_NAME_PLURAL| and libraries, you can customize operations through: #. a custom sequence of events #. custom |STEP_NAME_PLURAL| #. using |STEP_NAME_PLURAL| in different combinations This level of customization allows you nearly full control of the sequence of events, the flow of data, and communication with the device, while relieving you of having to worry about core functionality like error handling, logging, and code management. ******* Caching ******* The |FRAMEWORK_NAME| has a |STEP_NAME| type that enables caching. While any processor could be a Cacher, the Cacher |STEP_NAME| adds the ability to register a ``read`` function that enables the |FRAMEWORK_NAME| to fast-forward to the next step. By fast-forwarding and re-using cached data, the speed and efficiency of the framework can be improved by reusing past calculations. Cacher |STEP_NAME_PLURAL| do not have the ability to modify the result or ``result_container`` as they do not update the automatic cache key. The exception is when you are performing a ``read`` operation you are able to return the result of the read. ************************** Rewind / Collect more data ************************** The |FRAMEWORK_NAME| has the ability to have a step that requests more information from a Requestor. This functionality is referred to as rewinding within the |FRAMEWORK_NAME|. This feature allows us to continue to request more data until all data has been received. One example of this could be a paginated response from a REST API. To use this functionality the following requirements must be met: * The Requestor must be registered with a ``rewind`` function * ``@register_requestor(rewind=)`` * The processor must be registered with the correct type * ``@register_processor(type=silo.low_code.REQUEST_MORE_DATA_TYPE)`` * The processor must raise the exception ``silo.low_code.RequestMoreData`` * The index must not have been previously collected. * The maximum number of iterations is 100, unless otherwise specified. If these criteria are met, the |FRAMEWORK_NAME| will continue to collect the data until the Processor |STEP_NAME| determines there is no more data to collect. Once all of the data is collected, the result of the |STEP_NAME| will be an OrderedDictionary of all collected results. ******* Summary ******* The |FRAMEWORK_NAME| allows a developer to specify collection configuration and processes using: * snippet arguments * snippet functions * custom |STEP_NAME_PLURAL| Many issues can be solved with little to no code intervention. However, some issues problems can be solved with additional code that plugs into the framework. With this approach, you can focus less on tedious and repetitive work, and receive more value from the data that SL1 collects quickly.