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