Harlequin RIP SDK
Monitoring progress

The Harlequin RIP has a number of methods to monitor its progress and status when processing jobs. Some of these methods provide detail in machine-readable forms that can be parsed, logged and presented in user interfaces; other methods may only be suitable for log capture and human interpretation. The methods include:

Harlequin RIP output

As the Harlequin RIP runs, it outputs messages containing information about the RIP's configuration, operation, and the jobs it is processing. This information comes from a variety of sources:

  • Messages from the SDK and RIP. The RIP outputs some informational messages on startup indicating the amount of memory it is configured to use and the RIP version, and at shutdown indicating the peak amount of memory it did use. During operation, the RIP will announce when it is starting processing a job, it will output progress messages when it finishes various stages of processing pages (though these may be suppressed if not desired), and it announces the final completion and status of job processing. At times during processing, subsystems within the RIP may output messages about processing that is either expected to take significant time, or have informational value.
  • Messages from the configuration. The configuration stages for a job may include commands to output messages about how the RIP is being configured. For example, most procedure sets (ProcSets) that provide support for advanced features announce the version of the ProcSet when it is loaded.
  • Messages from the job. PostScript jobs may include commands to write data to files. The PostScript %stdout% and %stderr% file objects are connected by the interpreter to the message channels, and so data written to these file objects will appear in the RIP output. The PDF interpreter extracts metadata from PDF jobs and announces the PDF version, job title, creator, creation data and other details.
  • Warnings and errors. If the RIP or SDK encounter a problem processing a job, a warning or error message may be output, often including detail of the root cause and where the problem occurred.
  • Messages from raster backends and customer callbacks. The SDK provides an interface to the message system that raster backends and other code you supply can call. The SkinMonitorf(), SkinEMonitorf() and SkinVEMonitorf() functions can be called to format and output messages. These functions need the core library to be loadable, so RIPs on Windows must have set the DLL load path.

Log files

The "clrip" application layer can route the output messages from the RIP and SDK to one or more destinations. All messages are normally sent to the standard output stream of the application.

Messages can also be appended to a log file containing all messages for all jobs processed by using the -X command-line option. This log file is in the RIP's SW data directory, called SW/LE_LGFLE. If you are using a different writable data directory (using the -W command-line option), then the log file will be in that directory instead. This log file is never truncated by the RIP and it will accumulate over multiple runs of the RIP. If you are capturing this log file or using a similar method in a production application, you may want to delete or rotate the log file. Rotating the log file cannot be performed while the RIP is running. The -X option can be used with Scalable RIP, but note that there will be a separate log file for the controller RIP and each Farm RIP, in their respective data directories. The controller log file will show processing information for job submission and then feedback from the Scalable RIP's progress monitor, each Farm RIP log will contain a subset of the page information for the entire job.

Messages can be appended to a separate log file for each job, using clrip's -L option. This appends message output to a log file located in the same directory as the input file, which makes it unsuitable for use with some input sources such as hot folders. The log file name is constructed by appending .log to the input file name. These log files are not deleted or rotated by the RIP either, but can be deleted by the application or another process once the job is completed.

Both log files can be enabled at once, if desired.

Error output is normally sent to clrip's standard output for compatibility purposes, but can be sent to its standard error by using the -err command-line option.

Global Graphics strongly recommends that you do not try to parse log file output for data to present in user interface or use in your application. There are many problems with parsing log files, which can be solved by using the monitor events instead. Among the problems are:

  • Lost channel and type information. The message API contains information about whether each message is an error, warning, informational, or debugging, and about the source of the message. All of this information is lost when reduced to just printable text that can be sent to standard output or a log file.
  • Changing message text and formats. Global Graphics may change the text of messages or the format of data within a message in different releases to clarify it. If you are parsing messages from a log file, you may not recognize a message that was changed.
  • Localization. Some messages are localizable, and may go through a message translation layer for the user's configured locale. If you are parsing messages from a log file, you may not recognize messages that have been translated.
  • Thread interleaving. If log file output is constructed from more than one message, the output may be disrupted if more than one RIP outputs messages at the same time. Either lines from different messages sources may be interleaved in the log file, or even parts of the same line may be interleaved from different message sources. This is especially likely when the job includes commands to write output itself.
  • Timely delivery. Log file output is usually buffered by the standard output or the file system. You are not guaranteed to be see all of the output that has been generated until the log file is closed, which may be on SDK shutdown.
  • Transcoding issues. Job filenames and metadata (creator, job name, etc.) may be presented to the RIP in a mixture of languages and encodings. The RIP tries to transcode these when presenting messages through events, but when writing to standard output or a log file the user's locale may affect whether these transcodings are readable or parsable.

