1 /* 2 * Copyright © [2008-2009] Novell, Inc. All Rights Reserved. 3 * 4 * Novell grants permission, free of charge, to any person obtaining copies of this 5 * software and its associated documentation files (the "Software"), to deal in the 6 * Software without restriction, including to use, copy, adapt, publish, distribute, 7 * display, perform, sublicense, and sell copies of the Software, subject to the following 8 * condition: You must include the above copyright notice and this permission notice in 9 * all full or partial copies of the Software. 10 * 11 * NOVELL PROVIDES THE SOFTWARE "AS IS," WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 12 * INCLUDING WITHOUT THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 13 * PURPOSE, AND NON-INFRINGMENT. NOVELL, THE AUTHORS OF THE SOFTWARE, AND THE OWNERS OF 14 * COPYRIGHT IN THE SOFTWARE ARE NOT LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, 15 * WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN 16 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 */ 18 19 /** 20 * @fileoverview 21 * This file contains the non-template routines that must be completed to create a new 22 * Collector. The methods defined in this file extend a number of other classes. 23 */ 24 25 /** 26 * The initialize method is used to perform any event source-specific initialization 27 * routines required to support processing of data from this event source. 28 * <p>Common things done in this section are: 29 * <ul> 30 * <li>Load any custom parameters 31 * <li>Pre-set static event fields in the instance.protoEvt object 32 * <li>Send any initialization strings to the Connector 33 * </ul> 34 * @return {Boolean} Whether the initialization was successful 35 */ 36 Collector.prototype.initialize = function(){ 37 38 // This Boolean tells the Collector whether the event source reports in UTC or not (if not, it will report in local time) 39 instance.CONFIG.params.reportsUTC = false; 40 41 // Example code to define a parser that can determine the latest offset from new records 42 // Use this for DATABASE sources (see SQLQuery class) 43 this.PARSER.getOffsetData = function(input){ 44 // parser code, like "return input.RXMap.col_AutoID" 45 } 46 conn.addParser(this.PARSER.getOffsetData); 47 48 // Example code to load standard syslog maps - use this for SYSLOG sources 49 this.MAPS.syslogSev = new KeyMap(this.CONFIG.collDir + "syslog_severity.map"); 50 this.MAPS.syslogFac = new KeyMap(this.CONFIG.collDir + "syslog_facility.map"); 51 52 return true; 53 }; 54 55 /** 56 * Cleans up the environment when the Collector is stopped. 57 * Use this method to shut down or close any external connections necessary when the Collector is 58 * stopped. This is rarely necessary as most ESM components already shut down on their own. 59 * @return void 60 */ 61 Collector.prototype.cleanup = function(){ 62 return true; 63 }; 64 65 /** 66 * The sendQuery() method will transmit a string to the Connector for processing; 67 * for example with the DB Connector this would be the database query, and for the 68 * Process Connector this would be passed to STDIN of the process. See each Connector's 69 * documentation for details. 70 * Please note that for many Connectors this step is not necessary, and can be skipped. 71 * For the Database Connector in particular, the template will help handle offsets and suboffsets 72 * automatically if you define parsers for them (see SQLQuery class), and will handle the complexities 73 * of re-querying the DB (hence, you'd only use this in special circumstances). 74 * <p>Example: 75 * <code> 76 * // Note: not an example of usage, but of implementation: 77 * Record.prototype.sendQuery = function() { 78 * conn.send("exec fetch"); 79 * return true; 80 * } 81 * </code> 82 * @return {Boolean} Whether the query was sent correctly 83 * @see SQLQuery 84 */ 85 Connector.prototype.sendQuery = function(){ 86 return true; 87 }; 88 89 /** 90 * The preParse() method should be used to perform preliminary data 91 * cleaning prior to the main parsing step. 92 * For example, you might need to strip end-of-record characters, replace unsafe 93 * characters, check to make sure you have a full record, filter out certain events, etc. 94 * You should also check for error conditions coming back from the Connector, which are 95 * typically recorded in rec.connErr. 96 * <p>Example: 97 * <code> 98 * // Note: not an example of usage, but of implementation: 99 * Record.prototype.preParse = function(e) { 100 * if( rec.connErr != "" ) { return false; } 101 * this.replace(/\n/, "")); 102 * return true; 103 * } 104 * </code> 105 * @param {Event} e The current instance of the output event, this is in 106 * general not used directly but is provided for reference or for presetting fields. 107 * @return {Boolean} Whether the preParse() method completed without errors. 108 */ 109 Record.prototype.preParse = function(e){ 110 if (this.CONNECTION_ERROR != null || typeof this.RXMap == "undefined") { return false; } 111 112 // Example code on some standard syslog-style parsing 113 if (this.CONNECTION_METHOD == "SYSLOG" && this.CONNECTION_MODE == "map") { 114 // We can pre-set certain fields - we will do this directly against 115 // the Event object, even though this is in general bad practice 116 e.ReporterIP = this.s_SyslogRelayIp; 117 if (this.s_MessageOriginatorHost.search(/\d+\.\d+\.\d+\.\d+/) != -1) { 118 e.ObserverIP = this.s_MessageOriginatorHost; 119 } 120 else { 121 e.ObserverHostName = this.s_MessageOriginatorHost; 122 } 123 e.Severity = instance.MAPS.syslogSev.lookup(this.i_syslog_severity); 124 e.ObserverServiceComponent = instance.MAPS.syslogFac.lookup(this.i_syslog_facility); 125 // use the below logic for below 6r5 syslog connector 126 this.syslogMsg = this.s_RXBufferString.parseSyslog(); 127 e.setObserverEventTime(this.syslogMsg.date); 128 this.s_RXBufferString = this.syslogMsg.message; 129 } 130 return true; 131 }; 132 133 134 /** 135 * The parse() method is used to perform the main parsing on the input 136 * record. The focus here should be to break the input up into small 137 * data units that can be easily mapped to the Sentinel event structure 138 * in the convert() method. 139 * <p>Example: 140 * <code> 141 * // Note: not an example of usage, but of implementation: 142 * Record.prototype.parse = function(e) { 143 * this.inpArray = []; 144 * this.inpArray = this.safesplit(","); 145 * return true; 146 * } 147 * </code> 148 * @param {Event} e The current instance of the output event; this is in 149 * general not used directly but is provided for reference or for presetting fields. 150 * @return {Boolean} Whether the parse() method completed without errors. 151 */ 152 Record.prototype.parse = function(e){ 153 // parsing logic goes here 154 if (false) { // set SEND_EVENT to true if your parsing logic worked correctly 155 instance.SEND_EVENT = true; 156 } 157 // If you can't parse... 158 rec.sendUnsupported(); 159 return true; 160 }; 161 162 163 /** 164 * The normalize() method is used to convert data elements from the input 165 * record into Sentinel-friendly data, typically by using external 166 * translation files to look up the data or by performing simple data manipulation. 167 * Most of your normalization can be done in the Record object, but the output 168 * event 'e' is provided for your convenience if you wish to place your 169 * translated data in it directly. In general, however, it is safer and more 170 * convenient to do your work in the Record object, then just let convert() 171 * do the conversion to the output event. 172 * <p>Example: 173 * <code> 174 * // Note: not an example of usage, but of implementation: 175 * Record.prototype.normalize = function(e) { 176 * this.inpArray = []; 177 * this.inpArray = this.safesplit(","); 178 * return true; 179 * } 180 * </code> 181 * @param {Event} e The current instance of the output event; this is in 182 * general not used directly but is provided for reference or for presetting fields. 183 * @return {Boolean} Whether the parse() method completed without errors. 184 */ 185 Record.prototype.normalize = function(e){ 186 return true; 187 }; 188 189 /** 190 * The postParse() method performs any necessary post-processing steps after the 191 * input record is converted into the output event, but before the event is actually 192 * sent. In general this function will not be necessary, but is provided for 193 * special cases. 194 * <p>Example: 195 * <code> 196 * // Note: not an example of usage, but of implementation: 197 * Record.prototype.postParse = function(e) { 198 * var d = new Date(); 199 * e.EndTime = Date.getTime(); 200 * return true; 201 * } 202 * </code> 203 * @param {Event} e The current instance of the output event, which should have 204 * a complete set of data in it already. 205 * @return {Boolean} Whether the postParse() method completed without errors. 206 207 */ 208 Record.prototype.postParse = function(e){ 209 return true; 210 }; 211 212 /** 213 * The reply method should be used to perform any final acknowledgement to the 214 * Connector that might be necessary. In general this method is not used, but is 215 * provided for special cases. 216 * <p>Example: 217 * <code> 218 * // Note: not an example of usage, but of implementation: 219 * Record.prototype.reply = function(e) { 220 * conn.send("Event sent successfully\n"); 221 * return true; 222 * } 223 * </code> 224 * @param {Event} e The current instance of the output event that was just sent. 225 * @return {Boolean} Whether the reply method completed without errors. 226 */ 227 Record.prototype.reply = function(e){ 228 return true; 229 };