cpee-logging-xes-yaml 1.0.5 → 1.3.2

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: 897f6d719b02a41bbec8577cbcc0cfb0c21d45e4c82a569903a9d2260ec95ce6
4
- data.tar.gz: 52a03e45692b299d2548a132c5549787f04dc935268b467fb9c47dd777a26ac5
3
+ metadata.gz: 99c79d272d96fc0194b782ae5f93492b7a50f5daac07cb60da447d2be314cbc8
4
+ data.tar.gz: ceb9ac1ca98aa9bae3fc4fb15c3e617ec306fa00bc62e8f627888169ee8ca703
5
5
  SHA512:
6
- metadata.gz: 4dbab93362de5702354db2b62ccbe6fe5a2bf4d8305f87b9ccef877d542a62e62dc5804cae5b9d059c7930fdc1e2063dcce2d132fcf8a2e2b6418c7146e6db5c
7
- data.tar.gz: f1412da8132c5f8b7f67643ab8226a09262cef99f34b78f9de9a8941a5a3b947340acb85967b5f645c812853dd3c1740f5a4c34ea53040c34b1f3433d230d714
6
+ metadata.gz: fe2f39dad68c6a86308811d25df6a1e41e9133984c1c67c6512240128abce5fa57727f915615cbe2fae21ef61bead8ab20b36e5c8bbab43181d7a9a38d116459
7
+ data.tar.gz: 94fa1197bc3e2b820464c947204aaa3ec376c13d90a87f3f371c11c39548aee98c4ec6fc71de28969ef319e07df780eb024db674e5777e33796cfc8a62b9dc51
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "cpee-logging-xes-yaml"
3
- s.version = "1.0.5"
3
+ s.version = "1.3.2"
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)"
@@ -1,16 +1,16 @@
1
1
  # This file is part of CPEE-LOGGING-XES-YAML.
2
2
  #
3
3
  # CPEE-LOGGING-XES-YAML is free software: you can redistribute it and/or modify it
4
- # under the terms of the GNU General Public License as published by the Free
4
+ # under the terms of the GNU Lesser General Public License as published by the Free
5
5
  # Software Foundation, either version 3 of the License, or (at your option) any
6
6
  # later version.
7
7
  #
8
8
  # CPEE-LOGGING-XES-YAML is distributed in the hope that it will be useful, but
9
9
  # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
- # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
10
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
11
11
  # more details.
12
12
  #
13
- # You should have received a copy of the GNU General Public License along with
13
+ # You should have received a copy of the GNU Lesser General Public License along with
14
14
  # CPEE-LOGGING-XES-YAML (file LICENSE in the main directory). If not, see
15
15
  # <http://www.gnu.org/licenses/>.
16
16
 
@@ -21,95 +21,121 @@ require 'yaml'
21
21
  require 'riddl/server'
22
22
  require 'time'
23
23
 
24
+ require_relative 'tools'
25
+
24
26
  module CPEE
25
27
  module Logging
26
28
 
27
29
  SERVER = File.expand_path(File.join(__dir__,'logging.xml'))
28
30
 
29
- class Handler < Riddl::Implementation #{{{
30
- def doc(topic,event_name,log_dir,template,notification)
31
- instance = notification['instance-uuid']
32
- return unless instance
33
-
34
- instancenr = notification['instance']
35
- content = notification['content']
36
- activity = content['activity']
37
- parameters = content['parameters']
38
- receiving = content['received']
39
-
40
- log = YAML::load(File.read(template))
41
- log["log"]["trace"]["concept:name"] ||= instancenr
42
- log["log"]["trace"]["cpee:name"] ||= notification['instance-name'] if notification['instance-name']
43
- log["log"]["trace"]["cpee:instance"] ||= instance
44
- File.open(File.join(log_dir,instance+'.xes.yaml'),'w'){|f| f.puts log.to_yaml} unless File.exists? File.join(log_dir,instance+'.xes.yaml')
45
- event = {}
46
- event["concept:instance"] = instancenr
47
- event["concept:name"] = content["label"] if content["label"]
48
- if content["endpoint"]
49
- event["concept:endpoint"] = content["endpoint"]
50
- end
51
- event["id:id"] = (activity.nil? || activity == "") ? 'external' : activity
52
- event["cpee:activity"] = event["id:id"]
53
- event["cpee:activity_uuid"] = content['activity-uuid'] if content['activity-uuid']
54
- event["cpee:instance"] = instance
55
- case event_name
56
- when 'receiving', 'change', 'instantiation'
57
- event["lifecycle:transition"] = "unknown"
58
- when 'done'
59
- event["lifecycle:transition"] = "complete"
60
- else
61
- event["lifecycle:transition"] = "start"
31
+ class Handler < Riddl::Implementation
32
+ def response
33
+ opts = @a[0]
34
+ type = @p[0].value
35
+ topic = @p[1].value
36
+ event_name = @p[2].value
37
+ payload = @p[3].value.read
38
+ EM.defer do
39
+ CPEE::Logging::forward opts, topic, event_name, payload
40
+ end if type == 'event'
41
+ EM.defer do
42
+ CPEE::Logging::doc opts, topic, event_name, payload
62
43
  end
