Changeset 8119


Ignore:
Timestamp:
Mar 6, 2023, 2:17:35 PM (7 months ago)
Author:
Nicklas Nordborg
Message:

References #2295: Add API for services to send log messages that can be displayed by the web client

Added a web interface for viewing the log.

Location:
branches/3.19-stable
Files:
4 added
4 edited

Legend:

Unmodified
Added
Removed
  • branches/3.19-stable/src/clients/web/net/sf/basedb/clients/web/extensions/service/ServiceLog.java

    r8118 r8119  
    2222package net.sf.basedb.clients.web.extensions.service;
    2323
     24import java.util.Date;
     25import java.util.Deque;
    2426import java.util.HashMap;
     27import java.util.Iterator;
    2528import java.util.Map;
     29import java.util.concurrent.ConcurrentLinkedDeque;
     30
     31import org.apache.commons.collections4.iterators.UnmodifiableIterator;
    2632
    2733/**
     
    6874 
    6975  private final String extensionId;
     76  private final Deque<LogEntry> logEntries;
     77 
     78  private int maxEntries;
     79  private volatile int numEntries;
     80  private volatile int numWarnings;
     81  private volatile int numErrors;
     82 
    7083  private boolean isDebugEnabled;
    7184 
     
    7386  {
    7487    this.extensionId = extensionId;
     88    this.logEntries = new ConcurrentLinkedDeque<>();
     89    this.maxEntries = 200;
    7590  }
    7691 
     
    8398  }
    8499 
     100  /**
     101    Is the debug-level enabled?
     102  */
    85103  public boolean isDebugEnabled()
    86104  {
     
    89107 
    90108  /**
     109    Enable or disable debug-level logging.
     110  */
     111  public void setDebugEnabled(boolean debugEnabled)
     112  {
     113    this.isDebugEnabled = debugEnabled;
     114  }
     115 
     116  /**
     117    Get the max number of entries to keep in the log.
     118  */
     119  public int getMaxEntries()
     120  {
     121    return maxEntries;
     122  }
     123 
     124  /**
     125    Get the current number of entries in the log.
     126  */
     127  public int getNumEntries()
     128  {
     129    return numEntries;
     130  }
     131 
     132  /**
     133    Get the current number of warning entries in the log.
     134  */
     135  public int getNumWarnings()
     136  {
     137    return numWarnings;
     138  }
     139 
     140  /**
     141    Get the current number of error entries in the log.
     142  */
     143  public int getNumErrors()
     144  {
     145    return numErrors;
     146  }
     147 
     148  /**
    91149    Create a logger that adds messages to this log.
    92150  */
     
    96154  }
    97155
     156  /**
     157    Add a log entry.
     158    DEBUG level messages are skipped unless debug-level is enabled.
     159  */
    98160  void add(LogEntry entry)
    99161  {
    100     // TODO
    101     System.out.println(extensionId+" [" + entry.level.name()+"]: "+entry.msg);
    102     if (entry.t != null)
    103     {
    104       entry.t.printStackTrace(System.out);
    105     }
     162    if (entry.level == LogLevel.DEBUG && !isDebugEnabled) return; //
     163    logEntries.addFirst(entry);
     164    if (entry.level == LogLevel.WARNING) numWarnings++;
     165    if (entry.level == LogLevel.ERROR) numErrors++;
     166
     167    if (numEntries++ > maxEntries)
     168    {
     169      // Remove one entry
     170      numEntries--;
     171      LogEntry last = logEntries.removeLast();
     172      if (last.level == LogLevel.WARNING) numWarnings--;
     173      if (last.level == LogLevel.ERROR) numErrors--;
     174    }
     175  }
     176 
     177  /**
     178    Get an iterator that is returning all entries in the log.
     179    The returned iterator is read-only and the {@link Iterator#remove()}
     180    method will throw an exception.
     181  */
     182  public Iterator<LogEntry> getLogEntries()
     183  {
     184    return UnmodifiableIterator.unmodifiableIterator(logEntries.iterator());
    106185  }
    107186 
     
    111190  public enum LogLevel
    112191  {
    113     INFO,
    114     WARNING,
    115     ERROR,
    116     DEBUG
     192    INFO("info.png"),
     193    WARNING("warning.png"),
     194    ERROR("error.png"),
     195    DEBUG("bug.png");
     196   
     197    private final String icon;
     198   
     199    private LogLevel(String icon)
     200    {
     201      this.icon = icon;
     202    }
     203   
     204    /**
     205      Get the icon that represents this log level.
     206    */
     207    public String getIcon()
     208    {
     209      return icon;
     210    }
    117211  }
    118212 
     
    124218    private final long timestamp;
    125219    private final LogLevel level;
    126     private final String msg;
     220    private final String message;
    127221    private final Throwable t;
    128222   
    129     LogEntry(LogLevel level, String msg, Throwable t)
     223    LogEntry(LogLevel level, String message, Throwable t)
    130224    {
    131225      this.timestamp = System.currentTimeMillis();
    132226      this.level = level;
    133       this.msg = msg;
     227      this.message = message;
    134228      this.t = t;
    135229    }
     230   
     231    /**
     232      The level of the log entry.
     233    */
     234    public LogLevel getLevel()
     235    {
     236      return level;
     237    }
     238   
     239    /**
     240      The timestamp of the log entry.
     241    */
     242    public long getTimestamp()
     243    {
     244      return timestamp;
     245    }
     246   
     247    /**
     248      The timestamp of the log entry as a date.
     249    */
     250    public Date getDate()
     251    {
     252      return new Date(timestamp);
     253    }
     254   
     255    /**
     256      Get the log message.
     257    */
     258    public String getMessage()
     259    {
     260      return message;
     261    }
     262   
     263    /**
     264      Get the stacktrace of the log entry.
     265    */
     266    public Throwable getStacktrace()
     267    {
     268      return t;
     269    }
     270   
    136271  }
    137272
  • branches/3.19-stable/www/admin/services/index.jsp

    r7954 r8119  
    3434  import="net.sf.basedb.util.extensions.Extension"
    3535  import="net.sf.basedb.clients.web.extensions.ExtensionsControl"
     36  import="net.sf.basedb.clients.web.extensions.service.ServiceLogger"
     37  import="net.sf.basedb.clients.web.extensions.service.ServiceLog.LogLevel"
     38  import="net.sf.basedb.clients.web.extensions.service.ServiceLog"
    3639  import="java.util.List"
    3740%>
     
    7174    redirect = "services.jsp?ID=" + ID;
    7275  }
     76  else if ("SetDebug".equals(cmd))
     77  {
     78    String extensionId = request.getParameter("extensionId");
     79    boolean enable = Values.getBoolean(request.getParameter("enable"));
     80    ServiceLog serviceLog = ServiceLog.getLog(extensionId, true);
     81    if (enable != serviceLog.isDebugEnabled())
     82    {
     83      ServiceLogger logger = serviceLog.createLogger();
     84      if (!enable) logger.log(LogLevel.DEBUG, "Debug logging was disabled");
     85      serviceLog.setDebugEnabled(enable);
     86      if (enable) logger.log(LogLevel.DEBUG, "Debug logging was enabled");
     87    }
     88    redirect = "view_log.jsp?ID="+ID+"&extensionId="+HTML.urlEncode(extensionId);
     89  }
    7390  else
    7491  {
  • branches/3.19-stable/www/admin/services/services.js

    r7604 r8119  
    2828  var services = {};
    2929 
     30  services.initPage = function()
     31  {
     32    var pageId = Doc.getPageId();   
     33    if (pageId == 'view-page')
     34    {
     35      // Close button
     36      Buttons.addClickHandler('close', App.closeWindow);
     37     
     38      Events.addEventHandler('enableDebug', 'change', services.toggleDebugLog);
     39     
     40      // Auto-update timer
     41      setInterval(services.autoUpdate, 2000);
     42    }
     43    else if (pageId == 'list-page')
     44    {
     45      // Nothing here yet
     46    }
     47  }
     48 
    3049  services.initElements = function(element, autoInit)
    3150  {
     
    3756    {
    3857      Buttons.addClickHandler(element, services.toggleStacktrace);
     58    }
     59    else if (autoInit == 'view-log')
     60    {
     61      Buttons.addClickHandler(element, services.viewLog);
    3962    }
    4063  }
     
    5578  }
    5679 
     80  services.viewLog = function(event)
     81  {
     82    var extensionId = Data.get(event.currentTarget, 'extension-id');
     83    var url = 'view_log.jsp?ID='+App.getSessionId();
     84    url += '&extensionId='+extensionId;
     85    Dialogs.openPopup(url, 'ViewLog', 1000, 600);
     86  }
     87 
     88  services.toggleDebugLog = function()
     89  {
     90    var extensionId = Data.get('page-data', 'extension-id');
     91    var url = 'index.jsp?ID='+App.getSessionId();
     92    url += '&cmd=SetDebug';
     93    url += '&extensionId='+extensionId;
     94    url += '&enable='+(Doc.element('enableDebug').checked?1:0);
     95    location.replace(url);
     96  }
     97 
     98  services.autoUpdate = function()
     99  {
     100    if (Doc.element('autoUpdate').checked)
     101    {
     102      var extensionId = Data.get('page-data', 'extension-id');
     103      var url = 'view_log.jsp?ID='+App.getSessionId();
     104      url += '&extensionId='+extensionId;
     105      url += '&autoUpdate=1';
     106      location.replace(url);
     107    }
     108  }
     109 
    57110  return services;
    58111}();
    59112
    60113Doc.addElementInitializer(Services.initElements);
     114Doc.onLoad(Services.initPage);
  • branches/3.19-stable/www/admin/services/services.jsp

    r7954 r8119  
    1515  import="net.sf.basedb.clients.web.extensions.service.ServiceControllerAction"
    1616  import="net.sf.basedb.clients.web.extensions.service.Services"
     17  import="net.sf.basedb.clients.web.extensions.service.ServiceLog"
    1718  import="java.util.Iterator"
    1819%>
     
    4041{
    4142  %>
    42   <base:page title="Manage Services">
     43  <base:page title="Manage Services" id="list-page">
    4344  <base:head scripts="table.js,~services.js" styles="table.css">
    4445    <ext:scripts context="<%=jspContext %>" />
     
    8687          boolean isNewExtension = ext != last;
    8788          last = ext;
     89          ServiceLog serviceLog = ServiceLog.getLog(ext.getId(), false);
     90          String serviceLogSummary = "";
     91          String serviceLogIcon = "service_log.png";
     92          if (serviceLog != null)
     93          {
     94            serviceLogSummary = "View the log for this service; "+
     95              serviceLog.getNumEntries() +" entries; " +
     96              serviceLog.getNumErrors()+" errors; "+
     97              serviceLog.getNumWarnings()+" warnings";
     98            if (serviceLog.getNumErrors() > 0)
     99            {
     100              serviceLogIcon = "service_log_error.png";
     101            }
     102            else if (serviceLog.getNumWarnings() > 0)
     103            {
     104              serviceLogIcon = "service_log_warning.png";
     105            }
     106          }
    88107          boolean isRunning = false;
    89108          Throwable error = null;
     
    177196                }
    178197                %>
     198                <base:icon
     199                  id="<%="log."+ext.getId()%>"
     200                  subclass="auto-init"
     201                  data-auto-init="view-log"
     202                  data-extension-id="<%=ext.getId()%>"
     203                  image="<%=serviceLogIcon%>"
     204                  tooltip="<%=serviceLogSummary%>"
     205                  visible="<%=serviceLog != null%>"
     206                />
    179207                <ext:render extensions="<%=actionsInvoker%>" context="<%=jspContext%>" item="<%=action%>" />
    180208                <%
Note: See TracChangeset for help on using the changeset viewer.