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(automated-rules): implement automated rules #34

Merged
merged 21 commits into from
Aug 1, 2023

Conversation

maxcao13
Copy link
Member

@maxcao13 maxcao13 commented Jun 30, 2023

Related #15

sample test queries:

 http -f --auth=user:pass :8181/api/v2/rules name="asdf" matchExpression="true" eventSpecifier="template=ALL"

@maxcao13 maxcao13 added the feat New feature or request label Jun 30, 2023
@maxcao13
Copy link
Member Author

I used https://github.com/projectnessie/cel-java as the implementation for Google's CEL for java. Google's repo doesn't seem to support our use case for now: google/cel-java#68 but it seems the two projects are teaming up? google/cel-java#37

@maxcao13 maxcao13 requested a review from andrewazores July 19, 2023 22:42
@ebaron
Copy link
Member

ebaron commented Jul 21, 2023

I used https://github.com/projectnessie/cel-java as the implementation for Google's CEL for java. Google's repo doesn't seem to support our use case for now: google/cel-java#68 but it seems the two projects are teaming up? google/cel-java#37

The Project Nessie implementation looks easier to build downstream: Gradle instead of Bazel. The only drawback is if this implementation merges into Google's, we'll have to start from scratch in terms of building it.

Copy link
Member

@andrewazores andrewazores left a comment

Choose a reason for hiding this comment

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

Looking great from a read-through. I'll give this a try soon.

@andrewazores
Copy link
Member

I think the new uniqueness constraint on the ActiveRecording name isn't working as anticipated:

cryostat_1            | 2023-07-26 14:04:19,026 ERROR [org.hib.eng.jdb.spi.SqlExceptionHelper] (executor-thread-1) ERROR: duplicate key value violates unique constraint "activerecording_name_key"
cryostat_1            |   Detail: Key (name)=(auto_test) already exists.
cryostat_1            | 2023-07-26 14:04:19,026 WARN  [com.arj.ats.arjuna] (executor-thread-1) ARJUNA012125: TwoPhaseCoordinator.beforeCompletion - failed for SynchronizationImple< 0:ffff0a590115:83e1:64c1261c:82, org.hibernate.resource.transaction.backend.jta.internal.synchronization.RegisteredSynchronization@2dc0388b >: org.hibernate.exception.ConstraintViolationException: could not execute statement [ERROR: duplicatekey value violates unique constraint "activerecording_name_key"
cryostat_1            |   Detail: Key (name)=(auto_test) already exists.] [insert into ActiveRecording (continuous,duration,maxAge,maxSize,metadata,name,remoteId,startTime,state,target_id,toDisk,id) values (?,?,?,?,?,?,?,?,?,?,?,?)]
cryostat_1            | 	at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:95)
cryostat_1            | 	at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:56)
cryostat_1            | 	at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:108)
cryostat_1            | 	at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:278)
cryostat_1            | 	at org.hibernate.engine.jdbc.mutation.internal.AbstractMutationExecutor.performNonBatchedMutation(AbstractMutationExecutor.java:108)
cryostat_1            | 	at org.hibernate.engine.jdbc.mutation.internal.MutationExecutorSingleNonBatched.performNonBatchedOperations(MutationExecutorSingleNonBatched.java:40)
cryostat_1            | 	at org.hibernate.engine.jdbc.mutation.internal.AbstractMutationExecutor.execute(AbstractMutationExecutor.java:53)
cryostat_1            | 	at org.hibernate.persister.entity.mutation.InsertCoordinator.doStaticInserts(InsertCoordinator.java:170)
cryostat_1            | 	at org.hibernate.persister.entity.mutation.InsertCoordinator.coordinateInsert(InsertCoordinator.java:112)
cryostat_1            | 	at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2742)
cryostat_1            | 	at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:102)
cryostat_1            | 	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:606)
cryostat_1            | 	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475)
cryostat_1            | 	at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:358)
cryostat_1            | 	at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
cryostat_1            | 	at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:127)
cryostat_1            | 	at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1412)
cryostat_1            | 	at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:485)
cryostat_1            | 	at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2301)
cryostat_1            | 	at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:1966)
cryostat_1            | 	at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:439)
cryostat_1            | 	at org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl.beforeCompletion(JtaTransactionCoordinatorImpl.java:336)
cryostat_1            | 	at org.hibernate.resource.transaction.backend.jta.internal.synchronization.SynchronizationCallbackCoordinatorNonTrackingImpl.beforeCompletion(SynchronizationCallbackCoordinatorNonTrackingImpl.java:47)
cryostat_1            | 	at org.hibernate.resource.transaction.backend.jta.internal.synchronization.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:37)
cryostat_1            | 	at com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.beforeCompletion(SynchronizationImple.java:76)
cryostat_1            | 	at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.beforeCompletion(TwoPhaseCoordinator.java:360)
cryostat_1            | 	at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:91)
cryostat_1            | 	at com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:162)
cryostat_1            | 	at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1295)
cryostat_1            | 	at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:128)
cryostat_1            | 	at io.quarkus.narayana.jta.runtime.NotifyingTransactionManager.commit(NotifyingTransactionManager.java:70)
cryostat_1            | 	at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.endTransaction(TransactionalInterceptorBase.java:406)
cryostat_1            | 	at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.invokeInOurTx(TransactionalInterceptorBase.java:175)
cryostat_1            | 	at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.invokeInOurTx(TransactionalInterceptorBase.java:107)
cryostat_1            | 	at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorRequired.doIntercept(TransactionalInterceptorRequired.java:38)
cryostat_1            | 	at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.intercept(TransactionalInterceptorBase.java:61)
cryostat_1            | 	at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorRequired.intercept(TransactionalInterceptorRequired.java:32)
cryostat_1            | 	at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorRequired_Bean.intercept(Unknown Source)
cryostat_1            | 	at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:42)
cryostat_1            | 	at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:34)
cryostat_1            | 	at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:27)
cryostat_1            | 	at io.cryostat.rules.RuleService_Subclass.activate(Unknown Source)
cryostat_1            | 	at io.cryostat.rules.RuleService.lambda$applyRuleToMatchingTargets$3(RuleService.java:215)
cryostat_1            | 	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
cryostat_1            | 	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
cryostat_1            | 	at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
cryostat_1            | 	at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1845)
cryostat_1            | 	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
cryostat_1            | 	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
cryostat_1            | 	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
cryostat_1            | 	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
cryostat_1            | 	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
cryostat_1            | 	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
cryostat_1            | 	at io.cryostat.rules.RuleService.applyRuleToMatchingTargets(RuleService.java:212)
cryostat_1            | 	at io.cryostat.rules.RuleService.handleRuleModification(RuleService.java:107)
cryostat_1            | 	at io.cryostat.rules.RuleService_ClientProxy.handleRuleModification(Unknown Source)
cryostat_1            | 	at io.cryostat.rules.RuleService_VertxInvoker_handleRuleModification_6ddc9dceea9390a5453d509d4a35648ef52ee492.invokeBean(Unknown Source)
cryostat_1            | 	at io.quarkus.vertx.runtime.EventConsumerInvoker.invoke(EventConsumerInvoker.java:41)
cryostat_1            | 	at io.quarkus.vertx.runtime.VertxRecorder$3$1$1.handle(VertxRecorder.java:116)
cryostat_1            | 	at io.quarkus.vertx.runtime.VertxRecorder$3$1$1.handle(VertxRecorder.java:112)
cryostat_1            | 	at io.vertx.core.impl.ContextBase.lambda$null$0(ContextBase.java:137)
cryostat_1            | 	at io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:264)
cryostat_1            | 	at io.vertx.core.impl.ContextBase.lambda$executeBlocking$1(ContextBase.java:135)
cryostat_1            | 	at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
cryostat_1            | 	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
cryostat_1            | 	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
cryostat_1            | 	at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
cryostat_1            | 	at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
cryostat_1            | 	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
cryostat_1            | 	at java.base/java.lang.Thread.run(Thread.java:833)
cryostat_1            | Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "activerecording_name_key"
cryostat_1            |   Detail: Key (name)=(auto_test) already exists.
cryostat_1            | 	at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2713)
cryostat_1            | 	at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2401)
cryostat_1            | 	at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:368)
cryostat_1            | 	at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:498)
cryostat_1            | 	at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:415)
cryostat_1            | 	at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:190)
cryostat_1            | 	at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:152)
cryostat_1            | 	at io.agroal.pool.wrapper.PreparedStatementWrapper.executeUpdate(PreparedStatementWrapper.java:88)
cryostat_1            | 	at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:275)
cryostat_1            | 	... 66 more

To get this I just created a rule named test with the match expression true.

@andrewazores
Copy link
Member

Easy fix after all that I just applied myself.

This might be something to refactor and deal with later, but I thought that using quarkus-quartz to handle periodic archiving could be good. This would take the place of the executor in the RuleService.

@maxcao13
Copy link
Member Author

maxcao13 commented Jul 26, 2023

Easy fix after all that I just applied myself.

This might be something to refactor and deal with later, but I thought that using quarkus-quartz to handle periodic archiving could be good. This would take the place of the executor in the RuleService.

I can try fitting it here.

@andrewazores
Copy link
Member

andrewazores commented Jul 26, 2023

https://quarkus.io/guides/scheduler-reference#programmatic_scheduling

This might be a better link to reference. I think the part about Quartz being used for persistence of scheduled tasks makes sense - that's pretty much exactly what our archiver rules are.

@maxcao13
Copy link
Member Author

https://quarkus.io/guides/scheduler-reference#programmatic_scheduling

This might be a better link to reference. I think the part about Quartz being used for persistence of scheduled tasks makes sense - that's pretty much exactly what our archiver rules are.

I assume the Rules represent the persistent scheduled tasks themselves and used those.

@andrewazores
Copy link
Member

Yep exactly.

@andrewazores
Copy link
Member

Quartz change looks great from a reading.

@andrewazores
Copy link
Member

It doesn't seem that archive pruning is working - I created a rule with preserved archives: 3 but it looks like the list of archived recordings is just continuously growing.

@maxcao13
Copy link
Member Author

It doesn't seem that archive pruning is working - I created a rule with preserved archives: 3 but it looks like the list of archived recordings is just continuously growing.

Hm.. I don't see this issue, can you give me recreation instructions?

@andrewazores
Copy link
Member

I'll try it again in a few minutes, I have an integration test run on a 2.3.1 backport currently running so things are a little tied up.

@andrewazores
Copy link
Member

Okay:

  1. check out PR, mvn clean verify ; podman image prune -f (or quarkus build etc)
  2. sh smoketest.sh and wait for everything to come up
  3. open cryostat3 web-client in browser (Firefox, but should not matter)
  4. go to Automated Rules
  5. create the following:
{
  "id": 1,
  "name": "test",
  "description": "",
  "matchExpression": "true",
  "eventSpecifier": "template=ALL,type=TARGET",
  "archivalPeriodSeconds": 15,
  "initialDelaySeconds": 5,
  "preservedArchives": 3,
  "maxAgeSeconds": 30,
  "maxSizeBytes": 0,
  "enabled": true,
  "recordingName": "auto_test",
  "archiver": true
}

(I created it with the form view and then downloaded the JSON back - I think the archiver field should be ignored in JSON serialization since this is really just an internal implementation detail/convenience)

Observe these progress notifications:
image

  1. wait some time for archivals to occur
  2. query for all archives with http --auth=user:pass :8181/api/beta/fs/recordings

result:

[
  {
    "connectUrl": "lost-WeHQCvHoM2qGhg6jWioM2gWIwlenCrOTAKbe1M8-1-4=",
    "jvmId": "WeHQCvHoM2qGhg6jWioM2gWIwlenCrOTAKbe1M8-1-4=",
    "recordings": [
      {
        "name": "compose_cryostat_1_auto_test_20230727T195029Z.jfr",
        "downloadUrl": "/api/v3/download/V2VIUUN2SG9NMnFHaGc2aldpb00yZ1dJd2xlbkNyT1RBS2JlMU04LTEtND0vY29tcG9zZV9jcnlvc3RhdF8xX2F1dG9fdGVzdF8yMDIzMDcyN1QxOTUwMjlaLmpmcg",
        "reportUrl": "TODO",
        "metadata": {
          "labels": {
            "template.name": "ALL",
            "connectUrl": "lost-WeHQCvHoM2qGhg6jWioM2gWIwlenCrOTAKbe1M8-1-4=",
            "rule": "test",
            "template.type": "TARGET"
          }
        },
        "size": 20971520,
        "archivedTime": 1690487430
      },
      {
        "name": "compose_cryostat_1_auto_test_20230727T195044Z.jfr",
        "downloadUrl": "/api/v3/download/V2VIUUN2SG9NMnFHaGc2aldpb00yZ1dJd2xlbkNyT1RBS2JlMU04LTEtND0vY29tcG9zZV9jcnlvc3RhdF8xX2F1dG9fdGVzdF8yMDIzMDcyN1QxOTUwNDRaLmpmcg",
        "reportUrl": "TODO",
        "metadata": {
          "labels": {
            "template.name": "ALL",
            "connectUrl": "lost-WeHQCvHoM2qGhg6jWioM2gWIwlenCrOTAKbe1M8-1-4=",
            "rule": "test",
            "template.type": "TARGET"
          }
        },
        "size": 20971520,
        "archivedTime": 1690487445
      },
      {
        "name": "compose_cryostat_1_auto_test_20230727T195059Z.jfr",
        "downloadUrl": "/api/v3/download/V2VIUUN2SG9NMnFHaGc2aldpb00yZ1dJd2xlbkNyT1RBS2JlMU04LTEtND0vY29tcG9zZV9jcnlvc3RhdF8xX2F1dG9fdGVzdF8yMDIzMDcyN1QxOTUwNTlaLmpmcg",
        "reportUrl": "TODO",
        "metadata": {
          "labels": {
            "template.name": "ALL",
            "connectUrl": "lost-WeHQCvHoM2qGhg6jWioM2gWIwlenCrOTAKbe1M8-1-4=",
            "rule": "test",
            "template.type": "TARGET"
          }
        },
        "size": 20971520,
        "archivedTime": 1690487460
      },
      {
        "name": "compose_cryostat_1_auto_test_20230727T195114Z.jfr",
        "downloadUrl": "/api/v3/download/V2VIUUN2SG9NMnFHaGc2aldpb00yZ1dJd2xlbkNyT1RBS2JlMU04LTEtND0vY29tcG9zZV9jcnlvc3RhdF8xX2F1dG9fdGVzdF8yMDIzMDcyN1QxOTUxMTRaLmpmcg",
        "reportUrl": "TODO",
        "metadata": {
          "labels": {
            "template.name": "ALL",
            "connectUrl": "lost-WeHQCvHoM2qGhg6jWioM2gWIwlenCrOTAKbe1M8-1-4=",
            "rule": "test",
            "template.type": "TARGET"
          }
        },
        "size": 20971520,
        "archivedTime": 1690487475
      },
      {
        "name": "compose_cryostat_1_auto_test_20230727T195129Z.jfr",
        "downloadUrl": "/api/v3/download/V2VIUUN2SG9NMnFHaGc2aldpb00yZ1dJd2xlbkNyT1RBS2JlMU04LTEtND0vY29tcG9zZV9jcnlvc3RhdF8xX2F1dG9fdGVzdF8yMDIzMDcyN1QxOTUxMjlaLmpmcg",
        "reportUrl": "TODO",
        "metadata": {
          "labels": {
            "template.name": "ALL",
            "connectUrl": "lost-WeHQCvHoM2qGhg6jWioM2gWIwlenCrOTAKbe1M8-1-4=",
            "rule": "test",
            "template.type": "TARGET"
          }
        },
        "size": 20971520,
        "archivedTime": 1690487490
      },
      {
        "name": "compose_cryostat_1_auto_test_20230727T195144Z.jfr",
        "downloadUrl": "/api/v3/download/V2VIUUN2SG9NMnFHaGc2aldpb00yZ1dJd2xlbkNyT1RBS2JlMU04LTEtND0vY29tcG9zZV9jcnlvc3RhdF8xX2F1dG9fdGVzdF8yMDIzMDcyN1QxOTUxNDRaLmpmcg",
        "reportUrl": "TODO",
        "metadata": {
          "labels": {
            "template.name": "ALL",
            "connectUrl": "lost-WeHQCvHoM2qGhg6jWioM2gWIwlenCrOTAKbe1M8-1-4=",
            "rule": "test",
            "template.type": "TARGET"
          }
        },
        "size": 20971520,
        "archivedTime": 1690487504
      },
      {
        "name": "compose_cryostat_1_auto_test_20230727T195159Z.jfr",
        "downloadUrl": "/api/v3/download/V2VIUUN2SG9NMnFHaGc2aldpb00yZ1dJd2xlbkNyT1RBS2JlMU04LTEtND0vY29tcG9zZV9jcnlvc3RhdF8xX2F1dG9fdGVzdF8yMDIzMDcyN1QxOTUxNTlaLmpmcg",
        "reportUrl": "TODO",
        "metadata": {
          "labels": {
            "template.name": "ALL",
            "connectUrl": "lost-WeHQCvHoM2qGhg6jWioM2gWIwlenCrOTAKbe1M8-1-4=",
            "rule": "test",
            "template.type": "TARGET"
          }
        },
        "size": 20971520,
        "archivedTime": 1690487520
      },
      {
        "name": "compose_cryostat_1_auto_test_20230727T195214Z.jfr",
        "downloadUrl": "/api/v3/download/V2VIUUN2SG9NMnFHaGc2aldpb00yZ1dJd2xlbkNyT1RBS2JlMU04LTEtND0vY29tcG9zZV9jcnlvc3RhdF8xX2F1dG9fdGVzdF8yMDIzMDcyN1QxOTUyMTRaLmpmcg",
        "reportUrl": "TODO",
        "metadata": {
          "labels": {
            "template.name": "ALL",
            "connectUrl": "lost-WeHQCvHoM2qGhg6jWioM2gWIwlenCrOTAKbe1M8-1-4=",
            "rule": "test",
            "template.type": "TARGET"
          }
        },
        "size": 20971520,
        "archivedTime": 1690487535
      },
      {
        "name": "compose_cryostat_1_auto_test_20230727T195229Z.jfr",
        "downloadUrl": "/api/v3/download/V2VIUUN2SG9NMnFHaGc2aldpb00yZ1dJd2xlbkNyT1RBS2JlMU04LTEtND0vY29tcG9zZV9jcnlvc3RhdF8xX2F1dG9fdGVzdF8yMDIzMDcyN1QxOTUyMjlaLmpmcg",
        "reportUrl": "TODO",
        "metadata": {
          "labels": {
            "template.name": "ALL",
            "connectUrl": "lost-WeHQCvHoM2qGhg6jWioM2gWIwlenCrOTAKbe1M8-1-4=",
            "rule": "test",
            "template.type": "TARGET"
          }
        },
        "size": 20971520,
        "archivedTime": 1690487550
      },
      {
        "name": "compose_cryostat_1_auto_test_20230727T195244Z.jfr",
        "downloadUrl": "/api/v3/download/V2VIUUN2SG9NMnFHaGc2aldpb00yZ1dJd2xlbkNyT1RBS2JlMU04LTEtND0vY29tcG9zZV9jcnlvc3RhdF8xX2F1dG9fdGVzdF8yMDIzMDcyN1QxOTUyNDRaLmpmcg",
        "reportUrl": "TODO",
        "metadata": {
          "labels": {
            "template.name": "ALL",
            "connectUrl": "lost-WeHQCvHoM2qGhg6jWioM2gWIwlenCrOTAKbe1M8-1-4=",
            "rule": "test",
            "template.type": "TARGET"
          }
        },
        "size": 20971520,
        "archivedTime": 1690487565
      },
      {
        "name": "compose_cryostat_1_auto_test_20230727T195259Z.jfr",
        "downloadUrl": "/api/v3/download/V2VIUUN2SG9NMnFHaGc2aldpb00yZ1dJd2xlbkNyT1RBS2JlMU04LTEtND0vY29tcG9zZV9jcnlvc3RhdF8xX2F1dG9fdGVzdF8yMDIzMDcyN1QxOTUyNTlaLmpmcg",
        "reportUrl": "TODO",
        "metadata": {
          "labels": {
            "template.name": "ALL",
            "connectUrl": "lost-WeHQCvHoM2qGhg6jWioM2gWIwlenCrOTAKbe1M8-1-4=",
            "rule": "test",
            "template.type": "TARGET"
          }
        },
        "size": 20971520,
        "archivedTime": 1690487580
      },
      {
        "name": "compose_cryostat_1_auto_test_20230727T195314Z.jfr",
        "downloadUrl": "/api/v3/download/V2VIUUN2SG9NMnFHaGc2aldpb00yZ1dJd2xlbkNyT1RBS2JlMU04LTEtND0vY29tcG9zZV9jcnlvc3RhdF8xX2F1dG9fdGVzdF8yMDIzMDcyN1QxOTUzMTRaLmpmcg",
        "reportUrl": "TODO",
        "metadata": {
          "labels": {
            "template.name": "ALL",
            "connectUrl": "lost-WeHQCvHoM2qGhg6jWioM2gWIwlenCrOTAKbe1M8-1-4=",
            "rule": "test",
            "template.type": "TARGET"
          }
        },
        "size": 20971520,
        "archivedTime": 1690487595
      },
      {
        "name": "compose_cryostat_1_auto_test_20230727T195329Z.jfr",
        "downloadUrl": "/api/v3/download/V2VIUUN2SG9NMnFHaGc2aldpb00yZ1dJd2xlbkNyT1RBS2JlMU04LTEtND0vY29tcG9zZV9jcnlvc3RhdF8xX2F1dG9fdGVzdF8yMDIzMDcyN1QxOTUzMjlaLmpmcg",
        "reportUrl": "TODO",
        "metadata": {
          "labels": {
            "template.name": "ALL",
            "connectUrl": "lost-WeHQCvHoM2qGhg6jWioM2gWIwlenCrOTAKbe1M8-1-4=",
            "rule": "test",
            "template.type": "TARGET"
          }
        },
        "size": 20971520,
        "archivedTime": 1690487609
      },
      {
        "name": "compose_cryostat_1_auto_test_20230727T195344Z.jfr",
        "downloadUrl": "/api/v3/download/V2VIUUN2SG9NMnFHaGc2aldpb00yZ1dJd2xlbkNyT1RBS2JlMU04LTEtND0vY29tcG9zZV9jcnlvc3RhdF8xX2F1dG9fdGVzdF8yMDIzMDcyN1QxOTUzNDRaLmpmcg",
        "reportUrl": "TODO",
        "metadata": {
          "labels": {
            "template.name": "ALL",
            "connectUrl": "lost-WeHQCvHoM2qGhg6jWioM2gWIwlenCrOTAKbe1M8-1-4=",
            "rule": "test",
            "template.type": "TARGET"
          }
        },
        "size": 20971520,
        "archivedTime": 1690487625
      },
      {
        "name": "compose_cryostat_1_auto_test_20230727T195359Z.jfr",
        "downloadUrl": "/api/v3/download/V2VIUUN2SG9NMnFHaGc2aldpb00yZ1dJd2xlbkNyT1RBS2JlMU04LTEtND0vY29tcG9zZV9jcnlvc3RhdF8xX2F1dG9fdGVzdF8yMDIzMDcyN1QxOTUzNTlaLmpmcg",
        "reportUrl": "TODO",
        "metadata": {
          "labels": {
            "template.name": "ALL",
            "connectUrl": "lost-WeHQCvHoM2qGhg6jWioM2gWIwlenCrOTAKbe1M8-1-4=",
            "rule": "test",
            "template.type": "TARGET"
          }
        },
        "size": 20971520,
        "archivedTime": 1690487640
      },
      {
        "name": "compose_cryostat_1_auto_test_20230727T195414Z.jfr",
        "downloadUrl": "/api/v3/download/V2VIUUN2SG9NMnFHaGc2aldpb00yZ1dJd2xlbkNyT1RBS2JlMU04LTEtND0vY29tcG9zZV9jcnlvc3RhdF8xX2F1dG9fdGVzdF8yMDIzMDcyN1QxOTU0MTRaLmpmcg",
        "reportUrl": "TODO",
        "metadata": {
          "labels": {
            "template.name": "ALL",
            "connectUrl": "lost-WeHQCvHoM2qGhg6jWioM2gWIwlenCrOTAKbe1M8-1-4=",
            "rule": "test",
            "template.type": "TARGET"
          }
        },
        "size": 20971520,
        "archivedTime": 1690487655
      }
    ]
  },
  {
    "connectUrl": "lost-Wb5RaFhmFcB1LyKtn5w940EtCOAl82w2KA-2Q6pS5Yg=",
    "jvmId": "Wb5RaFhmFcB1LyKtn5w940EtCOAl82w2KA-2Q6pS5Yg=",
    "recordings": [
      {
        "name": "quarkus-test-agent_default_20230727T195314Z.jfr",
        "downloadUrl": "/api/v3/download/V2I1UmFGaG1GY0IxTHlLdG41dzk0MEV0Q09BbDgydzJLQS0yUTZwUzVZZz0vcXVhcmt1cy10ZXN0LWFnZW50X2RlZmF1bHRfMjAyMzA3MjdUMTk1MzE0Wi5qZnI",
        "reportUrl": "TODO",
        "metadata": {
          "labels": {
            "template.name": "default",
            "connectUrl": "lost-Wb5RaFhmFcB1LyKtn5w940EtCOAl82w2KA-2Q6pS5Yg=",
            "jvmId": "Wb5RaFhmFcB1LyKtn5w940EtCOAl82w2KA-2Q6pS5Yg=",
            "template.type": "TARGET",
            "pushType": "SCHEDULED"
          }
        },
        "size": 622315,
        "archivedTime": 1690487594
      },
      {
        "name": "quarkus-test-agent_default_20230727T195344Z.jfr",
        "downloadUrl": "/api/v3/download/V2I1UmFGaG1GY0IxTHlLdG41dzk0MEV0Q09BbDgydzJLQS0yUTZwUzVZZz0vcXVhcmt1cy10ZXN0LWFnZW50X2RlZmF1bHRfMjAyMzA3MjdUMTk1MzQ0Wi5qZnI",
        "reportUrl": "TODO",
        "metadata": {
          "labels": {
            "template.name": "default",
            "connectUrl": "lost-Wb5RaFhmFcB1LyKtn5w940EtCOAl82w2KA-2Q6pS5Yg=",
            "jvmId": "Wb5RaFhmFcB1LyKtn5w940EtCOAl82w2KA-2Q6pS5Yg=",
            "template.type": "TARGET",
            "pushType": "SCHEDULED"
          }
        },
        "size": 629972,
        "archivedTime": 1690487624
      },
      {
        "name": "quarkus-test-agent_default_20230727T195414Z.jfr",
        "downloadUrl": "/api/v3/download/V2I1UmFGaG1GY0IxTHlLdG41dzk0MEV0Q09BbDgydzJLQS0yUTZwUzVZZz0vcXVhcmt1cy10ZXN0LWFnZW50X2RlZmF1bHRfMjAyMzA3MjdUMTk1NDE0Wi5qZnI",
        "reportUrl": "TODO",
        "metadata": {
          "labels": {
            "template.name": "default",
            "connectUrl": "lost-Wb5RaFhmFcB1LyKtn5w940EtCOAl82w2KA-2Q6pS5Yg=",
            "jvmId": "Wb5RaFhmFcB1LyKtn5w940EtCOAl82w2KA-2Q6pS5Yg=",
            "template.type": "TARGET",
            "pushType": "SCHEDULED"
          }
        },
        "size": 313500,
        "archivedTime": 1690487654
      }
    ]
  }
]