Monitor event messages

Monitor information output from both the core library and the SDK is routed through monitor events. Monitor events carry metadata about each message, including a related timeline, the output channel, and the monitor information type (including an error code and in many cases a machine-parsable unique ID for the message). This is useful when you are performing complex integrations. Individual messages can be diverted, suppressed, or used to trigger warnings or alerts in your DFE or GUI.

The event system is available from starting the SDK for the entire duration until the SDK is shutdown. The SDK now allows installation of a default monitor callback function using SwLeSetMonitorFunction() that can be used to capture and contextualize monitor information that is not presented through events.

All messages sent from the core library, or from the SDK functions SkinMonitorf(), SkinEMonitorf() or SkinVEMonitorf(), are formatted into a message buffer, and then issued through a SWEVT_MONITOR event. This event has an associated SWMSG_MONITOR message. The SWMSG_MONITOR message contains a pointer to the message buffer, the length of the text in the message buffer, a timeline reference, a monitor channel, and a monitor type.

The message text is expected to be in UTF-8, potentially with a byte-order mark in front. However, since it may be generated from job output, it may potentially be badly formed, or have not been transcoded from a job-specific encoding. The message text may also not be zero-terminated, or may include internal zero bytes, so the message buffer length should always be used to determine how much valid data is in the buffer. If there is a byte-order mark at the start of the message buffer, then the client may use this to convert from UTF-8 to a desired encoding, but should check for errors in transcoding.

The timeline reference in the event message may provide a useful reference to associate the message with the process within the RIP or SDK that produced it. Not all messages have a valid timeline reference.

The channel identifier in the event message separates the routes that messages may take through the message system. There are a set of predefined channels that the RIP uses in SW_MON_CHANNELS, but you can add additional channels in your code. The channel may be used to separate the destination of messages at the last stage of the message system. For example, the "clrip" application may divert messages sent to the MON_CHANNEL_STDERR channel to the application's standard error stream, or may colorize messages for different channels when using the -! command-line option.

The message type in the event message is a field that combines the class of the message (is it an error, a warning, informational, or debug?) with a sub-categorization and in some cases a unique ID that identifies the exact semantic meaning of this particular message.

The event's channel and type (class and ID) should be used to distinguish messages and decide how to handle and respond messages in preference to parsing the message text.

If all that you require is to capture the entire message stream and route it into your application, then installing a message capture function with SwLeSetMonitorFunction() is sufficient. This will only give you access to the message text, and not the timeline reference, channel or type. If you need access to the timeline reference, channel, or type, then you will need to install an event handler for the SWEVT_MONITOR event. Event handlers can be installed individually using SwRegisterHandler(), and in groups using SwRegisterHandlers():

