Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/add distributed tracing support #32

Merged
merged 38 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
4cd3329
Merge pull request #12 from SolaceDev/dev
mcardy Apr 14, 2023
339b370
Merge pull request #13 from SolaceDev/dev
mcardy Jun 30, 2023
872aae1
chore: bumped up the packaged ccsmp lib to 7.27.0.1
oodigie Oct 6, 2023
66ecded
feat(SOL-103546): Implement code changes to expose context propagatio…
oodigie Oct 6, 2023
39e26f0
test: added unit tests for the new DT functions in the message_impl
oodigie Oct 10, 2023
5ed5619
test[SOL-103572]: Golang: Add the integration tests to support the co…
oodigie Oct 10, 2023
8ab3fec
test: fixed some failing integration tests
oodigie Oct 10, 2023
5e62bce
test: fixed the failing tests in the message impl class
oodigie Oct 10, 2023
d89a1b5
test: fixed some of the failing tests
oodigie Oct 11, 2023
44bad1f
test: fixed the string formating to fix the failing tests
oodigie Oct 11, 2023
ea395fe
test: fixed the string formating to fix the failing tests
oodigie Oct 11, 2023
513edaf
feat: removed the public interfaces for the tracing feature and updat…
oodigie Oct 12, 2023
f5f851e
feat: fixed the formatting errors within the code
oodigie Oct 30, 2023
f23cf93
test: fixed failing test
oodigie Oct 30, 2023
463fd27
test: updated to fix failing tests and handle nil trace state when se…
oodigie Nov 1, 2023
af7c3a1
feat[SOL-107285]: bumped up the CCSMP library to fix the traceFlag bu…
oodigie Nov 8, 2023
c0c29f7
fix: a fix for the tracestate corruption on a message
oodigie Nov 15, 2023
17a8b20
feat: updated the implementation of how the trace state is retrived f…
oodigie Nov 16, 2023
cc081e6
test: fixed failing test
oodigie Nov 16, 2023
6cbda70
feat: update for trace state
oodigie Nov 16, 2023
0b46e34
feat: updated the string formating method for trace state
oodigie Nov 16, 2023
3d4aa02
feat: mode updates for the trace state clean up
oodigie Nov 17, 2023
90147ca
feat: mode updates for the trace state clean up
oodigie Nov 17, 2023
9f0dd33
test: updated the trace state to handle non-null terminated strings a…
oodigie Nov 17, 2023
98eddd3
feat: more refactoring of the codebase
oodigie Nov 17, 2023
5dfb9c7
feat: testing approach for handling trace state string
oodigie Nov 21, 2023
e53b19e
fix[SOL-108089]: pubsubplus-go-client build is broken on syntax error
oodigie Nov 22, 2023
56e8968
fix[SOL-108089]: pubsubplus-go-client build is broken on syntax error
oodigie Nov 22, 2023
b7562de
Merge branch 'dev' into feat/add-distributed-tracing-support
oodigie Nov 27, 2023
e45f182
feat[SOL-107974]: Message dump with large creation+transport traceSta…
oodigie Dec 5, 2023
b6655d3
Merge branch 'dev' into feat/add-distributed-tracing-support
oodigie Dec 8, 2023
6afc240
chore: bumped the ccsmp lib to 7.28.0.3
oodigie Dec 17, 2023
5737ac1
chore: bumped the version for this module to 1.5.0
oodigie Dec 17, 2023
c01595f
chore: merged the dev changes into this branch
oodigie Jan 12, 2024
e81828a
Merge branch 'dev' into feat/add-distributed-tracing-support
cjwmorgan-sol Jan 18, 2024
55e06d2
SOL-110595: Update tracing go module from dev merge
cjwmorgan-sol Jan 18, 2024
e2439e1
Merge branch 'dev' into feat/add-distributed-tracing-support
oodigie Jan 18, 2024
e517eb5
Merge branch 'feat/add-distributed-tracing-support' of https://github…
oodigie Jan 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion internal/ccsmp/ccsmp_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,4 @@ typedef struct solClient_errorInfo_wrapper
void *
uintptr_to_void_p(solClient_uint64_t ptr);