63
- event["cpee:lifecycle:transition"] = "#{topic}/#{event_name}"
64
- event["cpee:state"] = content['state'] if content['state']
65
- event["cpee:description"] = content['dslx'] if content['dslx']
66
- data_send = ((parameters["arguments"].nil? ? [] : parameters["arguments"]) rescue [])
67
- event["data"] = {"data_send" => data_send} unless data_send.empty?
68
- if content['changed']&.any?
69
- if event.has_key? "data"
70
- event["data"]["data_changed"] ||= content['changed']
71
- else
72
- event["data"] = {"data_changer" => content['changed']}
73
- end
44
+ nil
45
+ end
46
+ end
47
+
48
+ class Overview < Riddl::Implementation #{{{
49
+ def response
50
+ Riddl::Parameter::Complex.new("overview","text/xml") do
51
+ <<-END
52
+ <overview xmlns='http://riddl.org/ns/common-patterns/notifications-producer/2.0'>
53
+ <topics/>
54
+ <subscriptions/>
55
+ </overview>
56
+ END
74
57
  end
75
- if content['values']&.any?
76
- if event.has_key? "data"
77
- event["data"]["data_values"] ||= content['values']
78
- else
79
- event["data"] = {"data_values" => content['values']}
80
- end
58
+ end
59
+ end #}}}
60
+
61
+ class Topics < Riddl::Implementation #{{{
62
+ def response
63
+ opts = @a[0]
64
+ Riddl::Parameter::Complex.new("overview","text/xml") do
65
+ File.read(opts[:topics])
81
66
  end
82
- if receiving && !receiving.empty?
83
- if event.has_key? "data"
84
- event["data"]["data_received"] ||= receiving
85
- else
86
- event["data"] = {"data_receiver" => receiving}
67
+ end
68
+ end #}}}
69
+
70
+ class Subscriptions < Riddl::Implementation #{{{
71
+ def response
72
+ opts = @a[0]
73
+ Riddl::Parameter::Complex.new("subscriptions","text/xml") do
74
+ ret = XML::Smart::string <<-END
75
+ <subscriptions xmlns='http://riddl.org/ns/common-patterns/notifications-producer/2.0'/>
76
+ END
77
+ Dir.glob(File.join(opts[:notifications_dir],'*','subscription.xml')).each do |f|
78
+ ret.root.add('subscription').tap do |n|
79
+ n.attributes['id'] = File.basename(File.dirname(f))
80
+ XML::Smart.open_unprotected(f) do |doc|
81
+ n.attributes['url'] = doc.root.attributes['url']
82
+ end
83
+ end
87
84
  end
85
+ ret.to_s
88
86
  end
89
- event["time:timestamp"]= event['cpee:timestamp'] || Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L%:z")
90
- File.open(File.join(log_dir,instance+'.xes.yaml'),'a') do |f|
91
- f << {'event' => event}.to_yaml
92
- end
93
- nil
94
87
  end
88
+ end #}}}
95
89
 
90
+ class Subscription < Riddl::Implementation #{{{
96
91
  def response
97
- topic = @p[1].value
98
- event_name = @p[2].value
99
- log_dir = @a[0]
100
- template = @a[1]
101
- notification = JSON.parse(@p[3].value.read)
102
- doc topic, event_name, log_dir, template, notification
92
+ opts = @a[0]
93
+ id = @r[-1]
94
+ doc = XML::Smart::open_unprotected(File.join(opts[:notifications_dir],id,'subscription.xml'))
95
+ doc.root.attributes['id'] = id
96
+ Riddl::Parameter::Complex.new("subscriptions","text/xml",doc.to_s)
103
97
  end
104
98
  end #}}}
105
99
 
106
100
  def self::implementation(opts)