static sw_event_result HQNCALL monitor_filter(void *ctx, sw_event *evt)
{
SWMSG_MONITOR *mon = evt->message ;
if (mon == NULL || evt->length < sizeof(*mon) )
if ( mon->channel == MON_CHANNEL_STDERR ) {
// ... set state to divert message
}
sw_event_result result = SwEventTail(evt) ;
// ... undo diversion
if ( result == SW_EVENT_UNHANDLED )
return result ;
}
static sw_event_result HQNCALL monitor_last(void *ctx, sw_event *evt)
{
SWMSG_MONITOR *mon = evt->message ;
if (mon == NULL || evt->length < sizeof(*mon) )
// ... process monitor message
return SW_EVENT_HANDLED ; // This stops further processing
}
// ... in initialisation code:
{ monitor_filter, NULL, 0, SWEVT_MONITOR, MON_PRE_DEFAULT},
{ monitor_last, NULL, 0, SWEVT_MONITOR, MON_DEFAULT_HANDLER},
} ;
// ... cleanup and return ...
}
HqnResult sw_event_result
A type used for return values from Event handlers.
Definition: eventapi.h:625
sw_rdr_result SwRegisterHandlers(sw_event_handlers *handlers, int count)
Register multiple Event Handlers atomically.
sw_event_result SwEventTail(sw_event *event)
Call the remaining Handlers for the current Event, returning the value that would have been returned ...
@ SW_EVENT_HANDLED
Definition: eventapi.h:604
@ SW_EVENT_FORCE_UNHANDLED
Definition: eventapi.h:602
@ SW_EVENT_UNHANDLED
Definition: eventapi.h:611
@ SW_EVENT_CONTINUE
Definition: eventapi.h:600
@ SW_RDR_SUCCESS
Definition: rdrapi.h:617
#define NUM_ARRAY_ITEMS(_array_)
Definition: std.h:144
@ MON_CHANNEL_STDERR
Definition: monevent.h:155
@ MON_DEFAULT_HANDLER
Definition: monevent.h:119
@ MON_PRE_DEFAULT
Definition: monevent.h:118
#define NULL
Definition of NULL pointer.
Definition: hqtypes.h:37
static sw_event_handlers mon_handlers[]
Definition: skintest.c:2065
Message for SWEVT_MONITOR event.
Definition: monevent.h:480
sw_mon_channel channel
Definition: monevent.h:485
Atomic multiple Handler registration.
Definition: eventapi.h:759
Event structure.
Definition: eventapi.h:650
void * message
Definition: eventapi.h:668
size_t length
Definition: eventapi.h:676
@ SWEVT_MONITOR
Definition: swevents.h:206

The example above show two event usage patterns that are useful with monitor events. The event handler declared as monitor_filter() looks at a message, decides whether to filter it in some way, and either modifies the message or sets state that will be used by a different layer to determine what to do with the message. It passes the event on to lower priority handlers, and then restores any state it modified when filtering. This is the method used by the "clrip" application when diverting output for the MON_CHANNEL_STDERR channel to the standard error if the -err command-line option is specified. The event handler declared as monitor_last() stops any lower-priority event handlers from running. This is the method used by the SDK's fallback message handler.

The priorities that should be used by monitor event handler are complex, and are explained in a separate section.

The "clrip" application uses C standard I/O at the last level of handling the monitor output, either from the events or from the monitor callback functions used to write data from the RIP or skin, and in some other locations before the skin is fully booted and for some internal debugging information. It is easy to divert output messages from the SDK and the RIP to other log files or log systems uniformly by reconfiguring a monitor callback function and/or installing event handlers.

The "clrip" application uses monitor event handlers to implement the color output console selected using the -! option. If you use that option you will notice some extra timeline information for the skin and skin job timelines, and also some messages appearing in different colors because they are routing to different channels internally.

The clrip skin normally runs in a compatibility mode, where output to the core's %stderr% stream is routed to the same output channel as the standard output, but skin calls to output to standard error are routed to the standard error channel. The -err option removes the compatibility routing and sends all %stderr% output from the core and the skin to standard error.

The monitor event system is active from starting the SDK to stopping the SDK. Any messages output using SkinMonitorf(), SkinEMonitorf() or SkinVEMonitorf() before starting the SDK or after stopping the SDK will be sent directly to the default message handler function set by SwLeSetMonitorFunction(), or will be ignored if no default handler function has been set.

All of the message formatting routines in SDK use the RIP core's swncopyf() call, so all the formats supported by it can be used.

Monitor event handler priorities

The monitor event interface defines a hierarchy of priorities, which are suggested for use when installing handlers. The core library and SDK only register handlers at a couple of levels, but understanding what the priorities are intended for may help you if you register your own monitor event handlers.

Most handler functions should pass monitor messages to lower priority handlers, by returning SW_EVENT_CONTINUE from the handlers. Monitor event handler functions that augment the message or the environmental state for processing the message should modify state, call SwEventTail() and capture the return value, restore state, and change the return value to SW_EVENT_FORCE_UNHANDLED if the SwEventTail() call returned SW_EVENT_UNHANDLED. This is the normal event handler filtering pattern.

The skin is expected to install its normal output handler at priority MON_DEFAULT_HANDLER. The "clrip" application color console handlers installed when using the -! command-line option are installed at this priority. The "clrip" application handler to direct MON_CHANNEL_STDERR output to the standard error stream is registered at the MON_PRE_DEFAULT priority, just above the color console handlers.

The SDK may install an event handler to filter the progress messages that will be output at the MON_FILTER priority. Filtering out messages should be done at this relatively high priority, so that lower layers don't waste time processing messages that will be discarded.