#endif
#endif
10 changes: 4 additions & 6 deletions internal/ccsmp/ccsmp_message.go
Original file line number Diff line number Diff line change
Expand Up @@ -538,8 +538,8 @@ func SolClientMessageSetTimeToLive(messageP SolClientMessagePt, timeToLive int64

// Utility functions

const defaultMsgDumpBufferSize = 1000
const msgDumpMultiplier = 5
// Set the default message dump buffer size to accommodate
// the Distributed Tracing properties in the message dump, SOL-107974
const maxDumpSize = 10000

// SolClientMessageDump function
Expand Down Expand Up @@ -587,11 +587,9 @@ func SolClientMessageDump(messageP SolClientMessagePt) string {
}
}

bufferSize := C.ulong(defaultMsgDumpBufferSize + payloadSize*msgDumpMultiplier)
// Truncate the message after 10,000 characters, SOL-62945
if bufferSize > maxDumpSize {
bufferSize = maxDumpSize
}
// removed the dynamic calculation of buffer size as defaultMsgDumpBufferSize{1000} + (payloadSize * msgDumpMultiplier{5})
bufferSize := C.ulong(maxDumpSize)
buffer := (*C.char)(C.malloc(bufferSize))
defer C.free(unsafe.Pointer(buffer))

Expand Down
352 changes: 352 additions & 0 deletions internal/ccsmp/ccsmp_message_tracing.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,352 @@
// pubsubplus-go-client
//
// Copyright 2021-2024 Solace Corporation. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ccsmp

/*
#include <stdlib.h>
#include <string.h>

#include "solclient/solClient.h"
#include "solclient/solClientMsg.h"
#include "solclient/solClientMsgTracingSupport.h"
*/
import "C"
import (
"fmt"
"unsafe"

"solace.dev/go/messaging/internal/impl/logging"
)

// Reexport of various CCSMP types

// SolClientMessageTracingContextType is assigned a value
type SolClientMessageTracingContextType = C.solClient_msg_tracing_context_type_t

// SolClientMessageTracingInjectionStandardType is assigned a value
type SolClientMessageTracingInjectionStandardType = C.solClient_msg_tracing_injection_standard_type_t

// SolClientContextTypeTransportContext is assigned a value
const SolClientContextTypeTransportContext = C.TRANSPORT_CONTEXT

// SolClientContextTypeCreationContext is assigned a value
const SolClientContextTypeCreationContext = C.CREATION_CONTEXT

// SolClientMessageTracingInjectionStandardTypeSMF is assigned a value
const SolClientMessageTracingInjectionStandardTypeSMF = C.SOLCLIENT_INJECTION_STANDARD_SMF

// SolClientMessageTracingInjectionStandardTypeW3C is assigned a value
const SolClientMessageTracingInjectionStandardTypeW3C = C.SOLCLIENT_INJECTION_STANDARD_W3C

// TODO the calls to handleCcsmpError are slow since they lock the thread.
// Ideally, we wrap these calls in C such that the golang scheduler cannot
// interrupt us, and then there is no need to lock the thread. This should
// be done for all datapath functionality, ie. the contents of this file.

// Distributed tracing properties

// SolClientMessageGetTraceContextTraceID function
func SolClientMessageGetTraceContextTraceID(messageP SolClientMessagePt, contextType SolClientMessageTracingContextType) ([16]byte, *SolClientErrorInfoWrapper) {
// to hold the traceID property
var cChar C.solClient_uint8_t

errorInfo := handleCcsmpError(func() SolClientReturnCode {
return C.solClient_msg_tracing_getTraceIdByte(messageP, contextType, &cChar, C.size_t(16))
})
if errorInfo != nil {
if errorInfo.ReturnCode == SolClientReturnCodeFail {
logging.Default.Warning(
fmt.Sprintf(
"Encountered error fetching Creation context traceID prop: %s, subcode: %d",
errorInfo.GetMessageAsString(),
errorInfo.SubCode))
}
return [16]byte{}, errorInfo
}

traceID := *(*[16]byte)(unsafe.Pointer(&cChar))
return traceID, errorInfo
}

