cpee-logging-xes-yaml 1.3.4 → 1.3.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aab20ce260e56f4571add36cef8c7fe6f638fad4a723d28f8a13e6e93e99a32c
4
- data.tar.gz: 122128fd3e956198fc7096409ff1f64bf47d0e17f5f2e72dd2f4cf3d138ea173
3
+ metadata.gz: 899e0d2f04869dfa68eb7c7922222c825f87a1bd90d3b73f0cbb528bd95779d3
4
+ data.tar.gz: 64ef69bebaad740bb8ef4944fb2a5fa3a37d26ab1e0156bf58b75392c9fe8d39
5
5
  SHA512:
6
- metadata.gz: f36ec97639c73e0735250eee61c39febc1b43e2bab34912780be9a393ccedc45ef3cffdcfd97cd432145a73fcb0935e10dfc405bdd9500117de9afb53522b9de
7
- data.tar.gz: 242461d18564a0c2fb9b2b5992e45a99e7506e79aab3eaa08be4c4a1bc4846733b39bc49b7b6e5c7714f719e74ce6afd6fa8225a91642be3188f61c597dfa4f2
6
+ metadata.gz: 0b0f53c72122468d2f3c4e6a17cd69a7bb7ca0c9088bb843e82ebe3700cb0e6b78a20b453d761648acba181afcb3f9122eb4e4a65c0da166f07249c7b3b48341
7
+ data.tar.gz: 0557b1e7f8cb2e1538b4984238530d713db7b7927b6ccba5abc949c1b2f180d307370c9d2d6781f689cfce156f1b19339e624dab2eae1a8dfc0478706329ed61
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "cpee-logging-xes-yaml"
3
- s.version = "1.3.4"
3
+ s.version = "1.3.6"
4
4
  s.platform = Gem::Platform::RUBY
5
5
  s.license = "LGPL-3.0"
6
6
  s.summary = "Logging for the cloud process execution engine (cpee.org)"
@@ -25,6 +25,8 @@ require 'typhoeus'
25
25
  require 'stringio'
26
26
  require 'typhoeus'
27
27
  require 'date'
28
+ require 'msgpack'
29
+ require 'csv'
28
30
 
29
31
  def wrap(s, width=78, indent=19, extra_indent=2)
30
32
  lines = []
@@ -46,7 +48,75 @@ def wrap(s, width=78, indent=19, extra_indent=2)
46
48
  return lines.join "\n"
47
49
  end
48
50
 
49
- def follow(fname,io,copy,deep=0)
51
+ TEMPLATE_XES_XML = <<-END
52
+ <log xmlns="http://www.xes-standard.org/" xes.version="2.0" xes.features="nested-attributes">
53
+ <string key="creator" value="cpee.org"/>
54
+ <extension name="Time" prefix="time" uri="http://www.xes-standard.org/time.xesext"/>
55
+ <extension name="Concept" prefix="concept" uri="http://www.xes-standard.org/concept.xesext"/>
56
+ <extension name="ID" prefix="id" uri="http://www.xes-standard.org/identity.xesext"/>
57
+ <extension name="Lifecycle" prefix="lifecycle" uri="http://www.xes-standard.org/lifecycle.xesext"/>
58
+ <extension name="CPEE" prefix="cpee" uri="http://cpee.org/cpee.xesext"/>
59
+ <extension name="stream" prefix="stream" uri="https://cpee.org/datastream/datastream.xesext"/>
60
+ <global scope="trace">
61
+ <string key="concept:name" value="__INVALID__"/>
62
+ <string key="cpee:name" value="__INVALID__"/>
63
+ </global>
64
+ <global scope="event">
65
+ <string key="concept:name" value="__INVALID__"/>
66
+ <string key="concept:instance" value="-1"/>
67
+ <string key="concept:endpoint" value=""/>
68
+ <string key="id:id" value=""/>
69
+ <string key="lifecycle:transition" value="complete" />
70
+ <string key="cpee:lifecycle:transition" value="activity/calling"/>
71
+ <date key="time:timestamp" value=""/>
72
+ </global>
73
+ <trace/>
74
+ </log>
75
+ END
76
+
77
+ def rec_type(it)
78
+ if (Time.parse(it) rescue nil)
79
+ 'x:date'
80
+ elsif it.is_a? Float
81
+ 'x:float'
82
+ elsif it.is_a? Integer
83
+ 'x:int'
84
+ elsif it.is_a? String
85
+ 'x:string'
86
+ end
87
+ end
88
+
89
+ def rec_a_insert(event,node,level=0)
90
+ event.each do |i|
91
+ tnode = node
92
+ # tnode = node.add('x:string', 'key' => 'item')
93
+ case i
94
+ when Hash
95
+ rec_insert(i,tnode,level+1)
96
+ when Array
97
+ rec_a_insert(i,tnode,level+1)
98
+ when String
99
+ node.add(rec_type(i), 'key' => i, 'value' => i)
100
+ end
101
+ end
102
+ end
103
+
104
+ def rec_insert(event,node,level=0)
105
+ event.each do |k,v|
106
+ case v
107
+ when String
108
+ node.add(rec_type(v), 'key' => k, 'value' => v)
109
+ when Array
110
+ tnode = node.add('x:list', 'key' => k)
111
+ rec_a_insert(v,tnode,level+1)
112
+ when Hash
113
+ tnode = node.add('x:string', 'key' => k)
114
+ rec_insert(v,tnode)
115
+ end
116
+ end
117
+ end
118
+
119
+ def follow(fname,io,copy,deep=0,index=nil)
50
120
  tname = if fname =~ /\.xes\.shift\.yaml/
