Skip to content

SAIF.Framework.Logging architecture

SAIF.Framework.Logging is a cross-cutting, application-agnostic logging utility library that provides audit, error, and (deprecated) trace logging concerns, each dispatching to either a local CSV file or a remote SOAP web service (wsLogging) depending on the hosting application type.

Responsibilities

  • Provide audit logging (clsLogAudit) for application/business-event messages, opt-in via IsEnabled (defaults False).
  • Provide error logging (clsLogError), including exception detail capture, ViewState-noise suppression, and optional email notification of errors.
  • Provide trace logging (clsLogTrace) for method-level tracing — functionally disabled (see Design constraints).
  • Provide a legacy login-event logger (clsLoginLog.LogItem) that writes monthly CSV files.
  • Provide an MSMQ queue path-name helper (clsLoggingQueues) that formats a queue path string from configuration.
  • Retain a deprecated, independently designed rolling-file logger (LogList/LogList.LogItem) for backward compatibility only.

Component boundaries

  • clsLogAudit, clsLogError, clsLogTrace: primary logging entry points, each following the same internal shape — a GetBasic*Info() context-gathering method, a value-type info struct (AuditInfoStruct/ErrorInfoStruct/TraceInfoStruct), and a WriteMessage dispatcher.
  • clsLogCommon: Public shared helper class. Its web/non-web context detection (IsWeb), environment/application-name derivation, calling-method reflection, and related helper methods/properties are Friend-scoped (assembly-internal) and not part of the external public surface; its format-string constants (e.g. STATEFMTSIMPLE, TOFILEFORMAT) are Public Const and are part of the external public surface.
  • wsLogging.clsWSLogging (generated SOAP client proxy, Web References/wsLogging/Reference.vb): remote sink boundary — marshals AuditInfoStruct/ErrorInfoStruct/TraceInfoStruct data to a legacy ASMX web service via WriteAudit/WriteError/WriteTrace operations.
  • clsLoginLog: independent boundary — writes directly to a monthly CSV file; does not use the wsLogging sink or the clsLogCommon info-struct pattern.
  • clsLoggingQueues: independent boundary — resolves an MSMQ path-name string from ConfigurationManager.AppSettings; does not open or write to a queue itself*.
  • LogList/LogList.LogItem: independent, obsolete boundary — a separate rolling-file logger unrelated to the clsLogXxx dual-sink pattern.

Interaction model

  • Callers (hosting applications) invoke one of the public logging entry points (clsLogAudit.AuditMessage/AuditCustomMessage, clsLogError.CreateError/CreateErrorWithEmail, clsLogTrace.MethodBegin/MethodEnd/MethodMessage).
  • Each entry point gathers ambient context (machine name, application name, page name, environment, username) via a GetBasic*Info() method, which constructs a clsSecurityPrincipal instance (from SAIF.Framework.Security) purely to read the current user's identity for inclusion in the log record.
  • clsLogCommon.IsWeb determines whether context is sourced from HttpContext.Server/Request (web) or Process/Environment (non-web), governing which sink is permitted (see Design constraints).
  • The populated info struct is passed to WriteMessage, which dispatches to either:
  • a local file sink (m_OutFile.WriteLine, CSV format), if ToFile() was previously called; or
  • the remote SOAP sink (wsLogging.clsWSLogging.WriteAudit/WriteError/WriteTrace), by default — with the endpoint URL resolved via AppGlobal.EnvironmentService.GetConfigSetting(EnvironmentConfigKeys.LoggingServiceUrl).
  • clsLogError.CreateErrorWithEmail additionally constructs a clsSAIFMessage (from SAIF.Framework.Mail) and calls SendMail(...) to notify a recipient by email, in parallel with the file/SOAP write.
  • All logging entry-point bodies (or their private write helpers) wrap execution in Try...Catch with empty/'gobble gobble catch blocks, so logging failures are silently swallowed and never propagate to the caller.

The following diagram shows high-level component interactions.