The core library registers some handlers at the very low MON_COMPATIBILITY priority. These handlers are only called if a default handler is not installed by the application. They convert unhandled monitor event messages for progress and halftone channels to output to files on the legacy progress device. The core library also registers a handler at the even lower MON_FALLBACK priority. This is called only if a default handler is not installed by the application. It converts all remaining monitor event messages to output to an unnamed file on the legacy %monitor% or %console% devices, if either are mounted.

The "clrip" application installs its own fallback handler at a lower priority than the core's MON_FALLBACK handler, in case neither %monitor% nor %console% devices are mounted. This is the handler that will direct any messages to the callback function registered using SwLeSetMonitorFunction().

Monitor class, error, and IDs

Error messages are issued by the RIP when an error is handled by the RIP's PostScript error handler. Errors will normally cause a job to be aborted, but the error handler can be overridden to suppress some errors. In this case, it is possible to see a monitor event message indicating an error even when the job does not terminate. Whether the job is terminated may also be affected by the error detail event handling.

The event message's type field can be decomposed into the class, sub-class, and for errors the error number and ID, as detailed in the sw_mon_type documentation. If the ID part of a message's type is non-zero, the entire type field can be treated as a unique identifier for that particular message and its root cause.

Not all errors or messages in the RIP have unique IDs (for those that are not unique, the ID part of sw_mon_type is zero). For memory allocation errors and interrupt errors, this is deliberate. The exact location that an interrupt or memory error is triggered is generally not informative, since it is related to a condition external to the code triggering the error, and may not be repeatably triggered at that location. Global Graphics is working on expanding the use of error IDs where it will be informative.

The distribution contains a CSV file with the unique IDs and their associated names and message reasons (monitoruids.csv), and also an HTML file with the unique IDs and their associated names and message reasons sorted both by number and by name (monitoruids.html, also here). Global Graphics has procedures in place to ensure that unique IDs for a particular root cause do not change between releases, and that obsolete unique IDs do not get re-used for different purposes. Comparing the unique IDs listed in these files against the monitor event message's type field is recommended as the most reliable method of identifying specific output messages.

Progress events

Some of the monitor event messages are output by the core library to provide job timing information. When a job is processed, information of the following type is displayed in the command window:

Starting Job On Tue Oct 24 19:50:29 2006
Interpretation time: 0.900 seconds (00:00:00.900)
Preparing to render page
Render prepare time: 0.000 seconds (00:00:00.000)
Value of /LE in /PageBufferType. Using TIFF by default.
Print time: 1.283 seconds (00:00:01.283)
Total time: 2.201 seconds (00:00:02.201)
Job Completed: untitled

The lines with timing information may be filtered out if you do not want this information to appear in the log. The SDK provides the progevts_suppress_types() function to filter out the types of message that you do not want to see.

Timelines

Timelines can be used to detect and measure the start and end of many processing steps in the RIP, and also to get meaningful indications of progress on many of these processes. A timeline represents an object or a process that has a finite life. Timelines are created by some processing steps when they start, updated with progress as they proceed, and either ended or aborted when they finish.

Timelines may be monitored through the use of timeline events. Timeline events are all associated with a SWMSG_TIMELINE message. This message contains, amongst other fields, the timeline reference, its parent timeline in the hierarchy, its state, the unit of progress, the start, end, and current progress position of the timeline, and a name or title associated with the timeline. Timelines may have context data associated with them, allowing any code with a timeline reference to attach a data pointer to a timeline that it can retrieve later. This is useful for maintaining an association between a timeline and objects represented in your application (for example, a reference to a progress bar in a user interface might be attached to a timeline).

Events are issued when timelines are started, ended, or aborted; when progress is recorded on them; and when the timeline title is changed. Timelines may be bounded or unbounded in progress, depending whether they represent a process with a known limit or not. The timeline extent may be modified for some timelines, which will issue another event type.

Each process or entity represented by a timeline will have a unique timeline reference. If there are multiple entities or processes of the same type running at the same time, then they will have different data associated with each different timeline reference.

To monitor progress using timelines, you need to register event handlers for the appropriate timeline events. You will probably want to register events for timeline start, end, and abort, and maybe also for progress, extent changes and maybe for title changes:

