NUS-specific logging taxonomy and JSON log field contract for custom-coded systems, based on the NUS IT Logging, Monitoring and Alerts guideline. This is an organisation-level, language-agnostic skill for implementing or reviewing application logs that must comply with the NUS standard log types, event codes, and file format.
Organisation-level skill: This skill is language-agnostic and sits alongside
.github/skills/coding/SKILL.mdas an NUS-wide standard.This skill defines the NUS-specific what-to-log and how-to-shape-the-log-entry rules. Use it together with the relevant language/framework logging skill for implementation mechanics. For Java, pair it with
.github/skills/java/logging/SKILL.md.Source basis: Confluence page
Custom Coded Systems - Logging, Monitoring and Alerts Guidelines(spacenusit, page28180623).
Apply this skill when a system needs to follow the NUS custom-coded application logging guideline, especially for:
This skill focuses on event taxonomy, required fields, field names, and safe content. It does not replace language/framework logging guidance.
For backend custom-coded systems, the NUS guideline distinguishes these application log categories:
| Category | Primary platform | Purpose |
|---|---|---|
| Exception / Incident | Splunk Enterprise | Unhandled failures or incidents requiring attention |
| Heartbeat | Splunk Enterprise | Presence/continuity signal proving logs are still flowing |
| Business Event | Splunk Enterprise | Important business actions and reads of confidential data |
| Authorization Update | Splunk Enterprise | Fine-grained permission changes |
| Authentication | Splunk Enterprise | Login attempts and outcomes |
| Metrics / Traces / APM / uncaught exceptions | Splunk Observability | Application performance monitoring and traces |
Use the following log types/categories for application logs:
ex — exception eventhbt — heartbeat eventauthn — authentication eventFor business / functional / authorization update / confidential data accessed /
configuration update logging, the event code is not fixed to literal values such as
func, authz, confi, or sysconf.
Instead, application teams SHOULD define domain-specific event codes that describe the actual business or security action, for example:
add-userdelete-usergrant-folder-accessread-student-profileupdate-password-policyRules:
The Confluence page contains some sample payload inconsistencies. When implementing logging, prefer the canonical table-defined values over inconsistent examples.
Canonical values to use:
dt in ISO8601 UTCdetails with non-sensitive values onlyDo not copy inconsistent sample values such as mixed-case event codes when the table defines a stricter format.
.jsonl files.details.details MUST NOT contain confidential data, secrets, or unmasked PII.dt MUST be ISO8601 in UTC timezone.2024-10-03T06:45:36ZThese fields form the NUS base contract for application logs.
| Logical field | Physical field | Rule |
|---|---|---|
| Datetime | dt | ISO8601 UTC timestamp |
| User ID | userid | User/account/system identifier related to the event |
| Is User | isUser | true for human-originated event, false for system-originated event |
| Environment | env | Environment name such as DEV, SIT, QAT, PRD |
| Application ID | appId | eApps ID / application identifier |
| Application Name | app | Human-readable application/system name |
| Module | mod | Deployable module name if applicable; empty/null if not applicable |
| Class / Controller | class | Logging originator class/component |
| Version | ver | Deployed application/module version |
| Caller IP | ip | Caller IP / forwarded client IP / machine IP |
| Server IP | sip | Server IP where relevant |
| Server Hostname | server | Hostname / endpoint / FQDN |
userid may contain:
system for system-initiated activity without a service accountanonymous for anonymous accessUse for exceptions/incidents requiring attention.
Required additional fields:
level: errorevent: exmsg: safe exception summarydetails: optional structured detailsRules:
details.stackTrace only if it does not expose sensitive data.Heartbeat events are used to detect missing logs.
Required additional fields:
level: infoevent: hbtmsg: optional heartbeat message, e.g. --- heartbeat ---Rules:
Required additional fields:
level: one of debug, info, warnevent: domain-specific event code such as add-user, delete-user, grant-role, read-user-profile, update-configmsg: concise event summarydetails: structured event detailsUse for important business actions and meaningful domain events.
details fields:
evCode — mandatory, lowercase, no spacesevDetails — additional event detailsevActor — actor user ID if applicableRules:
evCode MUST be stable and machine-friendly.event and evCode SHOULD align; if both are present, they should describe the same business action.evDetails MUST NOT contain confidential or PII data.Examples:
event: add-user, evCode: add-userevent: delete-user, evCode: delete-userUse for permission or grant changes.
details fields:
grantorgranteeobjt — role/object typeobj — role/object identifier/name where applicableExample event codes:
grant-rolerevoke-roleassign-folder-accessUse when confidential information is read/accessed.
details fields:
accId — accessor user IDobjt — data type accessedobj — object identifierRules:
Example event codes:
read-user-profileview-payslipdownload-transcriptUse for important configuration changes.
details fields:
updId — updater user IDobj — configuration identifier/nameval — updated valueRules:
val MUST NOT contain confidential values, secrets, tokens, or PII.Example event codes:
update-password-policychange-session-timeoutupdate-feature-toggleAuthentication logs are logged to a separate log index from general event logs.
Required additional fields:
event: authnsuccess: booleanfailReason: required when success == falsemfa: booleanmfat: MFA type when mfa == trueRules:
Use these NUS-aligned levels:
error — unhandled exception / incident requiring human interventionwarn — handled but abnormal conditioninfo — normal operational or business event, heartbeat, configuration update, successful significant actionsdebug — technical diagnostics and low-level event tracingWhen applying this skill with a language/framework logging skill:
msg, and detailsmsg or details.{
"dt": "2024-10-03T06:45:36Z",
"userid": "[email protected]",
"isUser": true,
"env": "PRD",
"appId": "1234",
"app": "uNivUS",
"mod": "Scholarship",
"class": "ScholarshipAdminController",
"ver": "1.5.1.2",
"ip": "185.123.152.50",
"sip": "185.123.152.50",
"server": "inetapps.nus.edu.sg",
"level": "error",
"event": "ex",
"msg": "Unable to load the configuration for XX service, system cannot proceed with processing.",
"details": {
"myCustomType": "Error",
"stackTrace": [
"at ScholarshipAdminController.LoadConfiguration() in C:\\Projects\\Scholarship\\ScholarshipAdminController.cs:line 45",
"at ScholarshipAdminController.ProcessRequest() in C:\\Projects\\Scholarship\\ScholarshipAdminController.cs:line 21",
"at Middleware.RequestHandler.Invoke() in C:\\Projects\\Middleware\\RequestHandler.cs:line 78"
],
"anyOtherCustomField": "Hello World"
}
}
{
"dt": "2024-10-03T06:45:36Z",
"userid": "system",
"isUser": false,
"env": "PRD",
"appId": "1234",
"app": "uNivUS",
"ip": "185.123.152.50",
"sip": "185.123.152.50",
"server": "inetapps.nus.edu.sg",
"level": "info",
"event": "hbt",
"msg": "--- heartbeat ---"
}
{
"dt": "2024-10-03T09:15:30Z",
"userid": "[email protected]",
"isUser": true,
"env": "PRD",
"appId": "1234",
"app": "uNivUS",
"mod": "Registration",
"class": "RegistrationController",
"ver": "2.3.4",
"ip": "192.168.0.1",
"sip": "10.0.0.1",
"server": "prodapps.nus.edu.sg",
"level": "info",
"event": "cancel-application",
"msg": "The user has cancelled the application process.",
"details": {
"evCode": "cancel-application",
"evDetails": "User cancelled the application process at step 3.",
"evActor": "[email protected]"
}
}
{
"dt": "2024-10-03T10:00:45Z",
"userid": "[email protected]",
"isUser": true,
"env": "PRD",
"appId": "5678",
"app": "PTS",
"mod": "Admin Panel",
"class": "AuthorizationController",
"ver": "1.0.0",
"ip": "192.168.0.2",
"sip": "10.0.0.2",
"server": "prodapps.nus.edu.sg",
"level": "info",
"event": "grant-role",
"msg": "Authorization role updated.",
"details": {
"grantor": "[email protected]",
"grantee": "[email protected]",
"objt": "Role",
"obj": "Admin"
}
}
{
"dt": "2024-10-03T11:20:30Z",
"userid": "[email protected]",
"isUser": true,
"env": "QAT",
"appId": "91011",
"app": "uNivUS",
"mod": "Student Services",
"class": "DataAccessController",
"ver": "4.0.1",
"ip": "192.168.0.3",
"sip": "10.0.0.3",
"server": "qatapps.nus.edu.sg",
"level": "warn",
"event": "read-user-profile",
"msg": "Sensitive data access detected.",
"details": {
"accId": "[email protected]",
"objt": "UserProfile",
"obj": "12345"
}
}
{
"dt": "2024-10-03T12:45:10Z",
"userid": "system",
"isUser": false,
"env": "DEV",
"appId": "13579",
"app": "ConfigManager",
"mod": "",
"class": "ConfigUpdateService",
"ver": "3.2.1",
"ip": "192.168.0.4",
"sip": "10.0.0.4",
"server": "devapps.nus.edu.sg",
"level": "debug",
"event": "update-max-connections",
"msg": "Configuration parameter updated.",
"details": {
"updId": "system",
"obj": "MaxConnections",
"val": "500"
}
}
{
"dt": "2024-10-03T13:05:45Z",
"userid": "[email protected]",
"isUser": true,
"env": "PRD",
"appId": "9876",
"app": "LoginPortal",
"mod": "WebAuth",
"class": "AuthController",
"ver": "1.0.2",
"ip": "192.168.1.1",
"sip": "10.1.1.1",
"server": "auth.nus.edu.sg",
"event": "authn",
"success": true,
"mfa": true,
"mfat": "TOTP"
}
{
"dt": "2024-10-03T13:10:22Z",
"userid": "[email protected]",
"isUser": true,
"env": "PRD",
"appId": "9876",
"app": "LoginPortal",
"mod": "WebAuth",
"class": "AuthController",
"ver": "1.0.2",
"ip": "192.168.1.2",
"sip": "10.1.1.2",
"server": "auth.nus.edu.sg",
"event": "authn",
"success": false,
"failReason": "Password was incorrect",
"mfa": false
}
.github/skills/java/logging/SKILL.md for SLF4J/Logback syntax, logger declaration, MDC, and exception logging mechanics.ex, hbt, domain-specific event code, or authndt, userid, isUser, env, appId, app, mod, class, ver, ip, sip, serverdt uses ISO8601 UTC.jsonlevCode is lowercase and has no spaces when useddetails contains structured, non-sensitive values onlymsg, details, or MDC