New post

Find

Article
· Aug 6, 2024 5m read

监控数据库增长 – 第 1 部分_数据收集

数据收集

这篇分步说明指南将讲解如何创建任务来收集 InterSystems 数据库及其全局变量的相关数据(如关联的 Open Exchange App 所示,其中包含所有相关代码)

免责声明:此软件仅用于测试/演示目的。 InterSystems 不支持将此代码作为任何发布产品的一部分。 它由 InterSystems 提供,作为特定产品和版本的演示/测试工具。 用户或客户全权负责此软件交付后的维护和测试,InterSystems 对此代码的错误或误用不承担任何责任

1) 首先,通过管理门户导入文件“DataCollection.xml”,并确保没有错误。 如果存在错误,则可能是版本问题,请发送电子邮件至 ari.glikman@intersystems.com 联系 Ari Glikman 获取适合你的版本的支持。 另外,确保将数据导入到你想要收集其内部数据以供后续检查的命名空间中。

3 Comments
Discussion (3)2
Log in or sign up to continue
Article
· Aug 6, 2024 2m read

将Production中的设定参数移动到系统默认设置(System Default Settings)

开发新的互操作性Production时,最初在Production中添加设置是很自然的做法。

不过,一旦要将Production从开发环境移动到测试或其他环境,你就会发现 HTTP 服务器、IP 地址和/或端口之类的设置都需要更改。 为了避免这些设置在后续重新部署时被覆盖,必须将这些设置从Production得设置中移动到系统默认设置(System Default Settings)。

虽然系统默认设置可以手动创建,但是当生产中有大量业务组件时会难以处理。 因此,@Wietze Drost 让我开发一个工具自动执行此流程,通过筛选表达式指定哪些设置必须创建为系统默认设置。

  • 这个表达式可以定义为“*:HTTPServer,SSLConfig*”,其中“\*”表示“为任何主机类名”。 冒号后面是需要移动的设置列表。 所以,这个表达式的意思是“为所有名为 HTTPServer 和 SSLConfig 的设置创建或更新系统默认设置”。
  • 可以定义多个筛选表达式,用分号分隔,例如 "*:HTTPServer,SSLConfig;FullClassName2:xxx,yyy"

根据他的请求,我编写了名为 GetSettingsFromProduction 的类方法,

ClassMethod GetSettingsFromProduction(production As %String, filter As %String = "", removeFromProduction As %Boolean = 0, updateSettings As %Boolean = 1) As %Status

production - Production名称,如果留空,将使用当前正在运行的Production的名称。

filter - 用于选择设置的筛选器,如“*:HTTPServer,SSLConfig”。 可以添加多个筛选器,用“;”分隔,也可以使用特定类名。 如果筛选器留空,将处理所有设置。

removeFromProduction - 如果设为 1,将从Production中移除筛选器选择的设置。

updateSettings - 如果设为 0,将不会在系统默认设置中更新设置。

运行时,有关所采取操作的信息将被写入终端。 完整的类文件已粘贴在本文评论区。 欢迎提出问题和反馈!

1 Comment
Discussion (1)1
Log in or sign up to continue
Article
· Aug 6, 2024 2m read

第二章 使用代理服务器

第二章 使用代理服务器

使用代理服务器

Web 客户端可以通过代理服务器与 Web 服务通信。要进行设置,请指定 Web 客户端实例的属性以指示要使用的代理服务器。这些属性如下:

HttpProxyServer

指定要使用的代理服务器的主机名。如果此属性不为空,则 HTTP 请求将定向到此计算机。

HttpProxyPort

指定代理服务器上要连接的端口。

HttpProxyHTTPS

如果使用代理服务器并且该代理服务器支持 HTTPS,则将其指定为 true

请注意,如果使用 HTTPS,则还必须将客户端的 SSLConfiguration 属性设置为 SSL/TLS 配置的名称;有关更多详细信息,请参阅配置客户端以使用 SSL

Discussion (0)1
Log in or sign up to continue
Question
· Aug 6, 2024

ERROR #6084: Unknown errors detected

Hi Guys,

I'm getting " ERROR #6084: Unknown errors detected" when compiling my CSP pages, the pages still works fine in the new 2018 system but can do any changes because of this error?

 

Thanks

Discussion (0)1
Log in or sign up to continue
Article
· Aug 6, 2024 10m read

Example of Overriding SDA to FHIR Transform Process to Include "RequestMethod" Setting

When building a bundle from legacy data, I (and others) wanted to be able to control whether or not the resources were generated with a FHIR Request Method of PUT instead of the hard coded POST.  I have extended the two classes responsible for transforming SDA to FHIR in an Interoperability Production to accomodate a setting that lets the user control the Request Method.

First is the Busines Process class.  This includes a new parameter exposed to the "Settings" tab in Interoperability called FHIRRequestMethod.  This also needs to pass the FHIRRequestMethod property to the transform class method as a parameter.

Class Demo.FHIR.DTL.Util.HC.SDA.FHIR.ProcessV2 Extends HS.FHIR.DTL.Util.HC.SDA3.FHIR.Process
{

/*  ; **********************************************************
	; *                   ** N O T I C E **                    *
	; *                - TEST/DEMO SOFTWARE -                  *
	; * This class is not supported by InterSystems as part    *
	; * of any released product.  It is supplied by            *
	; * InterSystems as a demo/test tool for a specific        *
	; * product and version.  The user or customer is fully    *
	; * responsible for the maintenance of this software       *
	; * after delivery, and InterSystems shall bear no         *
	; * responsibility nor liabilities for errors or misuse    *
	; * of this class.                                         *
	; **********************************************************/
Parameter SETTINGS = "FHIRRequestMethod:Basic";
/// This property can override the request method generated with each FHIR resource <br>
/// This property will only apply to new resources that do not have an identifier from the source data.
Property FHIRRequestMethod As %String(MAXLEN = 10) [ InitialExpression = "POST" ];
/// This is an instance method because it needs to SendSync to a business host and get
/// the response from the host.
Method ProcessSDARequest(pSDAStream, pSessionApplication As %String, pSessionId As %String, pPatientResourceId As %String = "") As %Status
{
	New %HSIncludeTimeZoneOffsets
	Set %HSIncludeTimeZoneOffsets = 1
	Set tSC = $$$OK
	Try {
		// Check the base class for the Target business host. Determine if it is
		// a FHIRServer Interop business host or not.
		If '$Data(%healthshare($$$CurrentClass, "isInteropHost"))#10 {
			$$$ThrowOnError(##class(HS.Director).OpenCurrentProduction(.tProdObj))
			Set tClassName = ""
			For i = 1:1:tProdObj.Items.Count() {
				If tProdObj.Items.GetAt(i).Name = ..TargetConfigName {
					Set tClassName = tProdObj.Items.GetAt(i).ClassName
					Quit
				}
			}
			Kill tProdObj
			
			Set tIsInteropHost = 0
			Set tRequiredHostBases("HS.FHIRServer.Interop.Operation") = ""
			Set tRequiredHostBases("HS.FHIRServer.Interop.HTTPOperation") = ""
			Set tHostBase = ""
			For {
				Set tHostBase = $Order(tRequiredHostBases(tHostBase))
				If tHostBase="" Quit
				If $ClassMethod(tClassName, "%IsA", tHostBase) {
					Set tIsInteropHost = 1
					Quit
				}
			}
			Set %healthshare($$$CurrentClass, "isInteropHost") = tIsInteropHost
			
		} Else {
			Set tIsInteropHost = %healthshare($$$CurrentClass, "isInteropHost")
		}
		
		// Get the host and web server port of the current instance, to be used for populating
		// the FHIR request message HOST header.  The HOST header is needed in the FHIR request
		// message when the message is being routed for processing in the local production, as
		// opposed to being passed to an external server.
		Do ..GetHostAndPort(.tHost, .tPort)
		Set tLocalHostAndPort = tHost_$Select(tPort'="":":",1:"")_tPort
		
		If ..FHIRFormat="JSON" {
			Set tMessageContentType = "application/fhir+json"
		} ElseIf ..FHIRFormat="XML" {
			Set tMessageContentType = "application/fhir+xml"
		}
		
		Set tFHIRMetadataSetKey = $ZStrip($Piece(..FHIRMetadataSet, "/", 1), "<>W")
		
		Set tSchema = ##class(HS.FHIRServer.Schema).LoadSchema(tFHIRMetadataSetKey)
		
		If '..FormatFHIROutput {
			Set tIndentChars = ""
			Set tLineTerminator = ""
			Set tFormatter = ""
		} Else {
			Set tIndentChars = $Char(9)
			Set tLineTerminator = $Char(13,10)
			Set tFormatter = ##class(%JSON.Formatter).%New()
			Set tFormatter.IndentChars = tIndentChars
			Set tFormatter.LineTerminator = tLineTerminator
		}
		
		#dim tTransformObj As HS.FHIR.DTL.Util.API.Transform.SDA3ToFHIR
		
		Set tTransformObj = $ClassMethod(..TransformClass, "TransformStream", pSDAStream, "HS.SDA3.Container", tFHIRMetadataSetKey, pPatientResourceId, "", ..FHIRRequestMethod)
		
		// tTransformObj.bundle is a %DynamicObject.
		Set tBundleObj = tTransformObj.bundle
		
		$$$HSTRACE("Bundle object", "tBundleObj", tBundleObj.%ToJSON())
		
		// "individual" is not a transaction type or interaction.
		// This mode causes each entry in the Bundle to be sent
		// to TargetConfigName individually, not as a transaction.
		If ..TransmissionMode="individual" {
			For i = 0:1:tBundleObj.entry.%Size()-1 {
				If tIsInteropHost {
					Set tSC = ..CreateAndSendInteropMessage(tBundleObj.entry.%Get(i), tSchema, tMessageContentType, tFormatter, tIndentChars, tLineTerminator, pSessionApplication, pSessionId)
				} Else {
					Set tSC = ..CreateAndSendFHIRMessage(tBundleObj.entry.%Get(i), tSchema, tLocalHostAndPort, tMessageContentType, tFormatter, tIndentChars, tLineTerminator, pSessionApplication, pSessionId)
				}
			}
		} Else {
			If tIsInteropHost {
				Set tSC = ..CreateAndSendInteropMessage(tBundleObj, tSchema, tMessageContentType, tFormatter, tIndentChars, tLineTerminator, pSessionApplication, pSessionId)
			} Else {
				Set tSC = ..CreateAndSendFHIRMessage(tBundleObj, tSchema, tLocalHostAndPort, tMessageContentType, tFormatter, tIndentChars, tLineTerminator, pSessionApplication, pSessionId)
			}
		}
		
	} Catch eException {
		Set tSC = eException.AsStatus()
	}
	
	Quit tSC
}

Storage Default
{
<Data name="ProcessV2DefaultData">
<Subscript>"ProcessV2"</Subscript>
<Value name="1">
<Value>FHIRRequestMethod</Value>
</Value>
</Data>
<DefaultData>ProcessV2DefaultData</DefaultData>
<Type>%Storage.Persistent</Type>
}

}

 