// SolClientMessageSetTraceContextTraceID function
func SolClientMessageSetTraceContextTraceID(messageP SolClientMessagePt, traceID [16]byte, contextType SolClientMessageTracingContextType) *SolClientErrorInfoWrapper {
if len(traceID) > 0 {
cTraceID := (*C.solClient_uint8_t)(C.CBytes(traceID[:]))

defer C.free(unsafe.Pointer(cTraceID)) // free the pointer after function executes

errorInfo := handleCcsmpError(func() SolClientReturnCode {
return C.solClient_msg_tracing_setTraceIdByte(messageP, contextType, cTraceID, C.size_t(len(traceID)))
})
return errorInfo
}
return nil
}

// SolClientMessageGetTraceContextSpanID function
func SolClientMessageGetTraceContextSpanID(messageP SolClientMessagePt, contextType SolClientMessageTracingContextType) ([8]byte, *SolClientErrorInfoWrapper) {
// to hold the spanID property
var cChar C.solClient_uint8_t

errorInfo := handleCcsmpError(func() SolClientReturnCode {
return C.solClient_msg_tracing_getSpanIdByte(messageP, contextType, &cChar, C.size_t(8))
})
if errorInfo != nil {
if errorInfo.ReturnCode == SolClientReturnCodeFail {
logging.Default.Warning(
fmt.Sprintf(
"Encountered error fetching Creation context spanID prop: %s, subcode: %d",
errorInfo.GetMessageAsString(),
errorInfo.SubCode))
}
return [8]byte{}, errorInfo
}

spanID := *(*[8]byte)(unsafe.Pointer(&cChar))
return spanID, errorInfo
}

// SolClientMessageSetTraceContextSpanID function
func SolClientMessageSetTraceContextSpanID(messageP SolClientMessagePt, spanID [8]byte, contextType SolClientMessageTracingContextType) *SolClientErrorInfoWrapper {
if len(spanID) > 0 {
cSpanID := (*C.solClient_uint8_t)(C.CBytes(spanID[:]))

defer C.free(unsafe.Pointer(cSpanID)) // free the pointer after function executes

errorInfo := handleCcsmpError(func() SolClientReturnCode {
return C.solClient_msg_tracing_setSpanIdByte(messageP, contextType, cSpanID, C.size_t(len(spanID)))
})
return errorInfo
}
return nil
}

// SolClientMessageGetTraceContextSampled function
func SolClientMessageGetTraceContextSampled(messageP SolClientMessagePt, contextType SolClientMessageTracingContextType) (bool, *SolClientErrorInfoWrapper) {
// to hold the Sampled property
var cSampled C.solClient_bool_t

errorInfo := handleCcsmpError(func() SolClientReturnCode {
return C.solClient_msg_tracing_isSampled(messageP, contextType, &cSampled)
})
if errorInfo != nil {
if errorInfo.ReturnCode == SolClientReturnCodeFail {
logging.Default.Warning(
fmt.Sprintf(
"Encountered error fetching Creation context sampled prop: %s, subcode: %d",
errorInfo.GetMessageAsString(),
errorInfo.SubCode))
}
return false, errorInfo
}

isSampled := *(*bool)(unsafe.Pointer(&cSampled))
return isSampled, errorInfo
}

// SolClientMessageSetTraceContextSampled function
func SolClientMessageSetTraceContextSampled(messageP SolClientMessagePt, sampled bool, contextType SolClientMessageTracingContextType) *SolClientErrorInfoWrapper {
var isSampled C.solClient_bool_t = 0
if sampled {
isSampled = 1
}
return handleCcsmpError(func() SolClientReturnCode {
return C.solClient_msg_tracing_setSampled(messageP, contextType, isSampled)
})
}

// SolClientMessageGetTraceContextTraceState function
func SolClientMessageGetTraceContextTraceState(messageP SolClientMessagePt, contextType SolClientMessageTracingContextType) (string, *SolClientErrorInfoWrapper) {
// to hold the trace state
var traceStateChar *C.char
var traceStateSize C.size_t
defer C.free(unsafe.Pointer(traceStateChar))

errorInfo := handleCcsmpError(func() SolClientReturnCode {
return C.solClient_msg_tracing_getTraceStatePtr(messageP, contextType, &traceStateChar, &traceStateSize)
})

if errorInfo != nil {
if errorInfo.ReturnCode == SolClientReturnCodeFail {
logging.Default.Warning(
fmt.Sprintf(
"Encountered error fetching Creation contex traceState prop: %s, subcode: %d",
errorInfo.GetMessageAsString(),
errorInfo.SubCode))
}
return "", errorInfo
}

return C.GoStringN(traceStateChar, C.int(traceStateSize)), errorInfo
}

