From 439e1fecbb93434b71f709014cb56d1ca36d87de Mon Sep 17 00:00:00 2001 From: Dmitry Nikolaev Date: Fri, 5 Apr 2024 16:26:20 +0200 Subject: [PATCH 01/36] Change log for PM client Signed-off-by: Dmitry Nikolaev --- pm-client/CHANGELOG.md | 530 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 530 insertions(+) create mode 100644 pm-client/CHANGELOG.md diff --git a/pm-client/CHANGELOG.md b/pm-client/CHANGELOG.md new file mode 100644 index 00000000..89a3c311 --- /dev/null +++ b/pm-client/CHANGELOG.md @@ -0,0 +1,530 @@ +# Change Log + +## 2.6.4 (2024-03-04) + +- Upgrade to Java 17. +- URL encoding fixes. + +## 2.6.3 (2023-12-12) + +- New Java version. + +## 2.6.2 (2023-10-03) + +- Open metric help url by default browser. +- Adjust poll time to get interval data once. + +## 2.6.1 (2023-07-14) + +- New Java version. + +## 2.6.0 (2023-03-02) + +- Upgrade to Java 11. + +## 2.5.16 (2023-02-01) + +- New Java version. + +## 2.5.15 (2022-10-12) + +- Fix metric list loading. +- General maintenance. + +## 2.5.14 (2022-04-11) + +- New Java version. + +## 2.5.13 (2022-02-23) + +- Host name validation fixed. +- General maintenance. +- Sort alphabetically menu item to sort tabs and tree. + +## 2.5.12 (2022-01-10) + +- New Java version. + +## 2.5.11 (2021-04-26) + +- Fix server certificate check based on truststore. +- Update installer signing certificate. + +## 2.5.10 (2021-02-19) + +- New Java version. + +## 2.5.09 (2021-01-08) + +- New Java version. + +## 2.5.08 (2020-09-18) + +- Fix error at populating perfdesks list after perfdesk save. +- Alphabetical sort of perfdesks in tree. + +## 2.5.07 (2020-09-16) + +- Integrity fixes, new Java version. + +## 2.5.06 (2020-07-31) + +- Integrity fixes, new Java version. + +## 2.5.05 (2020-03-24) + +- Integrity fixes, new Java version. + +## 2.5.04 (2019-12-06) + +- Integrity fixes, new Java version. + +## 2.5.03 (2019-12-02) + +- Various bug fixes. + +## 2.5.02 (2019-10-18) + +- Integrity fixes, new Java version. + +## 2.5.01 (2019-09-24) + +- Integrity fixes. + +## 2.5.00 (2019-06-26) + +Version for z/OS V2R4: +- New Monitor III CRYOVW report and metrics. +- New WLM resources and metrics. +- HTTPS support. + +## 2.4.91 (10/22/2018) + +- Integrity fixes, new Java version. + +## 2.4.90 (2018-06-22) + +- Corrected details description for SSID. + +## 2.4.89 (2018-04-03) + +- Integrity fixes, new Java version. + +## 2.4.88 (2018-01-22) + +- Integrity fixes, new Java version. + +## 2.4.87 (2017-06-02) + +- Integrity fixes. + +## 2.4.86 (2017-03-14) + +Version for z/OS V2R3: +- New metrics for various resources. +- Enable resource attributes for PCIE_FUNCTION resources. +- Add attribute "structure encrypted?" to CF_STRUCTURE. + +## 2.4.85 (2017-03-07) + +- New IBM Java 8 JRE. +- Installable image signed with new certificate. + +## 2.4.84 (2016-11-17) + +- Integrating 2GB support (OA48913). + +## 2.4.83 (2016-04-07) + +- Installable image signed with new certificate. + +## 2.4.82 (2016-01-25) + +- Enable resource attributes introduced with Absolute hardware group capping and OPT parameter ABSMSUCAPPING. +- Fixed error when asking for metric helps. + +## 2.4.81 (2015-07-21) + +- Bundled with IBM Java 8 JRE. + +## 2.4.73 (2015-04-15) + +- Fix error when changing the perfdesk color. + +## 2.4.72 (2015-03-17) + +- Version for z/OS V2R2. +- New resource for PCIE and SCM. +- New metrics for job USAGE and zFS Sysplex monitoring. + +## 2.4.71 (2014-10-22) + +- Include metrics for MT mode for z/OS V1R13 and z/OS V2R1. + +## 2.4.70 (2013-06-10) + +- Fix problem with CPC metric "# processors with medium share (IIP) by partition". + +## 2.4.69 (2013-03-15) + +- Version for z/OS V2R1. + +## 2.4.68 (2011-07-05) + +- Version for z/OS V1R13. + +## 2.4.67 (2011-02-14) + +- Bundled with IBM Java 6 JRE. + +## 2.4.66 (2010-10-08) + +- Removed limitation when exporting data. +- Fixed plot dialog problems when displaying large values. +- The message browser does no longer pop up to the foreground when a new message arrives. + +## 2.4.65 (2010-07-09) + +- Version for z/OS V1R12. + +## 2.4.62 (2010-01-21) + +- Omit '[asid]' when starting Analysis Perfdesk for job workscopes (PMR 19130,49R,000). + +## 2.4.61 (2009-07-21) + +- Version for z/OS V1R11. + +## 2.4.60 (2009-06-22) + +- New option in View menu to select a decimal separator used for numbers in CSV export. +- Fixed Plot dialog (selection of list-valued series). + +## 2.4.59 (2009-05-27) + +- Fixed error where wrapping of dataview sample buffers caused chart values to be overwritten (PMR92206). + +## 2.4.58 (2009-04-29) + +- 'Saving Plot Data': Output format changed to CSV (from WK1) in the CSV files, a ';' is used as a + column separator and numbers are represented using english/US format, i.e. a '.' is used as the + decimal symbol. + +## 2.4.57 (2009-02-10) + +- Version for z/OS V1R10 (PM 2.4.51). +- Bundled with IBM Java 5 JRE (PM 2.4.50). +- IPv6 support. +- Enable resource names with blanks (e.g. enclaves). +- Fixed Firefox invocation (error "Windows cannot find -requestpending"). +- Fix 'remove values' from dataview. +- Re-enable DDS level 2116 XML for Linux image. +- Re-enable z/OS 1.2 XML. +- XML parsing: make 'historical' flag dependent on mintime. +- Fixed ArrayIndexOutOfBounds Exception when opening a PerfDesk. + +## 2.4.49 (2008-01-29) + +- Initial System z10 and HiperDispatch support. + +## 2.4.48 (2007-07-16) + +- First version for z/OS V1R9. +- Introduced filters for XCF listtypes. +- If a filter string is chosen which contains special characters '(', ')' or '*', these + characters are masked with '\'. In case you need the '*' to respresent a string with + any character, please delete the '\'. +- Changed dataview plot/save functionality so that names containing '(' and ')' are allowed. +- Changed legend in dataviews: Time stamp shown now is the starting time of the intervall. +- Changed computation of space reserved for numbers to the left of the y-axis in horizontal + charts and plots; space was undercharged in some cases. + +## 2.4.44 (2007-02-01) + +- Adaption to Daylight Saving Time Changes in 2007. + In March 2007, the effective dates of Daylight Savings Time (DST) in the U.S. and + Canada will change. Dates and times could be affected by this change. If not addressed, + time and date calculations could be incorrect. The RMF PM is affected because of it's + dependency on the Java JRE. The JRE of RMF PM is replaced with a DST compatible JRE. +- Deactivated Single Logon. +- Updated resources/simulated.xml for z/OS 1.8. +- Fixed problem for historical sampling in DataView Properties menu and Set Sample Time + dialog ("Sample..." button of PerfDesk), if timezone of the system where RMF PM is running + is different from the timezone of the (DDS) host. +- DataView Properties Menu always has a Sampling Panel, also for Dataviews not yet started. +- Deleted unused error messages. +- For z/OS metrics, the help file from the DDS is used. +- Fixed PC/T0300MAI: fixed historical sampling problem, that cause RMF PM error message + "java.text.ParseException:Unparseable date ..". +- Fixed incorrect invocation of Firefox and Netscape browser. + +## 2.4.35 (2006-05-29) + +- Fixed error that wrong values were returned for time series data when drawing charts in a dataview. + +## 2.4.34 (2006-04-19) + +- Brackets around ASID in job names changed from () to [] so that 'Plot/Save Series' function will + work correctly. + +## 2.4.33 (2006-02-01) + +- Listtypes (i.e. metrics "by ...") which were newly introduced with z/OS 1.7 + are available in the filter list of the 'New Dataview' dialog. + +## 2.4.32 (2005-11-10) + +- Fixed PC/T0276MAI: RMF PM doesn't support password in mixed case. +- Fixed PC/T0272MAI: RMF PM working incorrectly after logon to DDS on RMF V1R2 and RMF V1R5 level 2123. + +## 2.4.30 (2005-07-05) + +- Attributes for dynamic resources are shown via popup menu in charts. +- If pm.ini is corrupted or missing, extracting it from gpmres.jar is attempted. +- If registry keys do not exist, default values are set and resources are unpacked. +- Fixed problem in Linux version that non-standard port (i.e. non-8803) was not accepted. +- For unknown listtypes, an empty filter list (i.e. only shwing --N/A-- ) is generated. + +## 2.4.25 (2005-04-14) + +- Communication with DDS to obtain performance data now done solely with HTTP (XML) protocol. +- Added resource zFS. +- Make jobnames unique by appending the ASID to the jobname. + +## 2.4.20 (2004-12-08) + +- Introduce export/import functionality for PerfDesks (for more information please. + Refer to the online help under menu 'Help' --> 'General Help'). +- Fixed the following problems: + - Problem with data paths containing non-ASCII characters (PC/T0240MAI). + - Legend texts of samples (i.e. resource name) in Linux PerfDesks are now displayed + in a better readable format (PC/T0245MAI). + - Installation failed with InstallShield Error Message: Error Code: -5006 (PC/T0237MAI). + - After starting Application RMF PM, the workstation freezes (PC/T0244MAI). + +## 2.4.16 (2004-01-28) + +- Fixed problem migrating PerfDesks from release before 2.3.70 (PC/T0219MAI). +- Fixed problem with Linux konqueror. +- Increase size for metric values from 4 to 6 characters. +- Added metric help for Linux metrics. +- Don't display "My Penguin" for saved Linux PerfDesks (PCI/0218MAI). +- Adjusted XML history gathering date (given time stamp is end, not start of interval). +- Removed problem with Linux-only RMF PM clients (no sysplex definition). + +## 2.4.8 (2003-11-06) + +- Removed restriction on available time zones. +- Improved accessibility. +- More Java WebStart-related enhancements and fixes. +- Fixed bug for case where DDS closed unexpectedly. + +## 2.3.70 (2003-08-05) + +- Under Windows, determine automatically the installed default browser + (Mozilla, Netscape, Internet Explorer, etc.) instead of having the user specify which browser to use. +- Abort Linux Overview PerfDesk startup if "My Penguin" Linux image does not respond. +- Various minor fixes. + +## 2.3.60 (2003-06-22) + +- Settings are now kept on a per-user basis in c:\Documents and Settings\\Application Data\RMF\... +- Compatible with JAVA WebStart version of RMF PM two JAR files only. + +## 2.3.53 (2002-12-10) + +- New feature: "SaveAllPerfDesks" menu item. +- New feature: change PerfDesk background color, in order to visually distinguish PerfDesks easily. +- Replaced GPM0405I message (DDS data receive error) by three different, more precise error messages. +- Added timeout error message. +- Support for IBM JDK Java Version 1.4. +- Renamed "Storage" into "Memory (Processor Storage)". +- Display Linux image name instead of resource name in order to make it easier to + identify which Linux image is actually monitored. +- Added Sysplex ID to every error message, as GPM0502I does not contain this vital information. +- No longer expects space characters before certain XML statements. +- Updated internet link to current DB2 PM web page. +- Added error message if user forgot to specify a resource name in the "I/O resource dialog". +- Removed error message (in log file) if given value in list-valued counter not found, + as this can be normal behavior. +- Fixed that DataView stopped after change of DataView properties and was not restartable. +- Fixed restart problem for multiple series from different Linux hosts where one Linux image re-IPLed. +- PMR 48660,122,000: re-written exception handling in order to prevent JVM crash. +- Fixed timezone problem. +- Fixed minor HTTP logon problem (only occured if DDS accepted any password, but requested one). + +## 2.3.33 (2002-06-12) + +- Solved Linux Plot ArrayIndexOutOfBounds problem. +- Added BIG_SCREEN configuration parameter in order to have PerfDesk buttons in one row. +- Fixed problem Analyis could not be opened every time (happened for recursive Analysis scenarios only). +- Made application launchable from other Java applications. + +## 2.3.29 (2002-01-31) + +- If RMF PM 2.2 PerfDesks were converted to version 2.3, RMF PM erroneously displayed + "-filtered" for some single filters; fixed. +- Forward/ backward button (under PerfDesks) sometimes displayed additional erroneous + samples in DataView (with empty values); fixed. +- Sometimes, needed to press "Start" after "Sampling..." multiple times in order to + re-start all DataViews of PerfDesk; fixed. +- Problem in DataView sampling DataView for selection of To/From times; removed. +- Log, if an unknown resource list was requested from the DDS server. + +## 2.3.25 (2002-01-09) + +- Fixed bug that Analysis was not available for newly created series (introduced with RMF PM Version 2.3). + +## 2.3.24 (2001-12-20) + +- Fixed problem empty sample properties dialog may appear for closed sampler. + +## 2.3.15-2.3.23 (2001-12-13) + +- Changed PerfDesk controls, so you can use RMF PM with a screen resolution of 800x600. +- Changed some filter types changed in APAR fix OW51646. +- Various bug fixes. + +## 2.3.13-2.3.14 (2001-10-23) + +- Various bug fixes. + +## 2.3.12 (2001-10-18) + +- Added CPC properties. +- Changed default filter to 20 elements. + +## 2.3.10-2.3.11 (2001-10-17) + +- Various bug fixes. + +## 2.3.9 (2001-09-27) + +- Fixed W2K-related bug: open/reopen crashed DDS. + +## 2.3.6-2.3.8 (2001-09-26) + +- Various bug fixes. + +## 2.3.5 (2001-09-21) + +- Added "<" and ">" buttons for historical data collection. + +## 2.3.4 (2001-09-19) + +- Added HTTP Basic Authentication. + +## 2.3.3 (2001-09-14) + +- Sample PerfDesk for Linux. +- Prevent auto-start of z/OS Overview PerfDesk if no z/OS host was defined. + +## 2.3.x (2001-09-06) + +Includes various fixes and SPE OW49807. +- Caught all exceptions in runnable threads (SwingUtilities). +- Autostart PerfDesks fixed. +- Single logon bug removed. +- Fixed SSpSection initializitaion bug. +- Removed "-work scope" appendix from DV series description. +- Fixed PDControl bug (new historical data collection). +- Bug in changing workScopes in copied DataView (interfered with parent DataView). +- Enhanced stability for startup perfDesks. +- Fixed PR050063MAI, PR050076MAI. +- New ResPropBrowser (XML-based). +- XML port now needed for z/OS performance monitoring minimal DDS functionality level 1670. +- Added trace command line argument. +- Made Linux configuration dynamic. +- Performance of New/Change Sysplex dialog improved. +- Single Logon. +- IBM License Manager Online support added. +- Some more FVT bug fixes. +- Added PerfDesk "Sample" button for historical data coll. +- XML protocol: changed start range into range (HTTP request). +- SPE OW49807 (License Manager Online support). + +## 2.2.16 (2001-05-15) + +- New z/OS V1R2 product ID. + +## 2.2.15 (2001-05-07) + +- Needless XML Open removed. + +## 2.2.14 (2001-04-11) + +- Added "Add DataView" to LINUX_SYSTEM pulldown menu. + +## 2.2.13 (2001-04-09) + +- Support for multi-headed W2K installations (should also work for Linux X11 systems). + +## 2.2.12 (2001-04-06) + +- Bug in historical data collection removed. + +## 2.2.11 (2001-04-02) + +- Frozen DataView bug (setSuspended) removed. + +## 2.2.10 (2001-04-02) + +- Linux: propagate gatherer interval seconds from client to server. + +## 2.2.9 (2001-03-20) + +- New RMF Mail address. +- Java 1.3. +- Xerces XML Parser. +- New tutorial in PDF format. + +## 2.2.8 (2001-01-22) + +- Added "Open" item to PerfDesk folder context menu. +- Explicitly forbidden duplicate PerfDesk names (can cause problems in saving them). +- Avoid the possibility to open the _same_ PerfDesk from the file menu several times. +- In list-valued counters for channels, PM displayed "?". +- If channel name was identical to some numerical value in list before. +- Data display incorrect if "RMF" and "RMFGAT" in listValued counter. +- "save changes..." even after changing only the window parameters (position, size). +- If adding several list-valued counter in one DataView, PM incorrectly displayed some "?" instead + of the correct values; fixed (see ListSeries.getValueForNameAt()). +- Bug removed, if opening DataView of closed Sysplex. + +## 2.2.0 (2000-12-24) + +- Linux support. + +## 2.1.13 (2000-10-17) + +- Bug after saving PerfDesk twice. + +## 2.1.12 (2000-09-18) + +- Rem. Copy&Paste exception thrown after complex user error. + +## 2.1.11 (2000-09-11) + +- Tile analysis PerfDesk bug removed. + +## 2.1.10 + +- Sysover.po cannot be overwritten. +- Installation problem fixed, (rmf.ini can be corrupted when doing a first time install). +- Automatic "Tile Dataviews" for Analysis Perfdesks: problem fixed (Null Pointer). + +## 2.1.9 + +- Memory leak removed (date wrap-around buffer). + +## 2.1.8 + +- Some Java multithreading enhancements. + +## 2.1.7 + +- Fix problem saving zoomed DataView (wrong interval saved). + +## 2.1.6 + +- Fix problems with Analysis PerfDesks: message "GPM0626I The metric "xxx" is not defined ... ". From 9edb4d25105496312b6f12d8e1a6cd82580cce0d Mon Sep 17 00:00:00 2001 From: Dmitry Nikolaev Date: Fri, 5 Apr 2024 16:46:10 +0200 Subject: [PATCH 02/36] Changelog for Spreadsheet Reporter Signed-off-by: Dmitry Nikolaev --- spreadsheet-reporter/CHANGELOG.md | 348 ++++++++++++++++++++++++++++++ 1 file changed, 348 insertions(+) create mode 100644 spreadsheet-reporter/CHANGELOG.md diff --git a/spreadsheet-reporter/CHANGELOG.md b/spreadsheet-reporter/CHANGELOG.md new file mode 100644 index 00000000..2f857360 --- /dev/null +++ b/spreadsheet-reporter/CHANGELOG.md @@ -0,0 +1,348 @@ +# Change Log + +## 5.5.6 + +- Upgrade to Java 17. +- Sort by date/time no longer default in RepCFSys, RepSubChn1 and RepSubChn2 graphs. + +## 5.5.5 + +- General maintenance. +- Support for AI-infused batch initiators in WLMGL report. + +## 5.5.4 + +- New Java 11 Runtime. + +## 5.5.3 + +- Update XML report display processing. +- Browse XML report through local web server. + +## 5.5.2 + +- New Java 11 Runtime. +- z/OS 3.1 support. + +## 5.5.1 + +- Date ordering fix for CF reports. + +## 5.5.0 + +- Upgrade to Java 11. + +## 5.4.46 + +- New Java 8 Runtime. + +## 5.4.45 + +- Keep remote dataset at transfer failure. +- Additional XCF Spreadsheet performance optimizations. +- CF Spreadsheet named range count overflow fix. +- Adapt to the new XCF report format. +- Fix CF report parsing. + +## 5.4.44 + +- WLM Enclave Transaction metrics parsing. + +## 5.4.43 + +- Fixing "Error(s) occurred during conversion." while creating working set. +- XCF Spreadsheet performance optimization. + +## 5.4.42 + +- New Java 8 Runtime. + +## 5.4.41 + +- New Java 8 Runtime. + +## 5.4.40 + +- Workload Activity report working set loading to spreadsheet regression fix. +- Coupling Facility Trend Report fix for large request number, change Long to Double. + +## 5.4.39 + +- Fix for CF and Workload Activity report parser to support V2R5 version. + +## 5.4.38 + +- Use default translation table while downloading report via FTP. +- Update Online Help. +- Update signing certificate. + +## 5.4.37 + +- Fixed Coupling Facility Trend Report, structure was missing in ReptrdStr and RepIntStr tabs. + +## 5.4.36 + +- Add new fields from XCF Signaling Report Path Usage Statistics. + +## 5.4.35 + +- New Java 8 Runtime. + +## 5.4.34 + +- Fixed RepCFSys tab in Spreadsheet Report failing to update the report heading. +- Fixed unexpected text RepIntAct. + +## 5.4.33 + +- New Java 8 Runtime. + +## 5.4.32 + +- New FFX/QSA fields in CRYPTO report spreadsheet. + +## 5.4.31 + +- New Java 8 Runtime. + +## 5.4.30 + +- New Java 8 Runtime. + +## 5.4.29 + +- Postprocessor Report Layout Changes. + +## 5.4.28 + +- Postprocessor Report Layout Changes. + +## 5.4.27 + +- New Java 8 Runtime. + +## 5.4.26 + +- New Java 8 Runtime. + +## 5.4.25 + +- New Java 8 Runtime. + +## 5.4.24 + +- Postprocessor Report Layout Changes. + +## 5.4.23 + +- Postprocessor Report Layout Changes. + +## 5.4.22 + +- New Crypto Hardware Activity Trend Report Spreadsheet. + +## 5.4.21 + +- New Java 8 Runtime. + +## 5.4.20 + +- Integrity fixes. + +## 5.4.19 + +- Support for changed report layout. +- New Java 8 Runtime. + +## 5.4.18 + +- New Java 8 Runtime. + +## 5.4.17 + +- XCF Trend Report Spreadsheet (Rmfr9xcf.xls): + Spreadsheet is now able to handle empty reports. + +## 5.4.16 + +- New Java 8 Runtime. + +## 5.4.15 + +- New Java 8 Runtime. + +## 5.4.14 + +- New Java 8 Runtime. + +## 5.4.13 + +- Support for changed report layout. + +## 5.4.12 + +- New Java 8 Runtime. + +## 5.4.11 + +- Support for changed report layout. + +## 5.4.10 + +- Support for changed report layout. +- New Java 8 Runtime. + +## 5.4.9 + +- Support for changed report layout. + +## 5.4.8 + +- New Java 8 Runtime. +- Enhance Excel compatibility. + +## 5.4.7 + +- Partition Data Report: LPARs may be incorrect converted. +- Support of Asynchronous duplexing CF Lock Structures. + +## 5.4.6 + +- Support for Super PAV Alias Tuning. +- New Java 8 Runtime. + +## 5.4.5 + +- Partition Data Report: IFL LPARs may be incorrect converted. + +## 5.4.4 + +- Support of LPAR Group Absolute Capping. +- CF Report: + Large number of requests in the CF to CF section maybe incorrect converted. +- Addressed passive FTP connection problem. + +## 5.4.3 + +- New Java 8 Runtime. + +## 5.4.2 + +- Support of WLM Workload Containers for Mobile Pricing. + +## 5.4.1 + +- New Java 8 Runtime. + +## 5.4.0 + +- New Java 8 Runtime. + +## 5.3.14 + +- New Java Runtime. + +## 5.3.13 + +- New Java Runtime. + +## 5.3.12 + +- Support for changed report layout. +- Enhance Excel compatibility. + +## 5.3.11 + +- Support for new RMF Postprocessor Reports in XML format. +- Coupling Facility Trend Report Spreadsheet (Rmfr9cf.xls): + - RepTrdStr sheet: Incorrect system list may be created (only systems available in the first + report are honored) (PR220062MAI). + - RepCFTrd sheet: Add metric: Effective CPs. +- XCF Trend Report Spreadsheet (Rmfr9xcf.xls): + PathOverview Sheet may report incorrect target system name. +- Channel Overview Report Spreadsheet (Rmfx9chn.xls): + Channel Utilization on LPAR level may incorrect reported. +- Coupling Facility Activity Report may be incorrect converted. +- XCF Activity Report may be incorrect converted. +- Workload Activity Report may be incorrect converted. + +## 5.3.10 + +- New Certificate. + +## 5.3.9 + +- Support for new RMF Postprocessor Reports in XML format. +- Coupling Facility Trend Report: RepTrdStr chart shows incorrect numbers data for changed requests. + +## 5.3.8 + +- System Overview Spreadsheet (Rmfy9ovw.xls): Data analysis section on Summary sheet shows + incorrect page faults (PR210056MAI). +- LPAR Trend Report Spreadsheet (Rmfr9lp.xls): + % of CEC Guaranteed /Max is incorrect calculated for none-CP Partitions (PR210092MAI). +- Workload Activity Trend Report Spreadsheet: Application Utilization for Report Classes may be + incorrect reported (PR210109MAI). +- Creating corrupted report index file when registering large report working set (PC/T0321MAI). + +## 5.3.7 + +- Support for new RMF Postprocessor Reports in XML format. +- Converted Overview Record is limited to 8200 rows (PR130182MAI). + +## 5.3.6 + +- New Java runtime. + +## 5.3.5 + +- New Certificate. + +## 5.3.4 + +Spreadsheet Reporter:. +- MigrateWSetsToXLS.bat cause java.lang.ArrayIndexOutOfBoundsException (at + com.ibm.erb.rmfsr.wset.ErbXLSFileInstance._extractSST (ErbXLSFileInstance.java:646) PR110135MAI. +- Processing Working Sets cause error messages 'Cannot process data...' when system regional + settings are switched to Turkish (may also apply to other regions) PR110136MAI. +- Coupling Facility Trend Report:Processing data may cause error message + "Cannot process data..." (PR120042MAI). +- Coupling Facility Trend Report:Modifing the report option on the RepTrdStr sheet may cause + Visual Basic run-time-error 1004 message (PC/T0318MAI). +- No Response Time Distribution may be displayed on the RepRsp worksheet (PR120058MAI). +- Workload Activity Spreadsheet (Rmfy9wkl.xls): The WeekChart may display incorrect date values (PR120079MAI). +- Incorrect conversion of z/OS Version number of the Workload Activity Spreadsheet (PR120088MAI). + +## 5.3.3 + +Spreadsheet Reporter: +- XML Report Support update. +- Workload Activity Report: Large CPU Service Times may be incorrect converted (PR110118MAI). + +## 5.3.2 + +Spreadsheet Reporter: +- XML Report Support. + +## 5.3.1 + +Spreadsheet Reporter: +- WLGML Report may be incorrect converted (PR100088MAI). +- Rangenames with nummeric sign "#" cannot be handled (PR100116MAI). +- Numbers of Processors in the Partition Data Report may be incorrect converted (PR100135MAI). +- Using CreateRptWset.bat file may cause error message "Internal index files are not accessible." + (PR100136MAI). +- Paging Activity Report may be incorrect converted (PR100142MAI). +- Invalid XLS file generated based on overview record (PR100143MAI). +- Corrupt RMFOV.XLS file cause SR hangup without any error messages (PR100144MAI). +- The Spreadsheet Reporter cannot delete or rename working sets (PR100149MAI). +- Processing data may cause error message "The Report Working Set may not contain the required..." + (PR100114MAI). +- Workload Activity Report: QMPL delays of may be incorrect converted (PR110076MAI). + +Spreadsheet Macros: +- XCF Trend Report: The System name may appear mutliple times in the system list (PR100110MAI). +- Channel Overview Report: When adding data to the macro, the workload busy percent is incorrect + calculated (PR100115MAI). +- LParsTrd sheet may report incorrect Physical Total Utilization for the Physical Partition (PR100146MAI). +- RMF System Overview Report Macro: Adding data may cause error message "Run-time error '9" (PR100148MAI). From 9d79dad0f466689545fbdf126f0b9ae07b68d84c Mon Sep 17 00:00:00 2001 From: Ramanath Shanbhag Date: Mon, 15 Apr 2024 15:38:07 +0530 Subject: [PATCH 03/36] Updated readme Signed-off-by: Ramanath Shanbhag --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1c643d63..f2364bae 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,10 @@ Resource Measurement Facility for z/OS -## IBM RMF for z/OS Grafana Plugin +## IBM RMF Performance Monitoring -The IBM® RMF for z/OS Grafana plugin provides effortless analysis and visualization of -RMF Monitor III metrics and reports within the Grafana platform. +The IBM® RMF Performance Monitoring (RMF PM) is a tool that enables you to manage the performance of your z/OS host right from your workstation. By establishing a TCP/IP connection to one or more z/OS sysplexes, you can effortlessly access real-time data on the resources of the corresponding sysplex. -See [IBM RMF for z/OS Grafana Plugin](grafana/rmf-app/README.md) for more details. +RMF PM offers great flexibility in creating unique scenarios to monitor the system's performance. You can easily sample data from different resources and combine it to comprehensively overview the system's performance. With RMF PM, you can visualize the performance data as bar charts to better understand the system's status. + +Refer to the [z/OS Resource Measurement Facility User's Guide](https://www.ibm.com/docs/en/zos/latest?topic=monitoring-performance-overview) for more information. \ No newline at end of file From e05b1466e4af00177558ff9f1bd3847db0678f04 Mon Sep 17 00:00:00 2001 From: Ramanath Shanbhag Date: Mon, 15 Apr 2024 15:42:59 +0530 Subject: [PATCH 04/36] Updated readme Signed-off-by: Ramanath Shanbhag --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1c643d63..cc03d066 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,8 @@ Resource Measurement Facility for z/OS -## IBM RMF for z/OS Grafana Plugin +## IBM RMF Spreadsheet Reporter -The IBM® RMF for z/OS Grafana plugin provides effortless analysis and visualization of -RMF Monitor III metrics and reports within the Grafana platform. +The RMF Spreadsheet Reporter is an advanced and efficient workstation solution that enables users to visualize RMF (Resource Measurement Facility) Postprocessor data in a graphical format. With the RMF Spreadsheet Reporter, you can convert your RMF data into a spreadsheet format, which makes it easier to analyze and manipulate the data. -See [IBM RMF for z/OS Grafana Plugin](grafana/rmf-app/README.md) for more details. +Refer to the [z/OS Resource Measurement Facility User's Guide](https://www.ibm.com/docs/en/zos/latest?topic=reporter-concepts-performance-analysis-rmf-spreadsheet) for more information. \ No newline at end of file From e782c0ea9dfcb205c5902ead299ba9e64de00efa Mon Sep 17 00:00:00 2001 From: Ramanath Shanbhag Date: Tue, 23 Apr 2024 22:03:03 +0530 Subject: [PATCH 05/36] Included the installer location Signed-off-by: Ramanath Shanbhag --- README.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f2364bae..801d571a 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,27 @@ Resource Measurement Facility for z/OS +## IBM RMF for z/OS Grafana Plugin + +The IBM® RMF for z/OS Grafana plugin provides effortless analysis and visualization of RMF Monitor III metrics and reports within the Grafana platform. + +See [IBM RMF for z/OS Grafana Plugin](https://github.com/IBM/RMF/blob/release/spreadsheet-reporter/grafana/rmf-app/README.md) for more details. + ## IBM RMF Performance Monitoring The IBM® RMF Performance Monitoring (RMF PM) is a tool that enables you to manage the performance of your z/OS host right from your workstation. By establishing a TCP/IP connection to one or more z/OS sysplexes, you can effortlessly access real-time data on the resources of the corresponding sysplex. RMF PM offers great flexibility in creating unique scenarios to monitor the system's performance. You can easily sample data from different resources and combine it to comprehensively overview the system's performance. With RMF PM, you can visualize the performance data as bar charts to better understand the system's status. -Refer to the [z/OS Resource Measurement Facility User's Guide](https://www.ibm.com/docs/en/zos/latest?topic=monitoring-performance-overview) for more information. \ No newline at end of file +You can download the installer from the following location: +https://github.com/IBM/RMF/releases + +Refer to the [z/OS Resource Measurement Facility User's Guide](https://www.ibm.com/docs/en/zos/latest?topic=monitoring-performance-overview) for more information. + +## IBM RMF Spreadsheet Reporter + +The RMF Spreadsheet Reporter is an advanced and efficient workstation solution that enables users to visualize RMF (Resource Measurement Facility) Postprocessor data in a graphical format. With the RMF Spreadsheet Reporter, you can convert your RMF data into a spreadsheet format, which makes it easier to analyze and manipulate the data. + +You can download the installer from the following location: (https://github.com/IBM/RMF/releases). + +Refer to the [z/OS Resource Measurement Facility User's Guide](https://www.ibm.com/docs/en/zos/latest?topic=reporter-concepts-performance-analysis-rmf-spreadsheet) for more information. \ No newline at end of file From 34301636bdcde0efc7588bf7cf2392d81a9c91af Mon Sep 17 00:00:00 2001 From: Ramanath Shanbhag Date: Tue, 23 Apr 2024 21:58:48 +0530 Subject: [PATCH 06/36] Included the installer location Signed-off-by: Ramanath Shanbhag --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index cc03d066..0458c844 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,28 @@ Resource Measurement Facility for z/OS +## IBM RMF for z/OS Grafana Plugin + +The IBM® RMF for z/OS Grafana plugin provides effortless analysis and visualization of +RMF Monitor III metrics and reports within the Grafana platform. + +See [IBM RMF for z/OS Grafana Plugin](grafana/rmf-app/README.md) for more details. + +## IBM RMF Performance Monitoring + +The IBM® RMF Performance Monitoring (RMF PM) is a tool that enables you to manage the performance of your z/OS host right from your workstation. By establishing a TCP/IP connection to one or more z/OS sysplexes, you can effortlessly access real-time data on the resources of the corresponding sysplex. + +RMF PM offers great flexibility in creating unique scenarios to monitor the system's performance. You can easily sample data from different resources and combine it to comprehensively overview the system's performance. With RMF PM, you can visualize the performance data as bar charts to better understand the system's status. + +You can download the installer from the following location: +https://github.com/IBM/RMF/releases + +Refer to the [z/OS Resource Measurement Facility User's Guide](https://www.ibm.com/docs/en/zos/latest?topic=monitoring-performance-overview) for more information. + ## IBM RMF Spreadsheet Reporter The RMF Spreadsheet Reporter is an advanced and efficient workstation solution that enables users to visualize RMF (Resource Measurement Facility) Postprocessor data in a graphical format. With the RMF Spreadsheet Reporter, you can convert your RMF data into a spreadsheet format, which makes it easier to analyze and manipulate the data. +You can download the installer from the following location: (https://github.com/IBM/RMF/releases). + Refer to the [z/OS Resource Measurement Facility User's Guide](https://www.ibm.com/docs/en/zos/latest?topic=reporter-concepts-performance-analysis-rmf-spreadsheet) for more information. \ No newline at end of file From 3001abdf87620e1f28db379cb1ba8439a3008341 Mon Sep 17 00:00:00 2001 From: Dmitry Prizentsov Date: Thu, 27 Jun 2024 11:44:01 +0200 Subject: [PATCH 07/36] PM 2.6.5, SR 5.5.7 Signed-off-by: Dmitry Prizentsov --- pm-client/CHANGELOG.md | 3 +++ spreadsheet-reporter/CHANGELOG.md | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/pm-client/CHANGELOG.md b/pm-client/CHANGELOG.md index 89a3c311..7df6e554 100644 --- a/pm-client/CHANGELOG.md +++ b/pm-client/CHANGELOG.md @@ -1,5 +1,8 @@ # Change Log +## 2.6.5 (2024-06-05) +- PM doesn't gather any data fix + ## 2.6.4 (2024-03-04) - Upgrade to Java 17. diff --git a/spreadsheet-reporter/CHANGELOG.md b/spreadsheet-reporter/CHANGELOG.md index 2f857360..4e0c56df 100644 --- a/spreadsheet-reporter/CHANGELOG.md +++ b/spreadsheet-reporter/CHANGELOG.md @@ -1,5 +1,12 @@ # Change Log +## 5.5.7 + + - Support CPU reports with multi-page IFL information + - Fix WLMGL working set creation + - Reset buttons in CF Trend macro + - General maintenance + ## 5.5.6 - Upgrade to Java 17. From cfaf7a366897a94f4674e349410718ef721fb26b Mon Sep 17 00:00:00 2001 From: dprizentsov Date: Fri, 19 Jul 2024 15:25:12 +0200 Subject: [PATCH 08/36] dependabot.yml to scan staging/v1.x branch Signed-off-by: dprizentsov --- .github/dependabot.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..e6601932 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +--- +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: daily + target-branch: staging/v1.x \ No newline at end of file From 65ac3cd18f69f0c015240ca9e4d1338d63a808b2 Mon Sep 17 00:00:00 2001 From: dprizentsov Date: Mon, 22 Jul 2024 11:32:01 +0200 Subject: [PATCH 09/36] dependabot config for npm and gomod Signed-off-by: dprizentsov --- .github/dependabot.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e6601932..06d4a872 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -2,6 +2,16 @@ version: 2 updates: - package-ecosystem: github-actions + directory: / + schedule: + interval: daily + target-branch: staging/v1.x + - package-ecosystem: npm + directory: / + schedule: + interval: daily + target-branch: staging/v1.x + - package-ecosystem: gomod directory: / schedule: interval: daily From cdd8fad69ab625f91b7c8fee579b60de1db631ae Mon Sep 17 00:00:00 2001 From: dprizentsov Date: Mon, 22 Jul 2024 11:48:20 +0200 Subject: [PATCH 10/36] dependabot config, update directory path Signed-off-by: dprizentsov --- .github/dependabot.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 06d4a872..868a55a6 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,12 +7,12 @@ updates: interval: daily target-branch: staging/v1.x - package-ecosystem: npm - directory: / + directory: /grafana/rmf-app schedule: interval: daily target-branch: staging/v1.x - package-ecosystem: gomod - directory: / + directory: /grafana/rmf-app schedule: interval: daily target-branch: staging/v1.x \ No newline at end of file From 31947e4cb4392ef2f984a80101674869bef61c30 Mon Sep 17 00:00:00 2001 From: dprizentsov Date: Mon, 22 Jul 2024 12:51:38 +0200 Subject: [PATCH 11/36] remove dependabot config to keep default behavior of security scans Signed-off-by: dprizentsov --- .github/dependabot.yml | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 868a55a6..00000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,18 +0,0 @@ ---- -version: 2 -updates: - - package-ecosystem: github-actions - directory: / - schedule: - interval: daily - target-branch: staging/v1.x - - package-ecosystem: npm - directory: /grafana/rmf-app - schedule: - interval: daily - target-branch: staging/v1.x - - package-ecosystem: gomod - directory: /grafana/rmf-app - schedule: - interval: daily - target-branch: staging/v1.x \ No newline at end of file From 33f58c028d3556a879d0a4be2b025163252d8f68 Mon Sep 17 00:00:00 2001 From: Ramanath Shanbhag Date: Thu, 5 Sep 2024 18:57:58 +0530 Subject: [PATCH 12/36] Updated changelog for PM and SR Signed-off-by: Ramanath Shanbhag --- pm-client/CHANGELOG.md | 3 +++ spreadsheet-reporter/CHANGELOG.md | 12 ++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/pm-client/CHANGELOG.md b/pm-client/CHANGELOG.md index 7df6e554..23ce583f 100644 --- a/pm-client/CHANGELOG.md +++ b/pm-client/CHANGELOG.md @@ -1,5 +1,8 @@ # Change Log +## 2.6.6 (2024-09-06) +- The Performance Monitoring has been updated to include the latest Java version 17. + ## 2.6.5 (2024-06-05) - PM doesn't gather any data fix diff --git a/spreadsheet-reporter/CHANGELOG.md b/spreadsheet-reporter/CHANGELOG.md index 4e0c56df..5e31010c 100644 --- a/spreadsheet-reporter/CHANGELOG.md +++ b/spreadsheet-reporter/CHANGELOG.md @@ -1,11 +1,15 @@ # Change Log +## 5.5.8 + +- The Spreadsheet Reporter has been updated to include the latest Java version 17. + ## 5.5.7 - - Support CPU reports with multi-page IFL information - - Fix WLMGL working set creation - - Reset buttons in CF Trend macro - - General maintenance +- Support CPU reports with multi-page IFL information +- Fix WLMGL working set creation +- Reset buttons in CF Trend macro +- General maintenance ## 5.5.6 From b44804350df16f738e4a829eb89c3afbd0015e46 Mon Sep 17 00:00:00 2001 From: rshanbhag-rocket <116624672+rshanbhag-rocket@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:15:10 +0530 Subject: [PATCH 13/36] Update CHANGELOG.md Updated date --- pm-client/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pm-client/CHANGELOG.md b/pm-client/CHANGELOG.md index 23ce583f..fc33d8e8 100644 --- a/pm-client/CHANGELOG.md +++ b/pm-client/CHANGELOG.md @@ -1,6 +1,6 @@ # Change Log -## 2.6.6 (2024-09-06) +## 2.6.6 (2024-09-11) - The Performance Monitoring has been updated to include the latest Java version 17. ## 2.6.5 (2024-06-05) From b81b15ce7cd538384bd8842ee921ca744e85b7ab Mon Sep 17 00:00:00 2001 From: rshanbhag-rocket <116624672+rshanbhag-rocket@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:16:18 +0530 Subject: [PATCH 14/36] Update CHANGELOG.md Updated date --- spreadsheet-reporter/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spreadsheet-reporter/CHANGELOG.md b/spreadsheet-reporter/CHANGELOG.md index 5e31010c..03f67649 100644 --- a/spreadsheet-reporter/CHANGELOG.md +++ b/spreadsheet-reporter/CHANGELOG.md @@ -1,6 +1,6 @@ # Change Log -## 5.5.8 +## 5.5.8 (2024-09-11) - The Spreadsheet Reporter has been updated to include the latest Java version 17. From ff50525ecb20ded8ee38a8cda515acc309ce4fe0 Mon Sep 17 00:00:00 2001 From: dprizentsov Date: Tue, 27 May 2025 10:19:21 +0200 Subject: [PATCH 15/36] spreadsheet-reporter/v5.5.9 Signed-off-by: dprizentsov --- spreadsheet-reporter/CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spreadsheet-reporter/CHANGELOG.md b/spreadsheet-reporter/CHANGELOG.md index 03f67649..fdf38997 100644 --- a/spreadsheet-reporter/CHANGELOG.md +++ b/spreadsheet-reporter/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## 5.5.9 (2025-05-27) + +- New Java 17 Runtime +- Fix Secure FTP connection + ## 5.5.8 (2024-09-11) - The Spreadsheet Reporter has been updated to include the latest Java version 17. From 17432e23d8866252235de7de4a63c888100ceef2 Mon Sep 17 00:00:00 2001 From: Dmitry Nikolaev Date: Wed, 17 Sep 2025 11:34:08 +0200 Subject: [PATCH 16/36] Document sample dashboards Signed-off-by: Dmitry Nikolaev --- README.md | 18 +++- grafana/dashboards/README.md | 95 +++++++++++++++++++ .../prometheus/zos-central-storage.json | 1 + .../prometheus/zos-common-storage.json | 1 + .../prometheus/zos-coupling-facility.json | 1 + .../prometheus/zos-msu-capacity.json | 1 + .../prometheus/zos-usage-by-job.json | 1 + .../dashboards/prometheus/zos-wlm-delays.json | 1 + 8 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 grafana/dashboards/README.md create mode 120000 grafana/dashboards/prometheus/zos-central-storage.json create mode 120000 grafana/dashboards/prometheus/zos-common-storage.json create mode 120000 grafana/dashboards/prometheus/zos-coupling-facility.json create mode 120000 grafana/dashboards/prometheus/zos-msu-capacity.json create mode 120000 grafana/dashboards/prometheus/zos-usage-by-job.json create mode 120000 grafana/dashboards/prometheus/zos-wlm-delays.json diff --git a/README.md b/README.md index 3dd2a59d..cae2a042 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,18 @@ Resource Measurement Facility for z/OS +## Grafana Sample Dashboards + +The IBM RMF Monitor III metrics can be exposed to third-party tools directly using the OpenMetrics exposition format. +Some examples of the tools are: +- Prometheus +- VictoriaMetrics +- Telegraf + +Grafana sample dashboards for Prometheus and VictoriaMetrics as well as usage information are available in the [grafana/dashboards](grafana/dashboards) directory. + +Refer to [z/OS Resource Measurement Facility User's Guide](https://www.ibm.com/docs/en/zos/latest?topic=rmf-zos-resource-measurement-facility-users-guide) for more information on configuring RMF DDS. + ## IBM RMF for z/OS Grafana Plugin The IBM® RMF for z/OS Grafana plugin provides effortless analysis and visualization of RMF Monitor III metrics and reports within the Grafana platform. @@ -10,9 +22,9 @@ See [IBM RMF for z/OS Grafana Plugin](grafana/rmf-app/README.md) for more detail ## IBM RMF Performance Monitoring -The IBM® RMF Performance Monitoring (RMF PM) is a tool that enables you to manage the performance of your z/OS host right from your workstation. By establishing a TCP/IP connection to one or more z/OS sysplexes, you can effortlessly access real-time data on the resources of the corresponding sysplex. +The IBM® RMF Performance Monitoring (RMF PM) is a tool that enables you to manage the performance of your z/OS host right from your workstation. By establishing a TCP/IP connection to one or more z/OS sysplexes, you can access real-time data on the resources of the corresponding sysplex. -RMF PM offers great flexibility in creating unique scenarios to monitor the system's performance. You can easily sample data from different resources and combine it to comprehensively overview the system's performance. With RMF PM, you can visualize the performance data as bar charts to better understand the system's status. +RMF PM offers flexibility in creating scenarios to monitor the system's performance. You can sample data from different resources and combine it to comprehensively overview the system's performance. With RMF PM, you can visualize the performance data as bar charts to better understand the system's status. You can download the installer from the following location: https://github.com/IBM/RMF/releases @@ -21,7 +33,7 @@ Refer to the [z/OS Resource Measurement Facility User's Guide](https://www.ibm.c ## IBM RMF Spreadsheet Reporter -The RMF Spreadsheet Reporter is an advanced and efficient workstation solution that enables users to visualize RMF (Resource Measurement Facility) Postprocessor data in a graphical format. With the RMF Spreadsheet Reporter, you can convert your RMF data into a spreadsheet format, which makes it easier to analyze and manipulate the data. +The RMF Spreadsheet Reporter is a workstation solution that enables users to visualize RMF (Resource Measurement Facility) Postprocessor data in a graphical format. With the RMF Spreadsheet Reporter, you can convert your RMF data into a spreadsheet format, which makes it easier to analyze and manipulate the data. You can download the installer from the following location: (https://github.com/IBM/RMF/releases). diff --git a/grafana/dashboards/README.md b/grafana/dashboards/README.md new file mode 100644 index 00000000..a08b2386 --- /dev/null +++ b/grafana/dashboards/README.md @@ -0,0 +1,95 @@ +# Grafana Sample Dashboards + +The IBM RMF Monitor III metrics can be exposed to third-party tools directly using the OpenMetrics exposition format. +Some examples of the tools are: +- Prometheus +- VictoriaMetrics +- Telegraf + + +The directory contains Grafana sample dashboards for Prometheus and VictoriaMetrics to visualize the Monitor III data. +Note: VictoriaMetrics is a drop-in replacement for Prometheus, the same dashboards can be used with both. + +[Go to Prometheus / VictoriaMetrics Configuration](#prometheus--victoriametrics-configuration) +[Go to Sample Dashboards Usage](#sample-dashboards-usage) + +## Prometheus / VictoriaMetrics Configuration + +The Monitor III data can be exposed through the `/metrics/m3` endpoint. +**Note**: OA67701 has to be applied for the feature. + +Make sure you have the Monitor III metrics being scraped by Prometheus or VictoriaMetrics, and a Grafana data source pointing to the Prometheus / VictoriaMetrics instance is configured. + +A target definition example to scrape all the metrics as defined in GPMOMC (to limit metrics being scraped, use the `groups` parameter of the endpoint or edit GPMOMC DDS configuration): + +```yaml +- job_name: "m3@plex00" + scrape_interval: 100s # Should be equal to the Monitor III mintime + scrape_timeout: 50s + metrics_path: /metrics/m3 + scheme: https # Remove or change to "http" if AT/TLS for DDS is not set + tls_config: + insecure_skip_verify: false # Change to “true” if self-signed certificates are used + basic_auth: # Use DDS credentials or remove if DDS authentication is disabled + username: ‘DDSUSER' + password: 'XXXXXXX' + static_configs: + - targets: [ "ddshostname:8803” ] +``` + +Refer to [z/OS Resource Measurement Facility User's Guide](https://www.ibm.com/docs/en/zos/latest?topic=rmf-zos-resource-measurement-facility-users-guide) for more information. + +## Sample Dashboards Usage + +The dashboards can be imported into Grafana in three ways: +- [Importing the dashboards directly into Grafana.](#import-dashboards) +- [Provision the dashboards using Grafana's provisioning system.](#provision-dashboards) +- [Installing IBM RMF for z/OS Grafana Plugin.](#install-the-ibm-rmf-for-zos-grafana-plugin) + +### Import Dashboards + +You can import dashboards directly into your Grafana instance via the UI: +- Log in to Grafana. +- Navigate to Dashboards → New → Import. +- Upload a .json file from this repository or paste its contents. + +Refer to [the Import Dashboard docs](https://grafana.com/docs/grafana/latest/dashboards/build-dashboards/import-dashboards/#import-dashboard) for more information. + +### Provision Dashboards + +For automation and version control, you can provision dashboards using Grafana's provisioning system: +- Copy the .json files from this repo into your `provisioning/directory` (the exact location depends on your Grafana installation and configuration). +- Define them in your provisioning YAML config, for example: + ```yaml + apiVersion: 1 + providers: + # an unique provider name. Required + - name: 'a unique provider name' + # Org id. Default to 1 + orgId: 1 + # name of the dashboard folder. + folder: '' + # folder UID. will be automatically generated if not specified + folderUid: '' + # provider type. Default to 'file' + type: file + # disable dashboard deletion + disableDeletion: false + # how often Grafana will scan for changed dashboards + updateIntervalSeconds: 10 + # allow updating provisioned dashboards from the UI + allowUiUpdates: false + options: + # path to dashboard files on disk. Required when using the 'file' type + path: /var/lib/grafana/dashboards + # use folder names from filesystem to create folders in Grafana + foldersFromFilesStructure: true + ``` + +Refer to [the Provisioning Dashboards docs](https://grafana.com/docs/grafana/latest/administration/provisioning/#dashboards) for more information. + + +### Install the IBM RMF for z/OS Grafana Plugin + +All the sample dashboards are bundled into [IBM RMF for z/OS Grafana Plugin](grafana/rmf-app/README.md). +Follow the instructions to install it and [deploy the sample dashboards](https://ibm.github.io/RMF/grafana/rmf-app/prometheus_sample_dashboards.html) from IBM RMF App in Grafana. diff --git a/grafana/dashboards/prometheus/zos-central-storage.json b/grafana/dashboards/prometheus/zos-central-storage.json new file mode 120000 index 00000000..f5922722 --- /dev/null +++ b/grafana/dashboards/prometheus/zos-central-storage.json @@ -0,0 +1 @@ +../../rmf-app/src/dashboards/prometheus/zos-central-storage.json \ No newline at end of file diff --git a/grafana/dashboards/prometheus/zos-common-storage.json b/grafana/dashboards/prometheus/zos-common-storage.json new file mode 120000 index 00000000..d6fa8a81 --- /dev/null +++ b/grafana/dashboards/prometheus/zos-common-storage.json @@ -0,0 +1 @@ +../../rmf-app/src/dashboards/prometheus/zos-common-storage.json \ No newline at end of file diff --git a/grafana/dashboards/prometheus/zos-coupling-facility.json b/grafana/dashboards/prometheus/zos-coupling-facility.json new file mode 120000 index 00000000..f7b07704 --- /dev/null +++ b/grafana/dashboards/prometheus/zos-coupling-facility.json @@ -0,0 +1 @@ +../../rmf-app/src/dashboards/prometheus/zos-coupling-facility.json \ No newline at end of file diff --git a/grafana/dashboards/prometheus/zos-msu-capacity.json b/grafana/dashboards/prometheus/zos-msu-capacity.json new file mode 120000 index 00000000..da5d129c --- /dev/null +++ b/grafana/dashboards/prometheus/zos-msu-capacity.json @@ -0,0 +1 @@ +../../rmf-app/src/dashboards/prometheus/zos-msu-capacity.json \ No newline at end of file diff --git a/grafana/dashboards/prometheus/zos-usage-by-job.json b/grafana/dashboards/prometheus/zos-usage-by-job.json new file mode 120000 index 00000000..01d79fe9 --- /dev/null +++ b/grafana/dashboards/prometheus/zos-usage-by-job.json @@ -0,0 +1 @@ +../../rmf-app/src/dashboards/prometheus/zos-usage-by-job.json \ No newline at end of file diff --git a/grafana/dashboards/prometheus/zos-wlm-delays.json b/grafana/dashboards/prometheus/zos-wlm-delays.json new file mode 120000 index 00000000..208f8853 --- /dev/null +++ b/grafana/dashboards/prometheus/zos-wlm-delays.json @@ -0,0 +1 @@ +../../rmf-app/src/dashboards/prometheus/zos-wlm-delays.json \ No newline at end of file From d56afb048b53a9ae04b041fe55f74525424dcf80 Mon Sep 17 00:00:00 2001 From: Dmitry Nikolaev Date: Thu, 18 Sep 2025 10:34:30 +0200 Subject: [PATCH 17/36] Fix quotes in doc samples Signed-off-by: Dmitry Nikolaev --- grafana/dashboards/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grafana/dashboards/README.md b/grafana/dashboards/README.md index a08b2386..8d3ae01c 100644 --- a/grafana/dashboards/README.md +++ b/grafana/dashboards/README.md @@ -31,10 +31,10 @@ A target definition example to scrape all the metrics as defined in GPMOMC (to l tls_config: insecure_skip_verify: false # Change to “true” if self-signed certificates are used basic_auth: # Use DDS credentials or remove if DDS authentication is disabled - username: ‘DDSUSER' + username: 'DDSUSER' password: 'XXXXXXX' static_configs: - - targets: [ "ddshostname:8803” ] + - targets: [ "ddshostname:8803" ] ``` Refer to [z/OS Resource Measurement Facility User's Guide](https://www.ibm.com/docs/en/zos/latest?topic=rmf-zos-resource-measurement-facility-users-guide) for more information. From d387e6e8ed1926da2a7af9a7e3c2cecc94b40ad3 Mon Sep 17 00:00:00 2001 From: Dmitry Nikolaev Date: Thu, 18 Sep 2025 10:38:44 +0200 Subject: [PATCH 18/36] Remove symbolic links for samples Signed-off-by: Dmitry Nikolaev --- .../prometheus/zos-central-storage.json | 480 ++++++++- .../prometheus/zos-common-storage.json | 987 +++++++++++++++++- .../prometheus/zos-coupling-facility.json | 728 ++++++++++++- .../prometheus/zos-msu-capacity.json | 473 ++++++++- .../prometheus/zos-usage-by-job.json | 841 ++++++++++++++- .../dashboards/prometheus/zos-wlm-delays.json | 720 ++++++++++++- 6 files changed, 4223 insertions(+), 6 deletions(-) mode change 120000 => 100644 grafana/dashboards/prometheus/zos-central-storage.json mode change 120000 => 100644 grafana/dashboards/prometheus/zos-common-storage.json mode change 120000 => 100644 grafana/dashboards/prometheus/zos-coupling-facility.json mode change 120000 => 100644 grafana/dashboards/prometheus/zos-msu-capacity.json mode change 120000 => 100644 grafana/dashboards/prometheus/zos-usage-by-job.json mode change 120000 => 100644 grafana/dashboards/prometheus/zos-wlm-delays.json diff --git a/grafana/dashboards/prometheus/zos-central-storage.json b/grafana/dashboards/prometheus/zos-central-storage.json deleted file mode 120000 index f5922722..00000000 --- a/grafana/dashboards/prometheus/zos-central-storage.json +++ /dev/null @@ -1 +0,0 @@ -../../rmf-app/src/dashboards/prometheus/zos-central-storage.json \ No newline at end of file diff --git a/grafana/dashboards/prometheus/zos-central-storage.json b/grafana/dashboards/prometheus/zos-central-storage.json new file mode 100644 index 00000000..8cd59ef8 --- /dev/null +++ b/grafana/dashboards/prometheus/zos-central-storage.json @@ -0,0 +1,479 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "panels": [], + "title": "Current Usage", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false, + "filterable": true + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*\\(%\\)/" + }, + "properties": [ + { + "id": "unit", + "value": "percentunit" + } + ] + } + ] + }, + "gridPos": { + "h": 12, + "w": 24, + "x": 0, + "y": 1 + }, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": ["sum"], + "show": false + }, + "showHeader": true + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "label_replace(\n mvs_system_storage_real_storage_frames{sysplex=~\"${sysplex}\"} * 4096,\n \"__name__\",\n \"Storage Online\",\n \"\",\n \".*\"\n)", + "instant": true, + "legendFormat": "{{sysname}}", + "range": false, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "label_replace(\n mvs_system_storage_frames_available_total{sysplex=~\"${sysplex}\"} * 4096,\n \"__name__\",\n \"Storage Available\",\n \"\",\n \".*\"\n)", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "label_replace(\n mvs_system_storage_frames_available_total{sysplex=~\"${sysplex}\"} / mvs_system_storage_real_storage_frames{sysplex=~\"${sysplex}\"},\n \"__name__\",\n \"Storage Available (%)\",\n \"\",\n \".*\"\n)", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "label_replace(\n (mvs_system_storage_real_storage_frames{sysplex=~\"${sysplex}\"} - mvs_system_storage_frames_available_total{sysplex=~\"${sysplex}\"}) * 4096,\n \"__name__\",\n \"Storage Used\",\n \"\",\n \".*\"\n)", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "label_replace(\n 1 - mvs_system_storage_frames_available_total{sysplex=~\"${sysplex}\"} / mvs_system_storage_real_storage_frames{sysplex=~\"${sysplex}\"},\n \"__name__\",\n \"Storage Used (%)\",\n \"\",\n \".*\"\n)", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "E" + } + ], + "title": "Current Central Storage by System", + "transformations": [ + { + "id": "joinByLabels", + "options": { + "value": "__name__" + } + }, + { + "id": "organize", + "options": { + "excludeByName": { + "instance": true, + "job": true + }, + "includeByName": {}, + "indexByName": { + "Storage Available": 5, + "Storage Available (%)": 6, + "Storage Online": 4, + "Storage Used": 7, + "Storage Used (%)": 8, + "instance": 0, + "job": 1, + "sysname": 2, + "sysplex": 3 + }, + "renameByName": { + "sysname": "Sysname", + "sysplex": "Sysplex" + } + } + } + ], + "type": "table" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 13 + }, + "panels": [], + "title": "Usage History", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "fieldMinMax": true, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 24, + "x": 0, + "y": 14 + }, + "interval": "${mintime}", + "options": { + "legend": { + "calcs": ["last", "min", "max", "mean"], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "(mvs_system_storage_real_storage_frames{sysplex=~\"${sysplex}\"} - mvs_system_storage_frames_available_total{sysplex=~\"${sysplex}\"}) * 4096", + "instant": false, + "legendFormat": "{{sysname}}", + "range": true, + "refId": "A" + } + ], + "title": "Central Storage Usage by System (bytes)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "fieldMinMax": true, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 24, + "x": 0, + "y": 26 + }, + "interval": "${mintime}", + "options": { + "legend": { + "calcs": ["last", "min", "max", "mean"], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "1 - mvs_system_storage_frames_available_total{sysplex=~\"${sysplex}\"} / mvs_system_storage_real_storage_frames{sysplex=~\"${sysplex}\"}", + "instant": false, + "legendFormat": "{{sysname}}", + "range": true, + "refId": "A" + } + ], + "title": "Central Storage Usage by System (percent)", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "1m", + "tags": ["RMF"], + "templating": { + "list": [ + { + "allowCustomValue": false, + "includeAll": false, + "label": "Data Source", + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(mvs_rmf_m3_mintime,sysplex)", + "includeAll": true, + "label": "Sysplex", + "multi": true, + "name": "sysplex", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(mvs_rmf_m3_mintime,sysplex)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "allowCustomValue": false, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "query_result(max(mvs_rmf_m3_mintime{sysplex=~\"${sysplex}\"}))", + "hide": 2, + "name": "mintime", + "options": [], + "query": { + "qryType": 3, + "query": "query_result(max(mvs_rmf_m3_mintime{sysplex=~\"${sysplex}\"}))", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "/\\S* (\\d+) \\d*/", + "type": "query" + } + ] + }, + "timepicker": { + "refresh_intervals": ["1m", "5m", "15m", "30m", "1h", "2h", "1d"] + }, + "timezone": "browser", + "title": "z/OS Central Storage Usage", + "weekStart": "" +} diff --git a/grafana/dashboards/prometheus/zos-common-storage.json b/grafana/dashboards/prometheus/zos-common-storage.json deleted file mode 120000 index d6fa8a81..00000000 --- a/grafana/dashboards/prometheus/zos-common-storage.json +++ /dev/null @@ -1 +0,0 @@ -../../rmf-app/src/dashboards/prometheus/zos-common-storage.json \ No newline at end of file diff --git a/grafana/dashboards/prometheus/zos-common-storage.json b/grafana/dashboards/prometheus/zos-common-storage.json new file mode 100644 index 00000000..5a0b39ad --- /dev/null +++ b/grafana/dashboards/prometheus/zos-common-storage.json @@ -0,0 +1,986 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "panels": [], + "title": "Current Usage", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 6, + "x": 0, + "y": 1 + }, + "options": { + "displayMode": "gradient", + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "maxVizHeight": 300, + "minVizHeight": 16, + "minVizWidth": 8, + "namePlacement": "left", + "orientation": "horizontal", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk(10, mvs_system_storage_csa_average_percent{sysplex=~\"${sysplex}\"})", + "instant": true, + "legendFormat": "{{sysname}}", + "range": false, + "refId": "A" + } + ], + "title": "CSA Usage by System (Top 10)", + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 6, + "x": 6, + "y": 1 + }, + "options": { + "displayMode": "gradient", + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "maxVizHeight": 300, + "minVizHeight": 16, + "minVizWidth": 8, + "namePlacement": "left", + "orientation": "horizontal", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk(10, mvs_system_storage_sqa_average_percent{sysplex=~\"${sysplex}\"})", + "instant": true, + "legendFormat": "{{sysname}}", + "range": false, + "refId": "A" + } + ], + "title": "SQA Usage by System (Top 10)", + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 6, + "x": 12, + "y": 1 + }, + "options": { + "displayMode": "gradient", + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "maxVizHeight": 300, + "minVizHeight": 16, + "minVizWidth": 8, + "namePlacement": "left", + "orientation": "horizontal", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk(10, mvs_system_storage_ecsa_average_percent{sysplex=~\"${sysplex}\"})", + "format": "time_series", + "instant": true, + "legendFormat": "{{sysname}}", + "range": false, + "refId": "A" + } + ], + "title": "ECSA Usage by System (Top 10)", + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 6, + "x": 18, + "y": 1 + }, + "options": { + "displayMode": "gradient", + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "maxVizHeight": 300, + "minVizHeight": 16, + "minVizWidth": 8, + "namePlacement": "left", + "orientation": "horizontal", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk(10, mvs_system_storage_esqa_average_percent{sysplex=~\"${sysplex}\"})", + "instant": true, + "legendFormat": "{{sysname}}", + "range": false, + "refId": "A" + } + ], + "title": "ESQA Usage by System (Top 10)", + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "fieldMinMax": true, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 11 + }, + "interval": "${mintime}", + "options": { + "displayMode": "gradient", + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "maxVizHeight": 300, + "minVizHeight": 16, + "minVizWidth": 8, + "namePlacement": "left", + "orientation": "horizontal", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "exemplar": false, + "expr": "topk(10, mvs_job_storage_csa_percent{sysplex=~\"${sysplex}\"})", + "format": "time_series", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": true, + "legendFormat": "{{sysname}}.{{job_name}} [{{asid_dec}}]", + "range": false, + "refId": "A", + "useBackend": false + } + ], + "title": "CSA Usage by Job (Top 10)", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": ["Time", "newid2", "Value", "job_name", "system_name"] + } + } + } + ], + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 11 + }, + "options": { + "displayMode": "gradient", + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "maxVizHeight": 300, + "minVizHeight": 16, + "minVizWidth": 8, + "namePlacement": "left", + "orientation": "horizontal", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk(10, mvs_job_storage_sqa_percent{sysplex=~\"${sysplex}\"})", + "instant": true, + "legendFormat": "{{sysname}}.{{job_name}} [{{asid_dec}}]", + "range": false, + "refId": "A" + } + ], + "title": "SQA Usage by Job (Top 10)", + "type": "bargauge" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 20 + }, + "panels": [], + "title": "Usage History", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "fieldMinMax": true, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 21 + }, + "interval": "${mintime}", + "options": { + "legend": { + "calcs": ["mean"], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "mvs_system_storage_csa_average_percent{sysplex=~\"${sysplex}\"}", + "instant": false, + "legendFormat": "{{sysname}}", + "range": true, + "refId": "A" + } + ], + "title": "CSA Usage by System", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "fieldMinMax": true, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 21 + }, + "interval": "${mintime}", + "options": { + "legend": { + "calcs": ["mean"], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "mvs_system_storage_sqa_average_percent{sysplex=~\"${sysplex}\"}", + "instant": false, + "legendFormat": "{{sysname}}", + "range": true, + "refId": "A" + } + ], + "title": "SQA Usage by System", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "fieldMinMax": true, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 12, + "x": 0, + "y": 31 + }, + "interval": "${mintime}", + "options": { + "legend": { + "calcs": ["mean"], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "mvs_system_storage_ecsa_average_percent{sysplex=~\"${sysplex}\"}", + "instant": false, + "legendFormat": "{{sysname}}", + "range": true, + "refId": "A" + } + ], + "title": "ECSA Usage by System", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "fieldMinMax": true, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 12, + "x": 12, + "y": 31 + }, + "interval": "${mintime}", + "options": { + "legend": { + "calcs": ["mean"], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "mvs_system_storage_esqa_average_percent{sysplex=~\"${sysplex}\"}", + "instant": false, + "legendFormat": "{{sysname}}", + "range": true, + "refId": "A" + } + ], + "title": "ESQA Usage by System", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "1m", + "tags": ["RMF"], + "templating": { + "list": [ + { + "allowCustomValue": false, + "includeAll": false, + "label": "Data Source", + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(mvs_rmf_m3_mintime,sysplex)", + "includeAll": true, + "label": "Sysplex", + "multi": true, + "name": "sysplex", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(mvs_rmf_m3_mintime,sysplex)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "allowCustomValue": false, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "query_result(max(mvs_rmf_m3_mintime{sysplex=~\"${sysplex}\"}))", + "hide": 2, + "name": "mintime", + "options": [], + "query": { + "qryType": 3, + "query": "query_result(max(mvs_rmf_m3_mintime{sysplex=~\"${sysplex}\"}))", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "/\\S* (\\d+) \\d*/", + "type": "query" + } + ] + }, + "timepicker": { + "refresh_intervals": ["1m", "5m", "15m", "30m", "1h", "2h", "1d"] + }, + "timezone": "browser", + "title": "z/OS Common Storage Usage", + "weekStart": "" +} diff --git a/grafana/dashboards/prometheus/zos-coupling-facility.json b/grafana/dashboards/prometheus/zos-coupling-facility.json deleted file mode 120000 index f7b07704..00000000 --- a/grafana/dashboards/prometheus/zos-coupling-facility.json +++ /dev/null @@ -1 +0,0 @@ -../../rmf-app/src/dashboards/prometheus/zos-coupling-facility.json \ No newline at end of file diff --git a/grafana/dashboards/prometheus/zos-coupling-facility.json b/grafana/dashboards/prometheus/zos-coupling-facility.json new file mode 100644 index 00000000..1de43b1d --- /dev/null +++ b/grafana/dashboards/prometheus/zos-coupling-facility.json @@ -0,0 +1,727 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "panels": [], + "title": "Current Usage", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 1 + }, + "interval": "${mintime}", + "options": { + "displayMode": "gradient", + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "maxVizHeight": 300, + "minVizHeight": 16, + "minVizWidth": 8, + "namePlacement": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "text": {}, + "valueMode": "color" + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk(10, mvs_cf_processor_utilization_percent)", + "instant": true, + "legendFormat": "{{sysplex}}.{{name}}", + "range": false, + "refId": "A" + } + ], + "title": "Processor Usage by Coupling Facility (Top 10)", + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 1 + }, + "interval": "${mintime}", + "options": { + "displayMode": "gradient", + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "maxVizHeight": 300, + "minVizHeight": 16, + "minVizWidth": 8, + "namePlacement": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk(10, mvs_cf_request_rate)", + "instant": true, + "legendFormat": "{{sysplex}}.{{name}}", + "range": false, + "refId": "A" + } + ], + "title": "Coupling Facility Request Rate (Top 10)", + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 1 + }, + "interval": "${mintime}", + "options": { + "displayMode": "gradient", + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "maxVizHeight": 300, + "minVizHeight": 16, + "minVizWidth": 8, + "namePlacement": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk(10, mvs_cf_storage_utilized_percent)", + "instant": true, + "legendFormat": "{{sysplex}}.{{name}}", + "range": false, + "refId": "A" + } + ], + "title": "Storage Usage by Coupling Facility (Top 10)", + "type": "bargauge" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 6 + }, + "panels": [], + "title": "Usage History", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 7 + }, + "interval": "${mintime}", + "options": { + "legend": { + "calcs": ["last", "mean", "min", "max"], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "mvs_cf_processor_utilization_percent", + "instant": false, + "legendFormat": "{{sysplex}}.{{name}}", + "range": true, + "refId": "A" + } + ], + "title": "Processor Usage by Coupling Facility", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 7 + }, + "interval": "${mintime}", + "options": { + "legend": { + "calcs": ["last", "mean", "min", "max"], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "mvs_cf_request_rate", + "instant": false, + "legendFormat": "{{sysplex}}.{{name}}", + "range": true, + "refId": "A" + } + ], + "title": "Coupling Facility Request Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 17 + }, + "interval": "${mintime}", + "options": { + "legend": { + "calcs": ["last", "mean", "min", "max"], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "mvs_cf_storage_size_bytes - mvs_cf_storage_available_bytes", + "instant": false, + "legendFormat": "{{sysplex}}.{{name}}", + "range": true, + "refId": "A" + } + ], + "title": "Storage Usage by Coupling Facility (bytes) ", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 17 + }, + "interval": "${mintime}", + "options": { + "legend": { + "calcs": ["last", "mean", "min", "max"], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "mvs_cf_storage_utilized_percent", + "instant": false, + "legendFormat": "{{sysplex}}.{{name}}", + "range": true, + "refId": "A" + } + ], + "title": "Storage Usage by Coupling Facility (percent) ", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "1m", + "tags": ["RMF"], + "templating": { + "list": [ + { + "allowCustomValue": false, + "includeAll": false, + "label": "Data Source", + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(mvs_rmf_m3_mintime,sysplex)", + "includeAll": true, + "label": "Sysplex", + "multi": true, + "name": "sysplex", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(mvs_rmf_m3_mintime,sysplex)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "allowCustomValue": false, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "query_result(max(mvs_rmf_m3_mintime{sysplex=~\"${sysplex}\"}))", + "hide": 2, + "name": "mintime", + "options": [], + "query": { + "qryType": 3, + "query": "query_result(max(mvs_rmf_m3_mintime{sysplex=~\"${sysplex}\"}))", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "/\\S* (\\d+) \\d*/", + "type": "query" + } + ] + }, + "timepicker": { + "refresh_intervals": ["1m", "5m", "15m", "30m", "1h", "2h", "1d"] + }, + "timezone": "browser", + "title": "z/OS Coupling Facility Usage", + "weekStart": "" +} diff --git a/grafana/dashboards/prometheus/zos-msu-capacity.json b/grafana/dashboards/prometheus/zos-msu-capacity.json deleted file mode 120000 index da5d129c..00000000 --- a/grafana/dashboards/prometheus/zos-msu-capacity.json +++ /dev/null @@ -1 +0,0 @@ -../../rmf-app/src/dashboards/prometheus/zos-msu-capacity.json \ No newline at end of file diff --git a/grafana/dashboards/prometheus/zos-msu-capacity.json b/grafana/dashboards/prometheus/zos-msu-capacity.json new file mode 100644 index 00000000..83124ed6 --- /dev/null +++ b/grafana/dashboards/prometheus/zos-msu-capacity.json @@ -0,0 +1,472 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "panels": [], + "title": "Current Usage", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "yellow", + "value": 0.8 + }, + { + "color": "red", + "value": 0.9 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 1 + }, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "horizontal", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sizing": "auto" + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "# Use average values since the same CPC info may come from different sysplexes\navg by(cpc_id) (sum by(cpc_id) (mvs_lpar_actual_msu_h{line_type=\"CP\",cpc_id=~\"${cpcId}\"}) / on(cpc_id) mvs_cpc_capacity_msu_h{cpc_id=~\"${cpcId}\"})", + "hide": false, + "instant": true, + "legendFormat": "{{cpc_sequence_number}}", + "range": false, + "refId": "A" + } + ], + "title": "Current CPC Capacity (percent)", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 1 + }, + "options": { + "displayMode": "gradient", + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "maxVizHeight": 300, + "minVizHeight": 16, + "minVizWidth": 8, + "namePlacement": "left", + "orientation": "horizontal", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "# Use average values since the same CPC info may come from different sysplexes\nsort_desc(avg by (cpc_id, lpar_name) (mvs_lpar_actual_msu_h{line_type=\"CP\", cpc_id=~\"${cpcId}\"}))", + "instant": true, + "legendFormat": "{{cpc_id}}.{{lpar_name}}", + "range": false, + "refId": "A" + } + ], + "title": "Current LPAR Capacity (MSU / hour)", + "type": "bargauge" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 11 + }, + "panels": [], + "title": "Usage History", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "fieldMinMax": true, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 12 + }, + "interval": "${mintime}", + "options": { + "legend": { + "calcs": ["last", "mean", "min", "max"], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "# Use average values since the same CPC info may come from different sysplexes\navg by (cpc_id) (sum by(cpc_id) (mvs_lpar_actual_msu_h{line_type=\"CP\",cpc_id=~\"${cpcId}\"}) / on(cpc_id) mvs_cpc_capacity_msu_h{cpc_id=~\"${cpcId}\"})", + "instant": false, + "legendFormat": "{{cpc_id}}", + "range": true, + "refId": "A" + } + ], + "title": "CPC Capacity (percent)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "fieldMinMax": true, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 21 + }, + "interval": "${mintime}", + "options": { + "legend": { + "calcs": ["last", "mean", "min", "max"], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "width": 390 + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "# Use average values since the same CPC info may come from different sysplexes\navg by (cpc_id, lpar_name) (mvs_lpar_actual_msu_h{line_type=\"CP\", cpc_id=~\"${cpcId}\"})", + "instant": false, + "legendFormat": "{{cpc_id}}.{{lpar_name}}", + "range": true, + "refId": "A" + } + ], + "title": "Actual LPAR Capacity (MSU / hour)", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "1m", + "tags": ["RMF"], + "templating": { + "list": [ + { + "allowCustomValue": false, + "includeAll": false, + "label": "Data Source", + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(mvs_cpc_capacity_msu_h,cpc_id)", + "includeAll": true, + "label": "CPC ID", + "multi": true, + "name": "cpcId", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(mvs_cpc_capacity_msu_h,cpc_id)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "allowCustomValue": false, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(mvs_cpc_capacity_msu_h{cpc_id=~\"$cpcId\"},sysplex)", + "hide": 2, + "multi": true, + "name": "sysplex", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(mvs_cpc_capacity_msu_h{cpc_id=~\"$cpcId\"},sysplex)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "", + "type": "query" + }, + { + "allowCustomValue": false, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "query_result(max(mvs_rmf_m3_mintime{sysplex=~\"${sysplex}\"}))", + "hide": 2, + "name": "mintime", + "options": [], + "query": { + "qryType": 3, + "query": "query_result(max(mvs_rmf_m3_mintime{sysplex=~\"${sysplex}\"}))", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "/\\S* (\\d+) \\d*/", + "type": "query" + } + ] + }, + "timepicker": { + "refresh_intervals": ["1m", "5m", "15m", "30m", "1h", "2h", "1d"] + }, + "timezone": "browser", + "title": "z/OS MSU Capacity", + "weekStart": "" +} diff --git a/grafana/dashboards/prometheus/zos-usage-by-job.json b/grafana/dashboards/prometheus/zos-usage-by-job.json deleted file mode 120000 index 01d79fe9..00000000 --- a/grafana/dashboards/prometheus/zos-usage-by-job.json +++ /dev/null @@ -1 +0,0 @@ -../../rmf-app/src/dashboards/prometheus/zos-usage-by-job.json \ No newline at end of file diff --git a/grafana/dashboards/prometheus/zos-usage-by-job.json b/grafana/dashboards/prometheus/zos-usage-by-job.json new file mode 100644 index 00000000..64c36b27 --- /dev/null +++ b/grafana/dashboards/prometheus/zos-usage-by-job.json @@ -0,0 +1,840 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "panels": [], + "title": "Current Usage", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "#EAB839", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 1 + }, + "options": { + "displayMode": "gradient", + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "maxVizHeight": 300, + "minVizHeight": 16, + "minVizWidth": 8, + "namePlacement": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": ["last"], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk(20, mvs_job_total_eappl_percent{sysplex=~\"${sysplex}\",sysname=~\"${sysname}\"})", + "instant": true, + "legendFormat": "{{sysname}}.{{job_name}} [{{asid_dec}}]", + "range": false, + "refId": "A" + } + ], + "title": "Current CP Usage (Top 20)", + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 1 + }, + "options": { + "displayMode": "gradient", + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "maxVizHeight": 300, + "minVizHeight": 16, + "minVizWidth": 8, + "namePlacement": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": ["last"], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk(20, mvs_job_working_set_frames_total{sysplex=~\"${sysplex}\",sysname=~\"${sysname}\"} * 4096)", + "instant": true, + "legendFormat": "{{sysname}}.{{job_name}} [{{asid_dec}}]", + "range": false, + "refId": "A" + } + ], + "title": "Current Working Sets (Top 20)", + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "#EAB839", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 11 + }, + "options": { + "displayMode": "gradient", + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "maxVizHeight": 300, + "minVizHeight": 16, + "minVizWidth": 8, + "namePlacement": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": ["last"], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk(20, mvs_job_cp_eappl_percent{sysplex=~\"${sysplex}\",sysname=~\"${sysname}\"})", + "instant": true, + "legendFormat": "{{sysname}}.{{job_name}} [{{asid_dec}}]", + "range": false, + "refId": "A" + } + ], + "title": "Current GCP Usage (Top 20)", + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "#EAB839", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 11 + }, + "options": { + "displayMode": "gradient", + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "maxVizHeight": 300, + "minVizHeight": 16, + "minVizWidth": 8, + "namePlacement": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": ["last"], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk(20, mvs_job_iip_eappl_percent{sysplex=~\"${sysplex}\",sysname=~\"${sysname}\"})", + "instant": true, + "legendFormat": "{{sysname}}.{{job_name}} [{{asid_dec}}]", + "range": false, + "refId": "A" + } + ], + "title": "Current ZIIP Usage (Top 20)", + "type": "bargauge" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 21 + }, + "panels": [], + "title": "Usage History", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "#EAB839", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 22 + }, + "interval": "${mintime}", + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Name", + "sortDesc": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "mvs_job_total_eappl_percent{sysplex=~\"${sysplex}\",sysname=~\"${sysname}\",job_name=~\"${jobname}\"}", + "instant": false, + "legendFormat": "{{sysname}}.{{job_name}} [{{asid_dec}}]", + "range": true, + "refId": "A" + } + ], + "title": "Total CP Usage by Job (percent)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "#EAB839", + "value": 40 + }, + { + "color": "red", + "value": 60 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 22 + }, + "interval": "${mintime}", + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Last", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "mvs_job_working_set_frames_total{sysplex=~\"${sysplex}\",sysname=~\"${sysname}\",job_name=~\"${jobname}\"} * 4096", + "instant": false, + "legendFormat": "{{sysname}}.{{job_name}} [{{asid_dec}}]", + "range": true, + "refId": "A" + } + ], + "title": "Working Sets by Job (bytes)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "#EAB839", + "value": 40 + }, + { + "color": "red", + "value": 60 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 32 + }, + "interval": "${mintime}", + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Name", + "sortDesc": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "mvs_job_cp_eappl_percent{sysplex=~\"${sysplex}\",sysname=~\"${sysname}\",job_name=~\"${jobname}\"}", + "instant": false, + "legendFormat": "{{sysname}}.{{job_name}} [{{asid_dec}}]", + "range": true, + "refId": "A" + } + ], + "title": "GCP Usage by Job (percent)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "#EAB839", + "value": 40 + }, + { + "color": "red", + "value": 60 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 32 + }, + "interval": "${mintime}", + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Name", + "sortDesc": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "mvs_job_iip_eappl_percent{sysplex=~\"${sysplex}\",sysname=~\"${sysname}\",job_name=~\"${jobname}\"}", + "instant": false, + "legendFormat": "{{sysname}}.{{job_name}} [{{asid_dec}}]", + "range": true, + "refId": "A" + } + ], + "title": "ZIIP Usage by Job (percent)", + "type": "timeseries" + } + ], + "preload": false, + "tags": ["RMF"], + "templating": { + "list": [ + { + "allowCustomValue": false, + "includeAll": false, + "label": "Data Source", + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(mvs_rmf_m3_mintime,sysplex)", + "includeAll": true, + "label": "Sysplex", + "multi": true, + "name": "sysplex", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(mvs_rmf_m3_mintime,sysplex)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "allowCustomValue": false, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "query_result(max(mvs_rmf_m3_mintime{sysplex=~\"${sysplex}\"}))", + "hide": 2, + "name": "mintime", + "options": [], + "query": { + "qryType": 3, + "query": "query_result(max(mvs_rmf_m3_mintime{sysplex=~\"${sysplex}\"}))", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "/\\S* (\\d+) \\d*/", + "type": "query" + }, + { + "allowCustomValue": true, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(mvs_wlm_group_delay_percent{sysplex=~\"$sysplex\"},sysname)", + "includeAll": true, + "label": "Sysname", + "multi": true, + "name": "sysname", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(mvs_wlm_group_delay_percent{sysplex=~\"$sysplex\"},sysname)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(mvs_job_total_eappl_percent{sysplex=~\"$sysplex\", sysname=~\"$sysname\"},job_name)", + "description": "Applied to historical views", + "label": "Jobname", + "multi": true, + "name": "jobname", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(mvs_job_total_eappl_percent{sysplex=~\"$sysplex\", sysname=~\"$sysname\"},job_name)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "timepicker": { + "refresh_intervals": ["1m", "5m", "15m", "30m", "1h", "2h", "1d"] + }, + "timezone": "browser", + "title": "z/OS Usage by Job" +} diff --git a/grafana/dashboards/prometheus/zos-wlm-delays.json b/grafana/dashboards/prometheus/zos-wlm-delays.json deleted file mode 120000 index 208f8853..00000000 --- a/grafana/dashboards/prometheus/zos-wlm-delays.json +++ /dev/null @@ -1 +0,0 @@ -../../rmf-app/src/dashboards/prometheus/zos-wlm-delays.json \ No newline at end of file diff --git a/grafana/dashboards/prometheus/zos-wlm-delays.json b/grafana/dashboards/prometheus/zos-wlm-delays.json new file mode 100644 index 00000000..92ae387d --- /dev/null +++ b/grafana/dashboards/prometheus/zos-wlm-delays.json @@ -0,0 +1,719 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "#EAB839", + "value": 40 + }, + { + "color": "red", + "value": 60 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 0 + }, + "options": { + "displayMode": "gradient", + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "maxVizHeight": 300, + "minVizHeight": 16, + "minVizWidth": 8, + "namePlacement": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk(20, label_replace({__name__=~\"mvs_wlm_group_delay_(.*)_percent\", group_type=\"W\",sysplex=~\"${sysplex}\",sysname=~\"${sysname}\"}, \"delay\", \"$1\", \"__name__\", \"mvs_wlm_group_delay_(.*)_percent\"))", + "instant": true, + "legendFormat": "{{sysname}}.{{group_name}} ({{delay}})", + "range": false, + "refId": "A" + } + ], + "title": "Current WLM Workload Delays by Type (Top 20)", + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "filterable": true, + "inspect": false + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "text" + }, + { + "color": "#EAB839", + "value": 40 + }, + { + "color": "red", + "value": 60 + } + ] + }, + "unit": "percent" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Sysplex" + }, + "properties": [ + { + "id": "custom.width", + "value": 94 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Sysname" + }, + "properties": [ + { + "id": "custom.width", + "value": 95 + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.* Delay/" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "type": "color-text" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Workload" + }, + "properties": [ + { + "id": "custom.width", + "value": 113 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total Delay" + }, + "properties": [ + { + "id": "custom.width", + "value": 116 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Processor Delay" + }, + "properties": [ + { + "id": "custom.width", + "value": 145 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Operator Delay" + }, + "properties": [ + { + "id": "custom.width", + "value": 137 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "JES Delay" + }, + "properties": [ + { + "id": "custom.width", + "value": 104 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "HSM Delay" + }, + "properties": [ + { + "id": "custom.width", + "value": 107 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Device Delay" + }, + "properties": [ + { + "id": "custom.width", + "value": 123 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Enqueue Delay" + }, + "properties": [ + { + "id": "custom.width", + "value": 135 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Storage Delay" + }, + "properties": [ + { + "id": "custom.width", + "value": 131 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Subsystem Delay" + }, + "properties": [ + { + "id": "custom.width", + "value": 152 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "XCF Delay" + }, + "properties": [ + { + "id": "custom.width", + "value": 105 + } + ] + } + ] + }, + "gridPos": { + "h": 12, + "w": 24, + "x": 0, + "y": 8 + }, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": ["sum"], + "show": false + }, + "frameIndex": 1, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Total Delay" + } + ] + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "label_replace(\n avg_over_time(mvs_wlm_group_delay_percent{group_type=\"W\",sysplex=~\"${sysplex}\",sysname=~\"${sysname}\"}[$__range]),\n \"__name__\",\n \"Total Delay\",\n \"\",\n \".*\"\n)", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "label_replace(\n avg_over_time(mvs_wlm_group_delay_proc_percent{group_type=\"W\",sysplex=~\"${sysplex}\",sysname=~\"${sysname}\"}[$__range]),\n \"__name__\",\n \"Processor Delay\",\n \"\",\n \".*\"\n)", + "format": "time_series", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "label_replace(\n avg_over_time(mvs_wlm_group_delay_oper_percent{group_type=\"W\",sysplex=~\"${sysplex}\",sysname=~\"${sysname}\"}[$__range]),\n \"__name__\",\n \"Operator Delay\",\n \"\",\n \".*\"\n)", + "format": "time_series", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "label_replace(\n avg_over_time(mvs_wlm_group_delay_jes_percent{group_type=\"W\",sysplex=~\"${sysplex}\",sysname=~\"${sysname}\"}[$__range]),\n \"__name__\",\n \"JES Delay\",\n \"\",\n \".*\"\n)", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "label_replace(\n avg_over_time(mvs_wlm_group_delay_hsm_percent{group_type=\"W\",sysplex=~\"${sysplex}\",sysname=~\"${sysname}\"}[$__range]),\n \"__name__\",\n \"HSM Delay\",\n \"\",\n \".*\"\n)", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "E" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "label_replace(\n avg_over_time(mvs_wlm_group_delay_dev_percent{group_type=\"W\",sysplex=~\"${sysplex}\",sysname=~\"${sysname}\"}[$__range]),\n \"__name__\",\n \"Device Delay\",\n \"\",\n \".*\"\n)", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "F" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "label_replace(\n avg_over_time(mvs_wlm_group_delay_enq_percent{group_type=\"W\",sysplex=~\"${sysplex}\",sysname=~\"${sysname}\"}[$__range]),\n \"__name__\",\n \"Enqueue Delay\",\n \"\",\n \".*\"\n)", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "G" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "label_replace(\n avg_over_time(mvs_wlm_group_delay_stor_percent{group_type=\"W\",sysplex=~\"${sysplex}\",sysname=~\"${sysname}\"}[$__range]),\n \"__name__\",\n \"Storage Delay\",\n \"\",\n \".*\"\n)", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "H" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "label_replace(\n avg_over_time(mvs_wlm_group_delay_subs_percent{group_type=\"W\",sysplex=~\"${sysplex}\",sysname=~\"${sysname}\"}[$__range]),\n \"__name__\",\n \"Subsystem Delay\",\n \"\",\n \".*\"\n)", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "I" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "label_replace(\n avg_over_time(mvs_wlm_group_delay_xcf_percent{group_type=\"W\",sysplex=~\"${sysplex}\",sysname=~\"${sysname}\"}[$__range]),\n \"__name__\",\n \"XCF Delay\",\n \"\",\n \".*\"\n)", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "J" + } + ], + "title": "Average WLM Workload Delays", + "transformations": [ + { + "id": "joinByLabels", + "options": { + "value": "__name__" + } + }, + { + "id": "organize", + "options": { + "excludeByName": { + "group_type": true, + "instance": true, + "job": true, + "mvs_wlm_batch_ai": true, + "sysname": false + }, + "includeByName": {}, + "indexByName": { + "Device Delay": 11, + "Enqueue Delay": 12, + "HSM Delay": 10, + "JES Delay": 9, + "Operator Delay": 8, + "Processor Delay": 7, + "Storage Delay": 13, + "Subsystem Delay": 14, + "Total Delay": 6, + "XCF Delay": 15, + "group_name": 0, + "group_type": 1, + "instance": 2, + "job": 3, + "sysname": 5, + "sysplex": 4 + }, + "renameByName": { + "group_name": "Workload", + "sysname": "Sysname", + "sysplex": "Sysplex" + } + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "#EAB839", + "value": 40 + }, + { + "color": "red", + "value": 60 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 24, + "x": 0, + "y": 20 + }, + "interval": "${mintime}", + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Name", + "sortDesc": false, + "width": 180 + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "mvs_wlm_group_delay_percent{group_type=\"W\",sysplex=~\"${sysplex}\",sysname=~\"${sysname}\"}", + "instant": false, + "legendFormat": "{{sysname}}.{{group_name}}", + "range": true, + "refId": "A" + } + ], + "title": "WLM Workload Total Delays", + "type": "timeseries" + } + ], + "preload": false, + "tags": ["RMF"], + "templating": { + "list": [ + { + "allowCustomValue": false, + "includeAll": false, + "label": "Data Source", + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(mvs_rmf_m3_mintime,sysplex)", + "includeAll": true, + "label": "Sysplex", + "multi": true, + "name": "sysplex", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(mvs_rmf_m3_mintime,sysplex)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "allowCustomValue": false, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "query_result(max(mvs_rmf_m3_mintime{sysplex=~\"${sysplex}\"}))", + "hide": 2, + "name": "mintime", + "options": [], + "query": { + "qryType": 3, + "query": "query_result(max(mvs_rmf_m3_mintime{sysplex=~\"${sysplex}\"}))", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "/\\S* (\\d+) \\d*/", + "type": "query" + }, + { + "allowCustomValue": true, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(mvs_wlm_group_delay_percent{sysplex=~\"$sysplex\"},sysname)", + "includeAll": true, + "label": "Sysname", + "multi": true, + "name": "sysname", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(mvs_wlm_group_delay_percent{sysplex=~\"$sysplex\"},sysname)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "", + "sort": 1, + "type": "query" + } + ] + }, + "timepicker": { + "refresh_intervals": ["1m", "5m", "15m", "30m", "1h", "2h", "1d"] + }, + "timezone": "browser", + "title": "z/OS WLM Workload Delays" +} From 66e9312eae0e6c603ee97a37abb0fa04b3c0f721 Mon Sep 17 00:00:00 2001 From: dprizentsov Date: Mon, 29 Sep 2025 13:11:38 +0200 Subject: [PATCH 19/36] user option to add link to OMEGAMON dashboards wile deploying RMF dashboards Signed-off-by: dprizentsov --- grafana/rmf-app/pkg/plugin/config.go | 13 +- grafana/rmf-app/pkg/plugin/datasource.go | 68 ++++++- grafana/rmf-app/pkg/plugin/dds/client.go | 24 ++- grafana/rmf-app/pkg/plugin/dds/response.go | 25 +++ grafana/rmf-app/pkg/plugin/frame/frame.go | 46 +++-- grafana/rmf-app/src/components/Root/Root.tsx | 73 ++++++-- grafana/rmf-app/src/components/Root/types.ts | 6 + grafana/rmf-app/src/components/Root/utils.ts | 173 +++++++++++++++++- grafana/rmf-app/src/constants.ts | 2 + .../rmf-app/src/dashboards/dds/CACHDET.json | 33 +++- .../rmf-app/src/dashboards/dds/CACHSUM.json | 33 +++- grafana/rmf-app/src/dashboards/dds/CFACT.json | 33 +++- .../rmf-app/src/dashboards/dds/CFOVER.json | 33 +++- grafana/rmf-app/src/dashboards/dds/CFSYS.json | 33 +++- .../rmf-app/src/dashboards/dds/CHANNEL.json | 37 +++- grafana/rmf-app/src/dashboards/dds/CPC.json | 37 +++- .../rmf-app/src/dashboards/dds/CRYOVW.json | 31 +++- .../Common Storage Activity (Timeline).json | 47 +++-- .../dds/Common Storage Activity.json | 43 +++-- ...Coupling Facility Overview (Timeline).json | 41 +++-- .../dds/Coupling Facility Overview.json | 37 +++- grafana/rmf-app/src/dashboards/dds/DELAY.json | 39 +++- grafana/rmf-app/src/dashboards/dds/DEV.json | 37 +++- grafana/rmf-app/src/dashboards/dds/DEVR.json | 37 +++- grafana/rmf-app/src/dashboards/dds/DSND.json | 37 +++- grafana/rmf-app/src/dashboards/dds/EADM.json | 37 +++- .../rmf-app/src/dashboards/dds/ENCLAVE.json | 37 +++- grafana/rmf-app/src/dashboards/dds/ENQ.json | 37 +++- .../dds/Execution Velocity (Timeline).json | 37 +++- .../dashboards/dds/Execution Velocity.json | 33 +++- .../dds/General Activity (Timeline).json | 49 +++-- .../src/dashboards/dds/General Activity.json | 45 +++-- grafana/rmf-app/src/dashboards/dds/HSM.json | 37 +++- grafana/rmf-app/src/dashboards/dds/IOQ.json | 37 +++- grafana/rmf-app/src/dashboards/dds/JES.json | 37 +++- .../rmf-app/src/dashboards/dds/LOCKSP.json | 37 +++- .../rmf-app/src/dashboards/dds/LOCKSU.json | 37 +++- grafana/rmf-app/src/dashboards/dds/OPD.json | 37 +++- .../Overall Image Activity (Timeline).json | 51 ++++-- .../dds/Overall Image Activity.json | 47 +++-- grafana/rmf-app/src/dashboards/dds/PCIE.json | 37 +++- grafana/rmf-app/src/dashboards/dds/PROC.json | 39 +++- grafana/rmf-app/src/dashboards/dds/PROCU.json | 39 +++- .../dds/Performance Index (Timeline).json | 35 +++- .../src/dashboards/dds/Performance Index.json | 31 +++- .../dds/Response Time (Timeline).json | 47 +++-- .../src/dashboards/dds/Response Time.json | 43 +++-- .../rmf-app/src/dashboards/dds/SPACED.json | 31 +++- .../rmf-app/src/dashboards/dds/SPACEG.json | 31 +++- grafana/rmf-app/src/dashboards/dds/STOR.json | 39 +++- grafana/rmf-app/src/dashboards/dds/STORC.json | 37 +++- .../rmf-app/src/dashboards/dds/STORCR.json | 37 +++- grafana/rmf-app/src/dashboards/dds/STORF.json | 39 +++- grafana/rmf-app/src/dashboards/dds/STORM.json | 37 +++- grafana/rmf-app/src/dashboards/dds/STORR.json | 37 +++- grafana/rmf-app/src/dashboards/dds/STORS.json | 37 +++- .../rmf-app/src/dashboards/dds/SYSINFO.json | 37 +++- grafana/rmf-app/src/dashboards/dds/SYSRG.json | 31 +++- .../rmf-app/src/dashboards/dds/SYSSUM.json | 31 +++- grafana/rmf-app/src/dashboards/dds/USAGE.json | 39 +++- .../dds/Using & Delays (Timeline).json | 51 ++++-- .../src/dashboards/dds/Using & Delays.json | 47 +++-- .../dds/XCF Activity (Timeline).json | 47 +++-- .../src/dashboards/dds/XCF Activity.json | 43 +++-- .../rmf-app/src/dashboards/dds/XCFGROUP.json | 31 +++- .../rmf-app/src/dashboards/dds/XCFOVW.json | 31 +++- .../rmf-app/src/dashboards/dds/XCFPATH.json | 31 +++- .../rmf-app/src/dashboards/dds/XCFSYS.json | 31 +++- grafana/rmf-app/src/dashboards/dds/ZFSFS.json | 31 +++- grafana/rmf-app/src/dashboards/dds/ZFSKN.json | 31 +++- .../rmf-app/src/dashboards/dds/ZFSOVW.json | 31 +++- .../rmf-datasource/common/common.helper.ts | 9 + .../rmf-datasource/common/configSettings.ts | 2 + .../rmf-datasource/common/types.ts | 1 + .../config-editor/config-editor.component.tsx | 46 ++++- .../table-component/table.component.tsx | 7 +- .../report/table-component/table.helper.ts | 36 ++-- grafana/rmf-app/src/panels/report/types.ts | 11 +- 78 files changed, 2226 insertions(+), 638 deletions(-) diff --git a/grafana/rmf-app/pkg/plugin/config.go b/grafana/rmf-app/pkg/plugin/config.go index 5ab25b57..902d0112 100644 --- a/grafana/rmf-app/pkg/plugin/config.go +++ b/grafana/rmf-app/pkg/plugin/config.go @@ -44,12 +44,13 @@ type Config struct { // Custom RMF settings. CacheSizeRaw string `json:"cacheSize"` // Legacy custom RMF settings. We should ge rid of these at some point. - Server *string `json:"path"` - Port string `json:"port"` - SSL bool `json:"ssl"` - Username string `json:"userName"` - Password string `json:"password"` - SSLVerify bool `json:"skipVerify"` // NB: the meaning of JSON field is inverted. + Server *string `json:"path"` + Port string `json:"port"` + SSL bool `json:"ssl"` + Username string `json:"userName"` + Password string `json:"password"` + SSLVerify bool `json:"skipVerify"` // NB: the meaning of JSON field is inverted. + OmegamonDs string `json:"omegamonDs"` } } diff --git a/grafana/rmf-app/pkg/plugin/datasource.go b/grafana/rmf-app/pkg/plugin/datasource.go index 4b052967..f4f68d8e 100644 --- a/grafana/rmf-app/pkg/plugin/datasource.go +++ b/grafana/rmf-app/pkg/plugin/datasource.go @@ -23,6 +23,7 @@ import ( "errors" "net/http" "runtime/debug" + "slices" "strings" "sync" "time" @@ -63,6 +64,7 @@ type RMFDatasource struct { frameCache *cache.FrameCache ddsClient *dds.Client single singleflight.Group + omegamonDs string } // NewRMFDatasource creates a new instance of the RMF datasource. @@ -79,6 +81,7 @@ func NewRMFDatasource(ctx context.Context, settings backend.DataSourceInstanceSe config.JSON.TlsSkipVerify, config.JSON.DisableCompression) ds.channelCache = cache.NewChannelCache(ChannelCacheSizeMB) ds.frameCache = cache.NewFrameCache(config.CacheSize) + ds.omegamonDs = config.JSON.OmegamonDs logger.Info("initialized a datasource", "uid", settings.UID, "name", settings.Name, "url", config.URL, "timeout", config.Timeout, "cacheSize", config.CacheSize, @@ -148,13 +151,28 @@ func (ds *RMFDatasource) CallResource(ctx context.Context, req *backend.CallReso switch req.Path { // FIXME: it's a contained.xml request for M3 resource tree. Re-factor accordingly. case "variablequery": - // Extract the query parameter from the POST request - jsonStr := string(req.Body) varRequest := VariableQueryRequest{} - err := json.Unmarshal([]byte(jsonStr), &varRequest) + err := json.Unmarshal(req.Body, &varRequest) if err != nil { return log.ErrorWithId(logger, log.InternalError, "could not unmarshal data", "error", err) } + q := varRequest.Query + q = strings.Trim(q, " ") + q = strings.ToLower(q) + + switch q { + case "sysplex": + data, _ := ds.sysplexContainedJson() + return sender.Send(&backend.CallResourceResponse{Status: http.StatusOK, Body: data}) + case "systems": + data, _ := ds.systemsContainedJson() + return sender.Send(&backend.CallResourceResponse{Status: http.StatusOK, Body: data}) + case "omegamonds": + data, _ := ds.omegamonContainedJson() + return sender.Send(&backend.CallResourceResponse{Status: http.StatusOK, Body: data}) + } + + // Extract the query parameter from the POST request ddsResource := varRequest.Query if len(strings.TrimSpace(ddsResource)) == 0 { return log.ErrorWithId(logger, log.InputError, "variable query cannot be blank") @@ -184,6 +202,50 @@ func (ds *RMFDatasource) CallResource(ctx context.Context, req *backend.CallReso } } +func (ds *RMFDatasource) sysplexContainedJson() ([]byte, error) { + sysplex := ds.ddsClient.GetSysplex() + return toContainedJson([]string{sysplex}) +} + +func (ds *RMFDatasource) systemsContainedJson() ([]byte, error) { + systems := ds.ddsClient.GetSystems() + slices.Sort(systems) + return toContainedJson(systems) +} + +func (ds *RMFDatasource) omegamonContainedJson() ([]byte, error) { + return toContainedJson([]string{ds.omegamonDs}) +} + +func toContainedJson(resources []string) ([]byte, error) { + type Resource struct { + Reslabel string `json:"reslabel"` + } + type Contained struct { + Resource []Resource `json:"resource"` + } + type ContainedResource struct { + Contained Contained `json:"contained"` + } + type Ddsml struct { + ContainedResourcesList []ContainedResource `json:"containedResourcesList"` + } + + contained := Contained{Resource: []Resource{}} + for _, res := range resources { + contained.Resource = append(contained.Resource, Resource{Reslabel: "," + res + ","}) + } + + var containedResource = ContainedResource{ + Contained: contained, + } + + result := Ddsml{ + ContainedResourcesList: []ContainedResource{containedResource}, + } + return json.Marshal(result) +} + type RequestParams struct { Resource struct { Value string `json:"value"` diff --git a/grafana/rmf-app/pkg/plugin/dds/client.go b/grafana/rmf-app/pkg/plugin/dds/client.go index 7d47c293..a064b307 100644 --- a/grafana/rmf-app/pkg/plugin/dds/client.go +++ b/grafana/rmf-app/pkg/plugin/dds/client.go @@ -64,6 +64,8 @@ type Client struct { httpClient *http.Client headerMap *HeaderMap timeData *TimeData + resource *Resource + systems []string useXmlExt atomic.Bool stopChan chan struct{} @@ -247,7 +249,7 @@ func (c *Client) ensureTimeData() *TimeData { func (c *Client) updateTimeData() *TimeData { logger := log.Logger.With("func", "updateTimeData") result, _, _ := c.single.Do("timeData", func() (any, error) { - response, err := c.Get(PerformPath, "resource", ",,SYSPLEX", "id", "8D0D50") + response, err := c.Get(PerformPath, "resource", ",,SYSPLEX", "id", "8D0D60") if err != nil { logger.Error("unable to fetch DDS time data", "error", err) return nil, err @@ -257,8 +259,15 @@ func (c *Client) updateTimeData() *TimeData { logger.Error("unable to fetch DDS time data", "error", "no time data in DDS response") return nil, err } + resource := response.Reports[0].Resource + if resource == nil { + logger.Error("unable to fetch DDS resource", "error", "no resource data in DDS response") + } + systems := response.Reports[0].GetRowNames() c.rwMutex.Lock() c.timeData = timeData + c.resource = resource + c.systems = systems c.rwMutex.Unlock() logger.Debug("DDS time data updated") return timeData, nil @@ -277,3 +286,16 @@ func (c *Client) GetCachedMintime() time.Duration { } return time.Duration(minTime) * time.Second } + +func (c *Client) GetSysplex() string { + c.ensureTimeData() + if c.resource != nil { + return c.resource.GetName() + } + return "" +} + +func (c *Client) GetSystems() []string { + c.ensureTimeData() + return c.systems +} diff --git a/grafana/rmf-app/pkg/plugin/dds/response.go b/grafana/rmf-app/pkg/plugin/dds/response.go index 65d731c6..d1cc8002 100644 --- a/grafana/rmf-app/pkg/plugin/dds/response.go +++ b/grafana/rmf-app/pkg/plugin/dds/response.go @@ -19,6 +19,7 @@ package dds import ( "fmt" + "strings" "time" ) @@ -55,12 +56,23 @@ type Report struct { Metric *Metric Message *Message Caption Caption + Resource *Resource `json:"resource"` Headers struct { Cols []Col `json:"col"` } `json:"columnHeaders"` Rows []Row `json:"row"` } +func (r Report) GetRowNames() []string { + var names []string + if r.Rows != nil { + for _, row := range r.Rows { + names = append(names, row.Cols[0]) + } + } + return names +} + type TimeData struct { // FIXME: don't use these in report headers: they are in DDS timezone. Remove from the mapping. LocalStart DateTime `json:"localStart"` @@ -81,6 +93,19 @@ type TimeData struct { } `json:"dataRange"` } +type Resource struct { + Reslabel string `json:"reslabel"` + Restype string `json:"restype"` +} + +func (r Resource) GetName() string { + ss := strings.Split(r.Reslabel, ",") + if len(ss) > 1 { + return ss[1] + } + return r.Reslabel +} + type DateTime struct { time.Time } diff --git a/grafana/rmf-app/pkg/plugin/frame/frame.go b/grafana/rmf-app/pkg/plugin/frame/frame.go index f85268d7..45bb08fe 100644 --- a/grafana/rmf-app/pkg/plugin/frame/frame.go +++ b/grafana/rmf-app/pkg/plugin/frame/frame.go @@ -50,45 +50,51 @@ func NoDataFrame(t time.Time) *data.Frame { ) } -func Build(ddsResponse *dds.Response, headers *dds.HeaderMap, wide bool) (*data.Frame, error) { +func validateResponse(ddsResponse *dds.Response) error { logger := log.Logger.With("func", "Build") reportsNum := len(ddsResponse.Reports) if reportsNum == 0 { - return nil, errors.New("no reports in DDS response") + return errors.New("no reports in DDS response") } else if reportsNum > 1 { - return nil, fmt.Errorf("too many reports (%d) in DDS response", reportsNum) + return fmt.Errorf("too many reports (%d) in DDS response", reportsNum) } report := ddsResponse.Reports[0] if message := report.Message; message != nil { if _, ok := dds.AcceptableMessages[message.Id]; !ok { - return nil, message + return message } else { logger.Debug(message.Error()) } } if report.TimeData == nil { - return nil, errors.New("no time data in DDS response") + return errors.New("no time data in DDS response") } if report.Metric == nil { - return nil, errors.New("no metric data in DDS response") + return errors.New("no metric data in DDS response") } if _, ok := dds.SupportedFormats[report.Metric.Format]; !ok { - return nil, fmt.Errorf("unsupported data format (%s) in DDS response", report.Metric.Format) + return fmt.Errorf("unsupported data format (%s) in DDS response", report.Metric.Format) } + return nil +} +func Build(ddsResponse *dds.Response, headers *dds.HeaderMap, wide bool) (*data.Frame, error) { + err := validateResponse(ddsResponse) + if err != nil { + return nil, err + } + report := ddsResponse.Reports[0] format := report.Metric.Format frameName := strings.Trim(report.Metric.Description, " ") - var newFrame *data.Frame if format == dds.ReportFormat { - newFrame = buildForReport(&report, headers, frameName) + return buildForReport(&report, headers, frameName), nil } else if wide { return buildWideForMetric(&report, frameName), nil } else { return buildLongForMetric(&report, frameName), nil } - return newFrame, nil } // buildWideForMetric creates a time series data frame for a metric from pre-parsed DDS response. @@ -191,7 +197,7 @@ func buildForReport(report *dds.Report, headers *dds.HeaderMap, frameName string var field *data.Field // The first value is a dummy to fit in captions and header. if col.Type == dds.NumericColType { - field = data.NewField(header, nil, []*float64{nil}) + field = data.NewField(header, nil, []float64{0}) //? } else { if col.Type != dds.TextColType { logger.Warn("unsupported column type, considering as string", "type", col.Type) @@ -200,8 +206,16 @@ func buildForReport(report *dds.Report, headers *dds.HeaderMap, frameName string } for _, row := range report.Rows { rawValue := row.Cols[i] + if field == nil { + if col.Type == dds.NumericColType { + field = data.NewField(header, nil, []float64{parseFloat2(rawValue)}) //? + } else { + field = data.NewField(header, nil, []string{rawValue}) + } + continue + } if col.Type == dds.NumericColType { - field.Append(parseFloat(rawValue)) + field.Append(parseFloat2(rawValue)) //? } else { field.Append(rawValue) } @@ -250,3 +264,11 @@ func parseFloat(value string) *float64 { } return nil } + +func parseFloat2(value string) float64 { + // Value can contain different kinds of text meaning n/a: NaN, blank value, Deact, etc. + if parsed, err := strconv.ParseFloat(value, 64); err == nil && !math.IsNaN(parsed) { + return parsed + } + return 0.0 +} diff --git a/grafana/rmf-app/src/components/Root/Root.tsx b/grafana/rmf-app/src/components/Root/Root.tsx index 330d525f..def8fee5 100644 --- a/grafana/rmf-app/src/components/Root/Root.tsx +++ b/grafana/rmf-app/src/components/Root/Root.tsx @@ -15,16 +15,16 @@ * limitations under the License. */ import React, { PureComponent } from 'react'; -import { PanelContainer, Button, TextLink, Box, Icon, Alert } from '@grafana/ui'; +import { PanelContainer, Button, TextLink, Box, Icon, Alert, InlineSwitch, Input, InlineField } from '@grafana/ui'; import { locationService, getBackendSrv, getDataSourceSrv, getAppEvents } from '@grafana/runtime'; import { AppRootProps, AppEvents } from '@grafana/data'; -import { DDS_OPEN_METRICS_DOC_URL, DATA_SOURCE_TYPE, APP_LOGO_URL } from '../../constants'; +import { DDS_OPEN_METRICS_DOC_URL, DATA_SOURCE_TYPE, APP_LOGO_URL, FALCON_AS_DASHBOARD, FALCON_SYS_DASHBOARD } from '../../constants'; import { GlobalSettings } from '../../types'; import { DASHBOARDS as DDS_DASHBOARDS } from '../../dashboards/dds'; import { DASHBOARDS as PROM_DASHBOARDS } from '../../dashboards/prometheus'; -import { findFolder, deleteFolder, installDashboards } from './utils'; -import { FolderStatus, Operation, OperCode, OperStatus } from './types'; +import { findFolder, deleteFolder, installDashboards, findDashboard } from './utils'; +import { FolderStatus, Operation, OperCode, OperStatus, FalconStatus } from './types'; import { StatusIcon } from './StatusIcon'; import { Space } from './Space'; import { Header } from './Header'; @@ -40,6 +40,7 @@ interface Props extends AppRootProps {} interface State { dds: FolderStatus; prom: FolderStatus; + falcon: FalconStatus; } export class Root extends PureComponent { @@ -56,6 +57,11 @@ export class Root extends PureComponent { installed: false, operation: { code: OperCode.None, status: OperStatus.None }, }, + falcon: { + enabled: false, + asDashboard: FALCON_AS_DASHBOARD, + sysDashboard: FALCON_SYS_DASHBOARD, + } }; } @@ -67,6 +73,8 @@ export class Root extends PureComponent { try { const ddsFolderPath = await findFolder(DDS_FOLDER_UID); const promFolderPath = await findFolder(PROM_FOLDER_UID); + const asDashboard = await findDashboard("Job CPU Details", ["omegamon", "zos", "lpar", "cpu"]); + const sysDashboard = await findDashboard("z/OS Enterprise Overview", ["omegamon", "zos", "enterprise"]); this.setState((prevState) => ({ dds: { ...prevState.dds, @@ -78,6 +86,11 @@ export class Root extends PureComponent { installed: promFolderPath !== undefined, folderPath: promFolderPath || PROM_FOLDER_NAME, }, + falcon: { + ...prevState.falcon, + asDashboard: asDashboard !== undefined ? asDashboard : FALCON_AS_DASHBOARD, + sysDashboard: sysDashboard !== undefined ? sysDashboard : FALCON_SYS_DASHBOARD, + } })); } catch (error) { console.error('failed to update state', error); @@ -113,7 +126,7 @@ export class Root extends PureComponent { })); }; - processFolder = async (folderUid: string, operCode: OperCode) => { + processFolder = async (folderUid: string, operCode: OperCode, falcon: FalconStatus) => { const isDds = folderUid === DDS_FOLDER_UID; const defaultFolderName = isDds ? DDS_FOLDER_NAME : PROM_FOLDER_NAME; const dashboards = isDds ? DDS_DASHBOARDS : PROM_DASHBOARDS; @@ -128,7 +141,7 @@ export class Root extends PureComponent { await deleteFolder(folderUid); } if (operCode === OperCode.Reset || operCode === OperCode.Install) { - await installDashboards(folderUid, defaultFolderName, dashboards); + await installDashboards(folderUid, defaultFolderName, dashboards, falcon); } this.setFolderState(isDds, { code: operCode, @@ -153,7 +166,7 @@ export class Root extends PureComponent { }; render() { - const { dds, prom } = this.state; + const { dds, prom, falcon } = this.state; const isBusy = dds.operation.status === OperStatus.InProgress || prom.operation.status === OperStatus.InProgress; return ( @@ -196,6 +209,40 @@ export class Root extends PureComponent { [UID='{DDS_FOLDER_UID}']
+
+ Link it with OMEGAMON Falcon UI (Experimental): + + { + falcon.enabled = e.currentTarget.checked; + this.updateFolderState(); + }} + /> +
+ + { + falcon.asDashboard = e.target.value; + }} + /> + +
+ + { + falcon.sysDashboard = e.target.value; + }} + /> + +
- Link it with OMEGAMON Falcon UI (Experimental): + Link it with OMEGAMON dashboards(Experimental): { From 8c34cad868e6ed60c455d9d2ab46688373a81be3 Mon Sep 17 00:00:00 2001 From: dprizentsov Date: Thu, 9 Oct 2025 13:01:42 +0200 Subject: [PATCH 22/36] text label fixes Signed-off-by: dprizentsov --- grafana/rmf-app/src/components/Root/Root.tsx | 6 +++++- grafana/rmf-app/src/dashboards/dds/CACHDET.json | 1 + grafana/rmf-app/src/dashboards/dds/CACHSUM.json | 1 + grafana/rmf-app/src/dashboards/dds/CFACT.json | 1 + grafana/rmf-app/src/dashboards/dds/CFOVER.json | 1 + grafana/rmf-app/src/dashboards/dds/CFSYS.json | 1 + grafana/rmf-app/src/dashboards/dds/CHANNEL.json | 1 + grafana/rmf-app/src/dashboards/dds/CPC.json | 1 + grafana/rmf-app/src/dashboards/dds/CRYOVW.json | 1 + .../dashboards/dds/Common Storage Activity (Timeline).json | 1 + .../rmf-app/src/dashboards/dds/Common Storage Activity.json | 1 + .../dds/Coupling Facility Overview (Timeline).json | 1 + .../src/dashboards/dds/Coupling Facility Overview.json | 1 + grafana/rmf-app/src/dashboards/dds/DELAY.json | 1 + grafana/rmf-app/src/dashboards/dds/DEV.json | 1 + grafana/rmf-app/src/dashboards/dds/DEVR.json | 1 + grafana/rmf-app/src/dashboards/dds/DSND.json | 1 + grafana/rmf-app/src/dashboards/dds/EADM.json | 1 + grafana/rmf-app/src/dashboards/dds/ENCLAVE.json | 1 + grafana/rmf-app/src/dashboards/dds/ENQ.json | 1 + .../src/dashboards/dds/Execution Velocity (Timeline).json | 1 + grafana/rmf-app/src/dashboards/dds/Execution Velocity.json | 1 + .../src/dashboards/dds/General Activity (Timeline).json | 1 + grafana/rmf-app/src/dashboards/dds/General Activity.json | 1 + grafana/rmf-app/src/dashboards/dds/HSM.json | 1 + grafana/rmf-app/src/dashboards/dds/IOQ.json | 1 + grafana/rmf-app/src/dashboards/dds/JES.json | 1 + grafana/rmf-app/src/dashboards/dds/LOCKSP.json | 1 + grafana/rmf-app/src/dashboards/dds/LOCKSU.json | 1 + grafana/rmf-app/src/dashboards/dds/OPD.json | 1 + .../dashboards/dds/Overall Image Activity (Timeline).json | 1 + .../rmf-app/src/dashboards/dds/Overall Image Activity.json | 1 + grafana/rmf-app/src/dashboards/dds/PCIE.json | 1 + grafana/rmf-app/src/dashboards/dds/PROC.json | 1 + grafana/rmf-app/src/dashboards/dds/PROCU.json | 1 + .../src/dashboards/dds/Performance Index (Timeline).json | 1 + grafana/rmf-app/src/dashboards/dds/Performance Index.json | 1 + .../src/dashboards/dds/Response Time (Timeline).json | 1 + grafana/rmf-app/src/dashboards/dds/Response Time.json | 1 + grafana/rmf-app/src/dashboards/dds/SPACED.json | 1 + grafana/rmf-app/src/dashboards/dds/SPACEG.json | 1 + grafana/rmf-app/src/dashboards/dds/STOR.json | 1 + grafana/rmf-app/src/dashboards/dds/STORC.json | 1 + grafana/rmf-app/src/dashboards/dds/STORCR.json | 1 + grafana/rmf-app/src/dashboards/dds/STORF.json | 1 + grafana/rmf-app/src/dashboards/dds/STORM.json | 1 + grafana/rmf-app/src/dashboards/dds/STORR.json | 1 + grafana/rmf-app/src/dashboards/dds/STORS.json | 1 + grafana/rmf-app/src/dashboards/dds/SYSINFO.json | 1 + grafana/rmf-app/src/dashboards/dds/SYSRG.json | 1 + grafana/rmf-app/src/dashboards/dds/SYSSUM.json | 1 + grafana/rmf-app/src/dashboards/dds/USAGE.json | 1 + .../src/dashboards/dds/Using & Delays (Timeline).json | 1 + grafana/rmf-app/src/dashboards/dds/Using & Delays.json | 1 + .../rmf-app/src/dashboards/dds/XCF Activity (Timeline).json | 1 + grafana/rmf-app/src/dashboards/dds/XCF Activity.json | 1 + grafana/rmf-app/src/dashboards/dds/XCFGROUP.json | 1 + grafana/rmf-app/src/dashboards/dds/XCFOVW.json | 1 + grafana/rmf-app/src/dashboards/dds/XCFPATH.json | 1 + grafana/rmf-app/src/dashboards/dds/XCFSYS.json | 1 + grafana/rmf-app/src/dashboards/dds/ZFSFS.json | 1 + grafana/rmf-app/src/dashboards/dds/ZFSKN.json | 1 + grafana/rmf-app/src/dashboards/dds/ZFSOVW.json | 1 + .../config-editor/config-editor.component.tsx | 2 -- 64 files changed, 67 insertions(+), 3 deletions(-) diff --git a/grafana/rmf-app/src/components/Root/Root.tsx b/grafana/rmf-app/src/components/Root/Root.tsx index 08d9745a..4af3c16f 100644 --- a/grafana/rmf-app/src/components/Root/Root.tsx +++ b/grafana/rmf-app/src/components/Root/Root.tsx @@ -211,7 +211,7 @@ export class Root extends PureComponent {
- Link it with OMEGAMON dashboards(Experimental): + Link it with OMEGAMON dashboards (experimental): { @@ -240,6 +240,10 @@ export class Root extends PureComponent { />
+ + Note: You must associate RMF data source with OMEGAMON data source (see RMF data source edit page) +
- Link it with OMEGAMON dashboards (experimental): + Link with IBM Z OMEGAMON Web UI dashboards: { diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/config-editor/config-editor.component.tsx b/grafana/rmf-app/src/datasources/rmf-datasource/config-editor/config-editor.component.tsx index 4c8809e6..33850eb5 100644 --- a/grafana/rmf-app/src/datasources/rmf-datasource/config-editor/config-editor.component.tsx +++ b/grafana/rmf-app/src/datasources/rmf-datasource/config-editor/config-editor.component.tsx @@ -14,9 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React, { PureComponent, ReactNode } from 'react'; -import { DataSourcePluginOptionsEditorProps } from '@grafana/data'; -import { FieldValidationMessage, InlineField, InlineSwitch, LegacyForms, SecretInput, Combobox, ComboboxOption } from '@grafana/ui'; +import React, { PureComponent } from 'react'; +import { DataSourcePluginOptionsEditorProps, SelectableValue } from '@grafana/data'; +import { FieldValidationMessage, InlineField, InlineSwitch, LegacyForms, SecretInput, Select, ComboboxOption } from '@grafana/ui'; import { RMFDataSourceSettings, RMFDataSourceJsonData, RMFDataSourceSecureJsonData } from '../common/types'; import { OMEGAMON_DS_TYPE_NAME } from '../common/configSettings'; import { getBackendSrv } from '@grafana/runtime'; @@ -41,7 +41,7 @@ interface State { httpTimeoutError?: string; basicAuthUserError?: string; cacheSizeError?: string; - omegOptionsArray?: Array; + omegOptionsArray?: SelectableValue[]; } // TODO: somehow prometheus can validate fields from "run and test" in v11 export default class ConfigEditor extends PureComponent { @@ -158,6 +158,32 @@ export default class ConfigEditor extends PureComponent { return optionsArray; }; + async componentDidMount() { + await this.updateDatasourceList(OMEGAMON_DS_TYPE_NAME); + } + + updateDatasourceList = async (type: string) => { + var items: Set = new Set(); + var optionsArray: Array> = new Array; + items.add(""); + optionsArray.push({label: "", value: "" } as SelectableValue); + if (this.props.options.jsonData?.omegamonDs && !items.has(this.props.options.jsonData?.omegamonDs)) { + items.add(this.props.options.jsonData?.omegamonDs); + optionsArray.push({label: this.props.options.jsonData?.omegamonDs, value: this.props.options.jsonData?.omegamonDs } as SelectableValue); + } + var datasources: any = await getBackendSrv().get("/api/datasources"); + datasources.forEach((ds: any) => { + if (ds.type === type && !items.has(ds.name)) { + items.add(ds.name); + optionsArray.push({label: ds.name, value: ds.name } as SelectableValue); + } + }); + this.setState((prevState) => ({ + ...prevState, + omegOptionsArray: optionsArray + })); + } + render() { const { options } = this.props; const { urlError, httpTimeoutError, basicAuthUserError, cacheSizeError } = this.state; @@ -312,16 +338,15 @@ export default class ConfigEditor extends PureComponent { - OMEGAMON (Experimental) + OMEGAMON (optional) - { this.updateSettings({ jsonData: { omegamonDs: String(event.value) } }); }} From 6ef3ae21e644d0fb9b8ae92ff1f94027d8201387 Mon Sep 17 00:00:00 2001 From: Dmitry Nikolaev Date: Wed, 8 Oct 2025 12:46:31 +0200 Subject: [PATCH 25/36] Address validator findings Signed-off-by: Dmitry Nikolaev --- .gitignore | 1 - LICENSE | 3 +- grafana/rmf-app/INSTALL.md | 2 +- grafana/rmf-app/LICENSE | 3 +- grafana/rmf-app/docker-compose.yaml | 6 +- grafana/rmf-app/makefile | 16 +- grafana/rmf-app/package.json | 4 +- .../rmf-app/provisioning/plugins/apps.yaml | 2 +- grafana/rmf-app/src/constants.ts | 2 +- .../autocomplete-textfield.css | 0 .../autocomplete-textfield.helper.ts | 0 .../autocomplete-textfield.tsx | 0 .../common/common.helper.ts | 0 .../common/configSettings.ts | 0 .../common/types.ts | 0 .../config-editor/config-editor.component.css | 0 .../config-editor/config-editor.component.tsx | 0 .../datasource.ts | 0 .../img/logo.svg | 0 .../img/searchicon.png | Bin .../rmf-datasource => datasource}/module.ts | 0 .../parser/core/customErrorListener.ts | 0 .../parser/core/filter.test.ts | 0 .../parser/core/index.ts | 0 .../parser/core/name.test.ts | 0 .../parser/core/parser.test.ts | 0 .../parser/core/parser.ts | 0 .../parser/core/report.test.ts | 0 .../parser/core/type.ts | 0 .../parser/core/ulq.test.ts | 0 .../parser/core/workscope.test.ts | 0 .../parser/index.ts | 0 .../datasource/parser/lib/RMFQueryLexer.ts | 404 ++++ .../datasource/parser/lib/RMFQueryListener.ts | 256 +++ .../datasource/parser/lib/RMFQueryParser.ts | 1903 +++++++++++++++++ .../rmf-datasource => datasource}/plugin.json | 2 +- .../queryeditor.parser.component.css | 0 .../queryeditor.parser.component.tsx | 0 grafana/rmf-app/src/img/sample-dashboard.png | Bin 0 -> 285790 bytes .../banner-component/banner.component.css | 0 .../banner-component/banner.component.tsx | 0 .../captions-component/captions.component.css | 0 .../captions-component/captions.component.tsx | 0 .../src/{panels/report => panel}/img/logo.svg | 0 .../report => panel}/main.component.tsx | 0 .../{panels/report => panel}/module.test.ts | 0 .../src/{panels/report => panel}/module.ts | 0 .../src/{panels/report => panel}/plugin.json | 8 +- .../table-component/table.component.css | 0 .../table-component/table.component.tsx | 0 .../table-component/table.helper.ts | 0 .../src/{panels/report => panel}/types.ts | 0 grafana/rmf-app/src/plugin.json | 14 +- grafana/rmf-app/tsconfig.json | 2 +- 54 files changed, 2597 insertions(+), 31 deletions(-) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/autocomplete-text/autocomplete-textfield.css (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/autocomplete-text/autocomplete-textfield.helper.ts (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/autocomplete-text/autocomplete-textfield.tsx (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/common/common.helper.ts (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/common/configSettings.ts (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/common/types.ts (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/config-editor/config-editor.component.css (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/config-editor/config-editor.component.tsx (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/datasource.ts (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/img/logo.svg (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/img/searchicon.png (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/module.ts (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/parser/core/customErrorListener.ts (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/parser/core/filter.test.ts (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/parser/core/index.ts (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/parser/core/name.test.ts (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/parser/core/parser.test.ts (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/parser/core/parser.ts (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/parser/core/report.test.ts (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/parser/core/type.ts (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/parser/core/ulq.test.ts (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/parser/core/workscope.test.ts (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/parser/index.ts (100%) create mode 100644 grafana/rmf-app/src/datasource/parser/lib/RMFQueryLexer.ts create mode 100644 grafana/rmf-app/src/datasource/parser/lib/RMFQueryListener.ts create mode 100644 grafana/rmf-app/src/datasource/parser/lib/RMFQueryParser.ts rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/plugin.json (96%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/query-editor/queryeditor.parser.component.css (100%) rename grafana/rmf-app/src/{datasources/rmf-datasource => datasource}/query-editor/queryeditor.parser.component.tsx (100%) create mode 100644 grafana/rmf-app/src/img/sample-dashboard.png rename grafana/rmf-app/src/{panels/report => panel}/banner-component/banner.component.css (100%) rename grafana/rmf-app/src/{panels/report => panel}/banner-component/banner.component.tsx (100%) rename grafana/rmf-app/src/{panels/report => panel}/captions-component/captions.component.css (100%) rename grafana/rmf-app/src/{panels/report => panel}/captions-component/captions.component.tsx (100%) rename grafana/rmf-app/src/{panels/report => panel}/img/logo.svg (100%) rename grafana/rmf-app/src/{panels/report => panel}/main.component.tsx (100%) rename grafana/rmf-app/src/{panels/report => panel}/module.test.ts (100%) rename grafana/rmf-app/src/{panels/report => panel}/module.ts (100%) rename grafana/rmf-app/src/{panels/report => panel}/plugin.json (69%) rename grafana/rmf-app/src/{panels/report => panel}/table-component/table.component.css (100%) rename grafana/rmf-app/src/{panels/report => panel}/table-component/table.component.tsx (100%) rename grafana/rmf-app/src/{panels/report => panel}/table-component/table.helper.ts (100%) rename grafana/rmf-app/src/{panels/report => panel}/types.ts (100%) diff --git a/.gitignore b/.gitignore index a9a97227..86fc5fa9 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,3 @@ .antlr *.interp *.tokens -grafana/rmf-app/**/rmf-datasource/parser/lib/RMFQuery*.ts diff --git a/LICENSE b/LICENSE index 261eeb9e..8fc0f403 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,8 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2023,2025 IBM Corporation + Copyright 2023-2025 Rocket Software, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/grafana/rmf-app/INSTALL.md b/grafana/rmf-app/INSTALL.md index 64b9a36a..3eb2a320 100644 --- a/grafana/rmf-app/INSTALL.md +++ b/grafana/rmf-app/INSTALL.md @@ -9,5 +9,5 @@ `ibm-rmf-report-panel`) must be run as unsigned plugins. For this specify the below in `Grafana.ini` file’s `[plugins]` section: ```ini - allow_loading_unsigned_plugins = ibm-rmf,ibm-rmf-datasource,ibm-rmf-report-panel + allow_loading_unsigned_plugins = ibm-rmf-app,ibm-rmf-datasource,ibm-rmf-report-panel ``` diff --git a/grafana/rmf-app/LICENSE b/grafana/rmf-app/LICENSE index 8dada3ed..a121b276 100644 --- a/grafana/rmf-app/LICENSE +++ b/grafana/rmf-app/LICENSE @@ -186,7 +186,8 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright {yyyy} {name of copyright owner} + Copyright 2023,2025 IBM Corporation + Copyright 2023-2025 Rocket Software, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/grafana/rmf-app/docker-compose.yaml b/grafana/rmf-app/docker-compose.yaml index 8682a825..96b33897 100644 --- a/grafana/rmf-app/docker-compose.yaml +++ b/grafana/rmf-app/docker-compose.yaml @@ -14,13 +14,13 @@ services: cap_add: - SYS_PTRACE volumes: - - ./dist:/var/lib/grafana/plugins/ibm-rmf + - ./dist:/var/lib/grafana/plugins/ibm-rmf-app - ./provisioning:/etc/grafana/provisioning - - .:/root/ibm-rmf + - .:/root/ibm-rmf-app environment: NODE_ENV: development GF_LOG_FILTERS: plugin.ibm-rmf-datasource:debug GF_LOG_LEVEL: info GF_DATAPROXY_LOGGING: 1 - GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS: ibm-rmf,ibm-rmf-datasource,ibm-rmf-report + GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS: ibm-rmf-app,ibm-rmf-datasource,ibm-rmf-report diff --git a/grafana/rmf-app/makefile b/grafana/rmf-app/makefile index 2cc2fcb2..c24efb59 100644 --- a/grafana/rmf-app/makefile +++ b/grafana/rmf-app/makefile @@ -3,9 +3,9 @@ default: help GRAFANA_PLUGIN_ID := $(shell jq -r '.id' src/plugin.json) GRAFANA_PLUGIN_VERSION := $(shell jq -r '.version' package.json) -GRAFANA_PLUGIN_ARTIFACT := $(GRAFANA_PLUGIN_ID)-grafana-$(GRAFANA_PLUGIN_VERSION).zip +GRAFANA_PLUGIN_ARTIFACT := ibm-rmf-grafana-$(GRAFANA_PLUGIN_VERSION).zip GRAFANA_PLUGIN_ARTIFACT_CHECKSUM := $(GRAFANA_PLUGIN_ARTIFACT).md5 -RMF_QUERY_PARSER_PATH := ./src/datasources/rmf-datasource/parser/lib +RMF_QUERY_PARSER_PATH := ./src/datasource/parser/lib RMF_QUERY_PARSER_FILES := \ $(RMF_QUERY_PARSER_PATH)/RMFQueryLexer.ts \ $(RMF_QUERY_PARSER_PATH)/RMFQueryListener.ts \ @@ -34,7 +34,7 @@ watch-frontend: deps-frontend ## Auto rebuilt frontend on file changes yarn run watch dev-backend: deps-backend ## Build backend data sources (development) - go build -race -o ./dist/datasources/redisrmf-datasource/gpx_ibm-rmf-datasource_$$(go env GOOS)_$$(go env GOARCH) -tags netgo -ldflags -w ./pkg + go build -race -o ./dist/datasource/gpx_ibm-rmf-datasource_$$(go env GOOS)_$$(go env GOARCH) -tags netgo -ldflags -w ./pkg restart-backend: ## Rebuild and restart backend data source (as root) sudo -u "$$(stat -c '%U' .)" make dev-backend @@ -65,14 +65,14 @@ build-frontend: deps-frontend $(RMF_QUERY_PARSER_FILES) ## Build frontend data s GO_LD_FLAGS := -w -s -extldflags "-static" build-backend: deps-backend ## Build backend data source for arch in amd64 arm64 s390x ppc64le; do \ - CGO_ENABLED=0 GOOS=linux GOARCH=$${arch} go build -o ./dist/datasources/rmf-datasource/gpx_ibm-rmf-datasource_linux_$${arch} -ldflags '$(GO_LD_FLAGS)' ./pkg; \ + CGO_ENABLED=0 GOOS=linux GOARCH=$${arch} go build -o ./dist/datasource/gpx_ibm-rmf-datasource_linux_$${arch} -ldflags '$(GO_LD_FLAGS)' ./pkg; \ done - CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o ./dist/datasources/rmf-datasource/gpx_ibm-rmf-datasource_darwin_amd64 -ldflags '$(GO_LD_FLAGS)' ./pkg - CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -o ./dist/datasources/rmf-datasource/gpx_ibm-rmf-datasource_darwin_arm64 -ldflags '$(GO_LD_FLAGS)' ./pkg - CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o ./dist/datasources/rmf-datasource/gpx_ibm-rmf-datasource_windows_amd64.exe -ldflags '$(GO_LD_FLAGS)' ./pkg + CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o ./dist/datasource/gpx_ibm-rmf-datasource_darwin_amd64 -ldflags '$(GO_LD_FLAGS)' ./pkg + CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -o ./dist/datasource/gpx_ibm-rmf-datasource_darwin_arm64 -ldflags '$(GO_LD_FLAGS)' ./pkg + CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o ./dist/datasource/gpx_ibm-rmf-datasource_windows_amd64.exe -ldflags '$(GO_LD_FLAGS)' ./pkg build-backend-amd64-linux: deps-backend ## Build backend data source - CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./dist/datasources/rmf-datasource/gpx_ibm-rmf-datasource_linux_amd64 -ldflags '$(GO_LD_FLAGS)' ./pkg; \ + CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./dist/datasource/gpx_ibm-rmf-datasource_linux_amd64 -ldflags '$(GO_LD_FLAGS)' ./pkg; \ test: deps-backend ## Run unittests go test -v ./... diff --git a/grafana/rmf-app/package.json b/grafana/rmf-app/package.json index 125bfc7b..bbca0b0e 100644 --- a/grafana/rmf-app/package.json +++ b/grafana/rmf-app/package.json @@ -16,8 +16,8 @@ "sign": "npx --yes @grafana/sign-plugin@latest", "format": "prettier-eslint --write '**/*.ts*'", "antlr": "antlr4-tool --help", - "generate-parser": "antlr4-tool -Dlanguage=JavaScript -o src/datasources/rmf-datasource/parser/lib -Xexact-output-dir ./grammar/RMFQuery.g4", - "generate-parser-java": "java -Xmx500M -cp '/usr/local/lib/antlr-4.10.1-complete.jar:$CLASSPATH' org.antlr.v4.Tool -Dlanguage=JavaScript -o src/datasources/rmf-datasource/parser/lib -Xexact-output-dir", + "generate-parser": "antlr4-tool -Dlanguage=JavaScript -o src/datasource/parser/lib -Xexact-output-dir ./grammar/RMFQuery.g4", + "generate-parser-java": "java -Xmx500M -cp '/usr/local/lib/antlr-4.10.1-complete.jar:$CLASSPATH' org.antlr.v4.Tool -Dlanguage=JavaScript -o src/datasource/parser/lib -Xexact-output-dir", "start": "yarn watch", "start-docker": "docker-compose up", "start-docker:dev": "docker-compose -f docker-compose/dev.yml pull && docker-compose -f docker-compose/dev.yml up", diff --git a/grafana/rmf-app/provisioning/plugins/apps.yaml b/grafana/rmf-app/provisioning/plugins/apps.yaml index 68ae8e9f..b05843e1 100644 --- a/grafana/rmf-app/provisioning/plugins/apps.yaml +++ b/grafana/rmf-app/provisioning/plugins/apps.yaml @@ -1,6 +1,6 @@ apiVersion: 1 apps: - - type: 'ibm-rmf' + - type: 'ibm-rmf-app' org_id: 1 disabled: false diff --git a/grafana/rmf-app/src/constants.ts b/grafana/rmf-app/src/constants.ts index 17a0c99b..bfce8a37 100644 --- a/grafana/rmf-app/src/constants.ts +++ b/grafana/rmf-app/src/constants.ts @@ -16,7 +16,7 @@ */ import appPluginJson from './plugin.json'; -import dataSourcePluginJson from './datasources/rmf-datasource/plugin.json'; +import dataSourcePluginJson from './datasource/plugin.json'; export const APP_NAME = appPluginJson.name; export const APP_DESC = appPluginJson.info.description; diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/autocomplete-text/autocomplete-textfield.css b/grafana/rmf-app/src/datasource/autocomplete-text/autocomplete-textfield.css similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/autocomplete-text/autocomplete-textfield.css rename to grafana/rmf-app/src/datasource/autocomplete-text/autocomplete-textfield.css diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/autocomplete-text/autocomplete-textfield.helper.ts b/grafana/rmf-app/src/datasource/autocomplete-text/autocomplete-textfield.helper.ts similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/autocomplete-text/autocomplete-textfield.helper.ts rename to grafana/rmf-app/src/datasource/autocomplete-text/autocomplete-textfield.helper.ts diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/autocomplete-text/autocomplete-textfield.tsx b/grafana/rmf-app/src/datasource/autocomplete-text/autocomplete-textfield.tsx similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/autocomplete-text/autocomplete-textfield.tsx rename to grafana/rmf-app/src/datasource/autocomplete-text/autocomplete-textfield.tsx diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/common/common.helper.ts b/grafana/rmf-app/src/datasource/common/common.helper.ts similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/common/common.helper.ts rename to grafana/rmf-app/src/datasource/common/common.helper.ts diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/common/configSettings.ts b/grafana/rmf-app/src/datasource/common/configSettings.ts similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/common/configSettings.ts rename to grafana/rmf-app/src/datasource/common/configSettings.ts diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/common/types.ts b/grafana/rmf-app/src/datasource/common/types.ts similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/common/types.ts rename to grafana/rmf-app/src/datasource/common/types.ts diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/config-editor/config-editor.component.css b/grafana/rmf-app/src/datasource/config-editor/config-editor.component.css similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/config-editor/config-editor.component.css rename to grafana/rmf-app/src/datasource/config-editor/config-editor.component.css diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/config-editor/config-editor.component.tsx b/grafana/rmf-app/src/datasource/config-editor/config-editor.component.tsx similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/config-editor/config-editor.component.tsx rename to grafana/rmf-app/src/datasource/config-editor/config-editor.component.tsx diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/datasource.ts b/grafana/rmf-app/src/datasource/datasource.ts similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/datasource.ts rename to grafana/rmf-app/src/datasource/datasource.ts diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/img/logo.svg b/grafana/rmf-app/src/datasource/img/logo.svg similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/img/logo.svg rename to grafana/rmf-app/src/datasource/img/logo.svg diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/img/searchicon.png b/grafana/rmf-app/src/datasource/img/searchicon.png similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/img/searchicon.png rename to grafana/rmf-app/src/datasource/img/searchicon.png diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/module.ts b/grafana/rmf-app/src/datasource/module.ts similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/module.ts rename to grafana/rmf-app/src/datasource/module.ts diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/parser/core/customErrorListener.ts b/grafana/rmf-app/src/datasource/parser/core/customErrorListener.ts similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/parser/core/customErrorListener.ts rename to grafana/rmf-app/src/datasource/parser/core/customErrorListener.ts diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/parser/core/filter.test.ts b/grafana/rmf-app/src/datasource/parser/core/filter.test.ts similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/parser/core/filter.test.ts rename to grafana/rmf-app/src/datasource/parser/core/filter.test.ts diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/parser/core/index.ts b/grafana/rmf-app/src/datasource/parser/core/index.ts similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/parser/core/index.ts rename to grafana/rmf-app/src/datasource/parser/core/index.ts diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/parser/core/name.test.ts b/grafana/rmf-app/src/datasource/parser/core/name.test.ts similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/parser/core/name.test.ts rename to grafana/rmf-app/src/datasource/parser/core/name.test.ts diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/parser/core/parser.test.ts b/grafana/rmf-app/src/datasource/parser/core/parser.test.ts similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/parser/core/parser.test.ts rename to grafana/rmf-app/src/datasource/parser/core/parser.test.ts diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/parser/core/parser.ts b/grafana/rmf-app/src/datasource/parser/core/parser.ts similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/parser/core/parser.ts rename to grafana/rmf-app/src/datasource/parser/core/parser.ts diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/parser/core/report.test.ts b/grafana/rmf-app/src/datasource/parser/core/report.test.ts similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/parser/core/report.test.ts rename to grafana/rmf-app/src/datasource/parser/core/report.test.ts diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/parser/core/type.ts b/grafana/rmf-app/src/datasource/parser/core/type.ts similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/parser/core/type.ts rename to grafana/rmf-app/src/datasource/parser/core/type.ts diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/parser/core/ulq.test.ts b/grafana/rmf-app/src/datasource/parser/core/ulq.test.ts similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/parser/core/ulq.test.ts rename to grafana/rmf-app/src/datasource/parser/core/ulq.test.ts diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/parser/core/workscope.test.ts b/grafana/rmf-app/src/datasource/parser/core/workscope.test.ts similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/parser/core/workscope.test.ts rename to grafana/rmf-app/src/datasource/parser/core/workscope.test.ts diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/parser/index.ts b/grafana/rmf-app/src/datasource/parser/index.ts similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/parser/index.ts rename to grafana/rmf-app/src/datasource/parser/index.ts diff --git a/grafana/rmf-app/src/datasource/parser/lib/RMFQueryLexer.ts b/grafana/rmf-app/src/datasource/parser/lib/RMFQueryLexer.ts new file mode 100644 index 00000000..a5bace75 --- /dev/null +++ b/grafana/rmf-app/src/datasource/parser/lib/RMFQueryLexer.ts @@ -0,0 +1,404 @@ +// Generated from ./grammar/RMFQuery.g4 by ANTLR 4.13.2 +// noinspection ES6UnusedImports,JSUnusedGlobalSymbols,JSUnusedLocalSymbols +import { + ATN, + ATNDeserializer, + CharStream, + DecisionState, DFA, + Lexer, + LexerATNSimulator, + RuleContext, + PredictionContextCache, + Token +} from "antlr4"; +export default class RMFQueryLexer extends Lexer { + public static readonly REPORT = 1; + public static readonly WORKSCOPE = 2; + public static readonly RANGE = 3; + public static readonly ULQ = 4; + public static readonly NAME = 5; + public static readonly FILTER = 6; + public static readonly PAT = 7; + public static readonly LB = 8; + public static readonly UB = 9; + public static readonly HI = 10; + public static readonly LO = 11; + public static readonly ORD = 12; + public static readonly ORD_OPTION = 13; + public static readonly RES_TYPE = 14; + public static readonly WORKSCOPE_TYPE = 15; + public static readonly INTEGER = 16; + public static readonly DECIMAL = 17; + public static readonly IDENTIFIER = 18; + public static readonly STRING_UNQUOTED = 19; + public static readonly STRING_QUOTED = 20; + public static readonly DOT = 21; + public static readonly SEMI = 22; + public static readonly COMMA = 23; + public static readonly LBRACE = 24; + public static readonly RBRACE = 25; + public static readonly EQUAL = 26; + public static readonly WS = 27; + public static readonly EOF = Token.EOF; + + public static readonly channelNames: string[] = [ "DEFAULT_TOKEN_CHANNEL", "HIDDEN" ]; + public static readonly literalNames: (string | null)[] = [ null, null, + null, null, + null, null, + null, null, + null, null, + null, null, + null, null, + null, null, + null, null, + null, null, + null, "'.'", + "';'", "','", + "'{'", "'}'", + "'='" ]; + public static readonly symbolicNames: (string | null)[] = [ null, "REPORT", + "WORKSCOPE", + "RANGE", "ULQ", + "NAME", "FILTER", + "PAT", "LB", + "UB", "HI", + "LO", "ORD", + "ORD_OPTION", + "RES_TYPE", + "WORKSCOPE_TYPE", + "INTEGER", + "DECIMAL", + "IDENTIFIER", + "STRING_UNQUOTED", + "STRING_QUOTED", + "DOT", "SEMI", + "COMMA", "LBRACE", + "RBRACE", "EQUAL", + "WS" ]; + public static readonly modeNames: string[] = [ "DEFAULT_MODE", ]; + + public static readonly ruleNames: string[] = [ + "REPORT", "WORKSCOPE", "RANGE", "ULQ", "NAME", "FILTER", "PAT", "LB", + "UB", "HI", "LO", "ORD", "ORD_OPTION", "RES_TYPE", "WORKSCOPE_TYPE", "INTEGER", + "DECIMAL", "IDENTIFIER", "STRING_UNQUOTED", "STRING_QUOTED", "DOT", "SEMI", + "COMMA", "LBRACE", "RBRACE", "EQUAL", "WS", "SINGLE_QUOTE", "DOUBLE_QOUTE", + "STRING_ITEM_NO_QUOTE", "STRING_ITEM_SINGLE_QUOTE", "STRING_ITEM_DOUBLE_QUOTE", + "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", + "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", + ]; + + + constructor(input: CharStream) { + super(input); + this._interp = new LexerATNSimulator(this, RMFQueryLexer._ATN, RMFQueryLexer.DecisionsToDFA, new PredictionContextCache()); + } + + public get grammarFileName(): string { return "RMFQuery.g4"; } + + public get literalNames(): (string | null)[] { return RMFQueryLexer.literalNames; } + public get symbolicNames(): (string | null)[] { return RMFQueryLexer.symbolicNames; } + public get ruleNames(): string[] { return RMFQueryLexer.ruleNames; } + + public get serializedATN(): number[] { return RMFQueryLexer._serializedATN; } + + public get channelNames(): string[] { return RMFQueryLexer.channelNames; } + + public get modeNames(): string[] { return RMFQueryLexer.modeNames; } + + public static readonly _serializedATN: number[] = [4,0,27,850,6,-1,2,0, + 7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,6,2,7,7,7,2,8,7,8,2,9, + 7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2,14,7,14,2,15,7,15,2,16,7, + 16,2,17,7,17,2,18,7,18,2,19,7,19,2,20,7,20,2,21,7,21,2,22,7,22,2,23,7,23, + 2,24,7,24,2,25,7,25,2,26,7,26,2,27,7,27,2,28,7,28,2,29,7,29,2,30,7,30,2, + 31,7,31,2,32,7,32,2,33,7,33,2,34,7,34,2,35,7,35,2,36,7,36,2,37,7,37,2,38, + 7,38,2,39,7,39,2,40,7,40,2,41,7,41,2,42,7,42,2,43,7,43,2,44,7,44,2,45,7, + 45,2,46,7,46,2,47,7,47,2,48,7,48,2,49,7,49,2,50,7,50,2,51,7,51,2,52,7,52, + 2,53,7,53,2,54,7,54,2,55,7,55,2,56,7,56,2,57,7,57,1,0,1,0,1,0,1,0,1,0,1, + 0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,2,1,2,1,2,1,2,1,2,1, + 3,1,3,1,3,1,3,1,4,1,4,1,4,1,4,1,4,1,5,1,5,1,5,1,5,1,5,1,5,1,5,1,6,1,6,1, + 6,1,6,1,7,1,7,1,7,1,8,1,8,1,8,1,9,1,9,1,9,1,10,1,10,1,10,1,11,1,11,1,11, + 1,11,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1, + 12,1,12,3,12,192,8,12,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13, + 1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1, + 13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13, + 1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1, + 13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13, + 1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1, + 13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13, + 1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1, + 13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13, + 1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1, + 13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13, + 1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1, + 13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13, + 1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1, + 13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13, + 1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1, + 13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13, + 1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1, + 13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13, + 1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1, + 13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13, + 1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1, + 13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13, + 1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1, + 13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13, + 1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1, + 13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13, + 1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1, + 13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13, + 1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1, + 13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13, + 1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1, + 13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13, + 1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1, + 13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13, + 1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1, + 13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,3,13,723,8,13, + 1,14,1,14,1,14,1,14,1,14,1,14,3,14,731,8,14,1,15,4,15,734,8,15,11,15,12, + 15,735,1,16,1,16,1,16,1,16,1,17,4,17,743,8,17,11,17,12,17,744,1,18,4,18, + 748,8,18,11,18,12,18,749,1,19,1,19,5,19,754,8,19,10,19,12,19,757,9,19,1, + 19,1,19,1,19,1,19,5,19,763,8,19,10,19,12,19,766,9,19,1,19,1,19,3,19,770, + 8,19,1,20,1,20,1,21,1,21,1,22,1,22,1,23,1,23,1,24,1,24,1,25,1,25,1,26,4, + 26,785,8,26,11,26,12,26,786,1,27,1,27,1,28,1,28,1,29,1,29,1,30,1,30,1,31, + 1,31,1,32,1,32,1,33,1,33,1,34,1,34,1,35,1,35,1,36,1,36,1,37,1,37,1,38,1, + 38,1,39,1,39,1,40,1,40,1,41,1,41,1,42,1,42,1,43,1,43,1,44,1,44,1,45,1,45, + 1,46,1,46,1,47,1,47,1,48,1,48,1,49,1,49,1,50,1,50,1,51,1,51,1,52,1,52,1, + 53,1,53,1,54,1,54,1,55,1,55,1,56,1,56,1,57,1,57,0,0,58,1,1,3,2,5,3,7,4, + 9,5,11,6,13,7,15,8,17,9,19,10,21,11,23,12,25,13,27,14,29,15,31,16,33,17, + 35,18,37,19,39,20,41,21,43,22,45,23,47,24,49,25,51,26,53,27,55,0,57,0,59, + 0,61,0,63,0,65,0,67,0,69,0,71,0,73,0,75,0,77,0,79,0,81,0,83,0,85,0,87,0, + 89,0,91,0,93,0,95,0,97,0,99,0,101,0,103,0,105,0,107,0,109,0,111,0,113,0, + 115,0,1,0,32,1,0,48,57,2,0,65,90,97,122,3,0,9,10,13,13,32,32,7,0,32,32, + 44,44,46,46,59,59,61,61,123,123,125,125,1,0,39,39,1,0,34,34,2,0,65,65,97, + 97,2,0,66,66,98,98,2,0,67,67,99,99,2,0,68,68,100,100,2,0,69,69,101,101, + 2,0,70,70,102,102,2,0,71,71,103,103,2,0,72,72,104,104,2,0,73,73,105,105, + 2,0,74,74,106,106,2,0,75,75,107,107,2,0,76,76,108,108,2,0,77,77,109,109, + 2,0,78,78,110,110,2,0,79,79,111,111,2,0,80,80,112,112,2,0,81,81,113,113, + 2,0,82,82,114,114,2,0,83,83,115,115,2,0,84,84,116,116,2,0,85,85,117,117, + 2,0,86,86,118,118,2,0,87,87,119,119,2,0,88,88,120,120,2,0,89,89,121,121, + 2,0,90,90,122,122,881,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0, + 9,1,0,0,0,0,11,1,0,0,0,0,13,1,0,0,0,0,15,1,0,0,0,0,17,1,0,0,0,0,19,1,0, + 0,0,0,21,1,0,0,0,0,23,1,0,0,0,0,25,1,0,0,0,0,27,1,0,0,0,0,29,1,0,0,0,0, + 31,1,0,0,0,0,33,1,0,0,0,0,35,1,0,0,0,0,37,1,0,0,0,0,39,1,0,0,0,0,41,1,0, + 0,0,0,43,1,0,0,0,0,45,1,0,0,0,0,47,1,0,0,0,0,49,1,0,0,0,0,51,1,0,0,0,0, + 53,1,0,0,0,1,117,1,0,0,0,3,124,1,0,0,0,5,134,1,0,0,0,7,140,1,0,0,0,9,144, + 1,0,0,0,11,149,1,0,0,0,13,156,1,0,0,0,15,160,1,0,0,0,17,163,1,0,0,0,19, + 166,1,0,0,0,21,169,1,0,0,0,23,172,1,0,0,0,25,191,1,0,0,0,27,722,1,0,0,0, + 29,730,1,0,0,0,31,733,1,0,0,0,33,737,1,0,0,0,35,742,1,0,0,0,37,747,1,0, + 0,0,39,769,1,0,0,0,41,771,1,0,0,0,43,773,1,0,0,0,45,775,1,0,0,0,47,777, + 1,0,0,0,49,779,1,0,0,0,51,781,1,0,0,0,53,784,1,0,0,0,55,788,1,0,0,0,57, + 790,1,0,0,0,59,792,1,0,0,0,61,794,1,0,0,0,63,796,1,0,0,0,65,798,1,0,0,0, + 67,800,1,0,0,0,69,802,1,0,0,0,71,804,1,0,0,0,73,806,1,0,0,0,75,808,1,0, + 0,0,77,810,1,0,0,0,79,812,1,0,0,0,81,814,1,0,0,0,83,816,1,0,0,0,85,818, + 1,0,0,0,87,820,1,0,0,0,89,822,1,0,0,0,91,824,1,0,0,0,93,826,1,0,0,0,95, + 828,1,0,0,0,97,830,1,0,0,0,99,832,1,0,0,0,101,834,1,0,0,0,103,836,1,0,0, + 0,105,838,1,0,0,0,107,840,1,0,0,0,109,842,1,0,0,0,111,844,1,0,0,0,113,846, + 1,0,0,0,115,848,1,0,0,0,117,118,3,99,49,0,118,119,3,73,36,0,119,120,3,95, + 47,0,120,121,3,93,46,0,121,122,3,99,49,0,122,123,3,103,51,0,123,2,1,0,0, + 0,124,125,3,109,54,0,125,126,3,93,46,0,126,127,3,99,49,0,127,128,3,85,42, + 0,128,129,3,101,50,0,129,130,3,69,34,0,130,131,3,93,46,0,131,132,3,95,47, + 0,132,133,3,73,36,0,133,4,1,0,0,0,134,135,3,99,49,0,135,136,3,65,32,0,136, + 137,3,91,45,0,137,138,3,77,38,0,138,139,3,73,36,0,139,6,1,0,0,0,140,141, + 3,105,52,0,141,142,3,87,43,0,142,143,3,97,48,0,143,8,1,0,0,0,144,145,3, + 91,45,0,145,146,3,65,32,0,146,147,3,89,44,0,147,148,3,73,36,0,148,10,1, + 0,0,0,149,150,3,75,37,0,150,151,3,81,40,0,151,152,3,87,43,0,152,153,3,103, + 51,0,153,154,3,73,36,0,154,155,3,99,49,0,155,12,1,0,0,0,156,157,3,95,47, + 0,157,158,3,65,32,0,158,159,3,103,51,0,159,14,1,0,0,0,160,161,3,87,43,0, + 161,162,3,67,33,0,162,16,1,0,0,0,163,164,3,105,52,0,164,165,3,67,33,0,165, + 18,1,0,0,0,166,167,3,79,39,0,167,168,3,81,40,0,168,20,1,0,0,0,169,170,3, + 87,43,0,170,171,3,93,46,0,171,22,1,0,0,0,172,173,3,93,46,0,173,174,3,99, + 49,0,174,175,3,71,35,0,175,24,1,0,0,0,176,177,3,91,45,0,177,178,3,65,32, + 0,178,192,1,0,0,0,179,180,3,91,45,0,180,181,3,71,35,0,181,192,1,0,0,0,182, + 183,3,107,53,0,183,184,3,65,32,0,184,192,1,0,0,0,185,186,3,107,53,0,186, + 187,3,71,35,0,187,192,1,0,0,0,188,189,3,91,45,0,189,190,3,91,45,0,190,192, + 1,0,0,0,191,176,1,0,0,0,191,179,1,0,0,0,191,182,1,0,0,0,191,185,1,0,0,0, + 191,188,1,0,0,0,192,26,1,0,0,0,193,194,3,101,50,0,194,195,3,113,56,0,195, + 196,3,101,50,0,196,197,3,95,47,0,197,198,3,87,43,0,198,199,3,73,36,0,199, + 200,3,111,55,0,200,723,1,0,0,0,201,202,3,89,44,0,202,203,3,107,53,0,203, + 204,3,101,50,0,204,205,5,95,0,0,205,206,3,81,40,0,206,207,3,89,44,0,207, + 208,3,65,32,0,208,209,3,77,38,0,209,210,3,73,36,0,210,723,1,0,0,0,211,212, + 3,81,40,0,212,213,5,47,0,0,213,214,3,93,46,0,214,215,5,95,0,0,215,216,3, + 101,50,0,216,217,3,105,52,0,217,218,3,67,33,0,218,219,3,101,50,0,219,220, + 3,113,56,0,220,221,3,101,50,0,221,222,3,103,51,0,222,223,3,73,36,0,223, + 224,3,89,44,0,224,723,1,0,0,0,225,226,3,65,32,0,226,227,3,87,43,0,227,228, + 3,87,43,0,228,229,5,95,0,0,229,230,3,101,50,0,230,231,3,101,50,0,231,232, + 3,81,40,0,232,233,3,71,35,0,233,234,3,101,50,0,234,723,1,0,0,0,235,236, + 3,65,32,0,236,237,3,87,43,0,237,238,3,87,43,0,238,239,5,95,0,0,239,240, + 3,87,43,0,240,241,3,69,34,0,241,242,3,105,52,0,242,243,3,101,50,0,243,723, + 1,0,0,0,244,245,3,65,32,0,245,246,3,87,43,0,246,247,3,87,43,0,247,248,5, + 95,0,0,248,249,3,69,34,0,249,250,3,79,39,0,250,251,3,65,32,0,251,252,3, + 91,45,0,252,253,3,91,45,0,253,254,3,73,36,0,254,255,3,87,43,0,255,256,3, + 101,50,0,256,723,1,0,0,0,257,258,3,65,32,0,258,259,3,87,43,0,259,260,3, + 87,43,0,260,261,5,95,0,0,261,262,3,107,53,0,262,263,3,93,46,0,263,264,3, + 87,43,0,264,265,3,105,52,0,265,266,3,89,44,0,266,267,3,73,36,0,267,268, + 3,101,50,0,268,723,1,0,0,0,269,270,3,69,34,0,270,271,3,99,49,0,271,272, + 3,113,56,0,272,273,3,95,47,0,273,274,3,103,51,0,274,275,3,93,46,0,275,723, + 1,0,0,0,276,277,3,95,47,0,277,278,3,69,34,0,278,279,3,81,40,0,279,280,3, + 73,36,0,280,723,1,0,0,0,281,282,3,101,50,0,282,283,3,69,34,0,283,284,3, + 89,44,0,284,723,1,0,0,0,285,286,3,115,57,0,286,287,3,75,37,0,287,288,3, + 101,50,0,288,723,1,0,0,0,289,290,3,65,32,0,290,291,3,77,38,0,291,292,3, + 77,38,0,292,293,3,99,49,0,293,294,3,73,36,0,294,295,3,77,38,0,295,296,3, + 65,32,0,296,297,3,103,51,0,297,298,3,73,36,0,298,723,1,0,0,0,299,300,3, + 95,47,0,300,301,3,99,49,0,301,302,3,93,46,0,302,303,3,69,34,0,303,304,3, + 73,36,0,304,305,3,101,50,0,305,306,3,101,50,0,306,307,3,93,46,0,307,308, + 3,99,49,0,308,723,1,0,0,0,309,310,3,101,50,0,310,311,3,103,51,0,311,312, + 3,93,46,0,312,313,3,99,49,0,313,314,3,65,32,0,314,315,3,77,38,0,315,316, + 3,73,36,0,316,723,1,0,0,0,317,318,3,65,32,0,318,319,3,105,52,0,319,320, + 3,111,55,0,320,321,3,81,40,0,321,322,3,87,43,0,322,323,3,81,40,0,323,324, + 3,65,32,0,324,325,3,99,49,0,325,326,3,113,56,0,326,327,5,95,0,0,327,328, + 3,101,50,0,328,329,3,103,51,0,329,330,3,93,46,0,330,331,3,99,49,0,331,332, + 3,65,32,0,332,333,3,77,38,0,333,334,3,73,36,0,334,723,1,0,0,0,335,336,3, + 69,34,0,336,337,3,73,36,0,337,338,3,91,45,0,338,339,3,103,51,0,339,340, + 3,99,49,0,340,341,3,65,32,0,341,342,3,87,43,0,342,343,5,95,0,0,343,344, + 3,101,50,0,344,345,3,103,51,0,345,346,3,93,46,0,346,347,3,99,49,0,347,348, + 3,65,32,0,348,349,3,77,38,0,349,350,3,73,36,0,350,723,1,0,0,0,351,352,3, + 69,34,0,352,353,3,101,50,0,353,354,3,65,32,0,354,723,1,0,0,0,355,356,3, + 101,50,0,356,357,3,97,48,0,357,358,3,65,32,0,358,723,1,0,0,0,359,360,3, + 73,36,0,360,361,3,69,34,0,361,362,3,101,50,0,362,363,3,65,32,0,363,723, + 1,0,0,0,364,365,3,73,36,0,365,366,3,91,45,0,366,367,3,97,48,0,367,368,3, + 105,52,0,368,369,3,73,36,0,369,370,3,105,52,0,370,371,3,73,36,0,371,723, + 1,0,0,0,372,373,3,93,46,0,373,374,3,95,47,0,374,375,3,73,36,0,375,376,3, + 99,49,0,376,377,3,65,32,0,377,378,3,103,51,0,378,379,3,93,46,0,379,380, + 3,99,49,0,380,723,1,0,0,0,381,382,3,101,50,0,382,383,3,109,54,0,383,384, + 5,95,0,0,384,385,3,101,50,0,385,386,3,105,52,0,386,387,3,67,33,0,387,388, + 3,101,50,0,388,389,3,113,56,0,389,390,3,101,50,0,390,391,3,103,51,0,391, + 392,3,73,36,0,392,393,3,89,44,0,393,394,3,101,50,0,394,723,1,0,0,0,395, + 396,3,83,41,0,396,397,3,73,36,0,397,398,3,101,50,0,398,723,1,0,0,0,399, + 400,3,111,55,0,400,401,3,69,34,0,401,402,3,75,37,0,402,723,1,0,0,0,403, + 404,3,79,39,0,404,405,3,101,50,0,405,406,3,89,44,0,406,723,1,0,0,0,407, + 408,3,69,34,0,408,409,3,95,47,0,409,410,3,69,34,0,410,723,1,0,0,0,411,412, + 3,87,43,0,412,413,3,95,47,0,413,414,3,65,32,0,414,415,3,99,49,0,415,723, + 1,0,0,0,416,417,3,69,34,0,417,418,3,93,46,0,418,419,3,105,52,0,419,420, + 3,95,47,0,420,421,3,87,43,0,421,422,3,81,40,0,422,423,3,91,45,0,423,424, + 3,77,38,0,424,425,5,95,0,0,425,426,3,75,37,0,426,427,3,65,32,0,427,428, + 3,69,34,0,428,429,3,81,40,0,429,430,3,87,43,0,430,431,3,81,40,0,431,432, + 3,103,51,0,432,433,3,113,56,0,433,723,1,0,0,0,434,435,3,69,34,0,435,436, + 3,75,37,0,436,437,5,95,0,0,437,438,3,101,50,0,438,439,3,103,51,0,439,440, + 3,99,49,0,440,441,3,105,52,0,441,442,3,69,34,0,442,443,3,103,51,0,443,444, + 3,105,52,0,444,445,3,99,49,0,445,446,3,73,36,0,446,723,1,0,0,0,447,448, + 3,109,54,0,448,449,3,87,43,0,449,450,3,89,44,0,450,451,5,95,0,0,451,452, + 3,65,32,0,452,453,3,69,34,0,453,454,3,103,51,0,454,455,3,81,40,0,455,456, + 3,107,53,0,456,457,3,73,36,0,457,458,5,95,0,0,458,459,3,95,47,0,459,460, + 3,93,46,0,460,461,3,87,43,0,461,462,3,81,40,0,462,463,3,69,34,0,463,464, + 3,113,56,0,464,723,1,0,0,0,465,466,3,65,32,0,466,467,3,87,43,0,467,468, + 3,87,43,0,468,469,5,95,0,0,469,470,3,109,54,0,470,471,3,87,43,0,471,472, + 3,89,44,0,472,473,5,95,0,0,473,474,3,109,54,0,474,475,3,93,46,0,475,476, + 3,99,49,0,476,477,3,85,42,0,477,478,3,87,43,0,478,479,3,93,46,0,479,480, + 3,65,32,0,480,481,3,71,35,0,481,482,3,101,50,0,482,723,1,0,0,0,483,484, + 3,109,54,0,484,485,3,87,43,0,485,486,3,89,44,0,486,487,5,95,0,0,487,488, + 3,109,54,0,488,489,3,93,46,0,489,490,3,99,49,0,490,491,3,85,42,0,491,492, + 3,87,43,0,492,493,3,93,46,0,493,494,3,65,32,0,494,495,3,71,35,0,495,723, + 1,0,0,0,496,497,3,109,54,0,497,498,3,87,43,0,498,499,3,89,44,0,499,500, + 5,95,0,0,500,501,3,101,50,0,501,502,3,73,36,0,502,503,3,99,49,0,503,504, + 3,107,53,0,504,505,3,81,40,0,505,506,3,69,34,0,506,507,3,73,36,0,507,508, + 5,95,0,0,508,509,3,69,34,0,509,510,3,87,43,0,510,511,3,65,32,0,511,512, + 3,101,50,0,512,513,3,101,50,0,513,723,1,0,0,0,514,515,3,109,54,0,515,516, + 3,87,43,0,516,517,3,89,44,0,517,518,5,95,0,0,518,519,3,101,50,0,519,520, + 3,69,34,0,520,521,5,95,0,0,521,522,3,95,47,0,522,523,3,73,36,0,523,524, + 3,99,49,0,524,525,3,81,40,0,525,526,3,93,46,0,526,527,3,71,35,0,527,723, + 1,0,0,0,528,529,3,65,32,0,529,530,3,87,43,0,530,531,3,87,43,0,531,532,5, + 95,0,0,532,533,3,109,54,0,533,534,3,87,43,0,534,535,3,89,44,0,535,536,5, + 95,0,0,536,537,3,99,49,0,537,538,3,73,36,0,538,539,3,95,47,0,539,540,3, + 93,46,0,540,541,3,99,49,0,541,542,3,103,51,0,542,543,5,95,0,0,543,544,3, + 69,34,0,544,545,3,87,43,0,545,546,3,65,32,0,546,547,3,101,50,0,547,548, + 3,101,50,0,548,549,3,73,36,0,549,550,3,101,50,0,550,723,1,0,0,0,551,552, + 3,109,54,0,552,553,3,87,43,0,553,554,3,89,44,0,554,555,5,95,0,0,555,556, + 3,99,49,0,556,557,3,73,36,0,557,558,3,95,47,0,558,559,3,93,46,0,559,560, + 3,99,49,0,560,561,3,103,51,0,561,562,5,95,0,0,562,563,3,69,34,0,563,564, + 3,87,43,0,564,565,3,65,32,0,565,566,3,101,50,0,566,567,3,101,50,0,567,723, + 1,0,0,0,568,569,3,109,54,0,569,570,3,87,43,0,570,571,3,89,44,0,571,572, + 5,95,0,0,572,573,3,99,49,0,573,574,3,69,34,0,574,575,5,95,0,0,575,576,3, + 95,47,0,576,577,3,73,36,0,577,578,3,99,49,0,578,579,3,81,40,0,579,580,3, + 93,46,0,580,581,3,71,35,0,581,723,1,0,0,0,582,583,3,65,32,0,583,584,3,87, + 43,0,584,585,3,87,43,0,585,586,5,95,0,0,586,587,3,109,54,0,587,588,3,87, + 43,0,588,589,3,89,44,0,589,590,5,95,0,0,590,591,3,99,49,0,591,592,3,73, + 36,0,592,593,3,101,50,0,593,594,3,93,46,0,594,595,3,105,52,0,595,596,3, + 99,49,0,596,597,3,69,34,0,597,598,3,73,36,0,598,599,5,95,0,0,599,600,3, + 77,38,0,600,601,3,99,49,0,601,602,3,93,46,0,602,603,3,105,52,0,603,604, + 3,95,47,0,604,605,3,101,50,0,605,723,1,0,0,0,606,607,3,109,54,0,607,608, + 3,87,43,0,608,609,3,89,44,0,609,610,5,95,0,0,610,611,3,99,49,0,611,612, + 3,73,36,0,612,613,3,101,50,0,613,614,3,93,46,0,614,615,3,105,52,0,615,616, + 3,99,49,0,616,617,3,69,34,0,617,618,3,73,36,0,618,619,5,95,0,0,619,620, + 3,77,38,0,620,621,3,99,49,0,621,622,3,93,46,0,622,623,3,105,52,0,623,624, + 3,95,47,0,624,723,1,0,0,0,625,626,3,69,34,0,626,627,3,79,39,0,627,628,3, + 65,32,0,628,629,3,91,45,0,629,630,3,91,45,0,630,631,3,73,36,0,631,632,3, + 87,43,0,632,633,5,95,0,0,633,634,3,95,47,0,634,635,3,65,32,0,635,636,3, + 103,51,0,636,637,3,79,39,0,637,723,1,0,0,0,638,639,3,87,43,0,639,640,3, + 93,46,0,640,641,3,77,38,0,641,642,3,81,40,0,642,643,3,69,34,0,643,644,3, + 65,32,0,644,645,3,87,43,0,645,646,5,95,0,0,646,647,3,69,34,0,647,648,3, + 93,46,0,648,649,3,91,45,0,649,650,3,103,51,0,650,651,3,99,49,0,651,652, + 3,93,46,0,652,653,3,87,43,0,653,654,5,95,0,0,654,655,3,105,52,0,655,656, + 3,91,45,0,656,657,3,81,40,0,657,658,3,103,51,0,658,723,1,0,0,0,659,660, + 3,101,50,0,660,661,3,101,50,0,661,662,3,81,40,0,662,663,3,71,35,0,663,723, + 1,0,0,0,664,665,3,107,53,0,665,666,3,93,46,0,666,667,3,87,43,0,667,668, + 3,105,52,0,668,669,3,89,44,0,669,670,3,73,36,0,670,723,1,0,0,0,671,672, + 3,69,34,0,672,673,3,99,49,0,673,674,3,113,56,0,674,675,3,95,47,0,675,676, + 3,103,51,0,676,677,3,93,46,0,677,678,5,95,0,0,678,679,3,69,34,0,679,680, + 3,65,32,0,680,681,3,99,49,0,681,682,3,71,35,0,682,723,1,0,0,0,683,684,3, + 95,47,0,684,685,3,69,34,0,685,686,3,81,40,0,686,687,3,73,36,0,687,688,5, + 95,0,0,688,689,3,75,37,0,689,690,3,105,52,0,690,691,3,91,45,0,691,692,3, + 69,34,0,692,693,3,103,51,0,693,694,3,81,40,0,694,695,3,93,46,0,695,696, + 3,91,45,0,696,723,1,0,0,0,697,698,3,101,50,0,698,699,3,69,34,0,699,700, + 3,89,44,0,700,701,5,95,0,0,701,702,3,69,34,0,702,703,3,65,32,0,703,704, + 3,99,49,0,704,705,3,71,35,0,705,723,1,0,0,0,706,707,3,73,36,0,707,708,3, + 101,50,0,708,709,3,97,48,0,709,710,3,65,32,0,710,723,1,0,0,0,711,712,3, + 75,37,0,712,713,3,81,40,0,713,714,3,87,43,0,714,715,3,73,36,0,715,716,3, + 101,50,0,716,717,3,113,56,0,717,718,3,101,50,0,718,719,3,103,51,0,719,720, + 3,73,36,0,720,721,3,89,44,0,721,723,1,0,0,0,722,193,1,0,0,0,722,201,1,0, + 0,0,722,211,1,0,0,0,722,225,1,0,0,0,722,235,1,0,0,0,722,244,1,0,0,0,722, + 257,1,0,0,0,722,269,1,0,0,0,722,276,1,0,0,0,722,281,1,0,0,0,722,285,1,0, + 0,0,722,289,1,0,0,0,722,299,1,0,0,0,722,309,1,0,0,0,722,317,1,0,0,0,722, + 335,1,0,0,0,722,351,1,0,0,0,722,355,1,0,0,0,722,359,1,0,0,0,722,364,1,0, + 0,0,722,372,1,0,0,0,722,381,1,0,0,0,722,395,1,0,0,0,722,399,1,0,0,0,722, + 403,1,0,0,0,722,407,1,0,0,0,722,411,1,0,0,0,722,416,1,0,0,0,722,434,1,0, + 0,0,722,447,1,0,0,0,722,465,1,0,0,0,722,483,1,0,0,0,722,496,1,0,0,0,722, + 514,1,0,0,0,722,528,1,0,0,0,722,551,1,0,0,0,722,568,1,0,0,0,722,582,1,0, + 0,0,722,606,1,0,0,0,722,625,1,0,0,0,722,638,1,0,0,0,722,659,1,0,0,0,722, + 664,1,0,0,0,722,671,1,0,0,0,722,683,1,0,0,0,722,697,1,0,0,0,722,706,1,0, + 0,0,722,711,1,0,0,0,723,28,1,0,0,0,724,731,3,77,38,0,725,731,3,109,54,0, + 726,731,3,101,50,0,727,731,3,95,47,0,728,731,3,99,49,0,729,731,3,83,41, + 0,730,724,1,0,0,0,730,725,1,0,0,0,730,726,1,0,0,0,730,727,1,0,0,0,730,728, + 1,0,0,0,730,729,1,0,0,0,731,30,1,0,0,0,732,734,7,0,0,0,733,732,1,0,0,0, + 734,735,1,0,0,0,735,733,1,0,0,0,735,736,1,0,0,0,736,32,1,0,0,0,737,738, + 3,31,15,0,738,739,3,41,20,0,739,740,3,31,15,0,740,34,1,0,0,0,741,743,7, + 1,0,0,742,741,1,0,0,0,743,744,1,0,0,0,744,742,1,0,0,0,744,745,1,0,0,0,745, + 36,1,0,0,0,746,748,3,59,29,0,747,746,1,0,0,0,748,749,1,0,0,0,749,747,1, + 0,0,0,749,750,1,0,0,0,750,38,1,0,0,0,751,755,3,55,27,0,752,754,3,61,30, + 0,753,752,1,0,0,0,754,757,1,0,0,0,755,753,1,0,0,0,755,756,1,0,0,0,756,758, + 1,0,0,0,757,755,1,0,0,0,758,759,3,55,27,0,759,770,1,0,0,0,760,764,3,57, + 28,0,761,763,3,63,31,0,762,761,1,0,0,0,763,766,1,0,0,0,764,762,1,0,0,0, + 764,765,1,0,0,0,765,767,1,0,0,0,766,764,1,0,0,0,767,768,3,57,28,0,768,770, + 1,0,0,0,769,751,1,0,0,0,769,760,1,0,0,0,770,40,1,0,0,0,771,772,5,46,0,0, + 772,42,1,0,0,0,773,774,5,59,0,0,774,44,1,0,0,0,775,776,5,44,0,0,776,46, + 1,0,0,0,777,778,5,123,0,0,778,48,1,0,0,0,779,780,5,125,0,0,780,50,1,0,0, + 0,781,782,5,61,0,0,782,52,1,0,0,0,783,785,7,2,0,0,784,783,1,0,0,0,785,786, + 1,0,0,0,786,784,1,0,0,0,786,787,1,0,0,0,787,54,1,0,0,0,788,789,5,39,0,0, + 789,56,1,0,0,0,790,791,5,34,0,0,791,58,1,0,0,0,792,793,8,3,0,0,793,60,1, + 0,0,0,794,795,8,4,0,0,795,62,1,0,0,0,796,797,8,5,0,0,797,64,1,0,0,0,798, + 799,7,6,0,0,799,66,1,0,0,0,800,801,7,7,0,0,801,68,1,0,0,0,802,803,7,8,0, + 0,803,70,1,0,0,0,804,805,7,9,0,0,805,72,1,0,0,0,806,807,7,10,0,0,807,74, + 1,0,0,0,808,809,7,11,0,0,809,76,1,0,0,0,810,811,7,12,0,0,811,78,1,0,0,0, + 812,813,7,13,0,0,813,80,1,0,0,0,814,815,7,14,0,0,815,82,1,0,0,0,816,817, + 7,15,0,0,817,84,1,0,0,0,818,819,7,16,0,0,819,86,1,0,0,0,820,821,7,17,0, + 0,821,88,1,0,0,0,822,823,7,18,0,0,823,90,1,0,0,0,824,825,7,19,0,0,825,92, + 1,0,0,0,826,827,7,20,0,0,827,94,1,0,0,0,828,829,7,21,0,0,829,96,1,0,0,0, + 830,831,7,22,0,0,831,98,1,0,0,0,832,833,7,23,0,0,833,100,1,0,0,0,834,835, + 7,24,0,0,835,102,1,0,0,0,836,837,7,25,0,0,837,104,1,0,0,0,838,839,7,26, + 0,0,839,106,1,0,0,0,840,841,7,27,0,0,841,108,1,0,0,0,842,843,7,28,0,0,843, + 110,1,0,0,0,844,845,7,29,0,0,845,112,1,0,0,0,846,847,7,30,0,0,847,114,1, + 0,0,0,848,849,7,31,0,0,849,116,1,0,0,0,11,0,191,722,730,735,744,749,755, + 764,769,786,0]; + + private static __ATN: ATN; + public static get _ATN(): ATN { + if (!RMFQueryLexer.__ATN) { + RMFQueryLexer.__ATN = new ATNDeserializer().deserialize(RMFQueryLexer._serializedATN); + } + + return RMFQueryLexer.__ATN; + } + + + static DecisionsToDFA = RMFQueryLexer._ATN.decisionToState.map( (ds: DecisionState, index: number) => new DFA(ds, index) ); +} \ No newline at end of file diff --git a/grafana/rmf-app/src/datasource/parser/lib/RMFQueryListener.ts b/grafana/rmf-app/src/datasource/parser/lib/RMFQueryListener.ts new file mode 100644 index 00000000..5b6fbb75 --- /dev/null +++ b/grafana/rmf-app/src/datasource/parser/lib/RMFQueryListener.ts @@ -0,0 +1,256 @@ +// Generated from ./grammar/RMFQuery.g4 by ANTLR 4.13.2 + +import {ParseTreeListener} from "antlr4"; + + +import { QueryContext } from "./RMFQueryParser.js"; +import { IdentifierContext } from "./RMFQueryParser.js"; +import { QualifiersContext } from "./RMFQueryParser.js"; +import { QualifierContext } from "./RMFQueryParser.js"; +import { UlqContext } from "./RMFQueryParser.js"; +import { NameContext } from "./RMFQueryParser.js"; +import { FilterContext } from "./RMFQueryParser.js"; +import { FilterValueContext } from "./RMFQueryParser.js"; +import { FilterItemContext } from "./RMFQueryParser.js"; +import { PatContext } from "./RMFQueryParser.js"; +import { LbContext } from "./RMFQueryParser.js"; +import { UbContext } from "./RMFQueryParser.js"; +import { HiContext } from "./RMFQueryParser.js"; +import { LoContext } from "./RMFQueryParser.js"; +import { OrdContext } from "./RMFQueryParser.js"; +import { WorkscopeContext } from "./RMFQueryParser.js"; +import { WorkscopeValueContext } from "./RMFQueryParser.js"; +import { NumberContext } from "./RMFQueryParser.js"; +import { StringUnquotedContext } from "./RMFQueryParser.js"; +import { StringSpacedContext } from "./RMFQueryParser.js"; +import { StringDottedContext } from "./RMFQueryParser.js"; +import { StringContext } from "./RMFQueryParser.js"; + + +/** + * This interface defines a complete listener for a parse tree produced by + * `RMFQueryParser`. + */ +export default class RMFQueryListener extends ParseTreeListener { + /** + * Enter a parse tree produced by `RMFQueryParser.query`. + * @param ctx the parse tree + */ + enterQuery?: (ctx: QueryContext) => void; + /** + * Exit a parse tree produced by `RMFQueryParser.query`. + * @param ctx the parse tree + */ + exitQuery?: (ctx: QueryContext) => void; + /** + * Enter a parse tree produced by `RMFQueryParser.identifier`. + * @param ctx the parse tree + */ + enterIdentifier?: (ctx: IdentifierContext) => void; + /** + * Exit a parse tree produced by `RMFQueryParser.identifier`. + * @param ctx the parse tree + */ + exitIdentifier?: (ctx: IdentifierContext) => void; + /** + * Enter a parse tree produced by `RMFQueryParser.qualifiers`. + * @param ctx the parse tree + */ + enterQualifiers?: (ctx: QualifiersContext) => void; + /** + * Exit a parse tree produced by `RMFQueryParser.qualifiers`. + * @param ctx the parse tree + */ + exitQualifiers?: (ctx: QualifiersContext) => void; + /** + * Enter a parse tree produced by `RMFQueryParser.qualifier`. + * @param ctx the parse tree + */ + enterQualifier?: (ctx: QualifierContext) => void; + /** + * Exit a parse tree produced by `RMFQueryParser.qualifier`. + * @param ctx the parse tree + */ + exitQualifier?: (ctx: QualifierContext) => void; + /** + * Enter a parse tree produced by `RMFQueryParser.ulq`. + * @param ctx the parse tree + */ + enterUlq?: (ctx: UlqContext) => void; + /** + * Exit a parse tree produced by `RMFQueryParser.ulq`. + * @param ctx the parse tree + */ + exitUlq?: (ctx: UlqContext) => void; + /** + * Enter a parse tree produced by `RMFQueryParser.name`. + * @param ctx the parse tree + */ + enterName?: (ctx: NameContext) => void; + /** + * Exit a parse tree produced by `RMFQueryParser.name`. + * @param ctx the parse tree + */ + exitName?: (ctx: NameContext) => void; + /** + * Enter a parse tree produced by `RMFQueryParser.filter`. + * @param ctx the parse tree + */ + enterFilter?: (ctx: FilterContext) => void; + /** + * Exit a parse tree produced by `RMFQueryParser.filter`. + * @param ctx the parse tree + */ + exitFilter?: (ctx: FilterContext) => void; + /** + * Enter a parse tree produced by `RMFQueryParser.filterValue`. + * @param ctx the parse tree + */ + enterFilterValue?: (ctx: FilterValueContext) => void; + /** + * Exit a parse tree produced by `RMFQueryParser.filterValue`. + * @param ctx the parse tree + */ + exitFilterValue?: (ctx: FilterValueContext) => void; + /** + * Enter a parse tree produced by `RMFQueryParser.filterItem`. + * @param ctx the parse tree + */ + enterFilterItem?: (ctx: FilterItemContext) => void; + /** + * Exit a parse tree produced by `RMFQueryParser.filterItem`. + * @param ctx the parse tree + */ + exitFilterItem?: (ctx: FilterItemContext) => void; + /** + * Enter a parse tree produced by `RMFQueryParser.pat`. + * @param ctx the parse tree + */ + enterPat?: (ctx: PatContext) => void; + /** + * Exit a parse tree produced by `RMFQueryParser.pat`. + * @param ctx the parse tree + */ + exitPat?: (ctx: PatContext) => void; + /** + * Enter a parse tree produced by `RMFQueryParser.lb`. + * @param ctx the parse tree + */ + enterLb?: (ctx: LbContext) => void; + /** + * Exit a parse tree produced by `RMFQueryParser.lb`. + * @param ctx the parse tree + */ + exitLb?: (ctx: LbContext) => void; + /** + * Enter a parse tree produced by `RMFQueryParser.ub`. + * @param ctx the parse tree + */ + enterUb?: (ctx: UbContext) => void; + /** + * Exit a parse tree produced by `RMFQueryParser.ub`. + * @param ctx the parse tree + */ + exitUb?: (ctx: UbContext) => void; + /** + * Enter a parse tree produced by `RMFQueryParser.hi`. + * @param ctx the parse tree + */ + enterHi?: (ctx: HiContext) => void; + /** + * Exit a parse tree produced by `RMFQueryParser.hi`. + * @param ctx the parse tree + */ + exitHi?: (ctx: HiContext) => void; + /** + * Enter a parse tree produced by `RMFQueryParser.lo`. + * @param ctx the parse tree + */ + enterLo?: (ctx: LoContext) => void; + /** + * Exit a parse tree produced by `RMFQueryParser.lo`. + * @param ctx the parse tree + */ + exitLo?: (ctx: LoContext) => void; + /** + * Enter a parse tree produced by `RMFQueryParser.ord`. + * @param ctx the parse tree + */ + enterOrd?: (ctx: OrdContext) => void; + /** + * Exit a parse tree produced by `RMFQueryParser.ord`. + * @param ctx the parse tree + */ + exitOrd?: (ctx: OrdContext) => void; + /** + * Enter a parse tree produced by `RMFQueryParser.workscope`. + * @param ctx the parse tree + */ + enterWorkscope?: (ctx: WorkscopeContext) => void; + /** + * Exit a parse tree produced by `RMFQueryParser.workscope`. + * @param ctx the parse tree + */ + exitWorkscope?: (ctx: WorkscopeContext) => void; + /** + * Enter a parse tree produced by `RMFQueryParser.workscopeValue`. + * @param ctx the parse tree + */ + enterWorkscopeValue?: (ctx: WorkscopeValueContext) => void; + /** + * Exit a parse tree produced by `RMFQueryParser.workscopeValue`. + * @param ctx the parse tree + */ + exitWorkscopeValue?: (ctx: WorkscopeValueContext) => void; + /** + * Enter a parse tree produced by `RMFQueryParser.number`. + * @param ctx the parse tree + */ + enterNumber?: (ctx: NumberContext) => void; + /** + * Exit a parse tree produced by `RMFQueryParser.number`. + * @param ctx the parse tree + */ + exitNumber?: (ctx: NumberContext) => void; + /** + * Enter a parse tree produced by `RMFQueryParser.stringUnquoted`. + * @param ctx the parse tree + */ + enterStringUnquoted?: (ctx: StringUnquotedContext) => void; + /** + * Exit a parse tree produced by `RMFQueryParser.stringUnquoted`. + * @param ctx the parse tree + */ + exitStringUnquoted?: (ctx: StringUnquotedContext) => void; + /** + * Enter a parse tree produced by `RMFQueryParser.stringSpaced`. + * @param ctx the parse tree + */ + enterStringSpaced?: (ctx: StringSpacedContext) => void; + /** + * Exit a parse tree produced by `RMFQueryParser.stringSpaced`. + * @param ctx the parse tree + */ + exitStringSpaced?: (ctx: StringSpacedContext) => void; + /** + * Enter a parse tree produced by `RMFQueryParser.stringDotted`. + * @param ctx the parse tree + */ + enterStringDotted?: (ctx: StringDottedContext) => void; + /** + * Exit a parse tree produced by `RMFQueryParser.stringDotted`. + * @param ctx the parse tree + */ + exitStringDotted?: (ctx: StringDottedContext) => void; + /** + * Enter a parse tree produced by `RMFQueryParser.string`. + * @param ctx the parse tree + */ + enterString?: (ctx: StringContext) => void; + /** + * Exit a parse tree produced by `RMFQueryParser.string`. + * @param ctx the parse tree + */ + exitString?: (ctx: StringContext) => void; +} + diff --git a/grafana/rmf-app/src/datasource/parser/lib/RMFQueryParser.ts b/grafana/rmf-app/src/datasource/parser/lib/RMFQueryParser.ts new file mode 100644 index 00000000..553bebf8 --- /dev/null +++ b/grafana/rmf-app/src/datasource/parser/lib/RMFQueryParser.ts @@ -0,0 +1,1903 @@ +// Generated from ./grammar/RMFQuery.g4 by ANTLR 4.13.2 +// noinspection ES6UnusedImports,JSUnusedGlobalSymbols,JSUnusedLocalSymbols + +import { + ATN, + ATNDeserializer, DecisionState, DFA, FailedPredicateException, + RecognitionException, NoViableAltException, BailErrorStrategy, + Parser, ParserATNSimulator, + RuleContext, ParserRuleContext, PredictionMode, PredictionContextCache, + TerminalNode, RuleNode, + Token, TokenStream, + Interval, IntervalSet +} from 'antlr4'; +import RMFQueryListener from "./RMFQueryListener.js"; +// for running tests with parameters, TODO: discuss strategy for typed parameters in CI +// eslint-disable-next-line no-unused-vars +type int = number; + +export default class RMFQueryParser extends Parser { + public static readonly REPORT = 1; + public static readonly WORKSCOPE = 2; + public static readonly RANGE = 3; + public static readonly ULQ = 4; + public static readonly NAME = 5; + public static readonly FILTER = 6; + public static readonly PAT = 7; + public static readonly LB = 8; + public static readonly UB = 9; + public static readonly HI = 10; + public static readonly LO = 11; + public static readonly ORD = 12; + public static readonly ORD_OPTION = 13; + public static readonly RES_TYPE = 14; + public static readonly WORKSCOPE_TYPE = 15; + public static readonly INTEGER = 16; + public static readonly DECIMAL = 17; + public static readonly IDENTIFIER = 18; + public static readonly STRING_UNQUOTED = 19; + public static readonly STRING_QUOTED = 20; + public static readonly DOT = 21; + public static readonly SEMI = 22; + public static readonly COMMA = 23; + public static readonly LBRACE = 24; + public static readonly RBRACE = 25; + public static readonly EQUAL = 26; + public static readonly WS = 27; + public static override readonly EOF = Token.EOF; + public static readonly RULE_query = 0; + public static readonly RULE_identifier = 1; + public static readonly RULE_qualifiers = 2; + public static readonly RULE_qualifier = 3; + public static readonly RULE_ulq = 4; + public static readonly RULE_name = 5; + public static readonly RULE_filter = 6; + public static readonly RULE_filterValue = 7; + public static readonly RULE_filterItem = 8; + public static readonly RULE_pat = 9; + public static readonly RULE_lb = 10; + public static readonly RULE_ub = 11; + public static readonly RULE_hi = 12; + public static readonly RULE_lo = 13; + public static readonly RULE_ord = 14; + public static readonly RULE_workscope = 15; + public static readonly RULE_workscopeValue = 16; + public static readonly RULE_number = 17; + public static readonly RULE_stringUnquoted = 18; + public static readonly RULE_stringSpaced = 19; + public static readonly RULE_stringDotted = 20; + public static readonly RULE_string = 21; + public static readonly literalNames: (string | null)[] = [ null, null, + null, null, + null, null, + null, null, + null, null, + null, null, + null, null, + null, null, + null, null, + null, null, + null, "'.'", + "';'", "','", + "'{'", "'}'", + "'='" ]; + public static readonly symbolicNames: (string | null)[] = [ null, "REPORT", + "WORKSCOPE", + "RANGE", "ULQ", + "NAME", "FILTER", + "PAT", "LB", + "UB", "HI", + "LO", "ORD", + "ORD_OPTION", + "RES_TYPE", + "WORKSCOPE_TYPE", + "INTEGER", + "DECIMAL", + "IDENTIFIER", + "STRING_UNQUOTED", + "STRING_QUOTED", + "DOT", "SEMI", + "COMMA", "LBRACE", + "RBRACE", "EQUAL", + "WS" ]; + // tslint:disable:no-trailing-whitespace + public static readonly ruleNames: string[] = [ + "query", "identifier", "qualifiers", "qualifier", "ulq", "name", "filter", + "filterValue", "filterItem", "pat", "lb", "ub", "hi", "lo", "ord", "workscope", + "workscopeValue", "number", "stringUnquoted", "stringSpaced", "stringDotted", + "string", + ]; + public get grammarFileName(): string { return "RMFQuery.g4"; } + public get literalNames(): (string | null)[] { return RMFQueryParser.literalNames; } + public get symbolicNames(): (string | null)[] { return RMFQueryParser.symbolicNames; } + public get ruleNames(): string[] { return RMFQueryParser.ruleNames; } + public get serializedATN(): number[] { return RMFQueryParser._serializedATN; } + + protected createFailedPredicateException(predicate?: string, message?: string): FailedPredicateException { + return new FailedPredicateException(this, predicate, message); + } + + constructor(input: TokenStream) { + super(input); + this._interp = new ParserATNSimulator(this, RMFQueryParser._ATN, RMFQueryParser.DecisionsToDFA, new PredictionContextCache()); + } + // @RuleVersion(0) + public query(): QueryContext { + let localctx: QueryContext = new QueryContext(this, this._ctx, this.state); + this.enterRule(localctx, 0, RMFQueryParser.RULE_query); + let _la: number; + try { + let _alt: number; + this.enterOuterAlt(localctx, 1); + { + this.state = 47; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===27) { + { + { + this.state = 44; + this.match(RMFQueryParser.WS); + } + } + this.state = 49; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 50; + this.match(RMFQueryParser.RES_TYPE); + this.state = 53; + this._errHandler.sync(this); + switch ( this._interp.adaptivePredict(this._input, 1, this._ctx) ) { + case 1: + { + this.state = 51; + this.match(RMFQueryParser.DOT); + this.state = 52; + this.match(RMFQueryParser.REPORT); + } + break; + } + this.state = 55; + this.match(RMFQueryParser.DOT); + this.state = 56; + this.identifier(); + this.state = 60; + this._errHandler.sync(this); + _alt = this._interp.adaptivePredict(this._input, 2, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 57; + this.match(RMFQueryParser.WS); + } + } + } + this.state = 62; + this._errHandler.sync(this); + _alt = this._interp.adaptivePredict(this._input, 2, this._ctx); + } + this.state = 64; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la===24) { + { + this.state = 63; + this.qualifiers(); + } + } + + this.state = 69; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===27) { + { + { + this.state = 66; + this.match(RMFQueryParser.WS); + } + } + this.state = 71; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 72; + this.match(RMFQueryParser.EOF); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public identifier(): IdentifierContext { + let localctx: IdentifierContext = new IdentifierContext(this, this._ctx, this.state); + this.enterRule(localctx, 2, RMFQueryParser.RULE_identifier); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 74; + this.stringSpaced(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public qualifiers(): QualifiersContext { + let localctx: QualifiersContext = new QualifiersContext(this, this._ctx, this.state); + this.enterRule(localctx, 4, RMFQueryParser.RULE_qualifiers); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 76; + this.match(RMFQueryParser.LBRACE); + this.state = 80; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===27) { + { + { + this.state = 77; + this.match(RMFQueryParser.WS); + } + } + this.state = 82; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 83; + this.qualifier(); + this.state = 87; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===27) { + { + { + this.state = 84; + this.match(RMFQueryParser.WS); + } + } + this.state = 89; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 106; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===23) { + { + { + this.state = 90; + this.match(RMFQueryParser.COMMA); + this.state = 94; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===27) { + { + { + this.state = 91; + this.match(RMFQueryParser.WS); + } + } + this.state = 96; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 97; + this.qualifier(); + this.state = 101; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===27) { + { + { + this.state = 98; + this.match(RMFQueryParser.WS); + } + } + this.state = 103; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + this.state = 108; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 109; + this.match(RMFQueryParser.RBRACE); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public qualifier(): QualifierContext { + let localctx: QualifierContext = new QualifierContext(this, this._ctx, this.state); + this.enterRule(localctx, 6, RMFQueryParser.RULE_qualifier); + try { + this.state = 115; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case 4: + this.enterOuterAlt(localctx, 1); + { + this.state = 111; + this.ulq(); + } + break; + case 5: + this.enterOuterAlt(localctx, 2); + { + this.state = 112; + this.name(); + } + break; + case 6: + this.enterOuterAlt(localctx, 3); + { + this.state = 113; + this.filter(); + } + break; + case 2: + this.enterOuterAlt(localctx, 4); + { + this.state = 114; + this.workscope(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public ulq(): UlqContext { + let localctx: UlqContext = new UlqContext(this, this._ctx, this.state); + this.enterRule(localctx, 8, RMFQueryParser.RULE_ulq); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 117; + this.match(RMFQueryParser.ULQ); + this.state = 118; + this.match(RMFQueryParser.EQUAL); + this.state = 119; + this.string_(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public name(): NameContext { + let localctx: NameContext = new NameContext(this, this._ctx, this.state); + this.enterRule(localctx, 10, RMFQueryParser.RULE_name); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 121; + this.match(RMFQueryParser.NAME); + this.state = 122; + this.match(RMFQueryParser.EQUAL); + this.state = 123; + this.string_(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public filter(): FilterContext { + let localctx: FilterContext = new FilterContext(this, this._ctx, this.state); + this.enterRule(localctx, 12, RMFQueryParser.RULE_filter); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 125; + this.match(RMFQueryParser.FILTER); + this.state = 126; + this.match(RMFQueryParser.EQUAL); + this.state = 127; + this.filterValue(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public filterValue(): FilterValueContext { + let localctx: FilterValueContext = new FilterValueContext(this, this._ctx, this.state); + this.enterRule(localctx, 14, RMFQueryParser.RULE_filterValue); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 129; + this.filterItem(); + this.state = 134; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===22) { + { + { + this.state = 130; + this.match(RMFQueryParser.SEMI); + this.state = 131; + this.filterItem(); + } + } + this.state = 136; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public filterItem(): FilterItemContext { + let localctx: FilterItemContext = new FilterItemContext(this, this._ctx, this.state); + this.enterRule(localctx, 16, RMFQueryParser.RULE_filterItem); + try { + this.state = 143; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case 7: + this.enterOuterAlt(localctx, 1); + { + this.state = 137; + this.pat(); + } + break; + case 8: + this.enterOuterAlt(localctx, 2); + { + this.state = 138; + this.lb(); + } + break; + case 9: + this.enterOuterAlt(localctx, 3); + { + this.state = 139; + this.ub(); + } + break; + case 10: + this.enterOuterAlt(localctx, 4); + { + this.state = 140; + this.hi(); + } + break; + case 11: + this.enterOuterAlt(localctx, 5); + { + this.state = 141; + this.lo(); + } + break; + case 12: + this.enterOuterAlt(localctx, 6); + { + this.state = 142; + this.ord(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public pat(): PatContext { + let localctx: PatContext = new PatContext(this, this._ctx, this.state); + this.enterRule(localctx, 18, RMFQueryParser.RULE_pat); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 145; + this.match(RMFQueryParser.PAT); + this.state = 146; + this.match(RMFQueryParser.EQUAL); + this.state = 147; + this.string_(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public lb(): LbContext { + let localctx: LbContext = new LbContext(this, this._ctx, this.state); + this.enterRule(localctx, 20, RMFQueryParser.RULE_lb); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 149; + this.match(RMFQueryParser.LB); + this.state = 150; + this.match(RMFQueryParser.EQUAL); + this.state = 151; + this.number_(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public ub(): UbContext { + let localctx: UbContext = new UbContext(this, this._ctx, this.state); + this.enterRule(localctx, 22, RMFQueryParser.RULE_ub); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 153; + this.match(RMFQueryParser.UB); + this.state = 154; + this.match(RMFQueryParser.EQUAL); + this.state = 155; + this.number_(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public hi(): HiContext { + let localctx: HiContext = new HiContext(this, this._ctx, this.state); + this.enterRule(localctx, 24, RMFQueryParser.RULE_hi); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 157; + this.match(RMFQueryParser.HI); + this.state = 158; + this.match(RMFQueryParser.EQUAL); + this.state = 159; + this.match(RMFQueryParser.INTEGER); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public lo(): LoContext { + let localctx: LoContext = new LoContext(this, this._ctx, this.state); + this.enterRule(localctx, 26, RMFQueryParser.RULE_lo); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 161; + this.match(RMFQueryParser.LO); + this.state = 162; + this.match(RMFQueryParser.EQUAL); + this.state = 163; + this.match(RMFQueryParser.INTEGER); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public ord(): OrdContext { + let localctx: OrdContext = new OrdContext(this, this._ctx, this.state); + this.enterRule(localctx, 28, RMFQueryParser.RULE_ord); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 165; + this.match(RMFQueryParser.ORD); + this.state = 166; + this.match(RMFQueryParser.EQUAL); + this.state = 167; + this.match(RMFQueryParser.ORD_OPTION); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public workscope(): WorkscopeContext { + let localctx: WorkscopeContext = new WorkscopeContext(this, this._ctx, this.state); + this.enterRule(localctx, 30, RMFQueryParser.RULE_workscope); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 169; + this.match(RMFQueryParser.WORKSCOPE); + this.state = 170; + this.match(RMFQueryParser.EQUAL); + this.state = 171; + this.workscopeValue(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public workscopeValue(): WorkscopeValueContext { + let localctx: WorkscopeValueContext = new WorkscopeValueContext(this, this._ctx, this.state); + this.enterRule(localctx, 32, RMFQueryParser.RULE_workscopeValue); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 174; + this._errHandler.sync(this); + _la = this._input.LA(1); + if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 1933310) !== 0)) { + { + this.state = 173; + this.string_(); + } + } + + this.state = 176; + this.match(RMFQueryParser.COMMA); + this.state = 178; + this._errHandler.sync(this); + _la = this._input.LA(1); + if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 1933310) !== 0)) { + { + this.state = 177; + this.string_(); + } + } + + this.state = 180; + this.match(RMFQueryParser.COMMA); + this.state = 181; + this.match(RMFQueryParser.WORKSCOPE_TYPE); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public number_(): NumberContext { + let localctx: NumberContext = new NumberContext(this, this._ctx, this.state); + this.enterRule(localctx, 34, RMFQueryParser.RULE_number); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 183; + _la = this._input.LA(1); + if(!(_la===16 || _la===17)) { + this._errHandler.recoverInline(this); + } + else { + this._errHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public stringUnquoted(): StringUnquotedContext { + let localctx: StringUnquotedContext = new StringUnquotedContext(this, this._ctx, this.state); + this.enterRule(localctx, 36, RMFQueryParser.RULE_stringUnquoted); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 185; + _la = this._input.LA(1); + if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 884734) !== 0))) { + this._errHandler.recoverInline(this); + } + else { + this._errHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public stringSpaced(): StringSpacedContext { + let localctx: StringSpacedContext = new StringSpacedContext(this, this._ctx, this.state); + this.enterRule(localctx, 38, RMFQueryParser.RULE_stringSpaced); + let _la: number; + try { + let _alt: number; + this.enterOuterAlt(localctx, 1); + { + this.state = 187; + this.stringUnquoted(); + this.state = 196; + this._errHandler.sync(this); + _alt = this._interp.adaptivePredict(this._input, 16, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 189; + this._errHandler.sync(this); + _la = this._input.LA(1); + do { + { + { + this.state = 188; + this.match(RMFQueryParser.WS); + } + } + this.state = 191; + this._errHandler.sync(this); + _la = this._input.LA(1); + } while (_la===27); + this.state = 193; + this.stringUnquoted(); + } + } + } + this.state = 198; + this._errHandler.sync(this); + _alt = this._interp.adaptivePredict(this._input, 16, this._ctx); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public stringDotted(): StringDottedContext { + let localctx: StringDottedContext = new StringDottedContext(this, this._ctx, this.state); + this.enterRule(localctx, 40, RMFQueryParser.RULE_stringDotted); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 199; + this.stringUnquoted(); + this.state = 204; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===21) { + { + { + this.state = 200; + this.match(RMFQueryParser.DOT); + this.state = 201; + this.stringUnquoted(); + } + } + this.state = 206; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public string_(): StringContext { + let localctx: StringContext = new StringContext(this, this._ctx, this.state); + this.enterRule(localctx, 42, RMFQueryParser.RULE_string); + try { + this.state = 209; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 16: + case 18: + case 19: + this.enterOuterAlt(localctx, 1); + { + this.state = 207; + this.stringDotted(); + } + break; + case 20: + this.enterOuterAlt(localctx, 2); + { + this.state = 208; + this.match(RMFQueryParser.STRING_QUOTED); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + + public static readonly _serializedATN: number[] = [4,1,27,212,2,0,7,0,2, + 1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,6,2,7,7,7,2,8,7,8,2,9,7,9,2, + 10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2,14,7,14,2,15,7,15,2,16,7,16,2,17, + 7,17,2,18,7,18,2,19,7,19,2,20,7,20,2,21,7,21,1,0,5,0,46,8,0,10,0,12,0,49, + 9,0,1,0,1,0,1,0,3,0,54,8,0,1,0,1,0,1,0,5,0,59,8,0,10,0,12,0,62,9,0,1,0, + 3,0,65,8,0,1,0,5,0,68,8,0,10,0,12,0,71,9,0,1,0,1,0,1,1,1,1,1,2,1,2,5,2, + 79,8,2,10,2,12,2,82,9,2,1,2,1,2,5,2,86,8,2,10,2,12,2,89,9,2,1,2,1,2,5,2, + 93,8,2,10,2,12,2,96,9,2,1,2,1,2,5,2,100,8,2,10,2,12,2,103,9,2,5,2,105,8, + 2,10,2,12,2,108,9,2,1,2,1,2,1,3,1,3,1,3,1,3,3,3,116,8,3,1,4,1,4,1,4,1,4, + 1,5,1,5,1,5,1,5,1,6,1,6,1,6,1,6,1,7,1,7,1,7,5,7,133,8,7,10,7,12,7,136,9, + 7,1,8,1,8,1,8,1,8,1,8,1,8,3,8,144,8,8,1,9,1,9,1,9,1,9,1,10,1,10,1,10,1, + 10,1,11,1,11,1,11,1,11,1,12,1,12,1,12,1,12,1,13,1,13,1,13,1,13,1,14,1,14, + 1,14,1,14,1,15,1,15,1,15,1,15,1,16,3,16,175,8,16,1,16,1,16,3,16,179,8,16, + 1,16,1,16,1,16,1,17,1,17,1,18,1,18,1,19,1,19,4,19,190,8,19,11,19,12,19, + 191,1,19,5,19,195,8,19,10,19,12,19,198,9,19,1,20,1,20,1,20,5,20,203,8,20, + 10,20,12,20,206,9,20,1,21,1,21,3,21,210,8,21,1,21,0,0,22,0,2,4,6,8,10,12, + 14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,0,2,1,0,16,17,3,0,1,14,16, + 16,18,19,214,0,47,1,0,0,0,2,74,1,0,0,0,4,76,1,0,0,0,6,115,1,0,0,0,8,117, + 1,0,0,0,10,121,1,0,0,0,12,125,1,0,0,0,14,129,1,0,0,0,16,143,1,0,0,0,18, + 145,1,0,0,0,20,149,1,0,0,0,22,153,1,0,0,0,24,157,1,0,0,0,26,161,1,0,0,0, + 28,165,1,0,0,0,30,169,1,0,0,0,32,174,1,0,0,0,34,183,1,0,0,0,36,185,1,0, + 0,0,38,187,1,0,0,0,40,199,1,0,0,0,42,209,1,0,0,0,44,46,5,27,0,0,45,44,1, + 0,0,0,46,49,1,0,0,0,47,45,1,0,0,0,47,48,1,0,0,0,48,50,1,0,0,0,49,47,1,0, + 0,0,50,53,5,14,0,0,51,52,5,21,0,0,52,54,5,1,0,0,53,51,1,0,0,0,53,54,1,0, + 0,0,54,55,1,0,0,0,55,56,5,21,0,0,56,60,3,2,1,0,57,59,5,27,0,0,58,57,1,0, + 0,0,59,62,1,0,0,0,60,58,1,0,0,0,60,61,1,0,0,0,61,64,1,0,0,0,62,60,1,0,0, + 0,63,65,3,4,2,0,64,63,1,0,0,0,64,65,1,0,0,0,65,69,1,0,0,0,66,68,5,27,0, + 0,67,66,1,0,0,0,68,71,1,0,0,0,69,67,1,0,0,0,69,70,1,0,0,0,70,72,1,0,0,0, + 71,69,1,0,0,0,72,73,5,0,0,1,73,1,1,0,0,0,74,75,3,38,19,0,75,3,1,0,0,0,76, + 80,5,24,0,0,77,79,5,27,0,0,78,77,1,0,0,0,79,82,1,0,0,0,80,78,1,0,0,0,80, + 81,1,0,0,0,81,83,1,0,0,0,82,80,1,0,0,0,83,87,3,6,3,0,84,86,5,27,0,0,85, + 84,1,0,0,0,86,89,1,0,0,0,87,85,1,0,0,0,87,88,1,0,0,0,88,106,1,0,0,0,89, + 87,1,0,0,0,90,94,5,23,0,0,91,93,5,27,0,0,92,91,1,0,0,0,93,96,1,0,0,0,94, + 92,1,0,0,0,94,95,1,0,0,0,95,97,1,0,0,0,96,94,1,0,0,0,97,101,3,6,3,0,98, + 100,5,27,0,0,99,98,1,0,0,0,100,103,1,0,0,0,101,99,1,0,0,0,101,102,1,0,0, + 0,102,105,1,0,0,0,103,101,1,0,0,0,104,90,1,0,0,0,105,108,1,0,0,0,106,104, + 1,0,0,0,106,107,1,0,0,0,107,109,1,0,0,0,108,106,1,0,0,0,109,110,5,25,0, + 0,110,5,1,0,0,0,111,116,3,8,4,0,112,116,3,10,5,0,113,116,3,12,6,0,114,116, + 3,30,15,0,115,111,1,0,0,0,115,112,1,0,0,0,115,113,1,0,0,0,115,114,1,0,0, + 0,116,7,1,0,0,0,117,118,5,4,0,0,118,119,5,26,0,0,119,120,3,42,21,0,120, + 9,1,0,0,0,121,122,5,5,0,0,122,123,5,26,0,0,123,124,3,42,21,0,124,11,1,0, + 0,0,125,126,5,6,0,0,126,127,5,26,0,0,127,128,3,14,7,0,128,13,1,0,0,0,129, + 134,3,16,8,0,130,131,5,22,0,0,131,133,3,16,8,0,132,130,1,0,0,0,133,136, + 1,0,0,0,134,132,1,0,0,0,134,135,1,0,0,0,135,15,1,0,0,0,136,134,1,0,0,0, + 137,144,3,18,9,0,138,144,3,20,10,0,139,144,3,22,11,0,140,144,3,24,12,0, + 141,144,3,26,13,0,142,144,3,28,14,0,143,137,1,0,0,0,143,138,1,0,0,0,143, + 139,1,0,0,0,143,140,1,0,0,0,143,141,1,0,0,0,143,142,1,0,0,0,144,17,1,0, + 0,0,145,146,5,7,0,0,146,147,5,26,0,0,147,148,3,42,21,0,148,19,1,0,0,0,149, + 150,5,8,0,0,150,151,5,26,0,0,151,152,3,34,17,0,152,21,1,0,0,0,153,154,5, + 9,0,0,154,155,5,26,0,0,155,156,3,34,17,0,156,23,1,0,0,0,157,158,5,10,0, + 0,158,159,5,26,0,0,159,160,5,16,0,0,160,25,1,0,0,0,161,162,5,11,0,0,162, + 163,5,26,0,0,163,164,5,16,0,0,164,27,1,0,0,0,165,166,5,12,0,0,166,167,5, + 26,0,0,167,168,5,13,0,0,168,29,1,0,0,0,169,170,5,2,0,0,170,171,5,26,0,0, + 171,172,3,32,16,0,172,31,1,0,0,0,173,175,3,42,21,0,174,173,1,0,0,0,174, + 175,1,0,0,0,175,176,1,0,0,0,176,178,5,23,0,0,177,179,3,42,21,0,178,177, + 1,0,0,0,178,179,1,0,0,0,179,180,1,0,0,0,180,181,5,23,0,0,181,182,5,15,0, + 0,182,33,1,0,0,0,183,184,7,0,0,0,184,35,1,0,0,0,185,186,7,1,0,0,186,37, + 1,0,0,0,187,196,3,36,18,0,188,190,5,27,0,0,189,188,1,0,0,0,190,191,1,0, + 0,0,191,189,1,0,0,0,191,192,1,0,0,0,192,193,1,0,0,0,193,195,3,36,18,0,194, + 189,1,0,0,0,195,198,1,0,0,0,196,194,1,0,0,0,196,197,1,0,0,0,197,39,1,0, + 0,0,198,196,1,0,0,0,199,204,3,36,18,0,200,201,5,21,0,0,201,203,3,36,18, + 0,202,200,1,0,0,0,203,206,1,0,0,0,204,202,1,0,0,0,204,205,1,0,0,0,205,41, + 1,0,0,0,206,204,1,0,0,0,207,210,3,40,20,0,208,210,5,20,0,0,209,207,1,0, + 0,0,209,208,1,0,0,0,210,43,1,0,0,0,19,47,53,60,64,69,80,87,94,101,106,115, + 134,143,174,178,191,196,204,209]; + + private static __ATN: ATN; + public static get _ATN(): ATN { + if (!RMFQueryParser.__ATN) { + RMFQueryParser.__ATN = new ATNDeserializer().deserialize(RMFQueryParser._serializedATN); + } + + return RMFQueryParser.__ATN; + } + + + static DecisionsToDFA = RMFQueryParser._ATN.decisionToState.map( (ds: DecisionState, index: number) => new DFA(ds, index) ); + +} + +export class QueryContext extends ParserRuleContext { + constructor(parser?: RMFQueryParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public RES_TYPE(): TerminalNode { + return this.getToken(RMFQueryParser.RES_TYPE, 0); + } + public DOT_list(): TerminalNode[] { + return this.getTokens(RMFQueryParser.DOT); + } + public DOT(i: number): TerminalNode { + return this.getToken(RMFQueryParser.DOT, i); + } + public identifier(): IdentifierContext { + return this.getTypedRuleContext(IdentifierContext, 0) as IdentifierContext; + } + public EOF(): TerminalNode { + return this.getToken(RMFQueryParser.EOF, 0); + } + public WS_list(): TerminalNode[] { + return this.getTokens(RMFQueryParser.WS); + } + public WS(i: number): TerminalNode { + return this.getToken(RMFQueryParser.WS, i); + } + public REPORT(): TerminalNode { + return this.getToken(RMFQueryParser.REPORT, 0); + } + public qualifiers(): QualifiersContext { + return this.getTypedRuleContext(QualifiersContext, 0) as QualifiersContext; + } + public get ruleIndex(): number { + return RMFQueryParser.RULE_query; + } + public enterRule(listener: RMFQueryListener): void { + if(listener.enterQuery) { + listener.enterQuery(this); + } + } + public exitRule(listener: RMFQueryListener): void { + if(listener.exitQuery) { + listener.exitQuery(this); + } + } +} + + +export class IdentifierContext extends ParserRuleContext { + constructor(parser?: RMFQueryParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public stringSpaced(): StringSpacedContext { + return this.getTypedRuleContext(StringSpacedContext, 0) as StringSpacedContext; + } + public get ruleIndex(): number { + return RMFQueryParser.RULE_identifier; + } + public enterRule(listener: RMFQueryListener): void { + if(listener.enterIdentifier) { + listener.enterIdentifier(this); + } + } + public exitRule(listener: RMFQueryListener): void { + if(listener.exitIdentifier) { + listener.exitIdentifier(this); + } + } +} + + +export class QualifiersContext extends ParserRuleContext { + constructor(parser?: RMFQueryParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public LBRACE(): TerminalNode { + return this.getToken(RMFQueryParser.LBRACE, 0); + } + public qualifier_list(): QualifierContext[] { + return this.getTypedRuleContexts(QualifierContext) as QualifierContext[]; + } + public qualifier(i: number): QualifierContext { + return this.getTypedRuleContext(QualifierContext, i) as QualifierContext; + } + public RBRACE(): TerminalNode { + return this.getToken(RMFQueryParser.RBRACE, 0); + } + public WS_list(): TerminalNode[] { + return this.getTokens(RMFQueryParser.WS); + } + public WS(i: number): TerminalNode { + return this.getToken(RMFQueryParser.WS, i); + } + public COMMA_list(): TerminalNode[] { + return this.getTokens(RMFQueryParser.COMMA); + } + public COMMA(i: number): TerminalNode { + return this.getToken(RMFQueryParser.COMMA, i); + } + public get ruleIndex(): number { + return RMFQueryParser.RULE_qualifiers; + } + public enterRule(listener: RMFQueryListener): void { + if(listener.enterQualifiers) { + listener.enterQualifiers(this); + } + } + public exitRule(listener: RMFQueryListener): void { + if(listener.exitQualifiers) { + listener.exitQualifiers(this); + } + } +} + + +export class QualifierContext extends ParserRuleContext { + constructor(parser?: RMFQueryParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public ulq(): UlqContext { + return this.getTypedRuleContext(UlqContext, 0) as UlqContext; + } + public name(): NameContext { + return this.getTypedRuleContext(NameContext, 0) as NameContext; + } + public filter(): FilterContext { + return this.getTypedRuleContext(FilterContext, 0) as FilterContext; + } + public workscope(): WorkscopeContext { + return this.getTypedRuleContext(WorkscopeContext, 0) as WorkscopeContext; + } + public get ruleIndex(): number { + return RMFQueryParser.RULE_qualifier; + } + public enterRule(listener: RMFQueryListener): void { + if(listener.enterQualifier) { + listener.enterQualifier(this); + } + } + public exitRule(listener: RMFQueryListener): void { + if(listener.exitQualifier) { + listener.exitQualifier(this); + } + } +} + + +export class UlqContext extends ParserRuleContext { + constructor(parser?: RMFQueryParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public ULQ(): TerminalNode { + return this.getToken(RMFQueryParser.ULQ, 0); + } + public EQUAL(): TerminalNode { + return this.getToken(RMFQueryParser.EQUAL, 0); + } + public string_(): StringContext { + return this.getTypedRuleContext(StringContext, 0) as StringContext; + } + public get ruleIndex(): number { + return RMFQueryParser.RULE_ulq; + } + public enterRule(listener: RMFQueryListener): void { + if(listener.enterUlq) { + listener.enterUlq(this); + } + } + public exitRule(listener: RMFQueryListener): void { + if(listener.exitUlq) { + listener.exitUlq(this); + } + } +} + + +export class NameContext extends ParserRuleContext { + constructor(parser?: RMFQueryParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public NAME(): TerminalNode { + return this.getToken(RMFQueryParser.NAME, 0); + } + public EQUAL(): TerminalNode { + return this.getToken(RMFQueryParser.EQUAL, 0); + } + public string_(): StringContext { + return this.getTypedRuleContext(StringContext, 0) as StringContext; + } + public get ruleIndex(): number { + return RMFQueryParser.RULE_name; + } + public enterRule(listener: RMFQueryListener): void { + if(listener.enterName) { + listener.enterName(this); + } + } + public exitRule(listener: RMFQueryListener): void { + if(listener.exitName) { + listener.exitName(this); + } + } +} + + +export class FilterContext extends ParserRuleContext { + constructor(parser?: RMFQueryParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public FILTER(): TerminalNode { + return this.getToken(RMFQueryParser.FILTER, 0); + } + public EQUAL(): TerminalNode { + return this.getToken(RMFQueryParser.EQUAL, 0); + } + public filterValue(): FilterValueContext { + return this.getTypedRuleContext(FilterValueContext, 0) as FilterValueContext; + } + public get ruleIndex(): number { + return RMFQueryParser.RULE_filter; + } + public enterRule(listener: RMFQueryListener): void { + if(listener.enterFilter) { + listener.enterFilter(this); + } + } + public exitRule(listener: RMFQueryListener): void { + if(listener.exitFilter) { + listener.exitFilter(this); + } + } +} + + +export class FilterValueContext extends ParserRuleContext { + constructor(parser?: RMFQueryParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public filterItem_list(): FilterItemContext[] { + return this.getTypedRuleContexts(FilterItemContext) as FilterItemContext[]; + } + public filterItem(i: number): FilterItemContext { + return this.getTypedRuleContext(FilterItemContext, i) as FilterItemContext; + } + public SEMI_list(): TerminalNode[] { + return this.getTokens(RMFQueryParser.SEMI); + } + public SEMI(i: number): TerminalNode { + return this.getToken(RMFQueryParser.SEMI, i); + } + public get ruleIndex(): number { + return RMFQueryParser.RULE_filterValue; + } + public enterRule(listener: RMFQueryListener): void { + if(listener.enterFilterValue) { + listener.enterFilterValue(this); + } + } + public exitRule(listener: RMFQueryListener): void { + if(listener.exitFilterValue) { + listener.exitFilterValue(this); + } + } +} + + +export class FilterItemContext extends ParserRuleContext { + constructor(parser?: RMFQueryParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public pat(): PatContext { + return this.getTypedRuleContext(PatContext, 0) as PatContext; + } + public lb(): LbContext { + return this.getTypedRuleContext(LbContext, 0) as LbContext; + } + public ub(): UbContext { + return this.getTypedRuleContext(UbContext, 0) as UbContext; + } + public hi(): HiContext { + return this.getTypedRuleContext(HiContext, 0) as HiContext; + } + public lo(): LoContext { + return this.getTypedRuleContext(LoContext, 0) as LoContext; + } + public ord(): OrdContext { + return this.getTypedRuleContext(OrdContext, 0) as OrdContext; + } + public get ruleIndex(): number { + return RMFQueryParser.RULE_filterItem; + } + public enterRule(listener: RMFQueryListener): void { + if(listener.enterFilterItem) { + listener.enterFilterItem(this); + } + } + public exitRule(listener: RMFQueryListener): void { + if(listener.exitFilterItem) { + listener.exitFilterItem(this); + } + } +} + + +export class PatContext extends ParserRuleContext { + constructor(parser?: RMFQueryParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public PAT(): TerminalNode { + return this.getToken(RMFQueryParser.PAT, 0); + } + public EQUAL(): TerminalNode { + return this.getToken(RMFQueryParser.EQUAL, 0); + } + public string_(): StringContext { + return this.getTypedRuleContext(StringContext, 0) as StringContext; + } + public get ruleIndex(): number { + return RMFQueryParser.RULE_pat; + } + public enterRule(listener: RMFQueryListener): void { + if(listener.enterPat) { + listener.enterPat(this); + } + } + public exitRule(listener: RMFQueryListener): void { + if(listener.exitPat) { + listener.exitPat(this); + } + } +} + + +export class LbContext extends ParserRuleContext { + constructor(parser?: RMFQueryParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public LB(): TerminalNode { + return this.getToken(RMFQueryParser.LB, 0); + } + public EQUAL(): TerminalNode { + return this.getToken(RMFQueryParser.EQUAL, 0); + } + public number_(): NumberContext { + return this.getTypedRuleContext(NumberContext, 0) as NumberContext; + } + public get ruleIndex(): number { + return RMFQueryParser.RULE_lb; + } + public enterRule(listener: RMFQueryListener): void { + if(listener.enterLb) { + listener.enterLb(this); + } + } + public exitRule(listener: RMFQueryListener): void { + if(listener.exitLb) { + listener.exitLb(this); + } + } +} + + +export class UbContext extends ParserRuleContext { + constructor(parser?: RMFQueryParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public UB(): TerminalNode { + return this.getToken(RMFQueryParser.UB, 0); + } + public EQUAL(): TerminalNode { + return this.getToken(RMFQueryParser.EQUAL, 0); + } + public number_(): NumberContext { + return this.getTypedRuleContext(NumberContext, 0) as NumberContext; + } + public get ruleIndex(): number { + return RMFQueryParser.RULE_ub; + } + public enterRule(listener: RMFQueryListener): void { + if(listener.enterUb) { + listener.enterUb(this); + } + } + public exitRule(listener: RMFQueryListener): void { + if(listener.exitUb) { + listener.exitUb(this); + } + } +} + + +export class HiContext extends ParserRuleContext { + constructor(parser?: RMFQueryParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public HI(): TerminalNode { + return this.getToken(RMFQueryParser.HI, 0); + } + public EQUAL(): TerminalNode { + return this.getToken(RMFQueryParser.EQUAL, 0); + } + public INTEGER(): TerminalNode { + return this.getToken(RMFQueryParser.INTEGER, 0); + } + public get ruleIndex(): number { + return RMFQueryParser.RULE_hi; + } + public enterRule(listener: RMFQueryListener): void { + if(listener.enterHi) { + listener.enterHi(this); + } + } + public exitRule(listener: RMFQueryListener): void { + if(listener.exitHi) { + listener.exitHi(this); + } + } +} + + +export class LoContext extends ParserRuleContext { + constructor(parser?: RMFQueryParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public LO(): TerminalNode { + return this.getToken(RMFQueryParser.LO, 0); + } + public EQUAL(): TerminalNode { + return this.getToken(RMFQueryParser.EQUAL, 0); + } + public INTEGER(): TerminalNode { + return this.getToken(RMFQueryParser.INTEGER, 0); + } + public get ruleIndex(): number { + return RMFQueryParser.RULE_lo; + } + public enterRule(listener: RMFQueryListener): void { + if(listener.enterLo) { + listener.enterLo(this); + } + } + public exitRule(listener: RMFQueryListener): void { + if(listener.exitLo) { + listener.exitLo(this); + } + } +} + + +export class OrdContext extends ParserRuleContext { + constructor(parser?: RMFQueryParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public ORD(): TerminalNode { + return this.getToken(RMFQueryParser.ORD, 0); + } + public EQUAL(): TerminalNode { + return this.getToken(RMFQueryParser.EQUAL, 0); + } + public ORD_OPTION(): TerminalNode { + return this.getToken(RMFQueryParser.ORD_OPTION, 0); + } + public get ruleIndex(): number { + return RMFQueryParser.RULE_ord; + } + public enterRule(listener: RMFQueryListener): void { + if(listener.enterOrd) { + listener.enterOrd(this); + } + } + public exitRule(listener: RMFQueryListener): void { + if(listener.exitOrd) { + listener.exitOrd(this); + } + } +} + + +export class WorkscopeContext extends ParserRuleContext { + constructor(parser?: RMFQueryParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public WORKSCOPE(): TerminalNode { + return this.getToken(RMFQueryParser.WORKSCOPE, 0); + } + public EQUAL(): TerminalNode { + return this.getToken(RMFQueryParser.EQUAL, 0); + } + public workscopeValue(): WorkscopeValueContext { + return this.getTypedRuleContext(WorkscopeValueContext, 0) as WorkscopeValueContext; + } + public get ruleIndex(): number { + return RMFQueryParser.RULE_workscope; + } + public enterRule(listener: RMFQueryListener): void { + if(listener.enterWorkscope) { + listener.enterWorkscope(this); + } + } + public exitRule(listener: RMFQueryListener): void { + if(listener.exitWorkscope) { + listener.exitWorkscope(this); + } + } +} + + +export class WorkscopeValueContext extends ParserRuleContext { + constructor(parser?: RMFQueryParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public COMMA_list(): TerminalNode[] { + return this.getTokens(RMFQueryParser.COMMA); + } + public COMMA(i: number): TerminalNode { + return this.getToken(RMFQueryParser.COMMA, i); + } + public WORKSCOPE_TYPE(): TerminalNode { + return this.getToken(RMFQueryParser.WORKSCOPE_TYPE, 0); + } + public string__list(): StringContext[] { + return this.getTypedRuleContexts(StringContext) as StringContext[]; + } + public string_(i: number): StringContext { + return this.getTypedRuleContext(StringContext, i) as StringContext; + } + public get ruleIndex(): number { + return RMFQueryParser.RULE_workscopeValue; + } + public enterRule(listener: RMFQueryListener): void { + if(listener.enterWorkscopeValue) { + listener.enterWorkscopeValue(this); + } + } + public exitRule(listener: RMFQueryListener): void { + if(listener.exitWorkscopeValue) { + listener.exitWorkscopeValue(this); + } + } +} + + +export class NumberContext extends ParserRuleContext { + constructor(parser?: RMFQueryParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public INTEGER(): TerminalNode { + return this.getToken(RMFQueryParser.INTEGER, 0); + } + public DECIMAL(): TerminalNode { + return this.getToken(RMFQueryParser.DECIMAL, 0); + } + public get ruleIndex(): number { + return RMFQueryParser.RULE_number; + } + public enterRule(listener: RMFQueryListener): void { + if(listener.enterNumber) { + listener.enterNumber(this); + } + } + public exitRule(listener: RMFQueryListener): void { + if(listener.exitNumber) { + listener.exitNumber(this); + } + } +} + + +export class StringUnquotedContext extends ParserRuleContext { + constructor(parser?: RMFQueryParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public IDENTIFIER(): TerminalNode { + return this.getToken(RMFQueryParser.IDENTIFIER, 0); + } + public RES_TYPE(): TerminalNode { + return this.getToken(RMFQueryParser.RES_TYPE, 0); + } + public REPORT(): TerminalNode { + return this.getToken(RMFQueryParser.REPORT, 0); + } + public WORKSCOPE(): TerminalNode { + return this.getToken(RMFQueryParser.WORKSCOPE, 0); + } + public RANGE(): TerminalNode { + return this.getToken(RMFQueryParser.RANGE, 0); + } + public ULQ(): TerminalNode { + return this.getToken(RMFQueryParser.ULQ, 0); + } + public NAME(): TerminalNode { + return this.getToken(RMFQueryParser.NAME, 0); + } + public FILTER(): TerminalNode { + return this.getToken(RMFQueryParser.FILTER, 0); + } + public PAT(): TerminalNode { + return this.getToken(RMFQueryParser.PAT, 0); + } + public LB(): TerminalNode { + return this.getToken(RMFQueryParser.LB, 0); + } + public UB(): TerminalNode { + return this.getToken(RMFQueryParser.UB, 0); + } + public HI(): TerminalNode { + return this.getToken(RMFQueryParser.HI, 0); + } + public LO(): TerminalNode { + return this.getToken(RMFQueryParser.LO, 0); + } + public ORD(): TerminalNode { + return this.getToken(RMFQueryParser.ORD, 0); + } + public ORD_OPTION(): TerminalNode { + return this.getToken(RMFQueryParser.ORD_OPTION, 0); + } + public INTEGER(): TerminalNode { + return this.getToken(RMFQueryParser.INTEGER, 0); + } + public STRING_UNQUOTED(): TerminalNode { + return this.getToken(RMFQueryParser.STRING_UNQUOTED, 0); + } + public get ruleIndex(): number { + return RMFQueryParser.RULE_stringUnquoted; + } + public enterRule(listener: RMFQueryListener): void { + if(listener.enterStringUnquoted) { + listener.enterStringUnquoted(this); + } + } + public exitRule(listener: RMFQueryListener): void { + if(listener.exitStringUnquoted) { + listener.exitStringUnquoted(this); + } + } +} + + +export class StringSpacedContext extends ParserRuleContext { + constructor(parser?: RMFQueryParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public stringUnquoted_list(): StringUnquotedContext[] { + return this.getTypedRuleContexts(StringUnquotedContext) as StringUnquotedContext[]; + } + public stringUnquoted(i: number): StringUnquotedContext { + return this.getTypedRuleContext(StringUnquotedContext, i) as StringUnquotedContext; + } + public WS_list(): TerminalNode[] { + return this.getTokens(RMFQueryParser.WS); + } + public WS(i: number): TerminalNode { + return this.getToken(RMFQueryParser.WS, i); + } + public get ruleIndex(): number { + return RMFQueryParser.RULE_stringSpaced; + } + public enterRule(listener: RMFQueryListener): void { + if(listener.enterStringSpaced) { + listener.enterStringSpaced(this); + } + } + public exitRule(listener: RMFQueryListener): void { + if(listener.exitStringSpaced) { + listener.exitStringSpaced(this); + } + } +} + + +export class StringDottedContext extends ParserRuleContext { + constructor(parser?: RMFQueryParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public stringUnquoted_list(): StringUnquotedContext[] { + return this.getTypedRuleContexts(StringUnquotedContext) as StringUnquotedContext[]; + } + public stringUnquoted(i: number): StringUnquotedContext { + return this.getTypedRuleContext(StringUnquotedContext, i) as StringUnquotedContext; + } + public DOT_list(): TerminalNode[] { + return this.getTokens(RMFQueryParser.DOT); + } + public DOT(i: number): TerminalNode { + return this.getToken(RMFQueryParser.DOT, i); + } + public get ruleIndex(): number { + return RMFQueryParser.RULE_stringDotted; + } + public enterRule(listener: RMFQueryListener): void { + if(listener.enterStringDotted) { + listener.enterStringDotted(this); + } + } + public exitRule(listener: RMFQueryListener): void { + if(listener.exitStringDotted) { + listener.exitStringDotted(this); + } + } +} + + +export class StringContext extends ParserRuleContext { + constructor(parser?: RMFQueryParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public stringDotted(): StringDottedContext { + return this.getTypedRuleContext(StringDottedContext, 0) as StringDottedContext; + } + public STRING_QUOTED(): TerminalNode { + return this.getToken(RMFQueryParser.STRING_QUOTED, 0); + } + public get ruleIndex(): number { + return RMFQueryParser.RULE_string; + } + public enterRule(listener: RMFQueryListener): void { + if(listener.enterString) { + listener.enterString(this); + } + } + public exitRule(listener: RMFQueryListener): void { + if(listener.exitString) { + listener.exitString(this); + } + } +} diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/plugin.json b/grafana/rmf-app/src/datasource/plugin.json similarity index 96% rename from grafana/rmf-app/src/datasources/rmf-datasource/plugin.json rename to grafana/rmf-app/src/datasource/plugin.json index 16927c63..4e34285e 100644 --- a/grafana/rmf-app/src/datasources/rmf-datasource/plugin.json +++ b/grafana/rmf-app/src/datasource/plugin.json @@ -40,7 +40,7 @@ "updated": "%TODAY%" }, "dependencies": { - "grafanaDependency": ">=10", + "grafanaDependency": ">=10.0", "plugins": [] } } diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/query-editor/queryeditor.parser.component.css b/grafana/rmf-app/src/datasource/query-editor/queryeditor.parser.component.css similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/query-editor/queryeditor.parser.component.css rename to grafana/rmf-app/src/datasource/query-editor/queryeditor.parser.component.css diff --git a/grafana/rmf-app/src/datasources/rmf-datasource/query-editor/queryeditor.parser.component.tsx b/grafana/rmf-app/src/datasource/query-editor/queryeditor.parser.component.tsx similarity index 100% rename from grafana/rmf-app/src/datasources/rmf-datasource/query-editor/queryeditor.parser.component.tsx rename to grafana/rmf-app/src/datasource/query-editor/queryeditor.parser.component.tsx diff --git a/grafana/rmf-app/src/img/sample-dashboard.png b/grafana/rmf-app/src/img/sample-dashboard.png new file mode 100644 index 0000000000000000000000000000000000000000..1ec1a8dcd6297393c7caf259d2769fcfa83af5e1 GIT binary patch literal 285790 zcmXtfWmr^g)HThZLkYsrrGyegNH;?Xk}BP;bmxFHQW6p(jetrD(hSnw&CoS;Gr$b- z&GWwB`{(?a`?{~W&pG?7z4l&f$7pFN6F;JTgoTAgtf~Uh!NMW{VqxLV0SGX^5JXL2 zt|3^e5V^O$rU%(RfluF|92x%=%+{7nSypB-!mo7Z@weM z+J5GyImiQ8!pZ*UBB2l#NB?oDsc>3zxOVT=o?-mAOU%++>_saNk1YMzv_tOauL`^F z^rN%aM8^64|1Qkd0X2WyioecF?H^`dbFnxRv4odOf`K}^HDy&^0W<^!6F=W}=4pH= zp8l2Vz(tgXS^wWZv|Le){6r>yK#R2NGSy|UF7&6@g1`?m zqqPcWHHSrYjcK%j73t;-|F>QKAgd2dCLe9md2bJL{ca%UH&ZaZoD%s{V9!|O$EWFE zx+`Z{wN=<*3AMVK5=&G(hL*F&9_1!pmjcbM%Yk$<76o2=3!OT2){TBz<3SN`KU-)? zyqau6*uV)D&JKDD&zwvV#)(3u>9j@~UD)GEtH6pYzs3&W3EkEH`{w$cy3>X}v((+N{{+UcVYYU*ykeRTSl$HEvN zGET!^LZEsUXz*m&E;B#qWX_+|=)4Bq8E+t9^X(=p| zvj6wG=BSe_n8V4MBk$(H_Hfv~smIXMa>0GpYf>8Fj-$pa(}2rqJ*PX=C2~EMFKs}L zuXU54qseRE@m}$9nZr4brY~KHnrq04V$7HfFsr)eA&MdL7Mt5PWp`DD!=>HBw79b)33@5XkW$w&7OAw<( zkk9TH7v1dK?ubAA!Rke_@3Fr5(;0{C9oZ{FQ{OfGfcqN+!#&e064QXgSIt4wFFr2S z1x2Wb6#;Q4h%TLzof5B{tX)V3YThVs&kHIG{oz1wHL9MhRNo+%GUiskFyTPOUaZ`U z@FH(YRv%_B9PMBI_dfoAT%qZoz5&W~ zc+S^L1@2#rsIi=d#Q$!o8qHN{;i`4HpyAwEJX38&y1#G;{%D|O&2=fbDEY+=69zFq zKXiupTnx}Vn9;n21o9Cl@JZBH6VpphY=8Gk;xY6rH*wn<_P&{*J1oH0n=9ffF+?XU zwGeyTnr)Q}5-6oROC9c( zd-Lb88s^97<*E_2xRjO_tz=icvvVZ`vRr`i>QDbn-(%(Oee{?4+Bj1r#Q&!RmH$s= z#SV*Kp;Cv7lQJ7{_HnV;M{Q-J;y?a6h-Qh~D5fh80b!8ESq#HQB_q z-BJRvsAf{z=(_ww;(X|4rVz2#U7+s?pU6{ZrL5C#?h?1%^??=kWSg5bUo8|atNk?c>$;j)4Qf^#6!zZ!ep9!3M(2p) zvNOzuDjW8W5E|7pM$MP#ZJ1tnt zJlxh~;eiNP0=HL0RswY$1-eQ&)|)?tMW(7Ls||q7k8rkm<^+UBVGLO=4_%_n6U^5S ziwTX+l;*%H=hw33qMac`NjHOmgd&XeS^IebrfI=UOPcTG?L==<#k|`iVtLqpYoDqX zY=}6$w~wVVb5UlJ`1zLK(QeM5mk#k__ADFoa^uMC9 z7Fli(_r1<>Ar^2~Tg>A`Oc@{+yk?iQ7iB71_NXMBZ&lNh=BxDk=%3V%zY$q+Dj5>} z9e&+^Hey10>LK$`@UqOpR8Z!jMnht@f_QLgfTw=ZYO*+&oZjknj4)P0_Ws3JJ!ydR zsuRykkrgWL27&i&dCsYByB#(&R{+}}7p-+)Z;q)5w3_J#6+C98mIx7J73-`!JvP!C zpZnn$hW>H6Csk!EL)MJ5;OIYw*rm9YIWRJ5X0p{S&e;yKU+A}6Sd)`+{*qKXR%tJtX^5d0kS`((oVfd|06Vi58he6b+0q zKZYV9cN;C{u;3V+VcvNBQs3?*sqjwZnbdEKQ`k*bX0{!LrszD0M4)-hofF&zH#lTf zT4-ac#%cSf$Kj3@J3c9tVM#K&qD>;2L5)oYnh+HQT8Jd40pN~bM*Ih4!O3M7AzxOC z99~Ksw+!CS|MJ?`m|>RcRhAWYoEjnkf-I;BkEL6}=-&qQuG4hT;FzFEmJW9cIp&M{ zOBNd3I1HN$c(Bn~tov<58viSP8g8iJna%mm26Qr#4KMv^BKqJ?CxyHY8Uf2H%RiR9YKic^ zkBBX|LgYY)UVSXVoAMZ&`Qvf!bkIQIxI2;MI2Y|EEh}#LULdt(Wam{7inz*af2Mhi z$pr*XZ1-6S(sQIb5qTy=a(y*#m)qD#)+V*x`D)g*K3n52Te1KUYy2UZu@QN9Es373 z_CqS1Tvfn`mzc3;+BsERzBt@v+0CmSdN}IK)&2dLx)q5Fw=1$+u)?LAf79v{l!_e> zJ?FWavr4SIN?`h|0T5MWXu^-b%8#u+4Q1T#QW7djBU2$y3klRKqxd}hJ#Yrmydyj= z;4`KDf+E4=aAvlXkYh*o!&& zKprfR?S#SA3Z(lkuRe71{<%Kv^k4Lc-|<@a45%zp!Ru}M#lyEE4w=l9xJeBTn(ZOD zHq~$94ZZGqPEa428aZhm%~d;DZm|nU{d$DzVM}b;A;5O(MWBz&KJL%DAU(YI%dh4Y zNTpmbkuHYW?flWqnrl)3QO_%62p-CQR4Z~9EDQ9+yQ5dvR^oe6rP7l51> zDOZ#;s)T3zNYSREldkIF&dq$Q(B_R1<(4u?BzDjb=IiR9-R?KekKU4wXrHG!9W)|@ z2}D}zmmKrrN^+sY%l`X%)}7KmO-ZH__fT*v=wY^(2T2CW5S{KXLxKQ7T71L(RB{-AtypZZT=eVvsWlk%WhcvkJ zwbAmw;m@v2f$8M6vzuHs2c?CYC&zu~zNmx8Wx=kDzNMcl6$;Lt9IE}t*w9q{AcB0b z@Jrw2Z=$D^zuz_A&m=W?)g@GwI}y_Bcj{7F(0U%ZmnJsFr_}^yUWWRNuL-*>ZwcRR z3LZ9W6r%*6=F<2+;hT#YxYE5`kJFq%)Kj+<(l>~m0HPge$$)igxbyM(wcUar!lyWmcFSn_L$#fyikdJENmM7~=-MnNkbA z`j^H7_nUw9p=T&+VkqpFFmUAYaxaYo(*sGH$3Y;2*obxa)r1OB25rmi`AGadQ5*$H6k?XrR=h|(o1%%gyT8THQ3ABf;Nh;`U9I>iFiZbp z{s1}&R*$&cpQTo&2`48Ql}49g3KS~|o=WZk8&DkQ(4PklXZwfDsWI5Mu`z$4e)p7+ zty`%wzceWc*529b6xszoUAhIthKG~Q1E!J#PyU)7tkt+NKrWsbe@x5XRg%AzE|6E? z{BTezm-0!;&hspcRLZOaY`(dJsSox;?KpR;pwN^wZ!5|&eaCXR zw8#>ZG>Vbz$c1e-{*K7-kol(`Bvqvt6G{?DaW7HkPokn zt02bPk;v^H8DIEybi!1I>+7W^e6Is9{ot4O?>4fj;vE zADygRNkp7)hm_(O&A7WJr4J>%>#5BaHV2Oz&c}6#!!ReUYd-QHl40{_3mp+Zlngj- ztqdhRXy^6JmE7Q_-d%yBJ(!3!7_8vEc$&ack(JvpshiE0yk{OTFd?`|2TUB+G@(53 zTD40YaFp>>a;_$E4BTMf{#8!m?bRXq20u$q@I8-Dq?@XQk60Hieo&LmnAvVRruH=& zRY<$S9`w=TJf1r!bke5Y54vV@O%iL)<7-!C}9z0&t&A}=Cr56ijeL;5Z9=Z# zK(=oOm-C40LjuxkA%-*jxtep8qFTjy-6J$>ugV?St{;dwIr2<&_WL9Tz;neT?n`8NKMxrDq|=#k>c(-4J#fDj{9&LXpq}|=RKVh?tc~Ofy6T_5OesYWJ6_J zu$}GJ*B3<$uI9t5G#`?Ozj@_M|1$CS1AN$}Ar7;vRumTZWwKlWoO|sR`%wzx3htHI zK25wWH{qC$XtW)M>l>bE(7Gsv6UduFV^7c}m z<3`fF-+3tv`sLf+a7E(YF|fYxuKP<)&NDRA)t|_AsnXi$FsW%UXF^xvZ{6!08k71K zE!#iq0j#1_%U{RwP^6%v1)OhG;w;}NPz&pWmGw!5i5`bh{^uis%YKhd)S^EC`@cA5 zw=SK3TiBca=-3&Vt_C773p`bM&52XDk*koy`)w4(LQY_|!zpr^zon)L3rlId8lUax zXD#0pIz56}QA%YeH0f@W<3=`?qBN@LExwK~0w#aNlxW*iD2)g#yqb5C*UzGKKQfHYKUH&>M4SagZ8o)^C{YvK$zxaLyweM(Ku`o!{(&LzsOjXhyzqX|u~+0#W?g?@>Zk>Ys)z1sqSBrq{2aB<)xDT6oCn z4M+ecfy(g798KxVUz!kk2~>9)d`{V+<@U_Ba$~O_Nf9*O!0wmFkN=B`=@TTY%<@hXnx-jXW1Ws?)-IPh@OqE_EIyI}ht5DoedMB^BOZ#^a4CWZu*7p%Bz zoo2fW@djS+w_kxsTSm_V6UTb$0G@#JB4(vk4ntyXL{^#KhP+ z!G0ARV$s?i(XSzLWS3z36MH5V_X9UwDb%McW8`c_>2GDzvxL|4DIB>U{QP(V>43O7 zGJbZhnPE$fe+49{%JxRx2#ff-(8{bmYa9LY zL3lZ1^Ik}_A>I6YZPNo|p~< z@J3?eijUKE*l4AFk`==w#QlZm#~al?9YRcRd(34BlE41FOK_C}6P>mSl@3PdK^Irf zzc~hIZu?kvoO0YSOO8Be=W9~n{;mFtj$?<)FW$;fsdn*?O5Mm*d8qc=-0%CgFM^3Q@#+7Tw4G!)zj z!BD0`o<{vXqC}9!BcKxRisv~k^)4AV`9&kybzGletF06DJh`Xd^8FXYA4c(m($%6? zia_XCM2U4mVuJXGAvfL@mVeJ)qOckGK7g=9a27(E5@ev?N~~EBlIxrNy>Cv*ryRqy zj6ssuEOVx<2f{9-@?M~%cop>~db}Ufm=94OJ+v@u050tjUmuIaTRVUF&K52M={=Gf}&YR?~F5WFrRX1^Wh5*8*2;$Bv5l(@QV@SaEZQr}! zrh{mKpp1`C*a+9eC`I|LF|vUJH4AyGLZ|sO11aI`@WLufOG$Hsv61W&MMR-C)xOmQ zv-!j}Tp2Vq_u*n1SqqLvM(>3uxaENT`=UlUp{DP78!tX2ewLNpYAQU2J)O#C;v1qy zVf8lH4pTV$yDeEhL-k;e@s=(c&||PWE~KtIHP;f}hGtb(&b=pxeIbmicJQEdVx?p=4X zTYe7mhGqgpD4+toz-7o}o?8~+KjxzWsJK)MjpDD%&n55v#1Hn{bMRg`IG1{*osk@U zF6W86;>KX9b;?YM3|s88%jMXt1uap%iSA{>|s!1j6xVNs&nH|BR@ z9(-p3GpFrpU?)wpe_)9IMwu21oqm=3LNljZN!UF(vS4nG@9J*bNpCpldWw%o`Q| z`=JDdW)0&O_mb}V_R8gOR5b%98Vz|4q!*e{WKjZ8$bkc|`MuX#2Bnm59?(vISEby` z=1XKRWjoV9f^nL>@L%D-)hjvxNi@UBxC9Ce*Cl!B8{yMGdJC z{6ojhzKxca8E4^VFwOUo7XQ3=Ah?8yXL50!O7s*h%8Z8&p?r^)t^D*hTa%A1AX;|I zY=uoafa6+wPiecoIimYaA7_G`B&dk=hMHm?hQS>F_;mEoIA-XS7VQjgmY`J_RX{Zq zQ^44wJZJ^3<30Pvft3Go+;KvG#>K%&qV7=>tQegq-E@Sf9w3PBlL*JTs`d()zrhv_ zLG(lUnZV)rhQL8{jo=|XBzL60c9LYc_8S+!V7@|%I(nZb(_14~{r7vHteB822&CPh zRq(LaJS#Z&tHa$RtKHZPJiq23C$F49_77(e&0L0CSF_|=t!6g+FCQx!mlSQfMtm(D z-osq00T!v`-(6ZS8%qd&zAvl`?u}^i8=U2xV|mZ&&o+^agSS@g(#GbbR`opwOr9g= zefE#f3^rk+tYi$kM=3kA7yUq7M}G`=R~lst!g}Na$AV?N+`cD=plAULe#Na!gK7 zE=xoHsVbUZma+1i*Iu)V|9TNk4r^pmSzKE2_g+S$V-cc(4;d>%-Mn3I7qD4UJz42R zoO%Hy3p8#-EVp$=$2IAu3!CzM1jBN#_UFnbN4-ud_#0Qq6@rRHBF8_qBLTk-CA@s( zo?>T+3q3;8WMve6iX8QhwnKlKkGXPEM^HMB+qF}m3xr_ zv3(?BjZ|d-8I0ci;8q7r=v&~C#dzAf#wR1~ZeG2tFV=K8)+Pe{Gp@PFOvv{4ZQGXE zmd{&Z-j=?<9(0~!;kKf;AR`uc_Z(yTfNG8Od&ZeA(2yqOG@F%+0zgqXHtv;q6~+&7 zWOgfnl7}le?xJ}+IB$9FFS3t~&o7I0YVx>Y+w}1fVT;fh_3mtjJLn~GC`@TSpG96Q z!yhuvY>c7WL8-9U2GRQ%X-IPn>2mY;pLlf5ZAJu_Lx&%b?7Ks(J)9%-eyH`)r;Lq# z+Jl!1!2_YlBHoOGmW*L3#QHiR-am7erZCuGYn1p|=7zd8$n}1=ke>Q3>RyuF_sbeS zQ0`&f98QEOqTQcNr);=&GW%+^AF!Z41>hsTl`;rU%uV4#%?r1xcSR;hI!?3Fp?eaZFAHxPmu8!xZS(%dX0sbI@gLKMY zZFhHaNchUTb33gGQyq=Z$Rw>@A=P(5H$Il4Tzw{=*$%A?JC1MkrRgn zM0Rj)Ns%ywjNS+RyUl~DubZZ63^t4Jb_emctp-u@gtVssN!Z1uo1lIw?=cGW9u)~| zTy9r}kHK;fe_ZFMgEf8uvV?X|$Z8?c^NBwLtn=c{+isj;sv?dY$n#+HiH+m72dG3C zbCSisqF%_eaCi?L!C+;h@b1-_0CAZA&&;%xOb1QP0kF{*ixpF{4a5zN@KtmM#zr;ZO-A>XD@9c}O3G~Z3*J)cAaGx0Q&?R4uPQy`yfTpb8tea#jJ z_FeBMmNpC_Zi)Ums~<(F1-NzWh13D^t1<4MgdzTAim9klye=~( zT)`Jx$akbD>oz*!E*$_y_IDZri@K+lc*_Zqa7dYg7R$)IY2r2f0u$%rvEo1p)D#t;U0@Y?NUR#66rb9DE?ajm0J1k-d^6spD+FNqP?C1f! z%G6dmAaY|I43ygZB1?f+B)~9qkf$^v#hzq{C_Di8eJ;HH=du!A=pCyluW4X*7D2eH z+eS&EtHSfLm&@RWplJo@Fh5QvIT{cTh>7WFu(Y)D2-w@zYklZmV73K)8Hklu$qn<` z7eRB{;=K*m?pOfFfdlO+P;ci50r_y@N`+ss9ix)xO%I?dlAt!L#T~y938&9k1Ajy1 zlmlED34!!S4;)LRhw60XL9#1Guv?^M7_c)$JmQLPB$1A~{gu3#{ZnqXj-9gAsFaOo z_@KKlXB`4R3$NBjr0$wH2f?dNtaoI0St#^)EH1_e~ zq#YVp!ND?+)iP2c?Ty&3XJXu=2xwYk0ON&21^Ed7Wl^vI_8EV##%X|Vph4Nn?<-lE z;A--FbuxymRhqRdZ`RkJFGO3O_2}3-Jy_Ax5^yUsBaROQ`4$a(Cqt=QGv-D*6G{nb?Z2G@GoM9Rbp)1DH)@YFr+ifJnJq`BfRg9TDS?^e@Mm z@-19P{2oggvPmMAZKE!IQhq4Dglg)RD~xGmFnEl>`jq3y-nfp3zP!z$r4?8->gfMI zC*o!PP^*lwQgKUOn1jeZGu=m4GtNp}c4`%x>97~OJEY7$#!yAe6&9LKEbOx2hc$20 zlY{O>oF7En(Z>praer$<5mfA|8mXNU;Wnv{i=N8w*sW6Hs;S_2Nvk}x+Yuy!U84|E zkY-mbyaFZYm9 z(0$GTyLJI*NLAFWL?CF1ws^6BxSmr96`-39FaVQGj_-V=;j4{Kv!SbSo?&Y}Vl( zAm-~N0=!QGm8yf57MVhPn6yEYZy`&Ymhq)_7%b~5Cu$*qsl>ny+Y9e$$v^;%z(L zKd|gG`HN@bA;u_?Mc?$2*DOEOY&F<&ONBpx$Yy9-XY)P#qrUw{1NcZr**%EQI19h<%_JCD*a?Y{HzasM- z6JoS)){1(g>jC|7hDu!lrx9FS52I(%e@fQ4me?ukxZ0nDU<@ip zl7a=&m91d@sF{&tK~VG;x` zG&U-C^>(+rF$Nu2wku1qdRN!mN`&~ zPi4wd<1NV4R8!Z{7Ee~e&&kniO5;l~`#jVs=+F8~ms4qqhr+=|n+u6ZD^Vtbm6Xx1!n34TFT2jit$G5o`N@4hSu^BX zH<*;H6Vf9U&?y>DyI)1nczPFJnr@Vm%zsSvT?Pu6m=8RT3VNy%-vahj8C2G&XpP`? zhdaB0qEvA*N`WWIv9gILn)ddA;n<{7APFc`$I8P>OXkQ1Bt=iC#9F94mqy64ZQSm; zy8I89VZUdz{Ru65KP`cC7eP?6RY83846}&q2mg%7U)D0@7$a5}OhF)0P85L^#^-x1 zUh3~SvFb|>tjWvEYgMMEp9xqcQ4}nAtitlP#2J?__A)qF){8E16SSgf3RT01UgXc*i&pS}nUSspSnNjMg;XcDT?zLG)A^gg06T!4b?CKu2t_tN+au zL^$h}oY4}bQaFXpA)MHWat8(8VCdni*%rO@f?U3p`$y-8Ny!Ho=L|fK#?ELk z?Ql^@^m-N6eFZ)eyv_A763En2!j#FQ7XR)d{j@R&S=eeWh$dc6f>(pS`@l}_NL#}% z>Vcr`AQ5AN{-ang8g7~Z7=>=5PJ%L0{4$$MNEB z?R4I0+UXW1#Htt3%g-ql@g!Qv8d5;$!&T4TJs_{94}1vUUj;ryAN6m06^}$~N>+XO z$k5I`ADiH>!&JcCcbYh-zz{`3hfo5rwUhUPP6vz1082%BHzp@vx~m0IxlvpbTuGDP z>Td2n5&9WSMOl5Eg~c+hBmi;GcH3@xO72&c(K@7fhB}AlkyShd1f-S#1W4#E$odMw z_z_ae&7z%;w@P}`I8vYhMTm27Bkm_e2b8^P}jcOM?*H%Yg;^w zKRW#^ro1rRV1oTS)+_%Z?dzoVMR%uaGrV^Lj}Tx{X5WV5#p^78*3N$}wGoOr1iO)R z@6r4yJcQf>D+3h)qm!8R&Rh{Ou8x<*5lfR*>6p*%N8`2&Hk1fj6uRCIg@Qr$0R!9^ zZgdakxL)(yh)*n6IMF$4#{D&a{CoODNHs3Q&Xfqne@;raHzcMELiFw()<5hNW`i}a zu{*&X#_LVlV*B)M94x{fWsvu7^i!|q#enuA6UsN69Vxc@Ve0CzO_X5ouHSv=eT>-a zE-VDk&__+C_2)#VVz=#<2Dwm$K+|aLb~Rd=IqpJkohve&K9!(7%`9Um#=G;Y3k4}N z^Ig7w2E+xbL44&&8m}fX#;IV}p?r&fsPD>3PspYf{nqX_qp>mlrYD!{k`$_n6~QRV z%TkJ|m_wQ*Hyc;t-tBBI2l3>y7{BL$%Q&g3E>?eE*$rb0VQ_L-x?xw~QQ`#+QjA@6 z1)~rKg}Q$uBo)0dS;*K=({`gVXf!IMaYkMkF5-&i{G8PADNG~;v3iTX&(-Zf*sGih zubFn<~H(d2(TF^m{bOo;i+kHLK21b!J4 zM;)v1`)@sqzL2By?{#2(4a0&z6YeJ@D=faYHX(EQQAnQ}7IlgaG<~ETbOT58RadEL z!FoRn354zB`;al-Plx$?$q0iJ_zHvd!_@=HMPmbqi=GK1yMna%CLSlj3iI;%-aJAM zOM?|u0wAvoFaiOFY9-7jc^4WhJ!4~xOai|8IDIwBHAKxdDH|l!zkG&5}f9Be?2iXomzTz`SO726GwDf&G7!*$E38xrHwzdcswm$kZ_x*z6SLb#PO zz&Y+^mKiB0*+Nm6WeGZ|pbo0!C3Vayi~IuY|9t$Ty}DZJ%6i1)n!)B2-MuIf#UNdJ zy_9{W4>j{Wwl(d69A8La>c<)&!@;+YmFE`<+BI0x*Q>bb(ct?U6HmE5O_@9E;QRC3 z!@skpFEvytNo`0#p4Jn`+cvZW(J08H?{gAM(v3y1JAZ}Gcb+DngW4p!p^ehrybM{} z+5{Ft?Q!?S2Wy!>y_ZfMyl1`;q@{dynErrK<=T-lCRvsb#C2%?Yl#3?+}{S3oA}HDGA-NH2S29jmv5HiAT4|Px zc(2j+lA_M}E`YZuiS)i=I6;CER%Cc-jfr zeL%*aKU<@K^5=Kc}xMPFpyDyzeC{C z!us}&TyTN(W&wwfw3A%hvv|^8WwhmLAZk};NlT7$YjM&nrh;o2%-j@mKVbhsda~Cq zpB^yH=4fAo$l@sdFUBvI(?P1k{7Ex}6kNiu zWxOY?SsfQ7gn-eE%%}*}nj7a2uFmAkVw&m+vE&qj1;q_tBs{ORVbZhGG8Oa`vlKF5 z4AL|P*mR(EM3UYH$86`iuWV^hQ@z3sp6b9>_v2T2}FF9<3T(oZBmjEm;* zq8!&!zwc5YPm#0uV@_gOz#I~FnV(q2H1qt01v2woat~)bE9R4**kh0D$&vA)b zTLFux%v6*%MWE6byJV+@gA2its|^mzaB^e}I|_L}R-DpCHrdNX=ds1{4=NuFCWd|Rpgt(=C3?vZ?x z8mj(3aQPqo+x8J-9VoEiDQNY*Y) zI2UIA6)HwTKtjJeY7gPKJ-Q;if%HovbSo!xM2T3ud8$((hf;3@ugV#v(APnqDL(+e zowvW=P*tsM9q)ah+xmM#sknA!JljZ|HJ8d&!`JVlPUB|~QXuYmmPR(pTmt5a< z>wvAVdY>`Lp1k#9LJc{sXZ96LRB&<}#RRRw41Y9>PGDu=-N4Yt^|!@5$xso#NibF% zR@dG8ctOXGHR6LC51oTqqx}U^k?Ft3&ZQp(34Zu}X4&Qiya~Bo1g;$AiD%9keTf9Mrri*522)`4>t^DlMoShE%;?L8UOjSq*D++U098hb>zo!Y&O3cmcpR)ovBwiuc5!@_8WX@E#1oASc#-ltE?v7D=$!4IYDqv_PfH$j^RyX! zouv9~nLX6K!Hw-qGedNESXgJz*lU`HcdACRiMUre%ZfK?on1Y?<32>(B2x1HnxIXI zD;G7Hu9E4FF>yD6Xpt#ud`3qd9*)^4=_HXPDhRc!dTPu`e8$5y1>K_Tc@)-)S<{Lc zm=|pCOSBq*VwVTo^z6aKccSY3j#|K56uW5|8B#3>Zd3Q{tCbT;K@>f9njgF9dlWCC zu(m*_WnB9UnzkYB-(K-RW!OL{hHG{uqpS1g+L*y?+Ig1 zgSW~{%2?P71G9vz9ZnQcP%?Bl2!A6V{hke9IoDGcWV1$3ASqPEkVFW$8FKp>K~1U;2nlq35r5p0&Om30={8mHZda(dG-SQ>RhKrK9Arv zXy-jwRH_j!Vf>5x?ER@rG8dVJ$Q2!!6;0Cn4C;)>TaCew{_D&g7h~L7%y}inHaA$p zz|d-|#H*yHwY~tQ8I4T$Z*4{t4qAq=2Ysk(&U}K`r+7PdU>I8hsL2Gyyw~00TGm;^ zM*a}(7VY&V1>O}Qz5I^Gc${wzdK>P*yU4OAsFTr1{$YAqI10O0HoVJiL-TBLQ}XyM zE<&YGVDHTfT~@pfA;ltzbq1VvGTeN<%6sWqoGmaaL+rq}g6-WCZ6F|;o>V&*GblLc zvHFeuNpxT6*c5OW!Wz{3+8usU4 zd8uJ!g~xR^SX{U}pp1CoLH_fjf#z2fa-_796O-CjtQ6g5<5vr3Q)0#1^>r8=EAr*V z0pbqf+;=Neo$%ee++IQG92XnL>wm=QnFT$+Hu-*t`>_zs9nU~Zz*5BcD-wH*yR**N zv=<6%O}nE!xpVsKG{1>@KgGJlA=@KaYRZxJxm2^40C^TFj@-}wdyxL_??H`?*FnF> z-h3CVzv%g|z>c@1I|b_gb|P`i z1L0i@ymc=0P5S7b@IzO+Iy=Aj&Q?rPbf1gi=>{tvnJH9kl4<$@wqNJ$03zZ876obG zX^lX-@GVyRa=mZ(<(77rSv%cucRS~6XgnN z!QiKd-pZ8H#Xsf}rUDthm_#r`^|%c_;?(cdakxHebrAq@M+xR`RQ5ye!t3Hz^gOex z)Rpu^oOQGo6AK2(^;onsWA^BpD<*Dp!m#L-UUc&zB#_j>#NB4;fr-(KrW6+#-TWPB z98$FLT9`pwMG@^$R&GV$NI9^H&kdyvE^snPl>X-vnDC7%a64dNwW0H{V5?g}Lh<qJ445nU3bk#3z z5%g;|nkb-p>p2^PeCMY_kO_U;N+|$jHtW=3?uh;)ts7PPk28Gk&NZ9;$>nd9fBB0} zEY3tn(rWF?uSUobG8icb8!R0ke#ST$@G@*S`p6E8krp5Kp$}DMe|jmMXq8fo|9p9P zP{D7XelX1~S(%3UIwcao#temp?iBUrYm>RKerbyC!)ZV)2b3GczJD%M^G5}vS+oO1 zfBAg73-sYZTX^xH-QMujpg%0=iOkmZ@|D`9Yrd}Dn$$U%kKLP-(VMO_JGSuSL2oWB z%(T7<(--RC)ljY#9Q#yIFgBv|)aE_D#FIxpwURX6Q&e0M`mn-7H7jK=<>)e%MoWa; zs_nX=&bz0zAM`5d3?0H{2yC*?&;Aq&+`wvWY^n>TTMGpW;Q^j~8K;cdWOU?a{`1XG zl#unDoC_8~-kvRM;@X1wF94%{7idn2Jvy5t^)^+{G7tfzmR{zRvMqAp1xF_G#YZ$G zyjMLH+oOZqxM5LO^#?mR{C~9BV;%BNbLFlsl)k5|rvakK@Na98)Ed>*xe?S2|qYerdPcuH77#PX|;*xooite`sY5QtL+!65E3@ zGUSY~bKvAXdgXy#hzR4IyM5O8uMIPyF~kOp1k$aAy)Hz*h;^qUc(rf4Fn*_VIIH{{ zo=7_73iYpQx;u0As!`tXE%HAJB1Yfj(<0a6{~nx->^f6H1}WsDIUDLv3lZHT?a?Rp z&$^G;=`$JcOy2?v2vkPH=j)o4E<7|ck0XSXio96G)e-ub$ee2{ebk8=1&65qS^&>c za8+LC04=sdIluDzK7FBMhg>RC%$GXdOzBR-U2D6J4)yJ1rgiuyGZfjcTk=kYtu(~q zi;bXCNk)0O?L)w?Zx44zNnr=Q9F`AJX1Nu%GSZBlIpww-#FZ|DGnO5_$y@)8>{}w* z?PE2mYb92(IRpPC8(^l6_XfgE048_m|+W*S-kvC~J*I@`ieg0;8n@eU7#8{!61eWBi$M@S9ztTA5%z{X^pt7-XJWU$xIxGVzF)D-3y zOdPmW9W#3_(%DLdD}O>Ccaks>)w8UoZtKx zkG@RiHeqaHhJCV_J4Z7rzA#ce9z(n6cS@rCa;yPCA!4=rd{buk$>zJa0)37nZR|H} z#!J#pd3oP}?~ue1d?6X$`OUZd{lti&j(&I2Orb+t} z!{GnY=0D_lQ!Gw5{vjOG~ zuia1BjT=*hl~j+3H5AB)Kc^yJ1b-~}@L!btocC6-=DL&aiSen9lfO?Im^Rau827Vm zNlGX5>7(B=5Pv^|yQGQ@KrmC_k#lUsdN%+iFOl-^V}DHyM#d*TIo|T0@&B5viI!8< z_>~~ee^1?Ci{+C3>mABJ2Xac${P7R@Z=k?jwRl?sMBcF3LL($_vH5(I3VV^IbH>OVVWVS)s-uOstB>}(BB{<z?;xOhDSw+{>JH_bi*ed18tb}qL z@W?b18)(qY-y_qTUfaLnR9eMQ)_r@4hVwq@|6We$lCIe4t1+l&nE6+j$a-?!cy&Pq zb@jF}L6CwcKpjUPb|v`%Tr#TQ<&ZwLZ%BC2cW=#d*22feK;7L}U>R@o{XUJY;QV{rnQt+q z(mMz9P9M_416YS$wrHY(U1G~*AktG@euKk)K9NW(+z_DUk6uh zew$)#I-7i{J!?ZdsBh{XrLP01rErW-Q@{9X0^IfH{DfX&*1OSH9ODGdmSR}Pk)k0i z0=4Gx73xVEFrJ9YTY|2L@;oWqZk98rCuGdGhhntw)TT_+zd7<;Wnd2s%x@g^u>bcx z5Ni;y6p3_qSB+X^I?@g{%+LVjd{TPp!HuzJ{Lt-^tnWa0?GI4triV-xtIZ}t&5Aq` z?cVMeXJ9-jGPGp?VNCT3|Fj+elblMcSkYfC38|0s0~@6bm)U1Fz#;QGH*QQ%`^mD~ zukGe8Mju&ijvjYY!u5W3OxYsA)Su14EUjiVk#%cYsn9KwRF|K$B5$|h<0e0pAzK&f zcD*AAbgXXZF-J|Q-kASGC+~Q ze)!iWzzjx}V;JkF!{RNc8d94pDFE1MVsW?~tW$dmx|mO+#B#^f6*%SLtjA%s<#@A+ zV-urC?5(X#yZeek$YjxuWwXJ{q`^aSv%P+^`+(<$&gh z@#r@J^x-Jt7)!=*zn73vY^vTx#_os4P;Uy+CT2rwNUv(!ILW{zO6qtwQu`MFaKW1om*ojuD1#0RVA?((|>WpDK10c(ayVT^Am)%3-6wk zvKPq>5s_oEpVb&LDZntZ{upCjlT@|w^Ich{Vsd8ISY+PU<4hk}dY6s&Z=sWq?3XkM8gtp+1s1XQ%g_v}8&q z|0cl3X7Zv;6`>_l7Iz>Gg{}H9*wG4;DZV}li!#_PbVRILHC4wonhc#T=@|S<(sBtA z>P`A@gVy1LLxI<>#9;rMcMV8n?D!%iutKTMQ|{wca1$m~zaeqAZm@*epkyY(cp=9Y zUG5h_^Lm{f9i|qVsGt0z%4B!D!M7a1Kvz{BzV5T0=qPteJrQCtAYdd<9+?cIW-#$BN1pcdzLh3 zwVoUm9`m_7PDJ(;=w8^_Zu_(W>*9k6ws8I-tw7x%fc&e{m_V@rILE6KR-=^+Z;B6Ec>^u$V>18cLw*XKOK;CL7H`hqN%>S{kG z6YblQa=Dx-GrfF#H5vZR0UGv9`oJ04a$M{Ug!q$;2%wF2Wq|ND!`|#YUC75y(lh%w z!tu}V&fb4A2x)C)x%Mkq32P%|LAh7fnac{1D{00GT(80X!&Ph%v0!Mcc5Dvr>1|lZ z{>F+AG2M$Wim?jVn&}cT9TRj}{wz9OsWtdvxb8k{b$NkJ`#icvx`wx;wnvq6Wa$wg z;Bv}+2GHil4851-QbjI75>A7Srg5pmn8j%6VG;YY+^E~auu;llqn62%hO3*KvzE^b zO)=XdpwQ@A?3E?@aB}th-JsYe+osH0x96D_BA9|O%%FtP#EjED=#SFo0aeNzvXmMt z+aE|thaG%)Js_20*S0r`p0q?&a%FmS<`UlAk(iiX9+Y6N0>DvkeiPX2XHJq+Rno7>sosuVNQfSL;8ZP~ZN8KIz7oiydmIBTH4K`-KKd7$mR zym@ueS1N+ZQMaEU$ehsj#r9-)9H2zp*HW0^IS<;e)rC_{kJY#QR4ZNw5Dh zhm>^b#(ZHNvaGGp0Jyr*T{&rTHT1BKN0|AYFwJUr19LboeGsff{5Ea(g2ZvMa=k(dO=cZfAcOwc8l(L9 z5Vxym_E>U#m>Q74!8i$;{QBT|JS%_(bZ+bh(@q`0hwGwutPUi1*f+;pENPA2e|FyT zDoeeEG;HWy^~)M?x-H_O_0cLQEm)N*g@Cn4Jpl&Lag2FiNgAt5pN0>#SQR>Ijl1l< z2sXjV+oBW3YBl)I%516op7$vDu;H!DUcKC7APl{L^Irr!NZlDWxs0w43&5AK5%M4AuivzzZ}&8=S+*lK8#CwWTdt7{pI(0Ec*yNPF+)J$ zAWcF2wvYe##I=$ZO;b%0&lI0xH8885IQfb-k5#-9N#TOJM7Z5ii7%$&RzmVd^$LM* zW*mKV&OB|dN^hLJDYGa?ir#qm##K9iFDp6M*sL zX+eO@*uA+9}y8fGA`B18W~DGdr6;jyDr@7vn{*mmm} zS7ZZ0Kmdbfw%!#z64ZxT15k93TA-N|fU(~&|rEa&|jW=>18mSzX zJngrWT=vE3-A0kq)~u@0Sx1ksMTY(Fuxy4C!&-^AN z6K8NO0rquhVFKCC8_>C66 zwf^jTH34W*p$`}XdBUQlEk4;#?pLW_^~u9xq^bv%RuIyQk7=uO&jV(y!G{lPW0YiB z=BdodCB_@jGk{E1PlQ0zhh%$?RT7E!-8!l68)DUBR!LN9X$$_+PGXG*7}~2OtB*({ zZ1<~DpBcRx^pavn1;U{c(8HNsg}H4(j{vlSr*yKQ1_;cf{n{PKW^vCg{nviW!_A9cT+QoX(H+LpLbCpGjWDh~ZE%1OQ}8h96}P(BNASt-dYuVp6=yNUhu*^3U; z7Blv=Q|lH*&!hW~Dt)L0K{&ZA$wz?-zWwjCygo>YEr#8* z8ZC*>zhkP2@@8$rp-6YX;n2Lyq#jpcx{Q~>g#}`EXmbAG(V;|SY|DPH{#JH~VVP}- z!SaFRYxkc6(jz|eS#i>u%>Y?R>e|9YR@1iL<(JvFi#EJBHd46l2e*Yl1rf}BFKfD@ zofWopw2M7D?&-b#N^<@i_OV*_XhOhlv?uXiQx7SQCa75VAW(^!oM#tc=bY9z-K3x2 z{8Sw(#_Z65_VEOG2?0XPE>uBlK{wMqrpnEE?N*AM!nt@>9I*hP$$Yr!Sjx=%oK*Sl z0}X{jAh0FhNYkEE4No5t)_!C5URwO z`Bro3dk&CD8h40ywPHF(4$By_)3G%+v%~ECIvL1Xg*~Bh(x{J+Ds?`4wO?_&4Sf)9 z>G3X(7;0GNGK2OBw#?wyDnP8-myMBR{f;v%a~~%>W_Fa&`JO|?$@`pOoaq%J^khz! zL81Li-4}@_IFVN&a}{QVUg6*Dpo61kedGs%Hy&qa44-@5RN6c6U6CcmG8@pSlE_!e z*3j)to8&pz-^|7|L_NBneb3Jcm2A#Z`PFy7e0jzYFjJ`HfnN^fXs(x}@{? zz0_Us_YugG#5W4|$=y_D<7hBJjN98kwixRYnkpTL53)k$df7!k);{p?Y z?wqp#2Oe$iu>X6d*IVm0+$uBK( zv}!kG!u^kZ!-^q(1K#oh1X?-W+vi9Bs&K(G4#sDW)6x(q_rHh2+{ZFSP`P= zsGIuF+igf1f^ct4GmNg#omxQA9QA4nryb(z?gO{0>DO1DR$l)37+iQ%y3>-=wSS#6ezb0N(G~N&xhzQX zI5hD|UpLR5w!y(636Kh_~ou2uct(-!djQPTo$>Vf%x>fL|cWzPRq1s+TI|GyX~ zE>HlVlRPE+b2Id=KZe@WmAq;ES%7oyrHj#>DQVN4J5#=Ym*GD@JEVIZdYQiVK=bx6 zIg$7U3e%dnltgsi1HVswuKbg)eyDBSL@E3r z8hfU!Ue;7#V|p2MKAtgTbeH+;Wn~M;vpP~daSs@!|wnb1^PBYUQ*b~JN#wrxMG4GrATs~WAUO`_aHqN9lX z7>{iKwOHg&3w3!r_xJVjcT~~E=CX0*4FqRKi=4$p1{$=sqt#kr%Ye-3Xr69%D&ep# zXQ1ngz}dCxoQ><}&-(mb#=n=zg)MtZ5EPr{S>7*-rO{+<&vJgd@W5tfX5-uavV<{^ zM$gy}RO=1>nwqo1AYC_T9m^14SrzL@x!Xv4~{v(I@%}PazWA+nP z$K$TPcX%aQCLp2rrfFIHuZ?C^UTM<+-LXe+z@f7rK>;0rMQ`|L>&gEFdO=&tK#OBp zHduBYID`irav>4|QL?ui?tct?XA<`fNe88o>8)6*Uu=| zVjo^3`d3fuw~hF2W=R^5Hp6+v6#h0TeRLvomcm=OV&A1d0*9~~orB{kU*#x=da%!>w)xYNItDM;Oancn*#2(AaS^iU$dz6pVBotO0c zZg8roZ(%VY?ese^G+-VB#P}x1v(40#9h3p7ZJ@)p^>OQ7`+TcS)s`Qg?HS6T4kZ;) zFH1jGW<&H-t;`Ok7%XcFjGFzYtCh1+5NhHV8aCnH7ACy4o^Mo9Gj}$_XB!jz7c8ZO`qKdpzu+v>B8;my3!3 zFFye3gkUlx%@dnW+BgB-ak4FJ#qpf4;jPIl?3|}7vIw%27O<4&G^lZh_|r@BFn<<0 zS)ptGcRpvmxf7oACV@rSpT*S0V0PA1=9sG4_mTIxd&=#(!+wbH!+?O}qxJ*b10Ppy z?U&le4I7PvVpZPfxHT4Nmm243rR}jo+wG+uf!R=s#l@JI#JF45{9wp8qMHmWgBh1y z&O5^>e#6G8jCghFx+M{Zna%N%*#(y!X-Y|T8AAKIt**xV1Joqr=QZ@|VKA^6!}}(3 zHn1i$^m!iluw3UNyGRZypZY5K$v{(>l;{KhkG?fC>qpxnbgv-Y8N#J~i2;&x?pvs$ zNvG+S;YG@T@`~kdZ#bdyAZaP%IIHch>*1Hk-W^sj3+34N+3taigJAtSn|NNW>Tu6P zC?AH=*==p1pObSp86H70T)xdgPG}XfW4S+w{DJEKeAnAE_mnyAkP-w&TuqW?!u3&j z2@5EyRw%hXA$(VNOE7`DDY1oV`Sf_y(Va}zgM^SFHFH;%^R8ef?VYi*Cpv0d*wNe9 z|88G}N^n&9e-s^RzVA}s@L`<`c!W2RCElXi^(y8`0=^W&9Td((rC9RgJ$Po_BD}N~ z&>P5`c%pXtHQ-2c^}gMhkU^x!T&-`ziwB0c3iV416`pB@hHp}TS*SNgBzuZ!Hoyw8`?qu|d7Z4uC5AeARuC1_aafU}5ygxtoT_KbfZhKj% zx7u~w8L(RLDJqwmSF~QB`DAh+rKv+cVCkGK(6T~f@s-F;370Js1O>t}Duq5(M{+QO0fl|C6`#DtZZBD$IQ$VI96sm)n? zp)}*xRRR)P*NRm>fQ`KMj$Rb)ywg}Qs+uAR|5-FUWIm9=3lkeYIH2a+upuH_S^Ua- z$2~po5rfraeY`%@G=L|-v88Fi*(WEzFOK&eo|)pJ0|_Dcl5VZwggZabz#WDY;E`BV z_c|hxan>LCs%{`v=EHQg_ZzHQvN*!fhfMlV$6siNz)F9yt9Z8cqa6RLx_{B<;FjLdGVd(GMnJl=erq)#0_NO$B_0GN7$uw?oq2Ro5eHa6rSoVhFx{B~$la)r;6?_tQCF;vqSRo41fV z9WG?vgg$v{d*|;!E6xX){8lITdExc}90{lKO^g11+9D-LW0SbkyWLqxQt2ZNDzfj$ zg4ODshilPHP4gRLwkd1^<||i68=|6kkabKV3X8)5g5Ogf6@U8 z{dKc+v+0XihOf7Nqv(f2M*)!&+w*$G=~#}HgA?)d9shbROXDM?N|-VE?d9@2PdM-| zWbRxrKoU>6aj%ZLD$beRItb6IY_VmY2gq}#aM6>!@+>mb}Irp>i{oD z%k`pz8d|AXO-U2qfno&mNAZM!(<_BbC=3S z0>)n!R}}r302b3xDq`4OMP;40ws$A1|t+ z4TL=m^+*U4;<+4IwZDJpq+eXKsFM^`2=Jic(cCDBa{b4+=P~zVweEtAJNWcVzMt>5 zQ#rJE9S=OqK(rx#Osta7Hq$xkbbv$Q$CjA}!b)WcV5uf!KT^Ea;k?L=1;QGW@6>|} zSSUO=7@3;d;~^)69WO@m>9k*s@*C8P7;c5~H$2MzwcS(FG%#Opi4a6KDajmP#0qYA zg#FlFiz6vH}1PTiAz_N6pLfh%CE)DG=gQ={y_d1bM)i;|n zpw2B-_6sYu(A5*4-PHqM;Y8XSeS7fzWOczsEVDjh?APXPw49O8;mOjILgQA~!=6+} zhw2CJo#7AADZ`6?2wl|nlye8r^^&-{SbL{2q6f*cm;Y|eE9J74qku9#-;$XR!bb$R zpd|6~_=GeTy1q0pMp~XNwFNQHj#-oNy`)l03L#4uUdZx1zS={EGm?0%?9d_=i91Yg zK}!`PZtl%tebOfD1Q+jK@Od#^ep`he)gPVjV!Z|>uH{?e2TVENZfHCW??7^K9CLH{ z%Vy7i@gPk}y*yazu^s0uLFQRcpRDp>bQiFPuz{;Rg!2B;o^yC~XI@79Qg^Mt>~5QW zvuTs(TAYdnq*S}5P%6~R@Yi0sMgNcIh4n!NeBNdTyE|_pxVc|f=A{ZBlWO(5pvCRn z(dBRYtdUzXZwvGr-&CbydcCys4dd~xl_4u;^U_W$w%Sb=-ma*CnA%^ksziRHovx@% z3V~bqt;fg5wvhhJ?4XdeXN*5y6r(K~>$?pn7_`5uD2Q5*Fd%bYa!FX6bnlfIVQFVb zsr~WUrmf1u1r#Ygrv6p2__W_LoR$pTqqQ={(lHbzq;`k! zvI*!H1MdR~iQa6yIlt=;$H6gP?8Qd-n$Wz%BDek8BhJ4W_x zTcEDP&^+zzXj7(ej031Kus?_p`;bH+uT-yQ{TB_NjyW=mKMhrlj(6w`kFsFtvO?e- zD;`BNW|k{o3%@5&_Q1A!n#?{Z`~hD|AVxU&{Zga#%(7%#{zISkGbv7&-Nlok_T()? z#)ogmLEV)No-w$X=aklhmV-j)vPw;GV*O%|CbwZfU-u_rUjUj(U24r5SfHEyW>>JP zN?>DIYeWR%X#%(9Dpl3+Vj-?clgQRPc15+yt468-PGo3?<+V<;!s!UMVgkGjM>ef5 zyNwi*s75NLzBF`~{BG@Z(|JK(YD*ctpiNFx(|hXg^&!jyc8JlBc=@wa&eN(mU_l%I z1{ZWDC*KmN*PHKNssi`h!I`?gE%B=q26eXy+9Y3>S$}0Z)L!#~nD2bH(iUAQ^-KiW zar)bHvb5`Sa?78*nMR)h`c_$%rIrEAJAJST;@s?TA^|55mYA?2pc-i8XIv+gjK9FT z_{)Mn@0MS_J=#9-8qy{(XzwbvmlU{}0X2oak%T&p>OqXX4nS`mH$<)8^*ObluLCbT zazaadXi<3cEOI((a}8P}=l?gjZ(ZrPzcrNdI3yc?FH_5vxy9&s3w{zJoA`jua1`1l zWJl$+$}bF;W_T7)i6dzUX;s@B*Vm_#%Gm#bEZE^xOGA&BqRa;4+CyS$R7eb4xs9?@ zJlDTkTa30ELWFcG%wEX18k?;EF5fBSW_m@!U>;+5u`s&L&@cBj(!qP6x;^E+T3JcE zMm)D?ivXUtkargw)kBwUNjt^K45`ezDC4rewA~D!GqIXCJ$gSRFomBu`r!013e!-B zU1#`;R*Bb7H@Um?=OsFIu%F+5c1tg&CBa*67ttdp-hIA{ydSf>2eWKfYP3sTuXaTJ z%#jv%-L^({CX?x_MbI!(fkm}$9Cb)fR7+joZEAqey3J7Ri;vKrcr@tQwhUp zGQ%3nh&?26Vo`EqF`!I-_Dv;uGsD{@Fe-a{_B^?rb?$tE=+thzaoGai!1MhxWKj}9 z<|4BJcj`Pggq+;39Tb*Lp73$wEF%^AM!A`!qsaz_FhNV3u~%Frx)m-i-hsD;5@T~h zZB3ai4qO7CXE3t)iOUT4*@gQVG&~tz3gXQ82!NgiCf;m<9NstNMV5gu3v+k8EZOv!5<2*yLeTmHpDG1<&y=(F$dym~) zJx3FT2|Y|4V(SPo<>*aebut^e$9bJhioufXp*bU{BuweFd7fzm4(`TYBoV!?SV5x| z0xYrB_U8kB-F1??+`ETRU)kY&0+P?5jnglekF*@8RK{*l1vkO)8qDCbHGr+%du(b4 zg_5iX?oO?yyiWDdqTQCTE_YiXWxB|T5@@6z$G2ajX)HKlofqz6I*xOy^<^gT?hc5E zi)VH@^FtI81m9*TCE@i0+i4= zmF=EVtt6f|q|zMX5f0>SyPLk{Gv8<14c3+JOX07%Jjw4GN+0*f9hL}{P7=7Zld*cI z>(u3|_B5+x_M8y$BF+t#<<+?X6Ha>Y@Loum-n74Gmv9GGaQDFU2q7Mf9kEWa)3OVoWM=y(KNk=M)A}KXn~&u1<23IJ<0q1 zR?g)kN&}daUZvZld@czKV4FkxK8?!bjy&6A4+n?(iFlvcV%Rg-2`+Vu^$a`#eE!`? zi8-oB+bh*=uNeHlA;cpwKmrM-(mnn}2yRajC0~3S_|Xp49Df}jZ@i#rQ*bC=nsdXQ zfkO=D*Ye{80=KXY2P*oo1zU-E0LR?s`ebQ!<%q=i*KIpAp!F%aJS=_ z5De{R@yG~0ieu;MI3568M6tbFHoMKd-|gM`bV=iC_wX_oDM$bh<+|lcU4}xxcr$?6t2XZo($m^5 zkA+hJ$xDF%;X6Ab;)lfYJIxJ!ImBfI?r%-!%8%H!xeBO)-);pgJXD!G$pB_pP|IlQq@A$4)>y?<$C8Xd#0W#L zIGR7P?lwrqEar&7!Bm=Mz82zonnAS{@;bi!VTjq;q4!)`gnNc^Sch0%qY{I0zs%)f zg+&8slRmLWB2X|)73}%q{Z0h1MGpl`O@qRJqCN5+IcKU? z$&lJ;Z-{s&r|NF>TpA5X^;r7EJ*pR|5C3;$e!MKiRR3mm)h4!<9%N6Wpi}LU0BF;mwlF4pvkZ) zv#GQFi|t}|WKKKD?qTw##oI0Vv{Wu5)&tI!E{&S<<-0@z3v92HG`T3~hKdwCkIkRA zD5~mBJ45V*)^>4}0P4pDB+Db|ht5D`qCDyAru~So+OXY;#lou0+tO4j5Ph>G3UPRQ4i9H4Ujl&iET*hgq$+b11>U`U`BXW2k)wQg7onG>_{IwUv zKDF*yR-&uF3|ihU=qHW@(RR0B;oc>(?TMIHiuB#27U?&H(qj@ne(zWMcf_52dYKF* zJLw7%;COA%ip_V;;I7oXSRQOe1-yDImrca>M)z;p;v`$|y28$ga15y1JA;&t74oBJ6fv^shGQhRgX~ zWvj@4MH+gJUR{l5UNIz0{xp1Vck3YE_dEi4Z0#pBEC zgzJW_(2NUd0y+e&o0cnxC)9)V10d(((jFY+lyna}5ZULYe*fBfV5m?yzYMhU4G#tA z1Y{Bm72cg(xZWG}iOC-qRbh#1=F=+NZjfQDS;_UKU@)VC@5Falf(CSQPaEP8_U-Jd z0lPR}JWc0?IkDf22fkx2s7BsvfzY!ty={meN-$Zz>KtS7)XO(u;vm!4r;=XOq5d*! zpTT?}WqNKgulCoZinTY#f9f-ekk*qR(R-=Cj>vi+b2 z)#-_|VjyJf&!XcOONiuPBLZY z^Ni8)To}F%GCMUA+9vbI@~Gwj{!54kn@LyD&GB(7<~;mCGbe+{j)%)44kP0ubY{~q zY3e55p19jEoJHQ7-_(zp-YA-#Ss!g2_nXZIyaR`<+?F*0q<@-Sw+_b)XhCi7X8XNQ z7L<|Sow*O?W0XN>cWAgcfOdL>6jkVh z!|QY^wV1##;Q_T?Z!?e+DpYOWYpdT3-fVgqS{4)w^*)#VVf%iOMGS_+9RTeXrr`y@ zD1HUE3(fR-KWX>5kqD}+iQ1#Gm^=^QdmtJACPR6X$b-eM~0y~plPUIrQu zmA(5RPk=`#i5KrpU3;&WFPuX0-A1>wpvo_fsFco_+cH80Z$K^^vf-)IbUa$@;N3FS zOz2R@HEB3_pzk)B&zM99ZsZ|%_>wGF&OB_sB0KNi=~hZpBgB94D8~4C#jEy{nTy8f zkg==fQZl_Iq8sOOvZvBhenj}Wl4Mdc&+~{Lm$AG?7uQrzR25PomvC1VUN?I=PbbhU zieWX4Seyr{=0oC=D7t*7R0DCGAJzHXFCaUP5kD{+5Cl}r%P3%E9KKpR3K4TIo^vu5 zR5U2yB`W+-D}P!;x1Olm4|r-bk;MY!ti-Z+G(RR0vt7qBNng~Zir9ZV;xQjDnjA`( zz!ryri0LlgdLQob94xI6xejH~7CU~4eJ*NfSVIL`BYRx5M&{#2Tp@S#b>~w(N*T5n z8NVQlBG=VobL){h8he!bW^Xa&HlDQyF`){#TXdgxk;}6?+x`ooQJi<_P!-PJ+@6p|)p0uR!#Rj>-dB zJ{O};dGoI&p8-&NI|>WQB;qV#3%>HzjHvkB)jL6dL`D63x<5=2uqPq7(GTuNE98B* zFo=-i9)A)ki^zY;%KK4$IsR79bwa=4o4E|Oa9X1@yJUhg{`sv}qB`mnjOgR>cB_jS zC-wm!*-J6e8TN&I`gL6g$3PDA8)~5wDrJm6i+*+wW;23~-aX=Ar1TDJYD-fKa4DyW z;)jzEPFR$sn>1ugA4=#_?yhw~!?_(JKTi-qzM0~5Dav{)Z>j|1@&tXN0_ngVrz(*f zJ6bJ)N9R8op7q$GfPRMX5T_-+>dlSN_`B8hPO>s4XqNCkt-q3UdQ_fHr#DU(}=AKrQhywosd%V|D4otRNx;SPpRKD&6Lrp!Fp)8@hs zL!Cju5bAD7(eI`BWpB|^@3!m6S6`Pi-U{njkr_66V4V#UfCuQVD1q(R8knnufwZw9{=hV=paJ;=I^)tl+ab zl!X$n;f}Mi+J~ow#`DT55SH6GaBCU0Z|X)?A{O}g<*D;o-XaCe2&1PN)Z27z9FK_+ zcxENYQN-7i4EU#P0>DD_h(+o6DeYYl{NQ82lWhfgYF|05draU5Tj6Qm?7TrJ5S?)= zEpzf`!Ozz88&_TJ*vVDJTHtjG$-g3oMQnCAN2+SRp3K*i$Vj zJXaDn7gX17n||);#={0SuH}5$gGVN1;}1JUw1|F1k`M;&8}Gs=!o+>J!Ml0dkNsG< zbiUrLQhDemcmiuD?yZx5>~>qkA-Q#k?wJh%UV=m9h}Sj&-c);g=x|0XUE3CM=Avig z(E4V4esd*rTOK}MTZt93xv>|61keX#hOu%7JfR4@Wq9r7k8vm#8BPI$oXj1!s!{|n zQ}$Z2(;1e45foO9va=-0W0R{Q`5DAyGZLUEc>qxC{*#FT|C-@rLr4~AqtR{8Cc?tF z?Xf(LqDkXvAyv4<#^uTYvrae<+YQPagv(n5!4p*99)wp&vzq4kVrh%K!7h6~^G3b+ z@}#%Cdb1tfvd^0H9PEMAL`1vfbze#Qvp0Z>ylVGC5MsiI)r$F80ti5EMG^?yhKN0S z^y_OVRK#No{lpgLxB4DvtZccrxgjdLEE`F>W1igRo?~whSPe+>UA-q|P%IwB$B`UE zxUX^JVt1D>m?z@B-Wzhy#}JI!W^977-&>gB-LyVI;$T{V3-C-X;q{zbziouyFn0FH zb1Nh$Ry?C>K(y_o{+MCyJpon2*bTzh6^4*7bIR}n-NrZWo6}mb7?Qf}Pv5mXt`qto zuIkR)G;mqVhX!oG-H@yZqLjcanYeP=<}o4c3Z;;|CZw(NTjY9EXpYkpfIb zj1(?q5yL)_Id1Rb+tyqzV<`)4lejz^6l5= zv`z$D0^}9siBgPmWaTYT0q@O%NG&!&2ik>JseFE>@t?|7{7<>TW$Sxn)$4-EkTStt zQR~pMD2PLu^S)iIb-l~xSljTUCgawJhtBO^q7BG$AG$p2Worv8 zueO`DOn$acWR_rw-@t@7U7pSu zQ0o&}WU*;&Ih=N0vq71Gl<0C*w~8MzPT&yYEst3rY?=3wy?6o0E_3Uf%v}_gXnszq zcDxplUilPc*V`75B2uO+kj(=wceKpw=k|xK@H6Yx&KT`@cKdM8>0nCehQl5{8eSp_ zCW?D2Wyl0n=Y)4ohhndw%fn=%PklNtJjCpjcPB_bGRuk({?Z#0RM9$&pohFI_>6GZ ztyqP696&U;%N7>3SiwsX0`bgNk&$-yRVoRxH5!*fjay^Gj9WKq z9eb4H<3WvGM7P?ojiAM7W{x4!(KD^|O#h zE1m}hig3ARF9kkP89)z%haD(1L|!i6eE}8h?Q3z(l*Oo=jA<^7BW^VkJsH=G+Q7l_ z!%>!(eWBbDLrNdTUcYB|;!2Y9x-W}az~Exoo}}y6@S{dMON8!5bN!XT!H5#hE>cAW zVhp07QQ8pR?x|caofJNwYJ0hd(68Kv=2aO#s?Y9Hoz|lUvB6g95*_7#^VR02I`7^B`4i>ze7GL;d&f*-1yV>KKI zmk*-`LA-(uyR*R`q0Ec?o3|QwClM5>#7CwBPi`~q7giX;OZ?ewJB`zy)>CicTWl8o z9Lgbwd=bz)O#Gbm#U#bn1P8wBvpb|)L1i36+%yrPlj2ZrQAT6o-GBQ*WG!|ojb~30 zliK|F1*El%nHprZS!sO`P<`1)>b}5n;LznDyTMZO(TvMC-h)V=`g8@FZfs^Eplrvk z48$UkM;_b^O3>9Z6h4ye((Wl~c1^(fBe5FcUC!U7>@%|SnPg#9EwB>^&59eNsC>Pz zj)L9G<>xt~DIV5I9%cZW-LKiCln6AobxKQ(YZrM-z`l*flrB#Aq28~+B+WQH7>f%T z-j)Y~^tL(XF-FcjMk7O@5i2~cM$*zwtq7&dZSsyGle(XUK?A?N0pdw1UyHWb7CST_*4*DiPUo+(-sHD#*k zF|ET1B(0%vl3N1aK3R|rN}n!6+=~Jed?op;L7*bVO%`ymGH|Yv-ht;wi*xi9B#$3? zYM0mlg-tS|(Y7-@{u8$~%+HBDj2Q9jYhM8TSl>U1LeUr0*Vr+!6?9$cXx?10o&%q! zM6RKLUO?4QNag!OpXKkWD+7MU3!?6-{K-O=6;4{8_BjNB4kS)a_yld>UWhg!70cO8 zGPfM>C)Y*pe#zU@{XDOb`XyFzBfI%B5nGs_0zn z5}nLR{YBlq!|9#)7r%kDsymYda47)Jv_x|Dg_xv^RnaT*EEH$U0P^9)EtTa}p&@c0 z}tik5|yXB;uxhMj9i0}C|6R1h=J7Tw#2}e4EPG-mO^wC z#60uOI9*+wc7%8bg-xF1Et4xl;T)mr4$77*;3bsPgdi_Q|0*)fjq%o^s4}rw%`kD} z__h++NhUj?qR(YUCgh!io`XQKY%! zmgDTVh~;=V4eYWbHfoKEpX>Kb&R>Z%#i8*8aq@ra?6u`QdYS;eeEe?7TvE#sv-;?y zK7C<^iWeMPegp3zMn}kYmjSaT*c#1hAc;{gcPfj)<>@G-J@ufd-bb~3!(`iE@FayvlGe&l_gUNo~`24*AXh=`CMvb%E zM$eS|22?5hh%Q+jMbrZ2!b#MmKjJh)JeIj>luBxVgifK4{%#>XUL<{Q#`UqV`#fL! zUX|}CN6Fv$*un{CzjNPyZct=ic5B{ITIsO+b4}I{R9W3}(PF26EM;n+l%VGCBpLj-`%SEW`GeeFC*)lodg3FL`k@1rWAy-3)96d#Nzr9ZI%=8I8fP7KIUI`{UXG_>%*mg<#K*sDYR<6WOJiW}ZWY}@RDzrQC) z`gC#(kPqlJ6833Q&hM;w7dZc#JoZyln_({^2plY(8~J57*cy3sDJsD&$SfPvhhVjc zy!?ewd%ZO;1$+o}TEAiy;G->OlnZG-Aj0qoqi}vcf8NBZI zZ1ZUU%l`O61Ja8qKkfp@G-h7;(;01G=xs{W3%%ffCcleu4zU_^Yt6^JG zsjiNyAEbm**5>75G$2*_N8VB)Wu=;Cj>}lExl;{n*diKJd!{zVG
dd<9+?cIW-#$BN1pcdzLh3 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
K(G4#sDW)6x(q_rHh2+{ZFSP`P= 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
+{ZFSP`P= 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
5Ogf6@U8 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
)fR7+joZEAqey3J7Ri;vKrcr@tQwhUp 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