├── .gitignore ├── Changelogs ├── File.markdown ├── LogViewer.markdown ├── LogWriter.markdown └── Logger.markdown ├── ExampleApp.fmp12 ├── LICENSE ├── Log.fmp12 ├── LogWriters ├── LogWriter_Email.fmp12 └── LogWriter_FM_BaseElements.fmp12 ├── README.md └── functions ├── LogData.fmfn ├── LogDataSession.fmfn └── LogWriteEnabled.fmfn /.gitignore: -------------------------------------------------------------------------------- 1 | Import.log 2 | commit.log 3 | Archive/ -------------------------------------------------------------------------------- /Changelogs/File.markdown: -------------------------------------------------------------------------------- 1 | ### 2.0.2 ### 2 | 3 | released 2024-AUG-02 4 | 5 | detailed list of changes: 6 | scripts 7 | modified 8 | Log Viewer module 9 | - update from 2.1.0 to 2.1.1 10 | 11 | 12 | ### 2.0.1 ### 13 | 14 | released 2024-JUL-23 15 | 16 | detailed list of changes: 17 | layouts 18 | modified 19 | Home 20 | - switch location of "hide" and "view log" buttons 21 | - hide the "view log" button when it can't be used 22 | scripts 23 | modified 24 | Log Viewer module 25 | - update from 2.0.0 to 2.1.0 26 | 27 | 28 | # 2.0.0 # 29 | 30 | released 2024-JUL-22 31 | 32 | - Switch from Let-notation to JSON as the expected format of the raw log data. 33 | - move Logger module to ExampleApp file 34 | - updated custom functions and moved them to ExampleApp file 35 | 36 | 37 | 38 | # 1.0.0 # 39 | 40 | released 2017-DEC-01 41 | 42 | - The first release of this file did not include a separate version script for the file. 43 | 44 | detailed list of changes: 45 | - scripts 46 | - modified 47 | - updated JSON module to 1.0.6 48 | - fields 49 | - modified 50 | - Log::id 51 | - don't validate unique 52 | In a hosted (WAN) file with 120,000 records, doing this cut the log creation time almost in half. 53 | -------------------------------------------------------------------------------- /Changelogs/LogViewer.markdown: -------------------------------------------------------------------------------- 1 | ### 2.1.1 ### 2 | 3 | released 2024-AUG-02 4 | 5 | scripts 6 | modified 7 | Log Viewer: FM: Delete Old Records 8 | - fix error trapping after Perform Find step 9 | 10 | 11 | ## 2.1.0 ## 12 | 13 | released 2024-JUL-23 14 | 15 | - Call startup script to size the window instead of doing it in the Hide Window script. 16 | - add script that can be called via server schedule to delete old records 17 | 18 | detailed list of changes: 19 | scripts 20 | modified 21 | Log Viewer: FM: Hide Window 22 | added 23 | Log Viewer: FM: Delete Old Records 24 | Log Viewer: FM: Delete Old Records PSoS 25 | 26 | 27 | # 2.0.0 # 28 | 29 | released 2024-JUL-22 30 | 31 | - Switch from Let-notation to JSON as the expected format of the raw log data. 32 | - Remove LogItem table 33 | - Update/improve UI adding various features which I'm going to try to list here 34 | 35 | 36 | 37 | ## 1.2.1 ## 38 | 39 | released 2019-JAN-04 40 | 41 | - bug fixes 42 | - JSON web viewer failed to parse JSON if it contained an array with a null value 43 | 44 | detailed list of changes: 45 | - layouts 46 | - modified 47 | - Log: Detail 48 | - update "JSON Web Viewer: JS" in text object off the visible area of the layout 49 | 50 | 51 | ## 1.2.0 ## 52 | 53 | released 2018-JAN-26 54 | 55 | - enhancements 56 | - improve JSON web viewer search feature: 57 | - improve UI 58 | - forward slash key will activate search input (when web viewer is active) 59 | - select prev/next found item 60 | - expand collapsed items to show selection, if needed 61 | 62 | 63 | ## 1.1.0 ## 64 | 65 | released 2017-DEC-01 66 | 67 | - bug fixes 68 | - json web viewer fails to load if any value is an array 69 | 70 | - enhancements 71 | - add search to JSON web viewer via https://markjs.io 72 | 73 | detailed list of changes: 74 | - layouts 75 | - modified 76 | - Log: Detail 77 | - add search javascript text to layout 78 | - update css 79 | - font to monospace (font stack borrowed from stackoverflow) 80 | - increase line-height 81 | - remove line between each value 82 | - change color of null value to have more contrast 83 | - update html of web viewer 84 | - update js 85 | - search to only match full string 86 | 87 | 88 | # 1.0.0 # 89 | 90 | released 2015-JUN-03 91 | 92 | - initial release 93 | -------------------------------------------------------------------------------- /Changelogs/LogWriter.markdown: -------------------------------------------------------------------------------- 1 | # 2.0.0 # 2 | 3 | released 2024-JUL-22 4 | 5 | - Switch from Let-notation to JSON as the expected format of the raw log data. 6 | - set log fields via Hook script instead of auto-enter calculation 7 | 8 | 9 | 10 | # 1.0.0 # 11 | 12 | released 2015-JUN-03 13 | 14 | - initial release 15 | -------------------------------------------------------------------------------- /Changelogs/Logger.markdown: -------------------------------------------------------------------------------- 1 | # 2.0.0 # 2 | 3 | released 2024-JUL-22 4 | 5 | - assume this will be used with JSON LogData and my recently updated error functions 6 | 7 | detailed list of changes: 8 | scripts 9 | modified 10 | Logger: Create Entry ( logData ) 11 | Logger: Test Installation 12 | 13 | 14 | 15 | # 1.0.1 # 16 | 17 | released 2017-DEC-01 18 | 19 | - enhancements 20 | - add to test data 21 | 22 | detailed list of changes: 23 | - scripts 24 | - modified 25 | - Logger: Test Installation 26 | 27 | 28 | # 1.0.0 # 29 | 30 | released 2015-JUN-03 31 | 32 | - initial release 33 | -------------------------------------------------------------------------------- /ExampleApp.fmp12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dansmith65/FileMaker-Logger/1cc9164af39a01dd329fcdc0d1adda733d0e1c37/ExampleApp.fmp12 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2024 Daniel Smith dan@filemaker.consulting 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Log.fmp12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dansmith65/FileMaker-Logger/1cc9164af39a01dd329fcdc0d1adda733d0e1c37/Log.fmp12 -------------------------------------------------------------------------------- /LogWriters/LogWriter_Email.fmp12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dansmith65/FileMaker-Logger/1cc9164af39a01dd329fcdc0d1adda733d0e1c37/LogWriters/LogWriter_Email.fmp12 -------------------------------------------------------------------------------- /LogWriters/LogWriter_FM_BaseElements.fmp12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dansmith65/FileMaker-Logger/1cc9164af39a01dd329fcdc0d1adda733d0e1c37/LogWriters/LogWriter_FM_BaseElements.fmp12 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FileMaker-Logger 2 | 3 | A modular open-source logging framework for [Claris FileMaker](https://www.claris.com/filemaker/). 4 | 5 | 6 | ## Components 7 | 8 | - `Logger` module: Provide an interface for logging. 9 | - Call this module from any script you want to create a log entry from. 10 | - `Log Writer` modules: Save log data to a single destination. 11 | - Call Log Writers from the Logger module. 12 | - `Log Viewer` modules: View log data. 13 | - Provide a user interface for viewing log data. 14 | 15 | 16 | ## File List 17 | 18 | - `Log.fmp12`: File that you can host on your server to save log data to. 19 | - It has been designed as both a self-standing logging application as well as an example file/documentation for the included Log-related modules. 20 | - `ExampleApp.fmp12`: This holds the code that should be copied into your FileMaker file. 21 | - `LogWriters` directory: Additional Log Writer modules. 22 | 23 | 24 | ## Getting Started 25 | 26 | Most documentation for this project exists in READ ME scripts: 27 | 28 | - File Module > READ ME 29 | - Modules > Logger > Logger: READ ME 30 | - Modules > Log Writer: FM > Log Writer: FM: READ ME 31 | - Modules > Log Viewer: FM > Log Viewer: FM: READ ME 32 | 33 | Consider using additional [LogWriters](LogWriters). View the READ ME scripts in each of those files if you choose to implement one. 34 | 35 | 36 | ## Log Level 37 | 38 | By including a log level with each call to the Logger module, it allows you to write your scripts with debugging code right from the start and leave that debugging code in your script while in production. By using the `LogWriteEnabled` function, you can reduce the overhead imposed by this logging method on code in production by only calling the `Logger` module if logs of the specified level are supposed to be saved. 39 | 40 | An example of this implementation can be seen in the [PluginChecker.fmp12](https://github.com/dansmith65/PluginManager/blob/master/PluginChecker.fmp12?raw=true) file from my [PluginManager](https://github.com/dansmith65/PluginManager) project. Open the `~PluginChecker: Test Plugin ( ... )` script from the `Modules` > `PluginChecker` > `PluginChecker: Private` folder. That script uses the `$$PLUGINCHECKER.LOGLEVELTOWRITE` global variable instead of the `LogWriteEnabled` custom function, but the concept is the same. It also calls the local `PluginChecker: Config: Create Log Entry` script instead of directly calling the `Logger` module, which allows users to configure logging (or not), however they choose. 41 | 42 | In the `~PluginChecker: Test Plugin ( ... )` script, you will see many calls to the `...Create Log Entry` script, but most of them are only called if the log level to write is defined as 4 (debug) or 5 (trace). This means that `$$PLUGINCHECKER.LOGLEVELTOWRITE` can be set to 1-3 while in production and the module would only create a single log entry and only if it encountered an error. Or, while developing/debugging an issue, you can set `$$PLUGINCHECKER.LOGLEVELTOWRITE` to 4 or 5 and get many log entries which explain every major decision the script made, along with the data that existed at the time that decision was made. 43 | 44 | When using this method of debugging, you don't have to remove your debugging code before going to production mode. That also means you don't have to add that code again when you run into issues while in production. It's also platform agnostic, this method of debugging works just as well for a script being run on the server as it does for one run in FileMaker Pro, or Pro Advanced. 45 | 46 | 47 | ## Recommended log levels and when to use them 48 | 49 | ### 1 Error 50 | 51 | The system is in distress, customers are probably being affected 52 | (or will soon be) and the fix probably requires human intervention. 53 | The "2AM rule" applies here- if you're on call, do you want to be 54 | woken up at 2AM if this condition happens? If yes, then log it as 55 | "error". 56 | 57 | ### 2 Warn 58 | An unexpected technical or business event happened, customers may be 59 | affected, but probably no immediate human intervention is required. On 60 | call people won't be called immediately, but support personnel will 61 | want to review these issues asap to understand what the impact is. 62 | Basically any issue that needs to be tracked but may not require 63 | immediate intervention. 64 | 65 | ### 3 Info 66 | Things we want to see at high volume in case we need to forensically 67 | analyze an issue. System lifecycle events (system start, stop) go here. 68 | "Session" lifecycle events (login, logout, etc.) go here. Significant 69 | boundary events should be considered as well (e.g. database calls, 70 | remote API calls). Typical business exceptions can go here (e.g. login 71 | failed due to bad credentials). Any other event you think you'll need 72 | to see in production at high volume goes here. 73 | 74 | ### 4 Debug 75 | Just about everything that doesn't make the "info" cut. Any message 76 | that is helpful in tracking the flow through the system and isolating 77 | issues, especially during the development and QA phases. We use "debug" 78 | level logs for entry/exit of most non-trivial methods and marking 79 | interesting events and decision points inside methods. 80 | 81 | ### 5 Trace 82 | For extremely detailed and potentially high volume logs that you don't 83 | typically want enabled even during normal development. Examples 84 | include dumping a full object hierarchy, logging some state during 85 | every iteration of a large loop, etc. 86 | -------------------------------------------------------------------------------- /functions/LogData.fmfn: -------------------------------------------------------------------------------- 1 | /** 2 | * ===================================== 3 | * LogData ( theLogLevel ; theLogMessage ; JSONObjectToLog ) 4 | * 5 | * RETURNS: 6 | * (string) JSON Object which describes the current environment. 7 | * 8 | * PARAMETERS: 9 | * theLogLevel = (numeric) 0 thru [n] 10 | * theLogMessage = (text, optional) some text describing the log entry 11 | * JSONObjectToLog = (optional) a JSON Object containing additional data to log 12 | * this will be the base object that additional data is added to 13 | * 14 | * EXAMPLE: 15 | * LogData ( LogLevel2Warn ; "error when going to layout: 'Customer: Detail'" ) 16 | * // where LogLevel2Warn is a custom function which returns a number 17 | * LogData ( $logLevelDebug ; "start section: create related records" ) 18 | * // where $logLevelDebug contains the numeric representation of a debug level log entry 19 | * LogData ( 3 ; "script runtime: 0.3 seconds" ) 20 | * 21 | * NOTES: 22 | * This function should be modified to capture any relevant values for your solution. 23 | * 24 | * HISTORY: 25 | * MODIFIED on 2024-JUL-12 by Daniel Smith dan@filemaker.consulting 26 | * - use JSONGetElementType for ScriptParameter and ScriptResult 27 | * - remove ScriptResult; that's more relevant to errors and should be manually 28 | * added to non-error log entries, if needed 29 | * - replace CurrentHostTimestamp with TimestampUTC 30 | * MODIFIED on 2024-APR-16 by Daniel Smith dan@filemaker.consulting 31 | * - convert to JSON and add JSONObjectToLog parameter 32 | * MODIFIED on 2015-JUN-02 by Daniel Smith dansmith65@gmail.com 33 | * - include ApplicationVersion for all log levels 34 | * MODIFIED on 2014-OCT-02 by Daniel Smith dansmith65@gmail.com 35 | * - add: AccountPrivilegeSetName, CurrentPrivilegeSetName, logLevelToWriteOffset, LOGLEVELTOWRITEOFFSETglobal 36 | * - move UserName to the ALL LOG LEVELS section (helps to differentiate two users logged on with the same account) 37 | * - include additional detail when log level is = 2 rather than = 1 38 | * - change theMessage parameter to theLogMessage 39 | * - encode theLogMessage parameter as logMessage instead of message 40 | * - modify documentation/notes 41 | * MODIFIED on 2014-FEB-05 by Daniel Smith dansmith65@gmail.com 42 | * - prepend parameter with "the" to prevent collision 43 | * - add theMessage parameter 44 | * - remove session-specific values (see LogDataSession function) 45 | * - manually encode name/value pairs, remove dependency on # 46 | * - add values added in FileMaker 13 47 | * - disable UserCount 48 | * MODIFIED on 2014-JAN-11 matt@filemakermagazine.com to use numeric logLevel 49 | * MODIFIED on 2012-NOV-21 by Daniel Smith dansmith65@gmail.com 50 | * - don't access $error variable directly 51 | * CREATED on 2012-NOV-21 Daniel Smith dansmith65@gmail.com 52 | * INSPIRED by ErrorData by matt@filemakermagazine.com 53 | * https://github.com/filemakerstandards/fmpstandards/tree/master/Functions 54 | * 55 | * LINK: 56 | * https://github.com/dansmith65/FileMaker-Logger 57 | * ===================================== 58 | */ 59 | 60 | Let ( [ 61 | ~result = Case ( 62 | IsEmpty ( JSONObjectToLog ) ; 63 | "{}" 64 | ; 65 | JSONGetElementType ( JSONObjectToLog ; "" ) = JSONObject ; 66 | JSONObjectToLog 67 | ; 68 | /* else: store it as a string */ 69 | JSONSetElement ( "{}" ; "JSONObjectToLog" ; JSONObjectToLog ; JSONString ) 70 | ) ; 71 | ~result = JSONSetElement ( ~result ; 72 | [ "logLevel" ; theLogLevel ; JSONNumber ] ; 73 | [ "logMessage" ; theLogMessage ; JSONString ] ; 74 | [ "AccountName" ; Get ( AccountName ) ; JSONString ] ; 75 | [ "UserName" ; Get ( UserName ) ; JSONString ] ; 76 | [ "TimestampUTC" ; GetAsTimestamp ( Get ( CurrentTimeUTCMilliseconds ) / 1000 ) ; JSONString ] ; 77 | [ "FileName" ; Get ( FileName ) ; JSONString ] ; 78 | [ "ScriptName" ; Get ( ScriptName ) ; JSONString ] ; 79 | [ "ScriptParameter" ; Get ( ScriptParameter ) ; JSONGetElementType ( Get ( ScriptParameter ) ; "" ) ] ; 80 | [ "ApplicationVersion" ; Get ( ApplicationVersion ) ; JSONString ] ; 81 | [ "AccountPrivilegeSetName" ; Get ( AccountPrivilegeSetName ) ; JSONString ] ; 82 | [ "CurrentPrivilegeSetName" ; Get ( CurrentPrivilegeSetName ) ; JSONString ] 83 | ) ; 84 | ~result = If ( IsEmpty ( $logLevelToWriteOffset ) ; ~result ; 85 | JSONSetElement ( ~result ; "logLevelToWriteOffset" ; $logLevelToWriteOffset ; JSONNumber ) 86 | ) ; 87 | ~result = If ( IsEmpty ( $$LOGLEVELTOWRITEOFFSET ) ; ~result ; 88 | JSONSetElement ( ~result ; "LOGLEVELTOWRITEOFFSET" ; $$LOGLEVELTOWRITEOFFSET ; JSONNumber ) 89 | ) ; 90 | ~result = If ( theLogLevel > 2 ; ~result ; 91 | JSONSetElement ( ~result ; 92 | [ "AllowAbortState" ; Get ( AllowAbortState ) ; JSONNumber ] ; 93 | [ "ErrorCaptureState" ; Get ( ErrorCaptureState ) ; JSONNumber ] ; 94 | [ "FilePath" ; Get ( FilePath ) ; JSONString ] ; 95 | [ "LayoutAccess" ; Get ( LayoutAccess ) ; JSONNumber ] ; 96 | [ "LayoutName" ; Get ( LayoutName ) ; JSONString ] ; 97 | [ "LayoutTableName" ; Get ( LayoutTableName ) ; JSONString ] ; 98 | [ "LayoutViewState" ; Get ( LayoutViewState ) ; JSONNumber ] ; 99 | [ "MultiUserState" ; Get ( MultiUserState ) ; JSONNumber ] ; 100 | [ "RecordAccess" ; Get ( RecordAccess ) ; JSONNumber ] ; 101 | [ "RecordID" ; Get ( RecordID ) ; JSONNumber ] ; 102 | [ "RecordOpenCount" ; Get ( RecordOpenCount ) ; JSONNumber ] ; 103 | [ "RecordOpenState" ; Get ( RecordOpenState ) ; JSONNumber ] ; 104 | [ "SortState" ; Get ( SortState ) ; JSONNumber ] ; 105 | [ "StatusAreaState" ; Get ( StatusAreaState ) ; JSONNumber ] ; 106 | [ "WindowMode" ; Get ( WindowMode ) ; JSONNumber ] ; 107 | [ "WindowName" ; Get ( WindowName ) ; JSONString ] ; 108 | [ "WindowOrientation" ; Get ( WindowOrientation ) ; JSONString ] ; 109 | [ "WindowStyle" ; Get ( WindowStyle ) ; JSONNumber ] ; 110 | [ "WindowVisible" ; Get ( WindowVisible ) ; JSONNumber ] ; 111 | [ "ActiveFieldName" ; Get ( ActiveFieldName ) ; JSONString ] ; 112 | [ "ActiveFieldTableName" ; Get ( ActiveFieldTableName ) ; JSONString ] ; 113 | [ "ActiveLayoutObjectName" ; Get ( ActiveLayoutObjectName ) ; JSONString ] 114 | ) 115 | ) 116 | ] ; ~result ) -------------------------------------------------------------------------------- /functions/LogDataSession.fmfn: -------------------------------------------------------------------------------- 1 | /** 2 | * ===================================== 3 | * LogDataSession ( JSONLogData ) 4 | * 5 | * RETURNS: 6 | * (string) JSONLogData with environmental data pertaining to the current session added to it. 7 | * 8 | * PARAMETERS: 9 | * JSONLogData = (JSONObject) as returned by the LogData function 10 | * 11 | * DEPENDENCIES: 12 | * $$SESSIONID global variable 13 | * 14 | * NOTES: 15 | * This function should be modified to capture the relevant session values for your solution. 16 | * Modify all log entries with this function. 17 | * In a multi-file solution, consider these options: 18 | * 19 | * 1. Calling this function from the file that writes the logs will 20 | * cause a session to include any file that was used the entire 21 | * time the log writing file was open. 22 | * 23 | * 2. Calling this function from every file will allow each file 24 | * to maintain their own session, but will not easily allow you to 25 | * see which files were opened during a single session. 26 | * 27 | * HISTORY: 28 | * MODIFIED on 2024-JUL-12 Daniel Smith dan@filemaker.consulting 29 | * - add JSONLogData parameter and convert from Let Notation to JSONObject 30 | * MODIFIED on 2024-APR-16 Daniel Smith dan@filemaker.consulting 31 | * - delete: CurrentTimestamp 32 | * - rename HighContrastColor to SystemAppearance 33 | * - add: ApplicationArchitecture, HostApplicationVersion, PersistentID, TimezoneOffset, 34 | * NetworkType, StatusAreaState, ScreenScaleFactor, multiple Window values 35 | * MODIFIED on 2015-JUN-02 Daniel Smith dansmith65@gmail.com 36 | * - Quote HighContrastState value since it is empty in Web Direct 37 | * MODIFIED on 2014-OCT-02 Daniel Smith dansmith65@gmail.com 38 | * - update documentation 39 | * CREATED on 2014-FEB-05 Daniel Smith dansmith65@gmail.com 40 | * 41 | * LINK: 42 | * https://github.com/dansmith65/FileMaker-Logger 43 | * ===================================== 44 | */ 45 | 46 | If ( JSONGetElementType ( JSONLogData ; "" ) ≠ JSONObject ; 47 | /* return parameter as-is since it's not a JSONObject */ 48 | JSONLogData ; 49 | 50 | If ( IsEmpty ( $$SESSIONID ) ; 51 | /* session has not started yet, so create a session id and return session data */ 52 | Let ( [ 53 | $$SESSIONID = Get ( UUID ) ; 54 | ~sessionData = 55 | JSONSetElement ( "{}" ; 56 | [ "ID" ; $$SESSIONID ; JSONString ] ; 57 | [ "ApplicationArchitecture" ; Get ( ApplicationArchitecture ) ; JSONString ] ; 58 | [ "ApplicationLanguage" ; Get ( ApplicationLanguage ) ; JSONString ] ; 59 | [ "ApplicationVersion" ; Get ( ApplicationVersion ) ; JSONString ] ; 60 | [ "ConnectionState" ; Get ( ConnectionState ) ; JSONNumber ] ; 61 | [ "Device" ; Get ( Device ) ; JSONNumber ] ; 62 | [ "EncryptionState" ; Get ( EncryptionState ) ; JSONString ] ; 63 | [ "FileMakerPath" ; Get ( FileMakerPath ) ; JSONString ] ; 64 | [ "HighContrastState" ; Get ( HighContrastState ) ; JSONNumber ] ; 65 | [ "HostApplicationVersion" ; Get ( HostApplicationVersion ) ; JSONString ] ; 66 | [ "HostIPAddress" ; Get ( HostIPAddress ) ; JSONString ] ; 67 | [ "HostName" ; Get ( HostName ) ; JSONString ] ; 68 | [ "InstalledFMPlugins" ; Get ( InstalledFMPlugins ) ; JSONString ] ; 69 | [ "SystemAppearance" ; Get ( SystemAppearance ) ; JSONString ] ; 70 | [ "SystemIPAddress" ; Get ( SystemIPAddress ) ; JSONString ] ; 71 | [ "SystemLanguage" ; Get ( SystemLanguage ) ; JSONString ] ; 72 | [ "SystemNICAddress" ; Get ( SystemNICAddress ) ; JSONString ] ; 73 | [ "SystemPlatform" ; Get ( SystemPlatform ) ; JSONNumber ] ; 74 | [ "SystemVersion" ; Get ( SystemVersion ) ; JSONString ] ; 75 | [ "UseSystemFormatsState" ; Get ( UseSystemFormatsState ) ; JSONNumber ] ; 76 | [ "PersistentID" ; Get ( PersistentID ) ; JSONString ] ; 77 | [ "TimezoneOffset" ; 78 | GetAsTime ( 79 | Get ( CurrentTimestamp ) - Floor ( Get ( CurrentTimeUTCMilliseconds ) / 1000 ) 80 | ) 81 | ; JSONString ] ; 82 | [ "NetworkType" ; Get ( NetworkType ) ; JSONString ] /* Only relevant for FM Go and returns a number */ 83 | ) 84 | ; 85 | ~sessionData = If ( Position ( Get ( ApplicationVersion ) ; "Server" ; 1 ; 1 ) = 1 ; ~sessionData ; 86 | /** 87 | * log screen/window size info so it can inform UI design decisions 88 | * don't log this for the server; it's windows are not shown to the user 89 | */ 90 | JSONSetElement ( ~sessionData ; 91 | [ "StatusAreaState" ; Get ( StatusAreaState ) ; JSONNumber ] ; 92 | [ "ScreenWidth" ; Get ( ScreenWidth ) ; JSONNumber ] ; 93 | [ "ScreenHeight" ; Get ( ScreenHeight ) ; JSONNumber ] ; 94 | [ "ScreenDepth" ; Get ( ScreenDepth ) ; JSONNumber ] ; 95 | [ "ScreenScaleFactor" ; Get ( ScreenScaleFactor ) ; JSONNumber ] ; 96 | [ "WindowDesktopWidth" ; Get ( WindowDesktopWidth ) ; JSONNumber ] ; 97 | [ "WindowDesktopHeight" ; Get ( WindowDesktopHeight ) ; JSONNumber ] ; 98 | [ "WindowWidth" ; Get ( WindowWidth ) ; JSONNumber ] ; 99 | [ "WindowHeight" ; Get ( WindowHeight ) ; JSONNumber ] ; 100 | [ "WindowContentWidth" ; Get ( WindowContentWidth ) ; JSONNumber ] ; 101 | [ "WindowContentHeight" ; Get ( WindowContentHeight ) ; JSONNumber ] ; 102 | [ "WindowOrientation" ; Get ( WindowOrientation ) ; JSONNumber ] 103 | ) 104 | ) 105 | ] ; 106 | JSONSetElement ( JSONLogData ; "SESSION" ; ~sessionData ; JSONObject ) 107 | ) ; 108 | 109 | /* else: add existing session id */ 110 | JSONSetElement ( JSONLogData ; 111 | [ "SESSION.ID" ; $$SESSIONID ; JSONString ] 112 | ) 113 | ) 114 | ) -------------------------------------------------------------------------------- /functions/LogWriteEnabled.fmfn: -------------------------------------------------------------------------------- 1 | /** 2 | * ===================================== 3 | * LogWriteEnabled ( theLogLevel ) 4 | * 5 | * RETURNS: 6 | * (boolean) True if logs of the specified level should be saved 7 | * 8 | * PARAMETERS: 9 | * theLogLevel = (numeric) 0 thru [n] 10 | * 11 | * NOTES: 12 | * Any necessary filtering logic can be used in this script. The most 13 | * efficient method is to hard-code a number into this calculation. 14 | * 15 | * $logLevelToWriteOffset and $$LOGLEVELTOWRITEOFFSET allow a developer 16 | * to increase the ~logLevelToWrite by setting one or both of these 17 | * values. This is useful when debugging on a production file as it 18 | * allows you to keep the default ~logLevelToWrite value for most 19 | * users/scripts and only increase the verbosity of logging when 20 | * necessary. 21 | * Local and global variables are included to help manage scope. A 22 | * local variable would not be very effective at increasing verbosity 23 | * for an entire session; on the other hand, a local variable is 24 | * ideal for increasing verbosity for a single script (without 25 | * increasing for sub-scripts). 26 | * If using the LogData custom function, it is recommended to modify 27 | * it to add these two variables to the log, if they are not empty. 28 | * 29 | * HISTORY: 30 | * MODIFIED on 2015-JUN-02 Daniel Smith dansmith65@gmail.com 31 | * - bug fix: allow theLogLevel to be less than or equal to ~logLevelToWrite 32 | * CREATED on 2014-FEB-05 Daniel Smith dansmith65@gmail.com 33 | * 34 | * LINK: 35 | * https://github.com/dansmith65/FileMaker-Logger 36 | * ===================================== 37 | */ 38 | 39 | Let ( [ 40 | // if the log level is less than or equal to this value, writing is enabled 41 | ~logLevelToWrite = 3 42 | + $logLevelToWriteOffset 43 | + $$LOGLEVELTOWRITEOFFSET 44 | ] ; 45 | theLogLevel ≤ ~logLevelToWrite 46 | ) --------------------------------------------------------------------------------