107
- opts[:log_dir] ||= File.join(__dir__,'logs')
108
- opts[:template] ||= File.join(__dir__,'template.xes_yaml')
101
+ opts[:log_dir] ||= File.expand_path(File.join(__dir__,'logs'))
102
+ opts[:notifications_dir] ||= File.expand_path(File.join(__dir__,'notifications'))
103
+ opts[:template] ||= File.expand_path(File.join(__dir__,'template.xes_yaml'))
104
+ opts[:topics] ||= File.expand_path(File.join(__dir__,'topics.xml'))
105
+ opts[:subscriptions] = {}
106
+
107
+ Dir.glob(File.join(opts[:notifications_dir],'*','subscription.xml')).each do |f|
108
+ XML::Smart::open_unprotected(f) do |doc|
109
+ doc.register_namespace :p, 'http://riddl.org/ns/common-patterns/notifications-producer/2.0'
110
+ doc.find('/p:subscription/p:topic').each do |t|
111
+ t.find('p:event').each do |e|
112
+ opts[:subscriptions][t.attributes['id']+'/'+e.text] ||= []
113
+ opts[:subscriptions][t.attributes['id']+'/'+e.text] << doc.root.attributes['url']
114
+ end
115
+ end
116
+ end
117
+ end
109
118
 
110
119
  Proc.new do
111
120
  interface 'events' do
112
- run Handler, opts[:log_dir], opts[:template] if post 'event'
121
+ run Handler, opts if post 'event'
122
+ end
123
+ interface 'notifications' do
124
+ on resource "notifications" do
125
+ run Overview if get
126
+ on resource "topics" do
127
+ run Topics, opts if get
128
+ end
129
+ on resource "subscriptions" do
130
+ run Subscriptions, opts if get
131
+ run CreateSubscription, opts if post 'create_subscription'
132
+ on resource do
133
+ run Subscription, opts if get
134
+ run UpdateSubscription, opts if put 'change_subscription'
135
+ run DeleteSubscription, opts if delete
136
+ end
137
+ end
138
+ end
113
139
  end
114
140
  end
115
141
  end
@@ -1,13 +1,38 @@
1
+ <!--
2
+ This file is part of CPEE-LOGGING-XES-YAML.
3
+
4
+ CPEE-LOGGING-XES-YAML is free software: you can redistribute it and/or modify
5
+ it under the terms of the GNU Lesser General Public License as published by the Free
6
+ Software Foundation, either version 3 of the License, or (at your option) any
7
+ later version.
8
+
9
+ CPEE-LOGGING-XES-YAML is distributed in the hope that it will be useful, but
10
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
12
+ more details.
13
+
14
+ You should have received a copy of the GNU Lesser General Public License along with
15
+ CPEE-LOGGING-XES-YAML (file LICENSE in the main directory). If not, see
16
+ <http://www.gnu.org/licenses/>.
17
+ -->
18
+
1
19
  <declaration xmlns="http://riddl.org/ns/declaration/1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
2
20
  <interface name="events">
3
21
  <xi:include href="http://www.riddl.org/ns/common-patterns/notifications-consumer/2.0/consumer.xml"/>
4
22
  </interface>
23
+ <interface name="notifications">
24
+ <xi:include href="http://www.riddl.org/ns/common-patterns/notifications-producer/2.0/producer.xml"/>
25
+ </interface>
5
26
 
6
27
  <facade>
7
28
  <tile>
8
29
  <layer name="events">
9
30
  <apply-to>/</apply-to>
10
31
  </layer>
32
+ <layer name="notifications">
33
+ <apply-to>/</apply-to>
34
+ <block method="sse">/notifications/subscriptions/{}/sse</block>
35
+ </layer>
11
36
  </tile>
12
37
  </facade>
13
38
  </declaration>
@@ -1,11 +1,19 @@
1
1
  ---
2
2
  log:
3
+ namespaces:
4
+ stream: https://cpee.org/datastream/
5
+ ssn: http://www.w3.org/ns/ssn/
6
+ sosa: http://www.w3.org/ns/sosa/
7
+ xes:
8
+ creator: cpee.org
9
+ features: nested-attributes
3
10
  extension:
4
11
  time: http://www.xes-standard.org/time.xesext
5
12
  concept: http://www.xes-standard.org/concept.xesext
6
- organisational: http://www.xes-standard.org/org.xesext
13
+ id: http://www.xes-standard.org/identity.xesext
7
14
  lifecycle: http://www.xes-standard.org/lifecycle.xesext
8
15
  cpee: http://cpee.org/cpee.xesext