This response contains archives pushed by an agent instance which are being properly pruned, but the list of archives coming from the rule definition is just growing over time.

@maxcao13
Copy link
Member Author

maxcao13 commented Jul 27, 2023

Okay, I think the problem is the naming scheme of the targets and the regex pattern that determines the recording name from the recording file name.

    private static final Pattern RECORDING_FILENAME_PATTERN = Pattern.compile( "([A-Za-z\\d\\.-]*)_([A-Za-z\\d-_]*)_([\\d]*T[\\d]*Z)(\\.[\\d]+)?(\\.jfr)?");

The compose_cryostat_1 sample app doesn't work well with it because it has underscores and the regex checks for a underscores to separate target with recording name. Would it make sense to enforce _ underscores to become - hyphens in the alias, or maybe some other solution?

@andrewazores
Copy link
Member

Right, makes sense.

In the short term, sanitizing the input and applying transformations like that is fine - Cryostat has been doing that since as long as it has had archives.


In the longer term I'm tempted to say let's do something much more radical. We can safely embed those details about the source target (alias, connectUrl, JVM ID, labels/annotations) into a .metadata.json file that accompanies the recording now that we have somewhere better to store those details than the recording filename. The file itself could just be named something simple like ${target_alias}.${sequence}.jfr - the timestamp can/should simply be in the created/modified timestamp of the file but might also be embedded in the JSON metadata, too. We can model this by creating something like an ArchivedRecording table in Postgres that has columns for:

  1. the recording primary key, just an int ID
  2. the source recording ID foreign key
  3. the filename as it was saved in S3