flowchart TD
    Caller[Hosting application] --> LogAudit[clsLogAudit]
    Caller --> LogError[clsLogError]
    Caller --> LogTrace["clsLogTrace<br>(obsolete, no-op sink)"]
    Caller --> LoginLog[clsLoginLog]
    Caller --> LoggingQueues[clsLoggingQueues]
    Caller --> LogListLegacy["LogList<br>(obsolete)"]

    LogAudit --> LogCommon[clsLogCommon]
    LogError --> LogCommon
    LogTrace --> LogCommon

    LogAudit --> SecurityPrincipal["clsSecurityPrincipal<br>(SAIF.Framework.Security)"]
    LogError --> SecurityPrincipal
    LogTrace --> SecurityPrincipal

    LogAudit --> EnvService["AppGlobal.EnvironmentService<br>(SAIF.Framework.Security.EnvironmentApi)"]
    LogError --> EnvService
    LogTrace --> EnvService

    LogAudit -->|IsWeb=False, ToFile called| FileSinkA["Local CSV file"]
    LogAudit -->|default| WsLogging["wsLogging.clsWSLogging<br>(SOAP/ASMX web service)"]
    LogError -->|IsWeb=False, ToFile called| FileSinkE["Local CSV file"]
    LogError -->|default| WsLogging
    LogTrace -.->|no-op, never writes| WsLogging

    LogError --> SaifMail["clsSAIFMessage<br>(SAIF.Framework.Mail)"]

    LoginLog --> FileSinkL["Monthly login CSV file"]
    LoggingQueues --> QueuePath["MSMQ path string<br>(no queue I/O in this library)"]

Sequence diagram

The following diagram shows the primary error-logging request/response sequence, including the file/web-service sink branch.

sequenceDiagram
    participant Caller
    participant clsLogError
    participant clsSecurityPrincipal
    participant wsLogging as wsLogging.clsWSLogging
    Caller->>clsLogError: CreateError(exception, stateInfo)
    clsLogError->>clsSecurityPrincipal: read current user identity
    clsSecurityPrincipal-->>clsLogError: UserName / IsAuthenticated
    clsLogError->>clsLogError: SuppressLogging() check (ViewState noise)
    alt not suppressed and ToFile() previously called
        clsLogError->>clsLogError: WriteMessageToFile (local CSV)
    else default (web-service sink)
        clsLogError->>wsLogging: WriteError(ErrorInfoStruct)
        wsLogging-->>clsLogError: (fire-and-forget / swallowed failure)
    end
    clsLogError-->>Caller: (no exception propagated on failure)

Design constraints

  • Dual-sink design: every main logging class writes to exactly one of two sinks — a local CSV file (opened via ToFile()) or the remote wsLogging SOAP web service (default) — selected per-instance, not concurrently.
  • File logging is prohibited for web applications: clsLogCommon.IsWeb (Not System.Web.HttpContext.Current Is Nothing) gates ToFile(); if IsWeb is True, ToFile() throws ApplicationException("Logging to files not valid for web applications."). Web applications must use the wsLogging web-service sink. See BR-003.
  • clsLogTrace is fully disabled and obsolete: all public trace methods (MethodBegin, MethodEnd, MethodMessage) are decorated <Obsolete("Log Trace No Longer Supported, Please remove")>, and the private WriteMessage sink is a no-op ('Removed Logic as tracing should not be used.). The class still exposes IsEnabled/UserTraceEnabled gating logic and a private WSWriteMessage path, but no trace data ever reaches the file or web-service sinks regardless of flag state. See BR-002.
  • Best-effort logging: all logging entry points swallow failures silently via empty/'gobble gobble Try...Catch blocks, so a failure to log (e.g., web service unreachable) never causes the calling application to fail. See BR-005.
  • Tight coupling to sibling framework libraries: logging classes directly construct clsSecurityPrincipal and reference AppGlobal.EnvironmentService rather than depending on abstractions, coupling this library to SAIF.Framework.Security and SAIF.Framework.Security.EnvironmentApi — architectural observation, inferred*.
  • Environment/application-name detection is convention-based: GetAppEnvironment/GetWebAppName parse the physical file/module path (splitting on : and \) rather than reading explicit configuration, an inferred convention rather than a documented contract*.
  • LogList and clsLoginLog bypass the dual-sink pattern: LogList is an independently designed rolling-file logger, and clsLoginLog writes directly to a monthly CSV file; neither uses the clsLogCommon/wsLogging pattern used by clsLogAudit/clsLogError/clsLogTrace.

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with ** could not be confirmed; treat as unknown until verified.

Sources

  • SAIF.Framework.Logging/clsLogAudit.vb
  • SAIF.Framework.Logging/clsLogCommon.vb
  • SAIF.Framework.Logging/clsLogError.vb
  • SAIF.Framework.Logging/clsLoggingQueues.vb
  • SAIF.Framework.Logging/clsLoginLog.vb
  • SAIF.Framework.Logging/clsLogTrace.vb
  • SAIF.Framework.Logging/LogList.vb
  • SAIF.Framework.Logging/Web References/wsLogging/Reference.vb
  • SAIF.Framework.Logging/SAIF.BOF.Framework.Logging.vbproj
  • SAIF.Framework.Logging/app.config