static sw_event_handlers event_handlers[] = {
} ;
if ( SwRegisterHandlers(event_handlers, NUM_ARRAY_ITEMS(event_handlers)) != SW_RDR_SUCCESS ) {
// ... cleanup and return ...
}
@ SW_EVENT_DEFAULT
Definition: eventapi.h:563
@ EVENT_TIMELINE_PROGRESS
The Timeline progress has changed.
Definition: timelineapi.h:604
@ EVENT_TIMELINE_ENDED
The Timeline has ended.
Definition: timelineapi.h:637
@ EVENT_TIMELINE_START
The Timeline has started.
Definition: timelineapi.h:581
@ EVENT_TIMELINE_ABORTED
The Timeline has aborted.
Definition: timelineapi.h:670
@ EVENT_TIMELINE_TITLE
The Timeline is about to be renamed.
Definition: timelineapi.h:590
@ EVENT_TIMELINE_EXTEND
The extent of the Timeline has changed.
Definition: timelineapi.h:597
static void tl_end(sw_timeline *tl, HqBool *broadcast)
Recurse through children, then issue an Event and discard timeline.
Definition: timeline.c:1124

Each timeline handler should test the timeline message to ensure it is operating on the correct timeline type, using the SWMSG_TIMELINE::type field. It is common to share the same handler for similar types of handler, such as timeline end and timeline abort events, or the timeline progress and extent events. You can distinguish the use cases by examining the event type field in sw_event::type. These fields have the same name, so be careful to ensure you are testing the correct structure:

static sw_event_result HQNCALL tl_end(void *context, sw_event *ev)
{
SWMSG_TIMELINE *msg = ev->message ;
if (msg == NULL || evt->length < sizeof(*msg) )
if (msg->type == SWTLT_JOB) { // Job timeline
HqBool ok = ev->type == EVENT_TIMELINE_ENDED ; // Did it end or abort?
// ... process timeline event
}
}
@ SWTLT_JOB
Definition: swtimelines.h:71
int HqBool
Harlequin standard boolean type.
Definition: hqtypes.h:502
Common timeline event message.
Definition: timelineapi.h:875
sw_tl_type type
Definition: timelineapi.h:878
sw_event_type type
Definition: eventapi.h:656

Event handlers should be deregistered if you no longer need them:

SwDeregisterHandlers(event_handlers, NUM_ARRAY_ITEMS(event_handlers)) ;
sw_rdr_result SwDeregisterHandlers(sw_event_handlers *handlers, int count)
Deregister multiple Event Handlers.

The description of each timeline in Harlequin Core Timelines or SDK and Skin timelines indicates what process or entity it represents, and the units of progress (if any) that are reported for it. The units of progress may be bytes, pages, lines, bands, or other units, so be careful to understand what is being represented.

Timeline events may also be used to trigger destruction of objects at suitable points. For example, skin code that allocates memory from the core library's memory pools may need to perform cleanup actions before the RIP is shut down. The SWTLT_CORE_READY timeline provides a convenient hook to monitor when the RIP is about to shut down, and to remove any references to core library memory pools.

SDK and Core library Timelines

The timelines defined by the core library are described in Harlequin Core Timelines. The well-known timelines used by the skin are described by SDK and Skin timelines. You may create your own timelines too.

The timelines that are probably of most interest for monitoring progress are:

  • SWTLT_CORE. This is an ancestor timeline for all other timelines created by the core. It is also a child of the SWTLT_SKIN timeline created by the SDK when it is started, discoverable by SDK and application code by calling SkinTimeline(). You should be able to navigate from any timeline reference to the skin timeline using SwTimelineOfType(), which also means that you have access to any content pointer attached to that timeline. This can help keep code modularized, avoiding the need for global variables to communicate between otherwise dissociated callbacks from the RIP. The SWTLT_CORE timeline notably does have a progress measure, it is the job number (but see the definition for more detail).
  • SWTLT_SKIN_JOB. This timeline tracks jobs submitted from the SDK to the core library. Its lifetime will encompass the entire processing of the job within the core, and so can be used to clean up files or other resources related to the job's management by the application.
  • SWTLT_JOB_STREAM, SWTLT_JOB_CONFIG, and SWTLT_JOB. A job submitted to the core library is a stream of data that may contain one or more configuration changes and print jobs. The job stream timeline is the parent of SWTLT_JOB_CONFIG and SWTLT_JOB. The latter of these is most interesting, it represents a running job, with progress measured in pages (as they are interpreted). Any of these timeline references may also be used when cancelling a job to ensure just the job specified is cancelled.
  • SWTLT_INTERPRET_PAGE and SWTLT_RENDER_PAGE. These timelines represent the interpretation or rendering of each individual page. Counting the start and end of these timelines can provide an alternate method of capturing progress of the RIP on a job. The page number being interpreted or rendered can be retrieved from a context attached to these timelines.
  • SWTLT_PGB. This timeline represents the output of each individual page. It has progress and extent measures that allow the number of lines output and the number of lines rendered by the RIP and ready for output to be monitored.
  • SWTLT_SCALABLERIP_JOB. This timeline only exists in the Scalable RIP's controller RIP. It represents jobs submitted to the Scalable RIP. Progress is measured as the number pages complete, without regard to the order of completion.