Second is the transformation class, for which we need to also add a new property to store the FHIRRequestMethod parameter.  The value of FHIRRequestMethod comes from the Class Method call to ..TransformStream.  Once this parameter from the Business Process is passed into ..TransformStream, I store it in the class property so that all methods of this transform class have access to the value.

Class Demo.FHIR.DTL.Util.API.Transform.SDA3ToFHIRV2 Extends HS.FHIR.DTL.Util.API.Transform.SDA3ToFHIR
{

/*  ; **********************************************************
	; *                   ** N O T I C E **                    *
	; *                - TEST/DEMO SOFTWARE -                  *
	; * This class is not supported by InterSystems as part    *
	; * of any released product.  It is supplied by            *
	; * InterSystems as a demo/test tool for a specific        *
	; * product and version.  The user or customer is fully    *
	; * responsible for the maintenance of this software       *
	; * after delivery, and InterSystems shall bear no         *
	; * responsibility nor liabilities for errors or misuse    *
	; * of this class.                                         *
	; **********************************************************/
/// Property to override the Request Method for unidentified resources
Property FHIRRequestMethod As %String(MAXLEN = 10);
/// Transforms an SDA stream (Container or SDA class) to the specified FHIR version. Returns an instance of this class
/// which contains a "bundle" property. That property will contain a FHIR Bundle with all the resources
/// generated during the transformation, and with all references resolved. If <var>patientId</var> or
/// <var>encounterId</var> are specified, those values will go into any applicable Patient and Encounter
/// references.
/// @API.Method
/// @Argument	stream			%Stream representation of an SDA object or Container
/// @Argument	SDAClassname	Classname for the object contained in the stream (eg. HS.SDA3.Container)
/// @Argument	fhirVersion		Version of FHIR used by the resource, eg. "STU3", "R4"
/// @Argument	patientId		(optional) FHIR resource id to be assigned to the Patient resource
/// @Argument	encounterId		(optional) FHIR resource id to be assigned to the Encounter resource, if not transforming a Container
ClassMethod TransformStream(stream As %Stream.Object, SDAClassname As %String, fhirVersion As %String, patientId As %String = "", encounterId As %String = "", FHIRRequestMethod As %String) As HS.FHIR.DTL.Util.API.Transform.SDA3ToFHIR
{
	set source = $classmethod(SDAClassname, "%New")
	if SDAClassname = "HS.SDA3.Container" {
		$$$ThrowOnError(source.InitializeXMLParse(stream, "SDA3"))
	}
	else {
		$$$ThrowOnError(source.XMLImportSDAString(stream.Read(3700000)))
	}
	return ..TransformObject(source, fhirVersion, patientId, encounterId, FHIRRequestMethod)
}

/// Transforms an SDA object (Container or SDA class) to the specified FHIR version. Returns an instance of this class
/// which contains a "bundle" property. That property will contain a FHIR Bundle with all the resources
/// generated during the transformation, and with all references resolved. If <var>patientId</var> or
/// <var>encounterId</var> are specified, those values will go into any applicable Patient and Encounter
/// references.
/// @API.Method
/// @Argument	source			SDA object or Container
/// @Argument	fhirVersion		Version of FHIR used by the resource, eg. "STU3", "R4"
/// @Argument	patientId		(optional) FHIR resource id to be assigned to the Patient resource
/// @Argument	encounterId		(optional) FHIR resource id to be assigned to the Encounter resource, if not transforming a Container
ClassMethod TransformObject(source, fhirVersion As %String, patientId As %String = "", encounterId As %String = "", FHIRRequestMethod As %String) As HS.FHIR.DTL.Util.API.Transform.SDA3ToFHIR
{
	set schema = ##class(HS.FHIRServer.Schema).LoadSchema(fhirVersion)
	set transformer = ..%New(schema)
	
    // Updated from parent class to set the FHIRRequestMethod for use of any class method
    Set transformer.FHIRRequestMethod = FHIRRequestMethod

	//SDA gets patient and encounter id and Container only gets patient id
	//because a Container can have multiple encounters and we can't assume which one they're referring to
	if source.%ClassName(1) = "HS.SDA3.Container" {
		do transformer.TransformContainer(source, patientId)
	}
	else {
		do transformer.TransformSDA(source, patientId, encounterId)
	}
	
	return transformer
}

/// Ensures the resource is valid FHIR, adds the resource to the output Bundle,
/// and returns a reference to that resource. Will also output the resource as a
/// %DynamicObject.
/// @Inputs
/// source			SDA object which created this resource
/// resource		Object model version of the resource
/// resourceJson	%DynamicObject version of the resource
/// One of <var>resource</var> or <var>resourceJson</var> must be provided. If both are provided,
/// the %DynamicObject representation will be given precedence 
Method AddResource(source As HS.SDA3.SuperClass, resource As %RegisteredObject = "", ByRef resourceJson As %DynamicObject = "") As HS.FHIR.DTL.vR4.Model.Base.Reference [ Internal ]
{
	if '$isobject(resourceJson) {
		set resourceJson = ##class(%DynamicObject).%FromJSON(resource.ToJSON())
	}
	
	try {
		do ..%resourceValidator.ValidateResource(resourceJson)
	} catch ex {
		do ..HandleInvalidResource(resourceJson, ex)
		return ""
	}
	
	set entry = ##class(%DynamicObject).%New()
	set entry.request = ##class(%DynamicObject).%New()
	
	set id = ..GetId(source, resourceJson) 
	if id '= "" {
		set resourceJson.id = id
	}
	
	//Check for an SDA identifier->id mapping to maintain references
	//Note: Provenance assigns a GUID to ExternalId for internal use, it is not an external id and shouldn't influence id assignment 
	set sourceIdentifier = ""
	if resourceJson.resourceType = "Encounter" {
		set sourceIdentifier = source.EncounterNumber
	}
	elseif ((source.%Extends("HS.SDA3.SuperClass")) && (resourceJson.resourceType '= "Provenance")) {
		set sourceIdentifier = source.ExternalId
	}
	
	if id = "" {
		if (resourceJson.resourceType = "Patient") && (..%patientId '= "") {
			set id = ..%patientId
		}
		elseif $get(..%resourceIds(resourceJson.resourceType)) '= "" {
			set id = ..%resourceIds(resourceJson.resourceType)
		}
		elseif (sourceIdentifier '= "") && $data(..%resourceIds(resourceJson.resourceType, sourceIdentifier)) {
			set id = ..%resourceIds(resourceJson.resourceType, sourceIdentifier)
		}
		
		if id '= "" {
			set resource.id = id
			set resourceJson.id = id
		}
	}
	
	if resourceJson.id '= "" {
		set id = resourceJson.id
		set entry.fullUrl = $select(..GetBaseURL()'="":..GetBaseURL() _ "/", 1:"") _ resourceJson.resourceType _ "/" _ resourceJson.id
		set entry.request.method = "PUT"
		set entry.request.url = resourceJson.resourceType _ "/" _ resourceJson.id
	}
	else {
		set id = $zconvert($system.Util.CreateGUID(), "L")
		set entry.fullUrl = "urn:uuid:" _ id
        // changed from parent class to accept parameter as input instead of hard coding "POST"
		set entry.request.method = ..FHIRRequestMethod
		set entry.request.url = resourceJson.resourceType
	}
	
	//Save id mappings for later access
	if resourceJson.resourceType = "Patient" {
		set ..%patientId = id
	}
	elseif sourceIdentifier '= "" {
		set ..%resourceIds(resourceJson.resourceType, sourceIdentifier) = id
	}
	
	set duplicate = ..IsDuplicate(resourceJson, id)
	if duplicate '= "" {
		return duplicate
	}
	
	//Index for O(1) lookup if needed for post-processing
	set ..%resourceIndex(resourceJson.resourceType, id) = resourceJson
	
	set entry.resource = resourceJson
	do ..%bundle.entry.%Push(entry)
	
	return ..CreateReference(resourceJson.resourceType, id)
}

}

 

These classes are designed to be used in an Interoperability Production.  The demonstration that highlights to base version of these classes can be found here:

Learning Services: Converting Legacy Data to HL7 FHIR R4 in InterSystems IRIS for Health & Github Repo for Legacy To FHIR Transformation Demo
 

2 Comments
Discussion (2)2
Log in or sign up to continue