16
+ stream: https://cpee.org/datastream/datastream.xesext
9
17
  global:
10
18
  trace:
11
19
  concept:name: __INVALID__
@@ -19,10 +27,4 @@ log:
19
27
  lifecycle:transition: complete
20
28
  cpee:lifecycle:transition: activity/calling
21
29
  time:timestamp: ''
22
- classifier:
23
- Data: data_send data_received data_changed data_values
24
- Data_Received: data_receiver
25
- Data_Send: data_send
26
- Data_Changed: data_changer
27
- Data_Values: data_values
28
30
  trace: {}
@@ -0,0 +1,359 @@
1
+ # This file is part of CPEE-LOGGING-XES-YAML.
2
+ #
3
+ # CPEE-LOGGING-XES-YAML is free software: you can redistribute it and/or modify it
4
+ # under the terms of the GNU Lesser General Public License as published by the Free
5
+ # Software Foundation, either version 3 of the License, or (at your option) any
6
+ # later version.
7
+ #
8
+ # CPEE-LOGGING-XES-YAML is distributed in the hope that it will be useful, but
9
+ # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
11
+ # more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public License along with
14
+ # CPEE-LOGGING-XES-YAML (file LICENSE in the main directory). If not, see
15
+ # <http://www.gnu.org/licenses/>.
16
+
17
+ require 'weel'
18
+ require 'digest/sha1'
19
+
20
+ class StreamPoint
21
+ attr_accessor :value, :timestamp, :source, :meta
22
+ attr_reader :id
23
+
24
+ def initialize(id)
25
+ @id = id
26
+ @value = nil
27
+ @timestamp = Time.now
28
+ @source = nil
29
+ @meta = nil
30
+ end
31
+
32
+ def to_h
33
+ tp = { }
34
+ tp['stream:id'] = @id
35
+ tp['stream:value'] = @value
36
+ tp['stream:timestamp'] = @timestamp
37
+ tp['stream:source'] = @source unless @source.nil?
38
+ tp['stream:meta'] = @meta unless @meta.nil?
39
+ tp
40
+ end
41
+ end
42
+ class Stream
43
+ attr_accessor :id, :source, :meta
44
+ attr_reader :name
45
+
46
+ def initialize(name)
47
+ @name = name
48
+ @id = nil
49
+ @source = nil
50
+ @meta = nil
51
+ @values = []
52
+ end
53
+
54
+ def <<(val)
55
+ @values << val
56
+ end
57
+
58
+ def to_list
59
+ tp = []
60
+ tp << {'stream:name' => @name}
61
+ tp << {'stream:id' => @id} unless @id.nil?
62
+ tp << {'stream:source' => @source} unless @source.nil?
63
+ tp << {'stream:meta' => @meta} unless @meta.nil?
64
+ @values.each do |e|
65
+ if e.is_a? Stream
66
+ e.source = @source if e.source.nil? && !@source.nil?
67
+ tp << { 'stream:datastream' => e.to_list }
68
+ elsif e.is_a? StreamPoint
69
+ e.source = @source if e.source.nil? && !@source.nil?
70
+ tp << { 'stream:point' => e.to_h }
71
+ end
72
+ end
73
+ tp
74
+ end
75
+ end
76
+
77
+ module CPEE
78
+ module Logging
79
+
80
+ def self::notify(opts,topic,event_name,payload)
81
+ opts[:subscriptions].each do |e,urls|
82
+ if e == topic + '/' + event_name
83
+ urls.each do |url|
84
+ client = Riddl::Client.new(url)
85
+ client.post [
86
+ Riddl::Parameter::Simple::new('type','event'),
87
+ Riddl::Parameter::Simple::new('topic',topic),
88
+ Riddl::Parameter::Simple::new('event',event_name),
89
+ Riddl::Parameter::Complex::new('notification','application/json',payload)
90
+ ]
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ def self::val_merge(target,val,tid,tso)
97
+ if val.is_a? Stream
98
+ val.source = tso if val.source.nil?
99
+ target.push *val.to_list
100
+ else
101
+ tp = nil
102
+ if val.is_a? StreamPoint
103
+ tp = val
104
+ tp.source = tso if tp.source.nil?
105
+ else
106
+ tp = StreamPoint.new(tid)
107
+ tp.source = tso
108
+ tp.value = val
109
+ end
110
+ target << { 'stream:point' => tp.to_h }
111
+ end
112
+ end
113
+
114
+ def self::extract_probes(where,xml)
115
+ XML::Smart::string(xml) do |doc|
116
+ doc.register_namespace 'd', 'http://cpee.org/ns/description/1.0'
117
+ doc.find('//d:call').each do |c|
118
+ File.unlink(where + '_' + c.attributes['id'] + '.probe') rescue nil
119
+ c.find('d:annotations/d:_context_data_analysis/d:probes[d:probe]').each do |p|
120
+ File.write(where + '_' + c.attributes['id'] + '.probe', p.dump)
121
+ end
122
+ end
123
+ end
124
+ end
125
+ def self::extract_annotations(where,xml)
126
+ ret = {}
127
+ XML::Smart::string(xml) do |doc|
128
+ doc.register_namespace 'd', 'http://cpee.org/ns/description/1.0'
129
+ doc.find('/d:description | //d:call').each do |c|
130
+ tid = c.attributes['id'] || 'start'
131
+ fname = where + '_' + tid + '.anno'
132
+ nset = if tid == 'start'
133
+ c.find('d:*[starts-with(name(),"_")]')
134
+ else
135
+ c.find('d:annotations')
136
+ end
137
+ nset.each do |p|
138
+ anno = p.dump
139
+ ret[tid] ||= []
140
+ ret[tid] << anno
141
+ end
142
+ if ret[tid]
143
+ if ret[tid].length > 1
144
+ ret[tid] = "<annotations xmlns=\"http://cpee.org/ns/description/1.0\">\n" +
145
+ ret[tid].join("\n") + "\n" +
146
+ "</annotations>"
147
+ else
148
+ ret[tid] = ret[tid][0]
149
+ end
150
+ hash = Digest::SHA1.hexdigest(ret[tid])
151
+ if !File.exist?(fname) || (File.exist?(fname) && File.read(fname) != hash)
152
+ File.write(fname,hash)
153
+ end
154
+ end
155
+ end
156
+ end
157
+ ret
158
+ end
159
+
160
+ def self::extract_result(result)
161
+ ret = result.map do |res|
162
+ if res['mimetype'].nil?
163
+ res['value']
164
+ elsif res['mimetype'] == 'application/json'
165
+ JSON::parse(res['data'])
166
+ elsif res['mimetype'] == 'application/xml' || res['mimetype'] == 'text/xml'
167
+ XML::Smart::string(res['data']) rescue nil
168
+ elsif res['mimetype'] == 'text/yaml'
169
+ YAML::load(res['data']) rescue nil
170
+ elsif res['mimetype'] == 'text/plain'
171
+ t = res['data']
172
+ if t.start_with?("<?xml version=")
173
+ t = XML::Smart::string(t)
174
+ else
175
+ t = t.to_f if t == t.to_f.to_s
176
+ t = t.to_i if t == t.to_i.to_s
177
+ end
178
+ t
179
+ elsif res['mimetype'] == 'text/html'
180
+ t = res['data']
181
+ t = t.to_f if t == t.to_f.to_s
182
+ t = t.to_i if t == t.to_i.to_s
183
+ t
184
+ else
185
+ res['data']
186
+ end
187
+ end
188
+ ret.length == 1 ? ret[0] : ret
189
+ end
190
+
191
+ def self::extract_sensor(rs,code,pid,result)
192
+ rs.instance_eval(code,'probe',1)
193
+ rescue => e
194
+ e.backtrace[0].gsub(/(\w+):(\d+):in.*/,'Probe ' + pid + ' Line \2: ') + e.message
195
+ end
196
+
197
+ def self::persist_values(where,values)
198
+ unless File.exist?(where)
199
+ File.write(where,'{}')
200
+ end
201
+ f = File.open(where,'r+')
202
+ f.flock(File::LOCK_EX)
203
+ json = JSON::load(f) || {}
204
+ json.merge!(values)
205
+ f.rewind
206
+ f.truncate(0)
207
+ f.write(JSON.generate(json))
208
+ f.close
209
+ end
210
+
211
+ def self::forward(opts,topic,event_name,payload)
212
+ if topic == 'state' && event_name == 'change'
213
+ self::notify(opts,topic,event_name,payload)
214
+ elsif topic == 'state' && event_name == 'change'
215
+ self::notify(opts,topic,event_name,payload)
216
+ elsif topic == 'gateway' && event_name == 'join'
217
+ self::notify(opts,topic,event_name,payload)
218
+ end
219
+ end
220
+
221
+ def self::doc(opts,topic,event_name,payload)
222
+ notification = JSON.parse(payload)
223
+ instance = notification['instance-uuid']
224
+ return unless instance
225
+
226
+ log_dir = opts[:log_dir]
227
+ template = opts[:template]
228
+
229
+ instancenr = notification['instance']
230
+ content = notification['content']
231
+ activity = content['activity']
232
+ parameters = content['parameters']
233
+ receiving = content['received']
234
+
235
+ if content['dslx']
236
+ CPEE::Logging::extract_probes(File.join(log_dir,instance),content['dslx'])
237
+ CPEE::Logging::extract_annotations(File.join(log_dir,instance),content['dslx']).each do |k,v|
238
+ so = Marshal.load(Marshal.dump(notification))
239
+ so['content'].delete('dslx')
240
+ so['content'].delete('dsl')
241
+ so['content'].delete('description')
242
+ so['content']['annotation'] = v
243
+ so['content']['activity'] = k
244
+ so['topic'] = 'annotation'
245
+ so['name'] = 'change'
246
+ EM.defer do
247
+ self::notify(opts,'annotation','change',so.to_json)
248
+ end
249
+ end
250
+ end
251
+
252
+ if topic == 'dataelements' && event_name == 'change'
253
+ if content['changed']&.any?
254
+ CPEE::Logging::persist_values(File.join(log_dir,instance + '.data.json'),content['values'])
255
+ end
256
+ end
257
+
258
+ log = YAML::load(File.read(template))
259
+ log["log"]["trace"]["concept:name"] ||= instancenr
260
+ log["log"]["trace"]["cpee:name"] ||= notification['instance-name'] if notification['instance-name']
261
+ log["log"]["trace"]["cpee:instance"] ||= instance
262
+ File.open(File.join(log_dir,instance+'.xes.yaml'),'w'){|f| f.puts log.to_yaml} unless File.exist? File.join(log_dir,instance+'.xes.yaml')
263
+ event = {}
264
+ event["concept:instance"] = instancenr
265
+ event["concept:name"] = content["label"] if content["label"]
266
+ if content["endpoint"]
267
+ event["concept:endpoint"] = content["endpoint"]
268
+ end
269
+ event["id:id"] = (activity.nil? || activity == "") ? 'external' : activity
270
+ event["cpee:activity"] = event["id:id"]
271
+ event["cpee:activity_uuid"] = content['activity-uuid'] if content['activity-uuid']
272
+ event["cpee:instance"] = instance
273
+ case event_name
274
+ when 'receiving', 'change', 'instantiation'
275
+ event["lifecycle:transition"] = "unknown"
276
+ when 'done'
277
+ event["lifecycle:transition"] = "complete"
278
+ else
279
+ event["lifecycle:transition"] = "start"
280
+ end
281
+ event["cpee:lifecycle:transition"] = "#{topic}/#{event_name}"
282
+ event["cpee:state"] = content['state'] if content['state']
283
+ event["cpee:description"] = content['dslx'] if content['dslx']
284
+ unless parameters["arguments"]&.nil?
285
+ event["data"] = parameters["arguments"]
286
+ end if parameters
287
+ if content['changed']&.any?
288
+ event["data"] = content['values'].map do |k,v|
289
+ { 'name' => k, 'value' => v }
290
+ end
291
+
292
+ fname = File.join(log_dir,instance + '_' + event["id:id"] + '.probe')
293
+ dname = File.join(log_dir,instance + '.data.json')
294
+
295
+ if File.exist?(fname)
296
+ rs = WEEL::ReadStructure.new(File.exist?(dname) ? JSON::load(File::open(dname)) : {},{},{},{})
297
+ XML::Smart::open_unprotected(fname) do |doc|
298
+ doc.register_namespace 'd', 'http://cpee.org/ns/description/1.0'
299
+ doc.find('//d:probe[d:extractor_type="intrinsic"]').each do |p|
300
+ pid = p.find('string(d:id)')
301
+ event['stream:datastream'] ||= []
302
+ val = CPEE::Logging::extract_sensor(rs,p.find('string(d:extractor_code)'),pid,nil) rescue nil
303
+ CPEE::Logging::val_merge(event['stream:datastream'],val,pid,p.find('string(d:source)'))
304
+ end
305
+ end
306
+ notification['datastream'] = event['stream:datastream']
307
+ EM.defer do
308
+ notification['topic'] = 'stream'
309
+ notification['name'] = 'extraction'
310
+ self::notify(opts,'stream','extraction',notification.to_json)
311
+ end
312
+ end
313
+ end
314
+ if topic == 'activity' && event_name == 'receiving' && receiving && !receiving.empty?
315
+ fname = File.join(log_dir,instance + '_' + event["id:id"] + '.probe')
316
+ dname = File.join(log_dir,instance + '.data.json')
317
+
318
+ if File.exist?(fname)
319
+ te = event.dup
320
+
321
+ rs = WEEL::ReadStructure.new(File.exist?(dname) ? JSON::load(File::open(dname)) : {},{},{},{})
322
+ XML::Smart::open_unprotected(fname) do |doc|
323
+ doc.register_namespace 'd', 'http://cpee.org/ns/description/1.0'
324
+ if doc.find('//d:probe/d:extractor_type[.="extrinsic"]').any?
325
+ rc = CPEE::Logging::extract_result(receiving)
326
+ doc.find('//d:probe[d:extractor_type="extrinsic"]').each do |p|
327
+ pid = p.find('string(d:id)')
328
+ te['stream:datastream'] ||= []
329
+ val = CPEE::Logging::extract_sensor(rs,p.find('string(d:extractor_code)'),pid,rc) rescue nil
330
+ CPEE::Logging::val_merge(te['stream:datastream'],val,pid,p.find('string(d:source)'))
331
+ end
332
+ end
333
+ end
334
+ if te['stream:datastream']
335
+ te["cpee:lifecycle:transition"] = "stream/data"
336
+ File.open(File.join(log_dir,instance+'.xes.yaml'),'a') do |f|
337
+ f << {'event' => te}.to_yaml
338
+ end
339
+ notification['datastream'] = te['stream:datastream']
340
+ EM.defer do
341
+ notification['topic'] = 'stream'
342
+ notification['name'] = 'extraction'
343
+ self::notify(opts,'stream','extraction',notification.to_json)
344
+ end
345
+ end
346
+ end
347
+ end
348
+ if receiving && !receiving.empty?
349
+ event["raw"] = receiving
350
+ end
351
+ event["time:timestamp"]= notification['timestamp'] || Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L%:z")
352
+ File.open(File.join(log_dir,instance+'.xes.yaml'),'a') do |f|
353
+ f << {'event' => event}.to_yaml
354
+ end
355
+ end
356
+
357
+ end
358
+ end
359
+
@@ -0,0 +1,36 @@
1
+ <!--
2
+ This file is part of CPEE-LOGGING-XES-YAML.
3
+
4
+ CPEE-LOGGING-XES-YAML is free software: you can redistribute it and/or modify
5
+ it under the terms of the GNU Lesser General Public License as published by the Free
6
+ Software Foundation, either version 3 of the License, or (at your option) any
7
+ later version.
8
+
9
+ CPEE-LOGGING-XES-YAML is distributed in the hope that it will be useful, but
10
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
12
+ more details.
13
+
14
+ You should have received a copy of the GNU Lesser General Public License along with
15
+ CPEE-LOGGING-XES-YAML (file LICENSE in the main directory). If not, see
16
+ <http://www.gnu.org/licenses/>.
17
+ -->
18
+
19
+ <topics xmlns='http://riddl.org/ns/common-patterns/notifications-producer/2.0'>
20
+ <topic id='annotation'>
21
+ <event>change</event>
22
+ </topic>
23
+ <topic id='stream'>
24
+ <event>extraction</event>
25
+ </topic>
26
+ <topic id='gateway'>
27
+ <event>decide</event>
28
+ <event>join</event>
29
+ </topic>
30
+ <topic id='state'>
31
+ <event>change</event>
32
+ </topic>
33
+ <topic id='task'>
34
+ <event>instantiation</event>
35
+ </topic>
36
+ </topics>
data/server/log CHANGED
@@ -1,4 +1,21 @@
1
1
  #!/usr/bin/ruby
