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 // Example code to define a parser that can determine the latest offset from new records 39 // Use this for DATABASE sources (see SQLQuery class) 40 this.PARSER.getOffsetData = function(input){ 41 // parser code, like "return input.RXMap.col_AutoID" 42 } 43 conn.addParser(this.PARSER.getOffsetData); 44 45 // Example code to load standard syslog maps - use this for SYSLOG sources 46 this.MAPS.syslogSev = new KeyMap(this.CONFIG.collDir + "syslog_severity.map"); 47 this.MAPS.syslogFac = new KeyMap(this.CONFIG.collDir + "syslog_facility.map"); 48 49 return true; 50 } 51 /** 52 * Cleans up the environment when the Collector is stopped. 53 * Use this method to shut down or close any external connections necessary when the Collector is 54 * stopped. This is rarely necessary as most ESM components already shut down on their own. 55 * @return void 56 */ 57 Collector.prototype.cleanup = function(){ 58 return true; 59 } 60 61 /** 62 * The sendQuery() method will transmit a string to the Connector for processing; 63 * for example with the DB Connector this would be the database query, and for the 64 * Process Connector this would be passed to STDIN of the process. See each Connector's 65 * documentation for details. 66 * Please note that for many Connectors this step is not necessary, and can be skipped. 67 * For the Database Connector in particular, the template will help handle offsets and suboffsets 68 * automatically if you define parsers for them (see SQLQuery class), and will handle the complexities 69 * of re-querying the DB (hence, you'd only use this in special circumstances). 70 * <p>Example: 71 * <code> 72 * // Note: not an example of usage, but of implementation: 73 * Record.prototype.sendQuery = function() { 74 * conn.send("exec fetch"); 75 * return true; 76 * } 77 * </code> 78 * @return {Boolean} Whether the query was sent correctly 79 * @see SQLQuery 80 */ 81 Connector.prototype.sendQuery = function(){ 82 return true; 83 } 84 85 /** 86 * The preParse() method should be used to perform preliminary data 87 * cleaning prior to the main parsing step. 88 * For example, you might need to strip end-of-record characters, replace unsafe 89 * characters, check to make sure you have a full record, filter out certain events, etc. 90 * You should also check for error conditions coming back from the Connector, which are 91 * typically recorded in rec.connErr. 92 * <p>Example: 93 * <code> 94 * // Note: not an example of usage, but of implementation: 95 * Record.prototype.preParse = function(e) { 96 * if( rec.connErr != "" ) { return false; } 97 * this.replace(/\n/, "")); 98 * return true; 99 * } 100 * </code> 101 * @param {Event} e The current instance of the output event, this is in 102 * general not used directly but is provided for reference or for presetting fields. 103 * @return {Boolean} Whether the preParse() method completed without errors. 104 */ 105 Record.prototype.preParse = function(e){ 106 if (this.CONNECTION_ERROR != null || typeof this.RXMap == "undefined") { return false; } 107 108 // Example code on some standard syslog-style parsing 109 if (this.CONNECTION_METHOD == "SYSLOG" && this.CONNECTION_MODE == "map") { 110 // We can pre-set certain fields - we will do this directly against 111 // the Event object, even though this is in general bad practice 112 e.ReporterIP = this.s_SyslogRelayIp; 113 if (this.s_MessageOriginatorHost.search(/\d+\.\d+\.\d+\.\d+/) != -1) { 114 e.ObserverIP = this.s_MessageOriginatorHost; 115 } 116 else { 117 e.ObserverHostName = this.s_MessageOriginatorHost; 118 } 119 e.Severity = instance.MAPS.syslogSev.lookup(this.i_syslog_severity); 120 e.ObserverChannel = instance.MAPS.syslogFac.lookup(this.i_syslog_facility); 121 // use the below logic for below 6r5 syslog connector 122 this.syslogMsg = this.s_RXBufferString.parseSyslog(); 123 e.setDeviceEventTime(this.syslogMsg.date); 124 this.s_RXBufferString = this.syslogMsg.message; 125 } 126 return true; 127 } 128 129 130 /** 131 * The parse() method is used to perform the main parsing on the input 132 * record. The focus here should be to break the input up into small 133 * data units that can be easily mapped to the Sentinel event structure 134 * in the convert() method. 135 * <p>Example: 136 * <code> 137 * // Note: not an example of usage, but of implementation: 138 * Record.prototype.parse = function(e) { 139 * this.inpArray = []; 140 * this.inpArray = this.safesplit(","); 141 * return true; 142 * } 143 * </code> 144 * @param {Event} e The current instance of the output event; this is in 145 * general not used directly but is provided for reference or for presetting fields. 146 * @return {Boolean} Whether the parse() method completed without errors. 147 */ 148 Record.prototype.parse = function(e){ 149 // parsing logic goes here 150 if (false) { // set SEND_EVENT to true if your parsing logic worked correctly 151 instance.SEND_EVENT = true; 152 } 153 // If you can't parse... 154 rec.sendUnsupported(); 155 return true; 156 } 157 158 159 /** 160 * The normalize() method is used to convert data elements from the input 161 * record into Sentinel-friendly data, typically by using external 162 * translation files to look up the data or by performing simple data manipulation. 163 * Most of your normalization can be done in the Record object, but the output 164 * event 'e' is provided for your convenience if you wish to place your 165 * translated data in it directly. In general, however, it is safer and more 166 * convenient to do your work in the Record object, then just let convert() 167 * do the conversion to the output event. 168 * <p>Example: 169 * <code> 170 * // Note: not an example of usage, but of implementation: 171 * Record.prototype.normalize = function(e) { 172 * this.inpArray = []; 173 * this.inpArray = this.safesplit(","); 174 * return true; 175 * } 176 * </code> 177 * @param {Event} e The current instance of the output event; this is in 178 * general not used directly but is provided for reference or for presetting fields. 179 * @return {Boolean} Whether the parse() method completed without errors. 180 */ 181 Record.prototype.normalize = function(e){ 182 return true; 183 } 184 185 /** 186 * The postParse() method performs any necessary post-processing steps after the 187 * input record is converted into the output event, but before the event is actually 188 * sent. In general this function will not be necessary, but is provided for 189 * special cases. 190 * <p>Example: 191 * <code> 192 * // Note: not an example of usage, but of implementation: 193 * Record.prototype.postParse = function(e) { 194 * var d = new Date(); 195 * e.EndTime = Date.getTime(); 196 * return true; 197 * } 198 * </code> 199 * @param {Event} e The current instance of the output event, which should have 200 * a complete set of data in it already. 201 * @return {Boolean} Whether the postParse() method completed without errors. 202 203 */ 204 Record.prototype.postParse = function(e){ 205 return true; 206 } 207 208 /** 209 * The reply method should be used to perform any final acknowledgement to the 210 * Connector that might be necessary. In general this method is not used, but is 211 * provided for special cases. 212 * <p>Example: 213 * <code> 214 * // Note: not an example of usage, but of implementation: 215 * Record.prototype.reply = function(e) { 216 * conn.send("Event sent successfully\n"); 217 * return true; 218 * } 219 * </code> 220 * @param {Event} e The current instance of the output event that was just sent. 221 * @return {Boolean} Whether the reply method completed without errors. 222 */ 223 Record.prototype.reply = function(e){ 224 return true; 225 }