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 +4 -4
- data/cpee-logging-xes-yaml.gemspec +1 -1
- data/lib/cpee-logging-xes-yaml/logging.rb +98 -72
- data/lib/cpee-logging-xes-yaml/logging.xml +25 -0
- data/lib/cpee-logging-xes-yaml/template.xes_yaml +9 -7
- data/lib/cpee-logging-xes-yaml/tools.rb +359 -0
- data/lib/cpee-logging-xes-yaml/topics.xml +36 -0
- data/server/log +18 -0
- data/tools/cpee-logging-xes-yaml +27 -5
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 99c79d272d96fc0194b782ae5f93492b7a50f5daac07cb60da447d2be314cbc8
|
4
|
+
data.tar.gz: ceb9ac1ca98aa9bae3fc4fb15c3e617ec306fa00bc62e8f627888169ee8ca703
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fe2f39dad68c6a86308811d25df6a1e41e9133984c1c67c6512240128abce5fa57727f915615cbe2fae21ef61bead8ab20b36e5c8bbab43181d7a9a38d116459
|
7
|
+
data.tar.gz: 94fa1197bc3e2b820464c947204aaa3ec376c13d90a87f3f371c11c39548aee98c4ec6fc71de28969ef319e07df780eb024db674e5777e33796cfc8a62b9dc51
|
@@ -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
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
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
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
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
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
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
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
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]
|
108
|
-
opts[:
|
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
|
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
|
-
|
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!
|
data/tools/cpee-logging-xes-yaml
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
|
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
|
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 + " (#{
|
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','
|
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.
|
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.
|
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.
|
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:
|
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.
|
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)
|