2
+ #
3
+ # This file is part of CPEE-LOGGING-XES-YAML.
4
+ #
5
+ # CPEE-LOGGING-XES-YAML is free software: you can redistribute it and/or modify it
6
+ # under the terms of the GNU Lesser General Public License as published by the Free
7
+ # Software Foundation, either version 3 of the License, or (at your option) any
8
+ # later version.
9
+ #
10
+ # CPEE-LOGGING-XES-YAML is distributed in the hope that it will be useful, but
11
+ # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
13
+ # more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License along with
16
+ # CPEE-LOGGING-XES-YAML (file LICENSE in the main directory). If not, see
17
+ # <http://www.gnu.org/licenses/>.
18
+
2
19
  require 'rubygems'
3
20
  require 'cpee-logging-xes-yaml/logging'
4
21
 
@@ -13,6 +30,7 @@ Riddl::Server.new(CPEE::Logging::SERVER, options) do
13
30
  cross_site_xhr true
14
31
 
15
32
  @riddl_opts[:log_dir] ||= File.join(__dir__,'logs')
33
+ @riddl_opts[:subscriptions_dir] ||= File.join(__dir__,'subscriptions')
16
34
 
17
35
  use CPEE::Logging::implementation(@riddl_opts)
18
36
  end.loop!
