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 +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
|