If we redo the tables for targets and active recordings so that we don't delete records when targets go offline or recordings are deleted, and instead add a status flag column, then we can always go back and look up the details of the source recording for an archived recording, and from there also look up the details of the source target.

@andrewazores
Copy link
Member

Okay, I think the problem is the naming scheme of the targets and the regex pattern that determines the recording name from the recording file name.

    private static final Pattern RECORDING_FILENAME_PATTERN = Pattern.compile( "([A-Za-z\\d\\.-]*)_([A-Za-z\\d-_]*)_([\\d]*T[\\d]*Z)(\\.[\\d]+)?(\\.jfr)?");

The compose_cryostat_1 sample app doesn't work well with it because it has underscores and the regex checks for a underscores to separate target with recording name. Would it make sense to enforce _ underscores to become - hyphens in the alias, or maybe some other solution?

Does this affect the 2.3/2.4 codebase as well then?

@maxcao13
Copy link
Member Author

maxcao13 commented Aug 1, 2023

Okay, I think the problem is the naming scheme of the targets and the regex pattern that determines the recording name from the recording file name.

    private static final Pattern RECORDING_FILENAME_PATTERN = Pattern.compile( "([A-Za-z\\d\\.-]*)_([A-Za-z\\d-_]*)_([\\d]*T[\\d]*Z)(\\.[\\d]+)?(\\.jfr)?");