@@ -1,4 +1,21 @@
1
1
  #!/usr/bin/ruby
2
+ #
3
+ # This file is part of CPEE-LOGGING-XES-YAML.
4
+ #
5
+ # CPEE-LOGGING-XES-YAML is free software: you can redistribute it and/or modify it
6
+ # under the terms of the GNU Lesser General Public License as published by the Free
7
+ # Software Foundation, either version 3 of the License, or (at your option) any
8
+ # later version.
9
+ #
10
+ # CPEE-LOGGING-XES-YAML is distributed in the hope that it will be useful, but
11
+ # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
13
+ # more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License along with
16
+ # CPEE-LOGGING-XES-YAML (file LICENSE in the main directory). If not, see
17
+ # <http://www.gnu.org/licenses/>.
18
+
2
19
  curpath = __dir__
3
20
  require 'rubygems'
4
21
  require 'optparse'
@@ -27,16 +44,21 @@ def wrap(s, width=78, indent=18, extra_indent=4)
27
44
  end
28
45
 
29
46
  def follow(fname,io,copy,deep=0)
47
+ tname = if fname =~ /\.xes\.shift\.yaml/
48
+ File.basename(fname,'.xes.shift.yaml')
49
+ elsif fname =~ /\.xes\.yaml/
50
+ File.basename(fname,'.xes.yaml')
51
+ end
30
52
  if copy
