cpee-logging-xes-yaml 1.3.4 → 1.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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