Compare commits
2 Commits
v0.72.0-cl
...
v0.72.0-cl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37558facbe | ||
|
|
12f65f4a72 |
2
.github/workflows/push.yaml
vendored
2
.github/workflows/push.yaml
vendored
@@ -68,6 +68,8 @@ jobs:
|
||||
echo 'TUNNEL_URL="${{ secrets.TUNNEL_URL }}"' >> frontend/.env
|
||||
echo 'TUNNEL_DOMAIN="${{ secrets.TUNNEL_DOMAIN }}"' >> frontend/.env
|
||||
echo 'POSTHOG_KEY="${{ secrets.POSTHOG_KEY }}"' >> frontend/.env
|
||||
echo 'CUSTOMERIO_ID="${{ secrets.CUSTOMERIO_ID }}"' >> frontend/.env
|
||||
echo 'CUSTOMERIO_SITE_ID="${{ secrets.CUSTOMERIO_SITE_ID }}"' >> frontend/.env
|
||||
- name: Setup golang
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
"overlayscrollbars": "^2.8.1",
|
||||
"overlayscrollbars-react": "^0.5.6",
|
||||
"papaparse": "5.4.1",
|
||||
"posthog-js": "1.160.3",
|
||||
"posthog-js": "1.215.5",
|
||||
"rc-tween-one": "3.0.6",
|
||||
"react": "18.2.0",
|
||||
"react-addons-update": "15.6.3",
|
||||
|
||||
@@ -98,7 +98,23 @@
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script async>
|
||||
const CUSTOMERIO_ID = '<%= htmlWebpackPlugin.options.CUSTOMERIO_ID %>';
|
||||
const CUSTOMERIO_SITE_ID = '<%= htmlWebpackPlugin.options.CUSTOMERIO_SITE_ID %>';
|
||||
!function(){var i="cioanalytics", analytics=(window[i]=window[i]||[]);if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","once","off","on","addSourceMiddleware","addIntegrationMiddleware","setAnonymousId","addDestinationMiddleware"];analytics.factory=function(e){return function(){var t=Array.prototype.slice.call(arguments);t.unshift(e);analytics.push(t);return analytics}};for(var e=0;e<analytics.methods.length;e++){var key=analytics.methods[e];analytics[key]=analytics.factory(key)}analytics.load=function(key,e){var t=document.createElement("script");t.type="text/javascript";t.async=!0;t.setAttribute('data-global-segment-analytics-key', i);t.setAttribute('data-global-segment-analytics-key', i);t.src="https://cdp.customer.io/v1/analytics-js/snippet/" + key + "/analytics.min.js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(t,n);analytics._writeKey=key;analytics._loadOptions=e};analytics.SNIPPET_VERSION="4.15.3";
|
||||
analytics.load(
|
||||
CUSTOMERIO_ID,
|
||||
{
|
||||
"integrations": {
|
||||
"Customer.io In-App Plugin": {
|
||||
siteId: CUSTOMERIO_SITE_ID
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
analytics.page();
|
||||
}}();
|
||||
</script>
|
||||
<script>
|
||||
//Set your SEGMENT_ID
|
||||
const SEGMENT_ID = '<%= htmlWebpackPlugin.options.SEGMENT_ID %>';
|
||||
|
||||
@@ -22,6 +22,8 @@ const plugins = [
|
||||
template: 'src/index.html.ejs',
|
||||
INTERCOM_APP_ID: process.env.INTERCOM_APP_ID,
|
||||
SEGMENT_ID: process.env.SEGMENT_ID,
|
||||
CUSTOMERIO_SITE_ID: process.env.CUSTOMERIO_SITE_ID,
|
||||
CUSTOMERIO_ID: process.env.CUSTOMERIO_ID,
|
||||
POSTHOG_KEY: process.env.POSTHOG_KEY,
|
||||
SENTRY_AUTH_TOKEN: process.env.SENTRY_AUTH_TOKEN,
|
||||
SENTRY_ORG: process.env.SENTRY_ORG,
|
||||
@@ -40,6 +42,8 @@ const plugins = [
|
||||
WEBSOCKET_API_ENDPOINT: process.env.WEBSOCKET_API_ENDPOINT,
|
||||
INTERCOM_APP_ID: process.env.INTERCOM_APP_ID,
|
||||
SEGMENT_ID: process.env.SEGMENT_ID,
|
||||
CUSTOMERIO_SITE_ID: process.env.CUSTOMERIO_SITE_ID,
|
||||
CUSTOMERIO_ID: process.env.CUSTOMERIO_ID,
|
||||
POSTHOG_KEY: process.env.POSTHOG_KEY,
|
||||
SENTRY_AUTH_TOKEN: process.env.SENTRY_AUTH_TOKEN,
|
||||
SENTRY_ORG: process.env.SENTRY_ORG,
|
||||
|
||||
@@ -27,6 +27,8 @@ const plugins = [
|
||||
template: 'src/index.html.ejs',
|
||||
INTERCOM_APP_ID: process.env.INTERCOM_APP_ID,
|
||||
SEGMENT_ID: process.env.SEGMENT_ID,
|
||||
CUSTOMERIO_SITE_ID: process.env.CUSTOMERIO_SITE_ID,
|
||||
CUSTOMERIO_ID: process.env.CUSTOMERIO_ID,
|
||||
POSTHOG_KEY: process.env.POSTHOG_KEY,
|
||||
SENTRY_AUTH_TOKEN: process.env.SENTRY_AUTH_TOKEN,
|
||||
SENTRY_ORG: process.env.SENTRY_ORG,
|
||||
@@ -50,6 +52,8 @@ const plugins = [
|
||||
WEBSOCKET_API_ENDPOINT: process.env.WEBSOCKET_API_ENDPOINT,
|
||||
INTERCOM_APP_ID: process.env.INTERCOM_APP_ID,
|
||||
SEGMENT_ID: process.env.SEGMENT_ID,
|
||||
CUSTOMERIO_SITE_ID: process.env.CUSTOMERIO_SITE_ID,
|
||||
CUSTOMERIO_ID: process.env.CUSTOMERIO_ID,
|
||||
POSTHOG_KEY: process.env.POSTHOG_KEY,
|
||||
SENTRY_AUTH_TOKEN: process.env.SENTRY_AUTH_TOKEN,
|
||||
SENTRY_ORG: process.env.SENTRY_ORG,
|
||||
|
||||
@@ -48,9 +48,6 @@ const (
|
||||
defaultTraceLocalTableName string = "signoz_index_v3"
|
||||
defaultTraceResourceTableV3 string = "distributed_traces_v3_resource"
|
||||
defaultTraceSummaryTable string = "distributed_trace_summary"
|
||||
|
||||
defaultMetadataDB string = "signoz_metadata"
|
||||
defaultMetadataTable string = "distributed_attributes_metadata"
|
||||
)
|
||||
|
||||
// NamespaceConfig is Clickhouse's internal configuration data
|
||||
@@ -91,9 +88,6 @@ type namespaceConfig struct {
|
||||
TraceLocalTableNameV3 string
|
||||
TraceResourceTableV3 string
|
||||
TraceSummaryTable string
|
||||
|
||||
MetadataDB string
|
||||
MetadataTable string
|
||||
}
|
||||
|
||||
// Connecto defines how to connect to the database
|
||||
@@ -147,9 +141,6 @@ func NewOptions(
|
||||
TraceLocalTableNameV3: defaultTraceLocalTableName,
|
||||
TraceResourceTableV3: defaultTraceResourceTableV3,
|
||||
TraceSummaryTable: defaultTraceSummaryTable,
|
||||
|
||||
MetadataDB: defaultMetadataDB,
|
||||
MetadataTable: defaultMetadataTable,
|
||||
},
|
||||
others: make(map[string]*namespaceConfig, len(otherNamespaces)),
|
||||
}
|
||||
|
||||
@@ -162,8 +162,6 @@ type ClickHouseReader struct {
|
||||
|
||||
fluxIntervalForTraceDetail time.Duration
|
||||
cache cache.Cache
|
||||
metadataDB string
|
||||
metadataTable string
|
||||
}
|
||||
|
||||
// NewTraceReader returns a TraceReader for the database
|
||||
@@ -259,8 +257,6 @@ func NewReaderFromClickhouseConnection(
|
||||
|
||||
fluxIntervalForTraceDetail: fluxIntervalForTraceDetail,
|
||||
cache: cache,
|
||||
metadataDB: options.primary.MetadataDB,
|
||||
metadataTable: options.primary.MetadataTable,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1459,7 +1455,7 @@ func (r *ClickHouseReader) GetWaterfallSpansForTraceWithMetadata(ctx context.Con
|
||||
var serviceNameIntervalMap = map[string][]tracedetail.Interval{}
|
||||
var hasMissingSpans bool
|
||||
|
||||
userEmail, emailErr := auth.GetEmailFromJwt(ctx)
|
||||
userEmail , emailErr := auth.GetEmailFromJwt(ctx)
|
||||
cachedTraceData, err := r.GetWaterfallSpansForTraceWithMetadataCache(ctx, traceID)
|
||||
if err == nil {
|
||||
startTime = cachedTraceData.StartTime
|
||||
@@ -1535,8 +1531,8 @@ func (r *ClickHouseReader) GetWaterfallSpansForTraceWithMetadata(ctx context.Con
|
||||
if startTime == 0 || startTimeUnixNano < startTime {
|
||||
startTime = startTimeUnixNano
|
||||
}
|
||||
if endTime == 0 || (startTimeUnixNano+jsonItem.DurationNano) > endTime {
|
||||
endTime = (startTimeUnixNano + jsonItem.DurationNano)
|
||||
if endTime == 0 || (startTimeUnixNano + jsonItem.DurationNano ) > endTime {
|
||||
endTime = (startTimeUnixNano + jsonItem.DurationNano )
|
||||
}
|
||||
if durationNano == 0 || jsonItem.DurationNano > durationNano {
|
||||
durationNano = jsonItem.DurationNano
|
||||
@@ -1713,12 +1709,12 @@ func (r *ClickHouseReader) GetFlamegraphSpansForTrace(ctx context.Context, trace
|
||||
}
|
||||
|
||||
// metadata calculation
|
||||
startTimeUnixNano := uint64(item.TimeUnixNano.UnixNano())
|
||||
startTimeUnixNano := uint64(item.TimeUnixNano.UnixNano())
|
||||
if startTime == 0 || startTimeUnixNano < startTime {
|
||||
startTime = startTimeUnixNano
|
||||
}
|
||||
if endTime == 0 || (startTimeUnixNano+jsonItem.DurationNano) > endTime {
|
||||
endTime = (startTimeUnixNano + jsonItem.DurationNano)
|
||||
if endTime == 0 || ( startTimeUnixNano + jsonItem.DurationNano ) > endTime {
|
||||
endTime = (startTimeUnixNano + jsonItem.DurationNano )
|
||||
}
|
||||
if durationNano == 0 || jsonItem.DurationNano > durationNano {
|
||||
durationNano = jsonItem.DurationNano
|
||||
@@ -1782,7 +1778,7 @@ func (r *ClickHouseReader) GetFlamegraphSpansForTrace(ctx context.Context, trace
|
||||
|
||||
trace.Spans = selectedSpansForRequest
|
||||
trace.StartTimestampMillis = startTime / 1000000
|
||||
trace.EndTimestampMillis = endTime / 1000000
|
||||
trace.EndTimestampMillis = endTime / 1000000
|
||||
return trace, nil
|
||||
}
|
||||
|
||||
@@ -4140,97 +4136,6 @@ func (r *ClickHouseReader) GetLogAttributeKeys(ctx context.Context, req *v3.Filt
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
func (r *ClickHouseReader) FetchRelatedValues(ctx context.Context, req *v3.FilterAttributeValueRequest) ([]string, error) {
|
||||
var andConditions []string
|
||||
|
||||
andConditions = append(andConditions, fmt.Sprintf("unix_milli >= %d", req.StartTimeMillis))
|
||||
andConditions = append(andConditions, fmt.Sprintf("unix_milli <= %d", req.EndTimeMillis))
|
||||
|
||||
if len(req.ExistingFilterItems) != 0 {
|
||||
for _, item := range req.ExistingFilterItems {
|
||||
// we only support string for related values
|
||||
if item.Key.DataType != v3.AttributeKeyDataTypeString {
|
||||
continue
|
||||
}
|
||||
|
||||
var colName string
|
||||
switch item.Key.Type {
|
||||
case v3.AttributeKeyTypeResource:
|
||||
colName = "resource_attributes"
|
||||
case v3.AttributeKeyTypeTag:
|
||||
colName = "attributes"
|
||||
default:
|
||||
// we only support resource and tag for related values as of now
|
||||
continue
|
||||
}
|
||||
// IN doesn't make use of map value index, we convert it to = or !=
|
||||
operator := item.Operator
|
||||
if v3.FilterOperator(strings.ToLower(string(item.Operator))) == v3.FilterOperatorIn {
|
||||
operator = "="
|
||||
} else if v3.FilterOperator(strings.ToLower(string(item.Operator))) == v3.FilterOperatorNotIn {
|
||||
operator = "!="
|
||||
}
|
||||
addCondition := func(val string) {
|
||||
andConditions = append(andConditions, fmt.Sprintf("mapContains(%s, '%s') AND %s['%s'] %s %s", colName, item.Key.Key, colName, item.Key.Key, operator, val))
|
||||
}
|
||||
switch v := item.Value.(type) {
|
||||
case string:
|
||||
fmtVal := utils.ClickHouseFormattedValue(v)
|
||||
addCondition(fmtVal)
|
||||
case []string:
|
||||
for _, val := range v {
|
||||
fmtVal := utils.ClickHouseFormattedValue(val)
|
||||
addCondition(fmtVal)
|
||||
}
|
||||
case []interface{}:
|
||||
for _, val := range v {
|
||||
fmtVal := utils.ClickHouseFormattedValue(val)
|
||||
addCondition(fmtVal)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
whereClause := strings.Join(andConditions, " AND ")
|
||||
|
||||
var selectColumn string
|
||||
switch req.TagType {
|
||||
case v3.TagTypeResource:
|
||||
selectColumn = "resource_attributes" + "['" + req.FilterAttributeKey + "']"
|
||||
case v3.TagTypeTag:
|
||||
selectColumn = "attributes" + "['" + req.FilterAttributeKey + "']"
|
||||
default:
|
||||
selectColumn = "attributes" + "['" + req.FilterAttributeKey + "']"
|
||||
}
|
||||
|
||||
filterSubQuery := fmt.Sprintf(
|
||||
"SELECT DISTINCT %s FROM %s.%s WHERE %s LIMIT 100",
|
||||
selectColumn,
|
||||
r.metadataDB,
|
||||
r.metadataTable,
|
||||
whereClause,
|
||||
)
|
||||
zap.L().Debug("filterSubQuery for related values", zap.String("query", filterSubQuery))
|
||||
|
||||
rows, err := r.db.Query(ctx, filterSubQuery)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while executing query: %s", err.Error())
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var attributeValues []string
|
||||
for rows.Next() {
|
||||
var value string
|
||||
if err := rows.Scan(&value); err != nil {
|
||||
return nil, fmt.Errorf("error while scanning rows: %s", err.Error())
|
||||
}
|
||||
if value != "" {
|
||||
attributeValues = append(attributeValues, value)
|
||||
}
|
||||
}
|
||||
|
||||
return attributeValues, nil
|
||||
}
|
||||
|
||||
func (r *ClickHouseReader) GetLogAttributeValues(ctx context.Context, req *v3.FilterAttributeValueRequest) (*v3.FilterAttributeValueResponse, error) {
|
||||
var err error
|
||||
var filterValueColumn string
|
||||
@@ -4332,11 +4237,6 @@ func (r *ClickHouseReader) GetLogAttributeValues(ctx context.Context, req *v3.Fi
|
||||
}
|
||||
}
|
||||
|
||||
relatedValues, _ := r.FetchRelatedValues(ctx, req)
|
||||
attributeValues.RelatedValues = &v3.FilterAttributeValueResponse{
|
||||
StringAttributeValues: relatedValues,
|
||||
}
|
||||
|
||||
return &attributeValues, nil
|
||||
|
||||
}
|
||||
@@ -5017,11 +4917,6 @@ func (r *ClickHouseReader) GetTraceAttributeValues(ctx context.Context, req *v3.
|
||||
}
|
||||
}
|
||||
|
||||
relatedValues, _ := r.FetchRelatedValues(ctx, req)
|
||||
attributeValues.RelatedValues = &v3.FilterAttributeValueResponse{
|
||||
StringAttributeValues: relatedValues,
|
||||
}
|
||||
|
||||
return &attributeValues, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -380,7 +380,6 @@ func (aH *APIHandler) RegisterQueryRangeV3Routes(router *mux.Router, am *AuthMid
|
||||
withCacheControl(AutoCompleteCacheControlAge, aH.autoCompleteAttributeKeys))).Methods(http.MethodGet)
|
||||
subRouter.HandleFunc("/autocomplete/attribute_values", am.ViewAccess(
|
||||
withCacheControl(AutoCompleteCacheControlAge, aH.autoCompleteAttributeValues))).Methods(http.MethodGet)
|
||||
subRouter.HandleFunc("/autocomplete/attribute_values", am.ViewAccess(aH.autoCompleteAttributeValuesPost)).Methods(http.MethodPost)
|
||||
subRouter.HandleFunc("/query_range", am.ViewAccess(aH.QueryRangeV3)).Methods(http.MethodPost)
|
||||
subRouter.HandleFunc("/query_range/format", am.ViewAccess(aH.QueryRangeV3Format)).Methods(http.MethodPost)
|
||||
|
||||
@@ -4816,35 +4815,6 @@ func (aH *APIHandler) autoCompleteAttributeValues(w http.ResponseWriter, r *http
|
||||
aH.Respond(w, response)
|
||||
}
|
||||
|
||||
func (aH *APIHandler) autoCompleteAttributeValuesPost(w http.ResponseWriter, r *http.Request) {
|
||||
var response *v3.FilterAttributeValueResponse
|
||||
req, err := parseFilterAttributeValueRequestBody(r)
|
||||
|
||||
if err != nil {
|
||||
RespondError(w, &model.ApiError{Typ: model.ErrorBadData, Err: err}, nil)
|
||||
return
|
||||
}
|
||||
|
||||
switch req.DataSource {
|
||||
case v3.DataSourceMetrics:
|
||||
response, err = aH.reader.GetMetricAttributeValues(r.Context(), req)
|
||||
case v3.DataSourceLogs:
|
||||
response, err = aH.reader.GetLogAttributeValues(r.Context(), req)
|
||||
case v3.DataSourceTraces:
|
||||
response, err = aH.reader.GetTraceAttributeValues(r.Context(), req)
|
||||
default:
|
||||
RespondError(w, &model.ApiError{Typ: model.ErrorBadData, Err: fmt.Errorf("invalid data source")}, nil)
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
RespondError(w, &model.ApiError{Typ: model.ErrorBadData, Err: err}, nil)
|
||||
return
|
||||
}
|
||||
|
||||
aH.Respond(w, response)
|
||||
}
|
||||
|
||||
func (aH *APIHandler) getSpanKeysV3(ctx context.Context, queryRangeParams *v3.QueryRangeParamsV3) (map[string]v3.AttributeKey, error) {
|
||||
data := map[string]v3.AttributeKey{}
|
||||
for _, query := range queryRangeParams.CompositeQuery.BuilderQueries {
|
||||
|
||||
@@ -769,25 +769,6 @@ func parseFilterAttributeValueRequest(r *http.Request) (*v3.FilterAttributeValue
|
||||
return &req, nil
|
||||
}
|
||||
|
||||
func parseFilterAttributeValueRequestBody(r *http.Request) (*v3.FilterAttributeValueRequest, error) {
|
||||
|
||||
var req v3.FilterAttributeValueRequest
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := req.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// offset by two windows periods for start for better results
|
||||
req.StartTimeMillis = req.StartTimeMillis - time.Hour.Milliseconds()*6*2
|
||||
req.EndTimeMillis = req.EndTimeMillis + time.Hour.Milliseconds()*6
|
||||
|
||||
return &req, nil
|
||||
}
|
||||
|
||||
func validateQueryRangeParamsV3(qp *v3.QueryRangeParamsV3) error {
|
||||
err := qp.CompositeQuery.Validate()
|
||||
if err != nil {
|
||||
|
||||
@@ -297,8 +297,6 @@ func (q AttributeKeyDataType) String() string {
|
||||
// for a selected aggregate operator, aggregate attribute, filter attribute key
|
||||
// and search text.
|
||||
type FilterAttributeValueRequest struct {
|
||||
StartTimeMillis int64 `json:"startTimeMillis"`
|
||||
EndTimeMillis int64 `json:"endTimeMillis"`
|
||||
DataSource DataSource `json:"dataSource"`
|
||||
AggregateOperator AggregateOperator `json:"aggregateOperator"`
|
||||
AggregateAttribute string `json:"aggregateAttribute"`
|
||||
@@ -307,50 +305,6 @@ type FilterAttributeValueRequest struct {
|
||||
TagType TagType `json:"tagType"`
|
||||
SearchText string `json:"searchText"`
|
||||
Limit int `json:"limit"`
|
||||
ExistingFilterItems []FilterItem `json:"existingFilterItems"`
|
||||
MetricNames []string `json:"metricNames"`
|
||||
}
|
||||
|
||||
func (f *FilterAttributeValueRequest) Validate() error {
|
||||
if f.FilterAttributeKey == "" {
|
||||
return fmt.Errorf("filterAttributeKey is required")
|
||||
}
|
||||
|
||||
if f.StartTimeMillis == 0 {
|
||||
return fmt.Errorf("startTimeMillis is required")
|
||||
}
|
||||
|
||||
if f.EndTimeMillis == 0 {
|
||||
return fmt.Errorf("endTimeMillis is required")
|
||||
}
|
||||
|
||||
if f.Limit == 0 {
|
||||
f.Limit = 100
|
||||
}
|
||||
|
||||
if f.Limit > 1000 {
|
||||
return fmt.Errorf("limit must be less than 1000")
|
||||
}
|
||||
|
||||
if f.ExistingFilterItems != nil {
|
||||
for _, value := range f.ExistingFilterItems {
|
||||
if value.Key.Key == "" {
|
||||
return fmt.Errorf("existingFilterItems must contain a valid key")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := f.DataSource.Validate(); err != nil {
|
||||
return fmt.Errorf("invalid data source: %w", err)
|
||||
}
|
||||
|
||||
if f.DataSource != DataSourceMetrics {
|
||||
if err := f.AggregateOperator.Validate(); err != nil {
|
||||
return fmt.Errorf("invalid aggregate operator: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type AggregateAttributeResponse struct {
|
||||
@@ -415,8 +369,6 @@ type FilterAttributeValueResponse struct {
|
||||
StringAttributeValues []string `json:"stringAttributeValues"`
|
||||
NumberAttributeValues []interface{} `json:"numberAttributeValues"`
|
||||
BoolAttributeValues []bool `json:"boolAttributeValues"`
|
||||
|
||||
RelatedValues *FilterAttributeValueResponse `json:"relatedValues"`
|
||||
}
|
||||
|
||||
type QueryRangeParamsV3 struct {
|
||||
|
||||
Reference in New Issue
Block a user