31
- File.write(File.basename(fname,'.xes.yaml') + '.xes.yaml',io.read)
53
+ File.write(File.basename(fname),io.read)
32
54
  io.rewind
33
55
  end
34
56
  YAML.load_stream(io) do |e|
35
57
  if name = e.dig('log','trace','cpee:name')
36
- puts " " * deep + name + " (#{File.basename(fname,'.xes.yaml')}) - #{e.dig('log','trace','concept:name')}"
58
+ puts " " * deep + name + " (#{tname}) - #{e.dig('log','trace','concept:name')}"
37
59
  end
38
60
  if e.dig('event','cpee:lifecycle:transition') == 'task/instantiation'
39
- base = e.dig('event','data','data_receiver')
61
+ base = e.dig('event','raw')
40
62
  val = base.dig('CPEE-INSTANCE') rescue nil
41
63
  if val.nil?
42
64
  val = File.basename(base)
@@ -62,7 +84,7 @@ def react(name,copy=false,deep=0)
62
84
  file.close
63
85
  file.unlink
64
86
  end
65
- elsif File.exists? name
87
+ elsif File.exist? name
66
88
  follow name, File.open(name), copy, deep
67
89
  else
68
90
  help
@@ -94,7 +116,7 @@ else
94
116
  end
95
117
 
