add new metric timestamp_delta
Browse files- logmetric.py +50 -10
logmetric.py
CHANGED
@@ -188,10 +188,12 @@ class LogMetric(evaluate.Metric):
|
|
188 |
def getTimestampsScore(self, pred_timestamps, ref_timestamps):
|
189 |
timestamp_amt_score = self.smapeScore(len(pred_timestamps), len(ref_timestamps))
|
190 |
|
191 |
-
|
192 |
-
|
193 |
-
return timestamp_amt_score, 1.0, 1.0
|
194 |
|
|
|
|
|
|
|
195 |
|
196 |
# replace all digits in the reference timestamp (first timestamp) with '/d' to get
|
197 |
# a regex that describes the format
|
@@ -199,6 +201,7 @@ class LogMetric(evaluate.Metric):
|
|
199 |
|
200 |
matchesPatternScore = 1.0
|
201 |
monotonicallyIncreasingScore = 1.0
|
|
|
202 |
|
203 |
# A variable to save the previous timestamp (as datetime obj) to check monotonicity
|
204 |
prev_datetime = None
|
@@ -212,7 +215,12 @@ class LogMetric(evaluate.Metric):
|
|
212 |
matchesPattern = re.fullmatch(pred_timestring_pattern, ts) is not None
|
213 |
# Check if the timestamps are monotonically increasing
|
214 |
cur_datetime = dateutil.parser.parse(ts)
|
215 |
-
|
|
|
|
|
|
|
|
|
|
|
216 |
prev_datetime = cur_datetime
|
217 |
|
218 |
# If one entry doesn't fulfill the matching pattern property or the monotinicity property, set to 0 for whole log
|
@@ -224,9 +232,43 @@ class LogMetric(evaluate.Metric):
|
|
224 |
# e.g. date format not parsable by dateutil.parser
|
225 |
matchesPatternScore = 0.0
|
226 |
monotonicallyIncreasingScore = 0.0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
227 |
|
|
|
228 |
# matchesPatternScore and monotonicallyIncreasingScore are in {0,1}
|
229 |
-
return timestamp_amt_score, matchesPatternScore, monotonicallyIncreasingScore
|
230 |
|
231 |
|
232 |
|
@@ -270,11 +312,8 @@ class LogMetric(evaluate.Metric):
|
|
270 |
|
271 |
linecontent_sacrebleu, linecontent_sacrebleu_withoutExplicitNumbers, linecontentlength_difference_SMAPE = self.getLineContentScore(pred_logMessages, ref_logMessages)
|
272 |
|
273 |
-
timestamps_difference_SMAPE, timestamps_formatConsistency_absolute, timestamps_monotinicity_absolute = self.getTimestampsScore(pred_timestamps, ref_timestamps)
|
274 |
|
275 |
-
#TODO:
|
276 |
-
# linecontentordering_permutations = getLineContentOrderingScore(pred_logMessages, ref_logMessages)
|
277 |
-
|
278 |
|
279 |
# return weighted overall score of all the different scores
|
280 |
return {"linecount_difference_SMAPE_score": linecount_difference_SMAPE,
|
@@ -283,7 +322,8 @@ class LogMetric(evaluate.Metric):
|
|
283 |
"linecontent_sacrebleu_withoutExplicitNumbers_score": linecontent_sacrebleu_withoutExplicitNumbers,
|
284 |
"timestamps_SMAPE_difference_score": timestamps_difference_SMAPE,
|
285 |
"timestamps_formatConsistency_score": timestamps_formatConsistency_absolute,
|
286 |
-
"timestamps_monotinicity_score": timestamps_monotinicity_absolute
|
|
|
287 |
}
|
288 |
|
289 |
def _compute(self, predictions, references):
|
|
|
188 |
def getTimestampsScore(self, pred_timestamps, ref_timestamps):
|
189 |
timestamp_amt_score = self.smapeScore(len(pred_timestamps), len(ref_timestamps))
|
190 |
|
191 |
+
if (len(pred_timestamps) == 0) and (len(ref_timestamps) == 0):
|
192 |
+
return timestamp_amt_score, 1.0, 1.0, 1.0
|
|
|
193 |
|
194 |
+
# if there are no predicted timestamps, return early. It is still consistent and monotonic.
|
195 |
+
if (len(pred_timestamps) == 0) and (len(ref_timestamps) != 0):
|
196 |
+
return timestamp_amt_score, 1.0, 1.0, 0.0
|
197 |
|
198 |
# replace all digits in the reference timestamp (first timestamp) with '/d' to get
|
199 |
# a regex that describes the format
|
|
|
201 |
|
202 |
matchesPatternScore = 1.0
|
203 |
monotonicallyIncreasingScore = 1.0
|
204 |
+
pred_timedeltas = []
|
205 |
|
206 |
# A variable to save the previous timestamp (as datetime obj) to check monotonicity
|
207 |
prev_datetime = None
|
|
|
215 |
matchesPattern = re.fullmatch(pred_timestring_pattern, ts) is not None
|
216 |
# Check if the timestamps are monotonically increasing
|
217 |
cur_datetime = dateutil.parser.parse(ts)
|
218 |
+
if prev_datetime == None:
|
219 |
+
monotonicallyIncreasing = True
|
220 |
+
else:
|
221 |
+
monotonicallyIncreasing = prev_datetime <= cur_datetime
|
222 |
+
pred_timedeltas.append((cur_datetime - prev_datetime).total_seconds())
|
223 |
+
|
224 |
prev_datetime = cur_datetime
|
225 |
|
226 |
# If one entry doesn't fulfill the matching pattern property or the monotinicity property, set to 0 for whole log
|
|
|
232 |
# e.g. date format not parsable by dateutil.parser
|
233 |
matchesPatternScore = 0.0
|
234 |
monotonicallyIncreasingScore = 0.0
|
235 |
+
pred_timedeltas.append(-1)
|
236 |
+
|
237 |
+
|
238 |
+
if (len(pred_timestamps) != 0) and (len(ref_timestamps) == 0):
|
239 |
+
return timestamp_amt_score, matchesPatternScore, monotonicallyIncreasingScore, 0.0
|
240 |
+
|
241 |
+
|
242 |
+
ref_timedeltas = []
|
243 |
+
prev_datetime = None
|
244 |
+
for i in range(len(ref_timestamps)):
|
245 |
+
ts = ref_timestamps[i]
|
246 |
+
try:
|
247 |
+
cur_datetime = dateutil.parser.parse(ts)
|
248 |
+
if prev_datetime == None:
|
249 |
+
pass
|
250 |
+
else:
|
251 |
+
ref_timedeltas.append((cur_datetime - prev_datetime).total_seconds())
|
252 |
+
|
253 |
+
prev_datetime = cur_datetime
|
254 |
+
|
255 |
+
except Exception as e:
|
256 |
+
ref_timedeltas.append(-1)
|
257 |
+
|
258 |
+
minlength = min(len(pred_timedeltas), len(ref_timedeltas))
|
259 |
+
|
260 |
+
pred_timedeltas = pred_timedeltas[:minlength]
|
261 |
+
ref_timedeltas = ref_timedeltas[:minlength]
|
262 |
+
|
263 |
+
print("pred_timedeltas:", pred_timedeltas)
|
264 |
+
print("ref_timedeltas:", ref_timedeltas)
|
265 |
+
|
266 |
+
|
267 |
+
timestampDeltaScore = self.smapeScore(pred_timedeltas, ref_timedeltas)
|
268 |
|
269 |
+
print("timestampDeltaScore:", timestampDeltaScore)
|
270 |
# matchesPatternScore and monotonicallyIncreasingScore are in {0,1}
|
271 |
+
return timestamp_amt_score, matchesPatternScore, monotonicallyIncreasingScore, timestampDeltaScore
|
272 |
|
273 |
|
274 |
|
|
|
312 |
|
313 |
linecontent_sacrebleu, linecontent_sacrebleu_withoutExplicitNumbers, linecontentlength_difference_SMAPE = self.getLineContentScore(pred_logMessages, ref_logMessages)
|
314 |
|
315 |
+
timestamps_difference_SMAPE, timestamps_formatConsistency_absolute, timestamps_monotinicity_absolute, timestamps_delta_SMAPE = self.getTimestampsScore(pred_timestamps, ref_timestamps)
|
316 |
|
|
|
|
|
|
|
317 |
|
318 |
# return weighted overall score of all the different scores
|
319 |
return {"linecount_difference_SMAPE_score": linecount_difference_SMAPE,
|
|
|
322 |
"linecontent_sacrebleu_withoutExplicitNumbers_score": linecontent_sacrebleu_withoutExplicitNumbers,
|
323 |
"timestamps_SMAPE_difference_score": timestamps_difference_SMAPE,
|
324 |
"timestamps_formatConsistency_score": timestamps_formatConsistency_absolute,
|
325 |
+
"timestamps_monotinicity_score": timestamps_monotinicity_absolute,
|
326 |
+
"timestamps_delta_SMAPE_score" : timestamps_delta_SMAPE
|
327 |
}
|
328 |
|
329 |
def _compute(self, predictions, references):
|