51
121
  File.basename(fname,'.xes.shift.yaml')
52
122
  elsif fname =~ /\.xes\.yaml/
@@ -58,7 +128,7 @@ def follow(fname,io,copy,deep=0)
58
128
  end
59
129
  YAML.load_stream(io) do |e|
60
130
  if name = e.dig('log','trace','cpee:name')
61
- puts " " * deep + name + " (#{tname}) - #{e.dig('log','trace','concept:name')}"
131
+ index.write " " * deep + name + " (#{tname}) - #{e.dig('log','trace','concept:name')}\n"
62
132
  end
63
133
  if e.dig('event','cpee:lifecycle:transition') == 'task/instantiation'
64
134
  base = e.dig('event','raw')
@@ -68,13 +138,14 @@ def follow(fname,io,copy,deep=0)
68
138
  end
69
139
  uuid = base.dig('CPEE-INSTANCE-UUID') rescue nil
70
140
  if uuid
71
- react File.dirname(fname) + "/#{uuid}.xes.yaml",copy,deep + 2
141
+ react File.dirname(fname) + "/#{uuid}.xes.yaml", copy, deep + 2, index
72
142
  end
73
143
  end
74
144
  end
75
145
  end
76
146
 
77
- def react(name,copy=false,deep=0)
147
+ def react(name,copy=false,deep=0,index=nil)
148
+ index ||= File.open('index.txt','w')
78
149
  if name.nil?
79
150
  help
80
151
  elsif name =~ /^https?:\/\//
@@ -83,59 +154,72 @@ def react(name,copy=false,deep=0)
83
154
  file = Tempfile.new('sic')
84
155
  file.write(res.body)
85
156
  file.rewind
86
- follow name, file, copy, deep
157
+ follow name, file, copy, deep, index
87
158
  file.close
88
159
  file.unlink
89
160
  end
90
161
  elsif File.exist? name
91
- follow name, File.open(name), copy, deep
162
+ follow name, File.open(name), copy, deep, index
92
163
  else
93
164
  help
94
165
  end
95
166
  end
96
167
 
97
168
  def extract(path)
169
+ unlink = false
98
170
  if path =~ /^http.*/
99
- response = Typhoeus.get(path)
100
- if response.success?
101
- text = response.response_body
171
+ unlink = true
172
+ text = Tempfile.new('extract-model-download')
173
+ request = Typhoeus::Request.new("www.example.com/huge.iso")
174
+ request.on_headers do |response|
175
+ if response.code != 200
176
+ raise "Request failed"
177
+ end
178
+ end
179
+ request.on_body do |chunk|
180
+ text.write(chunk)
181
+ end
182
+ request.on_complete do |response|
183
+ text.rewind
102
184
  end