96
118
  if command == 'new'
97
- if !File.exists?(dir)
119
+ if !File.exist?(dir)
98
120
  FileUtils.cp_r(File.join(curpath,'..','server'),dir)
99
121
  FileUtils.mkdir(File.join(dir,'logs')) rescue nil
100
122
  else
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.0.5
4
+ version: 1.3.2
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: 2021-11-04 00:00:00.000000000 Z
12
+ date: 2023-04-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: riddl
@@ -75,6 +75,8 @@ files:
75
75
  - lib/cpee-logging-xes-yaml/logging.rb
76
76
  - lib/cpee-logging-xes-yaml/logging.xml
77
77
  - lib/cpee-logging-xes-yaml/template.xes_yaml
78
+ - lib/cpee-logging-xes-yaml/tools.rb
79
+ - lib/cpee-logging-xes-yaml/topics.xml
78
80
  - server/log
79
81
  - tools/cpee-logging-xes-yaml
80
82
  homepage: http://cpee.org/
@@ -96,7 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
98
  - !ruby/object:Gem::Version
97
99
  version: '0'
98
100
  requirements: []
99
- rubygems_version: 3.2.22
101
+ rubygems_version: 3.3.26
100
102
  signing_key:
101
103
  specification_version: 4
102
104
  summary: Logging for the cloud process execution engine (cpee.org)