cpee-logging-xes-yaml 1.0.5 → 1.3.2

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: 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)