185
+ request.run
103
186
  else
104
- text = File.read(path)
187
+ text = File.open(path)
105
188
  end
106
189
  yaml = Psych.load_stream(text)
107
190
  changes = []
108
191
 
109
- info = yaml.shift()
192
+ info = yaml.shift
110
193
  uuid = info.dig('log','trace','cpee:instance')
111
- yaml.each() do |el|
112
- if(el['event']['id:id'] == 'external' && (el.dig('event','cpee:lifecycle:transition') == 'endpoints/change' || el.dig('event','cpee:lifecycle:transition') == 'dataelements/change'|| el.dig('event','cpee:lifecycle:transition') == 'description/change'))
194
+ yaml.each do |el|
195
+ if el['event']['id:id'] == 'external' && (el.dig('event','cpee:lifecycle:transition') == 'endpoints/change' || el.dig('event','cpee:lifecycle:transition') == 'dataelements/change'|| el.dig('event','cpee:lifecycle:transition') == 'description/change')
113
196
  changes.push(el)
114
197
  end
115
198
  end
116
- #puts "found #{changes.size()} changes"
117
199
 
118
- changes.sort!() {|a,b| DateTime.strptime(a.dig('event','time:timestamp'),'%Y-%m-%dT%H:%M:%S.%L%:z') <=> DateTime.strptime(b.dig('event','time:timestamp'),'%Y-%m-%dT%H:%M:%S.%L%:z')}
119
- #p changes.map() {|el| el.dig('event','time:timestamp')}
200
+ changes.sort! { |a,b| DateTime.strptime(a.dig('event','time:timestamp'),'%Y-%m-%dT%H:%M:%S.%L%:z') <=> DateTime.strptime(b.dig('event','time:timestamp'),'%Y-%m-%dT%H:%M:%S.%L%:z') }
120
201
 
121
202
  de = ep = desc = nil
122
203
  counter = 0
123
- changes.each() do |change|
124
- if(change.dig('event','cpee:lifecycle:transition') == 'dataelements/change') then
204
+ changes.each do |change|
205
+ if change.dig('event','cpee:lifecycle:transition') == 'dataelements/change'
125
206
  de = change.dig('event','data')
126
207
  end
127
- if(change.dig('event','cpee:lifecycle:transition') == 'endpoints/change') then
208
+ if change.dig('event','cpee:lifecycle:transition') == 'endpoints/change'
128
209
  ep = change.dig('event','data')
129
210
  end
130
- if(change.dig('event','cpee:lifecycle:transition') == 'description/change') then
211
+ if change.dig('event','cpee:lifecycle:transition') == 'description/change'
131
212
  desc = change.dig('event','cpee:description')
132
213
  end
133
- if(change.dig('event','cpee:lifecycle:transition') == 'description/change' || change.dig('event','cpee:lifecycle:transition') == 'endpoints/change') then
214
+ if change.dig('event','cpee:lifecycle:transition') == 'description/change' || change.dig('event','cpee:lifecycle:transition') == 'endpoints/change'
134
215
  yield uuid, de, ep, desc, counter if block_given?
135
216
  counter += 1
136
217
  end
137
218
  end
138
219
 
220
+ text.close
221
+ text.unlink if unlink
222
+
139
223
  [de, ep, desc]
140
224
  end
141
225
 