// SolClientMessageSetTraceContextTraceState function
func SolClientMessageSetTraceContextTraceState(messageP SolClientMessagePt, traceState string, contextType SolClientMessageTracingContextType) *SolClientErrorInfoWrapper {
cStr := C.CString(traceState)
// use the length of the traceState string not len(traceState) + 1
traceStateLen := len(traceState)
defer C.free(unsafe.Pointer(cStr)) // free the pointer after function executes

errorInfo := handleCcsmpError(func() SolClientReturnCode {
// trace state is not null terminal in SMF protocol
// write only char bytes not including null terminal, so use the length of the traceState string not len(traceState) + 1
return C.solClient_msg_tracing_setTraceStatePtr(messageP, contextType, cStr, C.ulong(traceStateLen))
})
return errorInfo
}

// For the Creation Context

// SolClientMessageGetCreationTraceContextTraceID function
func SolClientMessageGetCreationTraceContextTraceID(messageP SolClientMessagePt) ([16]byte, *SolClientErrorInfoWrapper) {
// return the traceID property for the creation trace context
return SolClientMessageGetTraceContextTraceID(messageP, SolClientContextTypeCreationContext)
}

// SolClientMessageSetCreationTraceContextTraceID function
func SolClientMessageSetCreationTraceContextTraceID(messageP SolClientMessagePt, traceID [16]byte) *SolClientErrorInfoWrapper {
// Sets the traceID property for the creation trace context
return SolClientMessageSetTraceContextTraceID(messageP, traceID, SolClientContextTypeCreationContext)
}

// SolClientMessageGetCreationTraceContextSpanID function
func SolClientMessageGetCreationTraceContextSpanID(messageP SolClientMessagePt) ([8]byte, *SolClientErrorInfoWrapper) {
// return the spanID property for the creation trace context
return SolClientMessageGetTraceContextSpanID(messageP, SolClientContextTypeCreationContext)
}

// SolClientMessageSetCreationTraceContextSpanID function
func SolClientMessageSetCreationTraceContextSpanID(messageP SolClientMessagePt, spanID [8]byte) *SolClientErrorInfoWrapper {
// Sets the spanID property for the creation trace context
return SolClientMessageSetTraceContextSpanID(messageP, spanID, SolClientContextTypeCreationContext)
}

// SolClientMessageGetCreationTraceContextSampled function
func SolClientMessageGetCreationTraceContextSampled(messageP SolClientMessagePt) (bool, *SolClientErrorInfoWrapper) {
// return the Sampled property for the creation trace context
return SolClientMessageGetTraceContextSampled(messageP, SolClientContextTypeCreationContext)
}

// SolClientMessageSetCreationTraceContextSampled function
func SolClientMessageSetCreationTraceContextSampled(messageP SolClientMessagePt, sampled bool) *SolClientErrorInfoWrapper {
// Sets the Sampled property for the creation trace context
return SolClientMessageSetTraceContextSampled(messageP, sampled, SolClientContextTypeCreationContext)
}

// SolClientMessageGetCreationTraceContextTraceState function
func SolClientMessageGetCreationTraceContextTraceState(messageP SolClientMessagePt) (string, *SolClientErrorInfoWrapper) {
// return the trace state property for the creation trace context
return SolClientMessageGetTraceContextTraceState(messageP, SolClientContextTypeCreationContext)
}

// SolClientMessageSetCreationTraceContextTraceState function
func SolClientMessageSetCreationTraceContextTraceState(messageP SolClientMessagePt, traceState string) *SolClientErrorInfoWrapper {
// Sets the trace state property for the creation trace context
return SolClientMessageSetTraceContextTraceState(messageP, traceState, SolClientContextTypeCreationContext)
}

// For the Transport Context

// SolClientMessageGetTransportTraceContextTraceID function
func SolClientMessageGetTransportTraceContextTraceID(messageP SolClientMessagePt) ([16]byte, *SolClientErrorInfoWrapper) {
// return the traceID property for the transport trace context
return SolClientMessageGetTraceContextTraceID(messageP, SolClientContextTypeTransportContext)
}