The compose_cryostat_1 sample app doesn't work well with it because it has underscores and the regex checks for a underscores to separate target with recording name. Would it make sense to enforce _ underscores to become - hyphens in the alias, or maybe some other solution?

Does this affect the 2.3/2.4 codebase as well then?

Never noticed, but seems like this was already done by Janelle 2 years ago now:

        String targetName =
                platformClient.listDiscoverableServices().stream()
                        .filter(
                                serviceRef -> {
                                    return serviceRef.getServiceUri().equals(serviceUri)
                                            && serviceRef.getAlias().isPresent();
                                })
                        .map(s -> s.getAlias().get())
                        .findFirst()
                        .orElse(connection.getHost())
                        .replaceAll("[\\._]+", "-");

https://github.com/cryostatio/cryostat/blob/main/src/main/java/io/cryostat/recordings/RecordingArchiveHelper.java#L969

So I assume it's safe to continue with this, It probably makes sense to change it to include periods and the backslash too.

Copy link
Member

@andrewazores andrewazores left a comment

Choose a reason for hiding this comment

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

Seems to be working very well, just a few more minor comments.

@andrewazores andrewazores merged commit 7b7ce94 into cryostatio:main Aug 1, 2023
@maxcao13 maxcao13 deleted the automated-rules branch August 2, 2023 23:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat New feature or request
Projects
No open projects
Status: Done
Development

Successfully merging this pull request may close these issues.

3 participants