@@ -153,21 +237,28 @@ ARGV.options { |opt|
153
237
  opt.on("")
154
238
  opt.on(wrap("new [DIR] scaffolds a sample logging service. Add a handler to a cpee instance to experience the pleasure."))
155
239
  opt.on("")
156
- opt.on(wrap("view [DIR] view the dependencies between processes and subprocesses. Works for local and remote logs. Examples:\n#{exname} view https://cpee.org/log/123.xes.yaml\n#{exname} view https://cpee.org/log/a.xes.yaml > index.txt\n#{exname} view ~/log/logs/456.xes.yaml"))
240
+ opt.on(wrap("view [LOG] view the dependencies between processes and subprocesses. Works for local and remote logs. Examples:\n#{exname} view https://cpee.org/log/123.xes.yaml\n#{exname} view https://cpee.org/log/a.xes.yaml > index.txt\n#{exname} view ~/log/logs/456.xes.yaml"))
157
241
  opt.on("")
158
- opt.on(wrap("copy [DIR] copy dependent processes and subprocesses to the current directory. Works for local and remote logs. Examples: \n#{exname} copy https://cpee.org/log/123.xes.yaml\n#{exname} copy ~/log/logs/456.xes.yaml"))
242
+ opt.on(wrap("copy [LOG] copy dependent processes and subprocesses to the current directory. Works for local and remote logs. Examples: \n#{exname} copy https://cpee.org/log/123.xes.yaml\n#{exname} copy ~/log/logs/456.xes.yaml"))
159
243
  opt.on("")
160
244
  opt.on(wrap("extract-all [LOG] extract cpee testset from cpee xes-yaml log. Works for local and remote logs. Write logs to files in folder named like the instance uuid contained in the log. Examples: \n#{exname} extract https://cpee.org/log/123.xes.yaml\n#{exname} extract ~/log/logs/456.xes.yaml"))
161
245
  opt.on("")
162
- opt.on(wrap("extract-last [LOG] extract cpee testset from cpee xes-yaml log. Works for local and remote logs. Write last revision of the model to stdout. Examples:\n#{exname} extract https://cpee.org/log/123.xes.yaml\n#{exname} extract ~/log/logs/456.xes.yaml"))
246
+ opt.on(wrap("extract-last [LOG] extract cpee testset from cpee xes-yaml log. Works for local and remote logs. When called with out [LOG], models for all log files in the current directory are extracted. Examples:\n#{exname} extract https://cpee.org/log/123.xes.yaml\n#{exname} extract ~/log/logs/456.xes.yaml"))
247
+ opt.on("")
248
+ opt.on(wrap("index [LOG] creates an index for a log file, for more efficient parsing. When called without [LOG], indexes all log files in the current directory. Examples:\n#{exname} index https://cpee.org/log/123.xes.yaml\n#{exname} index ~/log/logs/456.xes.yaml"))
249
+ opt.on("")
250
+ opt.on(wrap("to-xes-xml [LOG] convert cpee xes-yaml to xes-xml. Works for local and remote logs. When called with out [LOG], all log files in the current directory are converted. Examples:\n#{exname} to-xes-xml https://cpee.org/log/123.xes.yaml\n#{exname} to-xes-xml ~/log/logs/456.xes.yaml"))
163
251
  opt.parse!
164
252
  }
165
- if (ARGV.length != 2)
253
+
254
+ if (ARGV.length < 1 || ARGV.length > 2)
166
255
  puts ARGV.options
167
256
  exit
168
- else
257
+ elsif ARGV.length == 2
169
258
  command = ARGV[0]
170
259
  path = ARGV[1]
260
+ elsif ARGV.length == 1 && %w{index extract-last to-xes-xml}.include?(ARGV[0])
261
+ command = ARGV[0]
171
262
  end
172
263
 
173
264
  if command == 'new'
@@ -206,27 +297,108 @@ elsif command == 'extract-all'
206
297
  File.write(filename, xml.to_s())
207
298
  end
208
299
  elsif command == 'extract-last'
209
- de, ep, desc = extract(path)
300
+ path = if path
301
+ [path]
302
+ else
303
+ Dir.glob('*.xes.yaml')
304
+ end
305
+
306
+ path.each do |f|
307
+ de, ep, desc = extract(f)
210
308
 
211
- xml = XML::Smart.string('<testset xmlns="http://cpee.org/ns/properties/2.0"><executionhandler>ruby</executionhandler></testset>')
212
- dataelements = xml.root().add('dataelements')
213
- endpoints = xml.root().add('endpoints')
214
- description = xml.root().add('description').add(XML::Smart.string('<description xmlns="http://cpee.org/ns/description/1.0"/>').root())
215
- unless de.nil?
216
- de.each do |d|
217
- dataelements.add(d['name'],d['value'])
309
+ xml = XML::Smart.string('<testset xmlns="http://cpee.org/ns/properties/2.0"><executionhandler>ruby</executionhandler></testset>')
310
+ dataelements = xml.root().add('dataelements')
311
+ endpoints = xml.root().add('endpoints')
312
+ description = xml.root().add('description').add(XML::Smart.string('<description xmlns="http://cpee.org/ns/description/1.0"/>').root())
313
+ unless de.nil?
314
+ de.each do |d|
315
+ dataelements.add(d['name'],d['value'])
316
+ end
317
+ end
318
+ unless ep.nil?
319
+ ep.each do |e|
320
+ endpoints.add(e['name'],e['value'])
321
+ end
322
+ end
323
+ unless desc.nil?
324
+ description.replace_by(XML::Smart.string(desc).root())
218
325
  end
326
+
327
+ File.write(f + '.model', xml.to_s)
328
+ end
329
+ elsif command == 'index'
330
+ path = if path
331
+ [path]
332
+ else
333
+ Dir.glob('*.xes.yaml')
219
334
  end
220
- unless ep.nil?
221
- ep.each do |e|
222
- endpoints.add(e['name'],e['value'])
335
+
336
+ path.each do |f|
337
+ index = []
338
+ io = File.open(f)
339
+ while not io.eof?
340
+ start = io.pos
341
+ docs = io.readline("---\n",chomp: true)
342
+ doc = YAML::load(docs, permitted_classes: [Time])
343
+ if doc
344
+ transition = doc.dig('event','cpee:lifecycle:transition')
345
+ if transition =~ /^(activity\/calling|activity\/receiving|task\/instantiation)/
346
+ endpoint = doc.dig('event','concept:endpoint')
347
+ uuid = doc.dig('event','cpee:activity_uuid')
348
+ transition = case transition
349
+ when 'activity/calling'
350
+ 'c'
351
+ when 'activity/receiving'
352
+ 'r'
353
+ when 'task/instantiation'
354
+ 'i'
355
+ end
356
+ index << { :e => endpoint.to_s, :u => uuid.to_s, :t => transition.to_s, :s => start.to_i, :l => docs.length.to_i }
357
+ end
358
+ end
359
+ end
360
+ io.close
361
+ CSV.open(f + '.index.csv', 'w') do |csv|
362
+ index.each do |e|
363
+ csv << e.values
364
+ end
223
365
  end
366
+
367
+ nindex = index.group_by{ |a| a[:u] }.collect do |k,v|
368
+ [v[0][:e], v.collect{ |a| [ a[:t], {:s => a[:s], :l => a[:l]} ] } ]
369
+ end
370
+
371
+ File.write(f + '.index', MessagePack.pack(nindex))
224
372
  end
225
- unless desc.nil?
226
- description.replace_by(XML::Smart.string(desc).root())
373
+ elsif command == 'to-xes-xml'
374
+ path = if path
375
+ [path]
376
+ else
377
+ Dir.glob('*.xes.yaml')
227
378
  end
228
379
 
229
- puts xml.to_s
380
+ path.each do |f|
381
+ xml = XML::Smart.string(TEMPLATE_XES_XML)
382
+ xml.register_namespace 'x', 'http://www.xes-standard.org/'
383
+
384
+ io = File.open(f)
385
+ YAML.load_stream(io) do |e|
386
+ if trace = e.dig('log','trace')
387
+ trace.each do |t,tv|
388
+ xml.find('//x:trace').each do |ele|
389
+ ele.add('x:string', 'key' => t, 'value' => tv)
390
+ end
391
+ end
392
+ end
393
+ if e.dig('event')
394
+ xml.find('//x:trace').each do |node|
395
+ rec_insert(e.dig('event'),node.add('x:event'))
396
+ end
397
+ end
398
+ end
399
+
400
+ File.write(File.basename(f,'.xes.yaml') + '.xes.xml', xml.to_s)
401
+ end
230
402
  else
231
403
  puts ARGV.options
232
404
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cpee-logging-xes-yaml
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.4
4
+ version: 1.3.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juergen eTM Mangler
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: tools
11
11
  cert_chain: []
12
- date: 2024-01-17 00:00:00.000000000 Z
12
+ date: 2024-03-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: riddl