Skip to content

CASSGO-119 Add Table field to ObservedQuery and ObservedBatch for table-level observability#1941

Merged
joao-r-reis merged 1 commit into
apache:trunkfrom
raj14243:CASSGO-119-add-table-to-query-observations
Jun 22, 2026
Merged

CASSGO-119 Add Table field to ObservedQuery and ObservedBatch for table-level observability#1941
joao-r-reis merged 1 commit into
apache:trunkfrom
raj14243:CASSGO-119-add-table-to-query-observations

Conversation

@raj14243

@raj14243 raj14243 commented Apr 6, 2026

Copy link
Copy Markdown
Contributor

ObservedQuery and ObservedBatch did not expose the target table name, requiring consumers (metrics collectors, loggers, tracers) to parse the CQL statement string to determine which table a query targets.

This change adds a Table field to ObservedQuery and a Tables field to ObservedBatch, populated from prepared statement metadata returned by Cassandra. The table information was already available internally via preparedMetadata (used for routing), so no additional round-trips or CQL parsing are needed.

Patch by Raj Ummadisetty for CASSGO-119

@worryg0d worryg0d left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hi @raj14243,

I have spent some time reviewing this PR - LGTM.

One thing I noticed is that PR lacks integration testing for this change. This is a small change actually, but updating existing tests would be good anyway. There are TestObserve and TestBatchObserve integration tests for both query and batch observe respectively, that you can update to reflect this API change.

@raj14243 raj14243 force-pushed the CASSGO-119-add-table-to-query-observations branch 6 times, most recently from 6f70f04 to 5cb769b Compare April 10, 2026 00:37
Comment thread session.go Outdated

// StatementKeyspace is the keyspace of the table targeted by the query.
// It is populated from prepared statement metadata returned by Cassandra.
StatementKeyspace string

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think it is fine to populate the existing Keyspace field here - it is unclear to see the difference between Keyspace and StatementKeyspace

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The existing Keyspace field is populated with Keyspace the session is initialized with. I am concerned changing that might break if someone is using it with that assumption.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yeah, this is why I filed CASSGO-120, I'm unsure if this is the correct behavior. At least I was expecting it to be based on the query, if it is presented there

Comment thread query_executor.go Outdated
Query: q.originalQuery,
Keyspace: keyspace,
Statement: q.qryOpts.stmt,
StatementKeyspace: q.routingInfo.getKeyspace(),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

routingInfo could not have any information about keyspaces/tables for DDL queries that are unprepareable, so you probably should use internalQuery.Keyspace() here. It has some predefined defaulting behavior.

We should probably think about adding a kind of parsing of DDL queries to determine keyspace and table names from it before defaulting to session-level keyspace.

Also, there is an alternative for internalBatch.Keyspace() as well, but it just calls the underlying routingInfo, which is fine because it is impossible to batch DDL queries.

@joao-r-reis, could you please take a look at this?

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.

Hmm I don't think we should be adding CQL parsing for something like this, most if not all drivers avoid doing any kind of CQL parsing. What some drivers do is expose a statement builder / mapper API that will create statements and internally set fields so the driver is aware of some metadata like keyspace, table, idempotency without having to parse it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I will check the internalQuery.Keyspace() I agree with @joao-r-reis on not having CQL parsing. I started this PR as we were internally parsing statement to extract keyspace and wanted to avoid that :)

@joao-r-reis joao-r-reis left a comment

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 think the current design is not intuitive for cases where no prepared statement metadata is available.

I explored a bit and came up with something like this:

type PreparedMetadata struct {
    Keyspace string
    Table    string
}

type ObservedQuery struct {
    Keyspace          string
    Statement         string
    PreparedMetadata  PreparedMetadata  // zero value when unprepared
    IsPrepared        bool              // flag at query level
    // ...
}

type ObservedBatch struct {
    Keyspace          string
    Statements        []string
    PreparedMetadata  []PreparedMetadata  // zero values for unprepared
    IsPrepared        []bool              // parallel array of flags
    // ...
}

We could also just get rid of the IsPrepared flag and just make prepared metadata a pointer (so nil would mean it's not prepared) but that would lead to extra allocs.

Wdyt?

Comment thread CHANGELOG.md

## [2.1.1]

### Added

@joao-r-reis joao-r-reis Apr 17, 2026

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.

Add a new 2.2.0 section and move this under there

@worryg0d

worryg0d commented May 4, 2026

Copy link
Copy Markdown
Member

Wdyt?

Yeah I guess it would work, but API looks a bit gross. As alternative to exposing those fields to ObservedXY structs, you may call this method:

func (s *Session) StatementMetadata(ctx context.Context, stmt, keyspace string) (StatementMetadata, error) {

It basically allows to retrieve internally cached statement metadata. But this requires observers to be able to call session methods

@raj14243 raj14243 force-pushed the CASSGO-119-add-table-to-query-observations branch from 5cb769b to 5f3f136 Compare May 20, 2026 00:24
@worryg0d

Copy link
Copy Markdown
Member

Besides CASSGO-120, this PR looks good.

I guess you can get rid of CASSGO-120 in the commit message, and we will handle it separately if it is worth fixing

@raj14243 raj14243 force-pushed the CASSGO-119-add-table-to-query-observations branch 2 times, most recently from ebeec18 to 43d8359 Compare May 27, 2026 16:09
@joao-r-reis joao-r-reis changed the title Add Table field to ObservedQuery and ObservedBatch for table-level observability CASSGO-119 Add Table field to ObservedQuery and ObservedBatch for table-level observability Jun 1, 2026
@joao-r-reis

Copy link
Copy Markdown
Contributor

Let's hold off on merging this until 2.1.2 is released

@worryg0d worryg0d left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

+1

@joao-r-reis

Copy link
Copy Markdown
Contributor

@raj14243 can you add both of us as reviewers to the commit message and fix the git conflict? Will merge afterwards

@joao-r-reis

Copy link
Copy Markdown
Contributor

Or if you don't mind github not recognizing the PR as "merged" then I can do that for you and set you as author of the commit

…vedBatch

ObservedQuery and ObservedBatch did not expose the keyspace/table targeted
by a query, requiring consumers (metrics collectors, loggers, tracers) to
parse the CQL statement string.

This change introduces a PreparedMetadata struct (Keyspace, Table) on
ObservedQuery and a parallel []PreparedMetadata slice on ObservedBatch,
populated from prepared statement metadata returned by Cassandra. An
IsPrepared bool on ObservedQuery and a parallel []bool on ObservedBatch
explicitly report when the metadata is valid; statements that take the
unprepared path (e.g. DDL) report IsPrepared=false and zero PreparedMetadata.

The information was already available internally via preparedMetadata
(used for routing), so no additional round-trips or CQL parsing are needed.

Updated TestObserve (including a negative case for an unprepared DDL
statement) and TestBatchObserve to verify the new fields.

Patch by Raj Ummadisetty; reviewed by João Reis, Bohdan Siryk for CASSGO-119
@raj14243 raj14243 force-pushed the CASSGO-119-add-table-to-query-observations branch from 43d8359 to 9f74a18 Compare June 20, 2026 02:26
@raj14243

Copy link
Copy Markdown
Contributor Author

@raj14243 can you add both of us as reviewers to the commit message and fix the git conflict? Will merge afterwards

@joao-r-reis done

@joao-r-reis joao-r-reis merged commit 9bc3b5d into apache:trunk Jun 22, 2026
72 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants