dicom 0.9.1 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +17 -0
- data/README.rdoc +16 -3
- data/lib/dicom.rb +3 -1
- data/lib/dicom/anonymizer.rb +35 -54
- data/lib/dicom/d_client.rb +49 -64
- data/lib/dicom/d_object.rb +511 -416
- data/lib/dicom/d_read.rb +21 -34
- data/lib/dicom/d_server.rb +21 -61
- data/lib/dicom/d_write.rb +3 -6
- data/lib/dicom/element.rb +1 -1
- data/lib/dicom/file_handler.rb +14 -9
- data/lib/dicom/image_item.rb +7 -6
- data/lib/dicom/link.rb +42 -77
- data/lib/dicom/logging.rb +158 -0
- data/lib/dicom/parent.rb +9 -8
- data/lib/dicom/sequence.rb +1 -1
- data/lib/dicom/version.rb +1 -1
- metadata +5 -4
data/lib/dicom/link.rb
CHANGED
@@ -3,6 +3,7 @@ module DICOM
|
|
3
3
|
# This class handles the construction and interpretation of network packages as well as network communication.
|
4
4
|
#
|
5
5
|
class Link
|
6
|
+
include Logging
|
6
7
|
|
7
8
|
# A customized FileHandler class to use instead of the default FileHandler included with Ruby DICOM.
|
8
9
|
attr_accessor :file_handler
|
@@ -10,12 +11,6 @@ module DICOM
|
|
10
11
|
attr_accessor :max_package_size
|
11
12
|
# A hash which keeps track of the relationship between context ID and chosen transfer syntax.
|
12
13
|
attr_accessor :presentation_contexts
|
13
|
-
# A boolean which defines if notices/warnings/errors will be printed to the screen (true) or not (false).
|
14
|
-
attr_accessor :verbose
|
15
|
-
# An array containing any error messages recorded.
|
16
|
-
attr_reader :errors
|
17
|
-
# An array containing any status messages recorded.
|
18
|
-
attr_reader :notices
|
19
14
|
# A TCP network session where the DICOM communication is done with a remote host or client.
|
20
15
|
attr_reader :session
|
21
16
|
|
@@ -32,7 +27,6 @@ module DICOM
|
|
32
27
|
# * <tt>:host_ae</tt> -- String. The name of the server (application entity).
|
33
28
|
# * <tt>:max_package_size</tt> -- Fixnum. The maximum allowed size of network packages (in bytes).
|
34
29
|
# * <tt>:timeout</tt> -- Fixnum. The maximum period to wait for an answer before aborting the communication.
|
35
|
-
# * <tt>:verbose</tt> -- Boolean. If set to false, the DLink instance will run silently and not output warnings and error messages to the screen. Defaults to true.
|
36
30
|
#
|
37
31
|
def initialize(options={})
|
38
32
|
require 'socket'
|
@@ -44,11 +38,6 @@ module DICOM
|
|
44
38
|
@max_receive_size = @max_package_size
|
45
39
|
@timeout = options[:timeout] || 10 # seconds
|
46
40
|
@min_length = 10 # minimum number of bytes to expect in an incoming transmission
|
47
|
-
@verbose = options[:verbose]
|
48
|
-
@verbose = true if @verbose == nil # Default verbosity is 'on'.
|
49
|
-
# Other instance variables:
|
50
|
-
@errors = Array.new # errors and warnings are put in this array
|
51
|
-
@notices = Array.new # information on successful transmissions are put in this array
|
52
41
|
# Variables used for monitoring state of transmission:
|
53
42
|
@session = nil # TCP connection
|
54
43
|
@association = nil # DICOM Association status
|
@@ -70,10 +59,10 @@ module DICOM
|
|
70
59
|
if info[:pdu] != PDU_RELEASE_REQUEST
|
71
60
|
# For some reason we didnt get our expected release request. Determine why:
|
72
61
|
if info[:valid]
|
73
|
-
|
62
|
+
logger.error("Unexpected message type received (PDU: #{info[:pdu]}). Expected a release request. Closing the connection.")
|
74
63
|
handle_abort(false)
|
75
64
|
else
|
76
|
-
|
65
|
+
logger.error("Timed out while waiting for a release request. Closing the connection.")
|
77
66
|
end
|
78
67
|
stop_session
|
79
68
|
else
|
@@ -368,7 +357,7 @@ module DICOM
|
|
368
357
|
info = interpret_abort(message)
|
369
358
|
else
|
370
359
|
info = {:valid => false}
|
371
|
-
|
360
|
+
logger.error("An unknown PDU type was received in the incoming transmission. Can not decode this message. (PDU: #{pdu})")
|
372
361
|
end
|
373
362
|
return info
|
374
363
|
end
|
@@ -380,7 +369,7 @@ module DICOM
|
|
380
369
|
# * <tt>default_message</tt> -- A boolean which unless set as nil/false will make the method print the default status message.
|
381
370
|
#
|
382
371
|
def handle_abort(default_message=true)
|
383
|
-
|
372
|
+
logger.warn("An unregonizable (non-DICOM) message was received.") if default_message
|
384
373
|
build_association_abort
|
385
374
|
transmit
|
386
375
|
end
|
@@ -453,7 +442,7 @@ module DICOM
|
|
453
442
|
# Handles the rejection message (The response used to an association request when its formalities are not correct).
|
454
443
|
#
|
455
444
|
def handle_rejection
|
456
|
-
|
445
|
+
logger.warn("An incoming association request was rejected. Error code: #{association_error}")
|
457
446
|
# Insert the error code in the info hash:
|
458
447
|
info[:reason] = association_error
|
459
448
|
# Send an association rejection:
|
@@ -465,7 +454,7 @@ module DICOM
|
|
465
454
|
#
|
466
455
|
def handle_release
|
467
456
|
stop_receiving
|
468
|
-
|
457
|
+
logger.info("Received a release request. Releasing association.")
|
469
458
|
build_release_response
|
470
459
|
transmit
|
471
460
|
stop_session
|
@@ -557,7 +546,7 @@ module DICOM
|
|
557
546
|
end
|
558
547
|
else
|
559
548
|
# Length of the message is less than what is specified in the message. Need to listen for more. This is hopefully handled properly now.
|
560
|
-
#
|
549
|
+
#logger.error("Error. The length of the received message (#{msg.rest_length}) is smaller than what it claims (#{specified_length}). Aborting.")
|
561
550
|
@first_part = msg.string
|
562
551
|
end
|
563
552
|
else
|
@@ -707,7 +696,7 @@ module DICOM
|
|
707
696
|
else
|
708
697
|
# Value (variable length)
|
709
698
|
value = msg.decode(item_length, "STR")
|
710
|
-
|
699
|
+
logger.warn("Unknown user info item type received. Please update source code or contact author. (item type: #{item_type})")
|
711
700
|
end
|
712
701
|
end
|
713
702
|
stop_receiving
|
@@ -733,7 +722,7 @@ module DICOM
|
|
733
722
|
info[:source] = msg.decode(1, "BY")
|
734
723
|
# Reason (1 byte)
|
735
724
|
info[:reason] = msg.decode(1, "BY")
|
736
|
-
|
725
|
+
logger.warn("ASSOCIATE Request was rejected by the host. Error codes: Result: #{info[:result]}, Source: #{info[:source]}, Reason: #{info[:reason]} (See DICOM PS3.8: Table 9-21 for details.)")
|
737
726
|
stop_receiving
|
738
727
|
info[:valid] = true
|
739
728
|
return info
|
@@ -877,7 +866,7 @@ module DICOM
|
|
877
866
|
# Unknown item type:
|
878
867
|
# Value (variable length)
|
879
868
|
value = msg.decode(item_length, "STR")
|
880
|
-
|
869
|
+
logger.warn("Unknown user info item type received. Please update source code or contact author. (item type: " + item_type + ")")
|
881
870
|
end
|
882
871
|
end
|
883
872
|
stop_receiving
|
@@ -923,7 +912,7 @@ module DICOM
|
|
923
912
|
# Length (2 bytes)
|
924
913
|
length = msg.decode(2, "US")
|
925
914
|
if length > msg.rest_length
|
926
|
-
|
915
|
+
logger.error("Specified length of command element value exceeds remaining length of the received message! Something is wrong.")
|
927
916
|
end
|
928
917
|
# Reserved (2 bytes)
|
929
918
|
msg.skip(2)
|
@@ -948,7 +937,7 @@ module DICOM
|
|
948
937
|
end
|
949
938
|
# Special case: Handle a possible C-ECHO-RQ:
|
950
939
|
if info[:results]["0000,0100"] == C_ECHO_RQ
|
951
|
-
|
940
|
+
logger.info("Received an Echo request. Returning an Echo response.")
|
952
941
|
handle_response
|
953
942
|
end
|
954
943
|
elsif info[:presentation_context_flag] == DATA_MORE_FRAGMENTS or info[:presentation_context_flag] == DATA_LAST_FRAGMENT
|
@@ -977,7 +966,7 @@ module DICOM
|
|
977
966
|
length = msg.decode(4, "UL")
|
978
967
|
end
|
979
968
|
if length > msg.rest_length
|
980
|
-
|
969
|
+
logger.error("The specified length of the data element value exceeds the remaining length of the received message!")
|
981
970
|
end
|
982
971
|
# Fetch the name (& type if not defined already) for this data element:
|
983
972
|
result = LIBRARY.get_name_vr(tag)
|
@@ -993,7 +982,7 @@ module DICOM
|
|
993
982
|
end
|
994
983
|
else
|
995
984
|
# Unknown.
|
996
|
-
|
985
|
+
logger.error("Unknown presentation context flag received in the query/command response. (#{info[:presentation_context_flag]})")
|
997
986
|
stop_receiving
|
998
987
|
end
|
999
988
|
# If only parts of the string was read, return the rest:
|
@@ -1108,30 +1097,6 @@ module DICOM
|
|
1108
1097
|
private
|
1109
1098
|
|
1110
1099
|
|
1111
|
-
# Adds a warning or error message to the instance array holding messages,
|
1112
|
-
# and prints the information to the screen if verbose is set.
|
1113
|
-
#
|
1114
|
-
# === Parameters
|
1115
|
-
#
|
1116
|
-
# * <tt>error</tt> -- A single error message or an array of error messages.
|
1117
|
-
#
|
1118
|
-
def add_error(error)
|
1119
|
-
puts error if @verbose
|
1120
|
-
@errors << error
|
1121
|
-
end
|
1122
|
-
|
1123
|
-
# Adds a notice (information regarding progress or successful communications) to the instance array,
|
1124
|
-
# and prints the information to the screen if verbose is set.
|
1125
|
-
#
|
1126
|
-
# === Parameters
|
1127
|
-
#
|
1128
|
-
# * <tt>notice</tt> -- A single status message or an array of status messages.
|
1129
|
-
#
|
1130
|
-
def add_notice(notice)
|
1131
|
-
puts notice if @verbose
|
1132
|
-
@notices << notice
|
1133
|
-
end
|
1134
|
-
|
1135
1100
|
# Builds the application context (which is part of the association request/response).
|
1136
1101
|
#
|
1137
1102
|
def append_application_context
|
@@ -1299,7 +1264,7 @@ module DICOM
|
|
1299
1264
|
when C_ECHO_RQ
|
1300
1265
|
return C_ECHO_RSP
|
1301
1266
|
else
|
1302
|
-
|
1267
|
+
logger.error("Unknown or unsupported request (#{request}) encountered.")
|
1303
1268
|
return C_CANCEL_RQ
|
1304
1269
|
end
|
1305
1270
|
end
|
@@ -1313,19 +1278,19 @@ module DICOM
|
|
1313
1278
|
def process_reason(reason)
|
1314
1279
|
case reason
|
1315
1280
|
when "00"
|
1316
|
-
|
1281
|
+
logger.error("Reason specified for abort: Reason not specified")
|
1317
1282
|
when "01"
|
1318
|
-
|
1283
|
+
logger.error("Reason specified for abort: Unrecognized PDU")
|
1319
1284
|
when "02"
|
1320
|
-
|
1285
|
+
logger.error("Reason specified for abort: Unexpected PDU")
|
1321
1286
|
when "04"
|
1322
|
-
|
1287
|
+
logger.error("Reason specified for abort: Unrecognized PDU parameter")
|
1323
1288
|
when "05"
|
1324
|
-
|
1289
|
+
logger.error("Reason specified for abort: Unexpected PDU parameter")
|
1325
1290
|
when "06"
|
1326
|
-
|
1291
|
+
logger.error("Reason specified for abort: Invalid PDU parameter value")
|
1327
1292
|
else
|
1328
|
-
|
1293
|
+
logger.error("Reason specified for abort: Unknown reason (Error code: #{reason})")
|
1329
1294
|
end
|
1330
1295
|
end
|
1331
1296
|
|
@@ -1345,15 +1310,15 @@ module DICOM
|
|
1345
1310
|
# Analyse the result and report what is wrong:
|
1346
1311
|
case result
|
1347
1312
|
when 1
|
1348
|
-
|
1313
|
+
logger.warn("DICOM Request was rejected by the host, reason: 'User-rejection'")
|
1349
1314
|
when 2
|
1350
|
-
|
1315
|
+
logger.warn("DICOM Request was rejected by the host, reason: 'No reason (provider rejection)'")
|
1351
1316
|
when 3
|
1352
|
-
|
1317
|
+
logger.warn("DICOM Request was rejected by the host, reason: 'Abstract syntax not supported'")
|
1353
1318
|
when 4
|
1354
|
-
|
1319
|
+
logger.warn("DICOM Request was rejected by the host, reason: 'Transfer syntaxes not supported'")
|
1355
1320
|
else
|
1356
|
-
|
1321
|
+
logger.warn("DICOM Request was rejected by the host, reason: 'UNKNOWN (#{result})' (Illegal reason provided)")
|
1357
1322
|
end
|
1358
1323
|
end
|
1359
1324
|
end
|
@@ -1366,11 +1331,11 @@ module DICOM
|
|
1366
1331
|
#
|
1367
1332
|
def process_source(source)
|
1368
1333
|
if source == "00"
|
1369
|
-
|
1334
|
+
logger.warn("Connection has been aborted by the service provider because of an error by the service user (client side).")
|
1370
1335
|
elsif source == "02"
|
1371
|
-
|
1336
|
+
logger.warn("Connection has been aborted by the service provider because of an error by the service provider (server side).")
|
1372
1337
|
else
|
1373
|
-
|
1338
|
+
logger.warn("Connection has been aborted by the service provider, with an unknown cause of the problems. (error code: #{source})")
|
1374
1339
|
end
|
1375
1340
|
end
|
1376
1341
|
|
@@ -1391,26 +1356,26 @@ module DICOM
|
|
1391
1356
|
case status
|
1392
1357
|
when 0 # "0000"
|
1393
1358
|
# Last fragment (Break the while loop that listens continuously for incoming packets):
|
1394
|
-
|
1359
|
+
logger.info("Receipt for successful execution of the desired operation has been received.")
|
1395
1360
|
stop_receiving
|
1396
1361
|
when 42752 # "a700"
|
1397
1362
|
# Failure: Out of resources. Related fields: 0000,0902
|
1398
|
-
|
1363
|
+
logger.error("Failure! SCP has given the following reason: 'Out of Resources'.")
|
1399
1364
|
when 43264 # "a900"
|
1400
1365
|
# Failure: Identifier Does Not Match SOP Class. Related fields: 0000,0901, 0000,0902
|
1401
|
-
|
1366
|
+
logger.error("Failure! SCP has given the following reason: 'Identifier Does Not Match SOP Class'.")
|
1402
1367
|
when 49152 # "c000"
|
1403
1368
|
# Failure: Unable to process. Related fields: 0000,0901, 0000,0902
|
1404
|
-
|
1369
|
+
logger.error("Failure! SCP has given the following reason: 'Unable to process'.")
|
1405
1370
|
when 49408 # "c100"
|
1406
1371
|
# Failure: More than one match found. Related fields: 0000,0901, 0000,0902
|
1407
|
-
|
1372
|
+
logger.error("Failure! SCP has given the following reason: 'More than one match found'.")
|
1408
1373
|
when 49664 # "c200"
|
1409
1374
|
# Failure: Unable to support requested template. Related fields: 0000,0901, 0000,0902
|
1410
|
-
|
1375
|
+
logger.error("Failure! SCP has given the following reason: 'Unable to support requested template'.")
|
1411
1376
|
when 65024 # "fe00"
|
1412
1377
|
# Cancel: Matching terminated due to Cancel request.
|
1413
|
-
|
1378
|
+
logger.info("Cancel! SCP has given the following reason: 'Matching terminated due to Cancel request'.")
|
1414
1379
|
when 65280 # "ff00"
|
1415
1380
|
# Sub-operations are continuing.
|
1416
1381
|
# (No particular action taken, the program will listen for and receive the coming fragments)
|
@@ -1418,7 +1383,7 @@ module DICOM
|
|
1418
1383
|
# More command/data fragments to follow.
|
1419
1384
|
# (No particular action taken, the program will listen for and receive the coming fragments)
|
1420
1385
|
else
|
1421
|
-
|
1386
|
+
logger.error("Something was NOT successful regarding the desired operation. SCP responded with error code: #{status} (tag: 0000,0900). See DICOM PS3.7, Annex C for details.")
|
1422
1387
|
end
|
1423
1388
|
end
|
1424
1389
|
|
@@ -1465,7 +1430,7 @@ module DICOM
|
|
1465
1430
|
while @receive
|
1466
1431
|
if (Time.now.to_f - t1) > @timeout
|
1467
1432
|
Thread.kill(thr)
|
1468
|
-
|
1433
|
+
logger.error("No answer was received within the specified timeout period. Aborting.")
|
1469
1434
|
stop_receiving
|
1470
1435
|
end
|
1471
1436
|
end
|
@@ -1497,7 +1462,7 @@ module DICOM
|
|
1497
1462
|
# Query the library with our particular transfer syntax string:
|
1498
1463
|
valid_syntax, @explicit, @data_endian = LIBRARY.process_transfer_syntax(syntax)
|
1499
1464
|
unless valid_syntax
|
1500
|
-
|
1465
|
+
logger.warn("Invalid (unknown) transfer syntax encountered! Will try to continue, but errors may occur.")
|
1501
1466
|
end
|
1502
1467
|
end
|
1503
1468
|
|
@@ -1564,4 +1529,4 @@ module DICOM
|
|
1564
1529
|
end
|
1565
1530
|
|
1566
1531
|
end
|
1567
|
-
end
|
1532
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
module DICOM
|
2
|
+
|
3
|
+
# This module handles logging functionality.
|
4
|
+
#
|
5
|
+
# Logging functionality uses the Standard library's Logger class.
|
6
|
+
# To properly handle progname, which inside the DICOM module is simply
|
7
|
+
# "DICOM", in all cases, we use an implementation with a proxy class.
|
8
|
+
#
|
9
|
+
# === Examples
|
10
|
+
#
|
11
|
+
# require 'dicom'
|
12
|
+
# include DICOM
|
13
|
+
#
|
14
|
+
# # Logging to STDOUT with DEBUG level:
|
15
|
+
# DICOM.logger = Logger.new(STDOUT)
|
16
|
+
# DICOM.logger.level = Logger::DEBUG
|
17
|
+
#
|
18
|
+
# # Logging to a file:
|
19
|
+
# DICOM.logger = Logger.new('my_logfile.log')
|
20
|
+
#
|
21
|
+
# # Combine an external logger with DICOM:
|
22
|
+
# logger = Logger.new(STDOUT)
|
23
|
+
# logger.progname = "MY_APP"
|
24
|
+
# DICOM.logger = logger
|
25
|
+
# # Now you can call the logger in the following ways:
|
26
|
+
# DICOM.logger.info "Message" # => "DICOM: Message"
|
27
|
+
# DICOM.logger.info("MY_MODULE) {"Message"} # => "MY_MODULE: Message"
|
28
|
+
# logger.info "Message" # => "MY_APP: Message"
|
29
|
+
#
|
30
|
+
# For more information, please read the Standard library Logger documentation.
|
31
|
+
#
|
32
|
+
module Logging
|
33
|
+
|
34
|
+
require 'logger'
|
35
|
+
|
36
|
+
# Inclusion hook to make the ClassMethods available to whatever
|
37
|
+
# includes the Logging module, i.e. the DICOM module.
|
38
|
+
#
|
39
|
+
def self.included(base)
|
40
|
+
base.extend(ClassMethods)
|
41
|
+
end
|
42
|
+
|
43
|
+
module ClassMethods
|
44
|
+
|
45
|
+
# We use our own ProxyLogger to achieve the features wanted for DICOM logging,
|
46
|
+
# e.g. using DICOM as progname for messages logged within the DICOM module
|
47
|
+
# (for both the Standard logger as well as the Rails logger), while still allowing
|
48
|
+
# a custom progname to be used when the logger is called outside the DICOM module.
|
49
|
+
#
|
50
|
+
class ProxyLogger
|
51
|
+
|
52
|
+
# Creating the ProxyLogger instance.
|
53
|
+
#
|
54
|
+
# === Parameters
|
55
|
+
#
|
56
|
+
# * <tt>target</tt> -- A Logger instance (e.g. Standard Logger or ActiveSupport::BufferedLogger).
|
57
|
+
#
|
58
|
+
def initialize(target)
|
59
|
+
@target = target
|
60
|
+
end
|
61
|
+
|
62
|
+
# Catches missing methods.
|
63
|
+
# In our case, the methods of interest are the typical logger methods,
|
64
|
+
# i.e. log, info, fatal, error, debug, where the arguments/block are
|
65
|
+
# redirected to the logger in a specific way so that our stated logger
|
66
|
+
# features are achieved (this behaviour depends on the logger
|
67
|
+
# (Rails vs Standard) and in the case of Standard logger,
|
68
|
+
# whether or not a block is given).
|
69
|
+
#
|
70
|
+
# === Examples
|
71
|
+
#
|
72
|
+
# # Inside the DICOM module or an external class with 'include DICOM::Logging':
|
73
|
+
# logger.info "message"
|
74
|
+
#
|
75
|
+
# # Calling from outside the DICOM module:
|
76
|
+
# DICOM.logger.info "message"
|
77
|
+
#
|
78
|
+
def method_missing(method_name, *args, &block)
|
79
|
+
if method_name.to_s =~ /(log|debug|info|warn|error|fatal)/
|
80
|
+
# Rails uses it's own buffered logger which does not
|
81
|
+
# work with progname + block as the standard logger does:
|
82
|
+
if defined?(Rails)
|
83
|
+
@target.send(method_name, "DICOM: #{args.first}")
|
84
|
+
elsif block_given?
|
85
|
+
@target.send(method_name, *args) { yield }
|
86
|
+
else
|
87
|
+
@target.send(method_name, "DICOM") { args.first }
|
88
|
+
end
|
89
|
+
else
|
90
|
+
@target.send(method_name, *args, &block)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
# The logger class variable (must be initialized
|
97
|
+
# before it is referenced by the object setter).
|
98
|
+
#
|
99
|
+
@@logger = nil
|
100
|
+
|
101
|
+
# The logger object setter.
|
102
|
+
# This method is used to replace the default logger instance with
|
103
|
+
# a custom logger of your own.
|
104
|
+
#
|
105
|
+
# === Parameters
|
106
|
+
#
|
107
|
+
# * <tt>l</tt> -- A Logger instance (e.g. a custom standard Logger).
|
108
|
+
#
|
109
|
+
# === Examples
|
110
|
+
#
|
111
|
+
# # Create a logger which ages logfile once it reaches a certain size,
|
112
|
+
# # leaves 10 "old log files" with each file being about 1,024,000 bytes:
|
113
|
+
# DICOM.logger = Logger.new('foo.log', 10, 1024000)
|
114
|
+
#
|
115
|
+
def logger=(l)
|
116
|
+
@@logger = ProxyLogger.new(l)
|
117
|
+
end
|
118
|
+
|
119
|
+
# The logger object getter.
|
120
|
+
# Returns the logger class variable, if defined.
|
121
|
+
# If not defined, sets up the Rails logger (if in a Rails environment),
|
122
|
+
# or a Standard logger if not.
|
123
|
+
#
|
124
|
+
# === Examples
|
125
|
+
#
|
126
|
+
# # Inside the DICOM module (or a class with 'include DICOM::Logging'):
|
127
|
+
# logger # => Logger instance
|
128
|
+
#
|
129
|
+
# # Accessing from outside the DICOM module:
|
130
|
+
# DICOM.logger # => Logger instance
|
131
|
+
#
|
132
|
+
def logger
|
133
|
+
@@logger ||= lambda {
|
134
|
+
if defined?(Rails)
|
135
|
+
ProxyLogger.new(Rails.logger)
|
136
|
+
else
|
137
|
+
l = Logger.new(STDOUT)
|
138
|
+
l.level = Logger::INFO
|
139
|
+
ProxyLogger.new(l)
|
140
|
+
end
|
141
|
+
}.call
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
# A logger object getter.
|
147
|
+
# Forwards the call to the logger class method of the Logging module.
|
148
|
+
#
|
149
|
+
def logger
|
150
|
+
self.class.logger
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
# Include the Logging module so we can use DICOM.logger.
|
156
|
+
include Logging
|
157
|
+
|
158
|
+
end
|