// SolClientMessageSetTransportTraceContextTraceID function
func SolClientMessageSetTransportTraceContextTraceID(messageP SolClientMessagePt, traceID [16]byte) *SolClientErrorInfoWrapper {
// Sets the traceID property for the transport trace context
return SolClientMessageSetTraceContextTraceID(messageP, traceID, SolClientContextTypeTransportContext)
}

// SolClientMessageGetTransportTraceContextSpanID function
func SolClientMessageGetTransportTraceContextSpanID(messageP SolClientMessagePt) ([8]byte, *SolClientErrorInfoWrapper) {
// return the spanID property for the transport trace context
return SolClientMessageGetTraceContextSpanID(messageP, SolClientContextTypeTransportContext)
}

// SolClientMessageSetTransportTraceContextSpanID function
func SolClientMessageSetTransportTraceContextSpanID(messageP SolClientMessagePt, spanID [8]byte) *SolClientErrorInfoWrapper {
// Sets the spanID property for the transport trace context
return SolClientMessageSetTraceContextSpanID(messageP, spanID, SolClientContextTypeTransportContext)
}

// SolClientMessageGetTransportTraceContextSampled function
func SolClientMessageGetTransportTraceContextSampled(messageP SolClientMessagePt) (bool, *SolClientErrorInfoWrapper) {
// return the Sampled property for the transport trace context
return SolClientMessageGetTraceContextSampled(messageP, SolClientContextTypeTransportContext)
}

// SolClientMessageSetTransportTraceContextSampled function
func SolClientMessageSetTransportTraceContextSampled(messageP SolClientMessagePt, sampled bool) *SolClientErrorInfoWrapper {
// Sets the Sampled property for the transport trace context
return SolClientMessageSetTraceContextSampled(messageP, sampled, SolClientContextTypeTransportContext)
}

// SolClientMessageGetTransportTraceContextTraceState function
func SolClientMessageGetTransportTraceContextTraceState(messageP SolClientMessagePt) (string, *SolClientErrorInfoWrapper) {
// return the trace state property for the transport trace context
return SolClientMessageGetTraceContextTraceState(messageP, SolClientContextTypeTransportContext)
}

// SolClientMessageSetTransportTraceContextTraceState function
func SolClientMessageSetTransportTraceContextTraceState(messageP SolClientMessagePt, traceState string) *SolClientErrorInfoWrapper {
// Sets the trace state property for the transport trace context
return SolClientMessageSetTraceContextTraceState(messageP, traceState, SolClientContextTypeTransportContext)
}

// For the Baggage

// SolClientMessageGetBaggage function
func SolClientMessageGetBaggage(messageP SolClientMessagePt) (string, *SolClientErrorInfoWrapper) {
var baggageChar *C.char
var baggageSize C.size_t
errorInfo := handleCcsmpError(func() SolClientReturnCode {
return C.solClient_msg_tracing_getBaggagePtr(messageP, &baggageChar, &baggageSize)
})
if errorInfo != nil {
if errorInfo.ReturnCode == SolClientReturnCodeFail {
logging.Default.Warning(
fmt.Sprintf(
"Encountered error fetching baggage: %s, subcode: %d",
errorInfo.GetMessageAsString(),
errorInfo.SubCode))
}
return "", errorInfo
}

// use baggageSize - 1 to exclude the null character at the end of the baggage string
return C.GoStringN(baggageChar, C.int(baggageSize)-1), errorInfo
}

// SolClientMessageSetBaggage function
func SolClientMessageSetBaggage(messageP SolClientMessagePt, baggage string) *SolClientErrorInfoWrapper {
// if the baggage is empty, delete the baggage from the message pointer
if baggage == "" {
deleteErrorInfo := handleCcsmpError(func() SolClientReturnCode {
return C.solClient_msg_tracing_deleteBaggage(messageP)
})
return deleteErrorInfo
}
// set the baggage if there is an actual baggage string
cStr := C.CString(baggage)
defer C.free(unsafe.Pointer(cStr)) // free the pointer after function executes
errorInfo := handleCcsmpError(func() SolClientReturnCode {
return C.solClient_msg_tracing_setBaggage(messageP, cStr)
})
return errorInfo
}
Empty file modified internal/ccsmp/lib/linux_arm64/libsolclient.a
100755 → 100644
Empty file.
Loading
Loading