Error detail events

Monitor event messages for errors may be output when an error is handled even if it does not terminate a job, so they are useful for capturing error detail, but not a definitive indication that a job was terminated. A different method should be used to confirm whether a job was terminated due to an error, such as monitoring the job timeline or monitoring the error events.

The events SWEVT_INTERPRET_ERROR or SWEVT_RENDER_ERROR are issued if a job fails, and the normal PostScript error handling did not suppress the error. A SWMSG_ERROR message is associated with both of these events. These events with their message act both as a notification about an unhandled error, information about the error detail, and a last-chance control to indicate how to report or handle the error.

The SWMSG_ERROR message contains a timeline reference of the component generating the error; the page number on which the error occurred; the error UID, error name, command, and detail that were provided to the PostScript error handler, and two boolean fields indicating whether the job should be marked as failing; and whether normal error reporting should be suppressed.

The job may already have been aborted by a different error, so setting the job failure boolean to FALSE is not guaranteed to ensure it continues.

If the SWEVT_INTERPRET_ERROR event is issued, the job has already been terminated, so setting the suppress handling boolean just suppresses the normal error report. If the SWEVT_RENDER_ERROR is issued, setting the job failure boolean to FALSE and suppress handling to TRUE may allow subsequent pages of a job to continue outputting.

Legacy devices

If no default monitor event handler is installed by the application, the core library's compatibility layers may redirect messages to files on some legacy devices, if they are mounted. These methods of reporting progress are compatibility methods for legacy integrations only, and should not be used for new integrations. Install a default monitor event handler instead.

The legacy %progress% device

If no monitor event handler handles a message before the core library's ::MON_COMPATIBILTY priority handlers, messages on the progress channel will be directed to the %progress%JobLog file, and messages on the halftone channel will be directed to the %progress%HalftoneInfo file. If a device is mounted using the %progress% name, then these files will be opened, written, and closed for these messages.

The legacy %monitor% and %console% devices

If no monitor event handler handles a message before the core library's ::MON_FALLBACK priority handlers, messages will be directed to an unnamed file on the %monitor% or %console% devices. If a device is mounted using the %monitor% or %console% name, then an unnamed file will be opened, written, and closed for all remaining messages.

Formatting durations

The timing messages produced by the RIP have a format that includes both a human-friendly and a machine-parsable part (as shown in Progress events). If you want to output messages using the same format as the RIP, you can call the core library utility function swncopyduration(). This is the same function as the RIP uses to format durations specified in milliseconds to include in output messages.

Monitoring Scalable RIP

Scalable RIP timing information

The console and job log output from the Scalable RIP differs in the detail from a single RIP:

Initial RIP virtual memory: 4 MiB (4584 KiB) used, 64 MiB (65536 KiB) commit limit, 128 MiB (131072 KiB) reserved
RIP Version 14.0r0 (#1f33df00)
Ripping file %C%ggtest/OneHundredPages-01.pdf as PDF.
Starting Job On Thu Jun 15 00:03:03 2023
Title: untitled
Subject: Not Available
Author: Not Available
Creator: Not Available
Producer: Acrobat Distiller 10.0.0 (Windows)
CreationDate: D:20190502124728+01'00'
ModDate: D:20190502124728+01'00'
Trapped: Not Available
Scalable RIP Accepted Job 1 On Thu Jun 15 00:03:03 2023
File: %C%ggtest/OneHundredPages-01.pdf
Config: %configps%CMYKComposite300dpi
Priority: 0
Scalable RIP Metadata for Job 1
File: %C%ggtest/OneHundredPages-01.pdf
Pages: 100
Chunk Size: 1
Scalable RIP Starting Job 1 On Thu Jun 15 00:03:03 2023
Total time: 0.024 seconds (00:00:00.024)
Job Completed: untitled
Scalable RIP Job 1 rendered 25 pages of 100...
Scalable RIP Job 1 rendered 51 pages of 100...
Scalable RIP Job 1 rendered 77 pages of 100...
Scalable RIP Job 1 rendered 100 pages of 100...
Scalable RIP Job 1 Schedule time: 15.120 seconds (00:00:15.120)
Scalable RIP Job 1 Active time: 4.016 seconds (00:00:04.016)
Scalable RIP Job 1 Elapsed time: 4.016 seconds (00:00:04.016)
Scalable RIP Job 1 Completed: %C%ggtest/OneHundredPages-01.pdf
Peak process working set memory: 40960 KiB used
Peak process RIP memory: 15944 KiB used

Jobs are submitted and processed asynchronously, so the Total time reported by the RIP is just the time required to submit the job to the Scalable RIP's job controller, and is reported before the job is actually rendered. The Scalable RIP reports:

  • When it accepts a job for processing
  • When it starts processing pages from the job, and
  • When it has completed (or failed to complete) all pages from the job.

On completion, it reports three times:

Elapsed Time
This is the time from accepting a job until all pages from the job are completed. If there is a job of the same or higher priority running already, then the job will not start until that job is finished, so the elapsed time will include the amount of time spent waiting to start. Similarly, if a higher priority job interrupts the job, the elapsed time will include the time spent waiting for the higher priority job.
Active Time
This is the time from starting to process the first page range of a job until all pages from the job are completed. In the first scenario above (i.e., if there is already a job of the same or higher priority running), the time waiting to start will not be included in the active time. However, in the second case where a job is interrupted after the first page range has been started, the active time will include time spent waiting for the higher priority job.
Schedule Time
This is the accumulated time for processing all page ranges in the job, measured from the time the page range is sent to a Farm RIP for processing until the time the page range completion was received from the Farm RIP. It is not an exact measure of the amount of processing time used because the page range processing is pipelined to prevent idle RIPs. The request to process a page range can be sent before a Farm RIP is actually available, so the Schedule Time will include time waiting for the previous page range to complete for each page range.

Scalable RIP console and log output

In the Scalable RIP, Farm RIP monitor output cannot be seen by default. This can make the Scalable RIP appear to be doing nothing for large jobs where all RIPs are busy processing a single job for a long period of time. The controlling RIP will report progress made by the Farm RIPs, to give the user feedback that the RIPs are making progress. Page progress monitoring is time based and is controlled by the global JSON configuration. For example, progress lines look like the following:

Scalable RIP Job 2 rendered 3 pages of 31...
Scalable RIP Job 2 rendered 9 pages of 31...
Scalable RIP Job 2 rendered 15 pages of 31...
Scalable RIP Job 2 rendered 21 pages of 31...
Scalable RIP Job 2 rendered 27 pages of 31...

By default, a progress line will be output every 1000 milliseconds (1 second). This default value can be changed by modifying the value associated with the key ProgressReportMillisec in the global configuration JSON (usually in the SW/RIPFarmConfig/ripfarm_global.json file).

Farm RIP monitor output

On MacOS and Linux, when Farm RIPs are launched by the controlling RIP, the standard out, standard error, and the standard input file descriptors are redirected to /dev/null. This means you will not see any output from the Farm RIPs directly. Should you wish to see monitor output from all the farm RIPs you can set the global configuration option FarmRIPOpenConsoleWindow to true. This means that the Farm RIPs inherit the standard input, output, and error file descriptors from the controlling RIP when they are forked and execed. Doing this results in you seeing all the interleaved monitor output from all RIPs, which can sometimes be useful for debugging or trying to find issues, but is difficult for users to comprehend.

On Windows, console applications work differently to UNIX-based systems and each Farm RIP launched gets its own console to interact with. By default, these consoles do not have a window. This means you will not see monitor output from the Farm RIPs on Windows by default. As a debug aid, you can use the global configuration options FarmRIPOpenConsoleWindow and FarmRIPOpenConsoleMinimized to see these console windows. The console Windows are named carefully so that you can set properties on these console Windows to save their position, size and color.