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 +4 -4
- data/cpee-logging-xes-yaml.gemspec +1 -1
- data/tools/cpee-logging-xes-yaml +212 -40
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 899e0d2f04869dfa68eb7c7922222c825f87a1bd90d3b73f0cbb528bd95779d3
|
4
|
+
data.tar.gz: 64ef69bebaad740bb8ef4944fb2a5fa3a37d26ab1e0156bf58b75392c9fe8d39
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b0f53c72122468d2f3c4e6a17cd69a7bb7ca0c9088bb843e82ebe3700cb0e6b78a20b453d761648acba181afcb3f9122eb4e4a65c0da166f07249c7b3b48341
|
7
|
+
data.tar.gz: 0557b1e7f8cb2e1538b4984238530d713db7b7927b6ccba5abc949c1b2f180d307370c9d2d6781f689cfce156f1b19339e624dab2eae1a8dfc0478706329ed61
|
data/tools/cpee-logging-xes-yaml
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
100
|
-
|
101
|
-
|
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.
|
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
|
112
|
-
if
|
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!
|
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
|
124
|
-
if
|
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
|
208
|
+
if change.dig('event','cpee:lifecycle:transition') == 'endpoints/change'
|
128
209
|
ep = change.dig('event','data')
|
129
210
|
end
|
130
|
-
if
|
211
|
+
if change.dig('event','cpee:lifecycle:transition') == 'description/change'
|
131
212
|
desc = change.dig('event','cpee:description')
|
132
213
|
end
|
133
|
-
if
|
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 [
|
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 [
|
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.
|
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
|
-
|
253
|
+
|
254
|
+
if (ARGV.length < 1 || ARGV.length > 2)
|
166
255
|
puts ARGV.options
|
167
256
|
exit
|
168
|
-
|
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
|
-
|
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
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
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
|
-
|
221
|
-
|
222
|
-
|
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
|
-
|
226
|
-
|
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
|
-
|
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
|
+
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-
|
12
|
+
date: 2024-03-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: riddl
|