Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 3 additions & 4 deletions plugin/storage/es/spanstore/service_operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package spanstore

import (
"context"
"fmt"
"time"

"github.com/pkg/errors"
Expand Down Expand Up @@ -74,10 +73,10 @@ func (s *ServiceOperationStorage) Write(indexName string, jsonSpan *jModel.Span)
ServiceName: jsonSpan.Process.ServiceName,
OperationName: jsonSpan.OperationName,
}
serviceID := fmt.Sprintf("%s|%s", service.ServiceName, service.OperationName)
cacheKey := fmt.Sprintf("%s:%s", indexName, serviceID)

cacheKey := service.hashCode()
if !keyInCache(cacheKey, s.serviceCache) {
s.client.Index().Index(indexName).Type(serviceType).Id(serviceID).BodyJson(service).Add()
s.client.Index().Index(indexName).Type(serviceType).Id(cacheKey).BodyJson(service).Add()
writeCache(cacheKey, s.serviceCache)
}
}
Expand Down
8 changes: 6 additions & 2 deletions plugin/storage/es/spanstore/service_operation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ func TestWriteService(t *testing.T) {
indexService := &mocks.IndexService{}

indexName := "jaeger-1995-04-21"
serviceHash := "de3b5a8f1a79989d"

indexService.On("Index", stringMatcher(indexName)).Return(indexService)
indexService.On("Type", stringMatcher(serviceType)).Return(indexService)
indexService.On("Id", stringMatcher("service|operation")).Return(indexService)
indexService.On("Id", stringMatcher(serviceHash)).Return(indexService)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a big fan of using the same hash function here to test that the service was hashed, I'd prefer if you generated this hash once and compare against the actual hash string.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed calls to hashCode() and put static hash in those tests.

indexService.On("BodyJson", mock.AnythingOfType("spanstore.Service")).Return(indexService)
indexService.On("Add")

Expand Down Expand Up @@ -64,9 +66,11 @@ func TestWriteServiceError(t *testing.T) {
indexService := &mocks.IndexService{}

indexName := "jaeger-1995-04-21"
serviceHash := "de3b5a8f1a79989d"

indexService.On("Index", stringMatcher(indexName)).Return(indexService)
indexService.On("Type", stringMatcher(serviceType)).Return(indexService)
indexService.On("Id", stringMatcher("service|operation")).Return(indexService)
indexService.On("Id", stringMatcher(serviceHash)).Return(indexService)
indexService.On("BodyJson", mock.AnythingOfType("spanstore.Service")).Return(indexService)
indexService.On("Add")

Expand Down
9 changes: 9 additions & 0 deletions plugin/storage/es/spanstore/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ package spanstore

import (
"context"
"fmt"
"hash/fnv"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -73,6 +75,13 @@ type Span struct {
StartTimeMillis uint64 `json:"startTimeMillis"`
}

func (s Service) hashCode() string {
h := fnv.New64a()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this be cached?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@black-adder It could be but it will introduce issue with concurrency. Every simultaneous call to this function would potentially cause race condition and would render unpredictable hash results. I would need to introduce some kind of semaphore and mark this part as critical section. Do you think it is worth?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unpredictable hash results -> shouldn't this always produce the same hash results for the same key even if run concurrently? I actually dont know the inner workings of the implementation so maybe completely wrong, we can skip for now but can you add a TODO to investigate in the future (unless you already know that there will be race conditions).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@black-adder so my reasoning is like this.

  1. You store cached hasher object somewhere (most likely in the writer.go) and use it whenever someone calls hashCode()
  2. First process (1) calls hashCode(), fetches (creates if not cached) hasher object
  3. (1) Pushes data: OperationName and ServiceName to the hasher
  4. Second process (2) calls hashCode() which fetches the same (cached) hasher object
  5. (2) pushes its OperationName and ServiceName to the same hasher
  6. (1) calculates checksum by calling Sum64() on the same hasher (which now holds data from two possibly different instances of Service)
  7. (2) does the calculations too and gets the same (wrong) hash as (1)

I did actually run into this issue while fixing the tests :-)

Even if I introduce hash.Reset() just after Sum64() or before data is pushed it the hasher I still have no guarantees that other process is not doing some operation on the cached object. Putting Write semaphore would probably do the trick but I think it is a bit overkill in this case.

I hope this helps.

h.Write([]byte(s.ServiceName))
h.Write([]byte(s.OperationName))
return fmt.Sprintf("%x", h.Sum64())
}

// NewSpanWriter creates a new SpanWriter for use
func NewSpanWriter(
client es.Client,
Expand Down
3 changes: 2 additions & 1 deletion plugin/storage/es/spanstore/writer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ func TestSpanWriter_WriteSpan(t *testing.T) {

spanIndexName := "jaeger-span-1995-04-21"
serviceIndexName := "jaeger-service-1995-04-21"
serviceHash := "de3b5a8f1a79989d"

serviceExistsService := &mocks.IndicesExistsService{}
spanExistsService := &mocks.IndicesExistsService{}
Expand All @@ -159,7 +160,7 @@ func TestSpanWriter_WriteSpan(t *testing.T) {
indexService.On("Type", stringMatcher(serviceType)).Return(indexServicePut)
indexService.On("Type", stringMatcher(spanType)).Return(indexSpanPut)

indexServicePut.On("Id", stringMatcher("service|operation")).Return(indexServicePut)
indexServicePut.On("Id", stringMatcher(serviceHash)).Return(indexServicePut)
indexServicePut.On("BodyJson", mock.AnythingOfType("spanstore.Service")).Return(indexServicePut)
indexServicePut.On("Add")

Expand Down