Fork me on GitHub
#datomic
<
2021-11-09
>
Gavin Davies14:11:21

Hello! I have a poorly performing Clojure+Datomic application I have been tasked with tuning. Unfortunately, I am not a Clojure developer and have no Datomic experience at all! I am trying to configure Cloudwatch, but I cannot see anything appearing in my CloudWatch metrics at all. 1. Datomic 0.9.6045 in Docker clojure:openjdk-8-tools-deps-alpine on ECS using OpenJDK 1.8.0_212 2. Following this guide https://docs.datomic.com/on-prem/overview/aws.html#other-storages 3. Running bin/datomic ensure-transactor config/transactor.properties config/transactor.properties gives me java.lang.IllegalArgumentException: No method in multimethod 'ensure-transactor*' for dispatch value: :sql 4. The only search result I can find for this is here https://clojurians-log.clojureverse.org/datomic/2018-03-20 but I don’t see an explanation or a resolution 5. I tried pushing a new image and it does start with my config file, I see no errors in the logs, so I assume I am running ensure-transactor incorrectly or I am missing something? My config/transactor.properties is:

protocol=sql
host=<REDACTED>
port=<REDACTED>
metrics-callback=<REDACTED>.datomic-logging.core/report-metrics
license-key=<REDACTED>
alt-host=0.0.0.0
sql-url=jdbc:postgresql://<REDACTED>
sql-user=<REDACTED>
sql-password=<REDACTED>
sql-driver-class=org.postgresql.Driver
memory-index-threshold=32m
memory-index-max=512m
object-cache-max=1g
ping-host=0.0.0.0
ping-port=9999
ping-concurrency=6
aws-cloudwatch-dimension-value=datomic
aws-cloudwatch-region=us-west-2
I would appreciate any advice you can offer! Thanks.

Gavin Davies14:11:24

I found this question a few above my own https://clojurians.slack.com/archives/C03RZMDSH/p1635985753218600 - does this mean I cannot use ensure-transactor for SQL?

Joe Lane15:11:23

Hey @U02LH3SBBEJ, the information you're looking for is on the https://docs.datomic.com/on-prem/overview/storage.html page. For your storage you're going to want to follow https://docs.datomic.com/on-prem/overview/storage.html#sql-database. bin/ensure-transactor currently supports DynamoDB.

Gavin Davies15:11:48

thank you 🙂 Will give that a go!

Joe Lane15:11:02

Start from the top and once you finish the SQL section don't skip the other non-storage sections, you will need them.

Gavin Davies15:11:34

so, we already have our database, the connection all works and what I want to do is turn on Cloudwatch metrics, I’m not clear on how specifically to turn on Cloudwatch metrics? (this is a pre-existing app, been running about 3 years, it just needs Cloudwatch 🙂 ) Please excuse my ignorance, this is day 0 for me of trying to work with Datomic 🙂

Gavin Davies15:11:08

I guess that I don’t need ensure-transactor because I created the AWS role myself?

Joe Lane15:11:45

ensure-transactor is a convenience script, but since you're already running in prod, you probably don't need it 🙂

Joe Lane15:11:08

Before we get into the Cloudwatch metrics effort, can you describe how you know the "Clojure+Datomic" application is performing poorly? What have you observed to lead you to that conclusion?

Gavin Davies15:11:11

ahh, right Should I expect the metrics to be appearing? Like, I assume there’s a heartbeat metric or something? OR does my app have to explicitly say “send this metric to Cloudwatch”?

Gavin Davies15:11:20

> can you describe how you know the “Clojure+Datomic” application is performing poorly? What have you observed to lead you to that conclusion? Hoo boy, that’s a long story 😄 I’ll condense! Customers reported degrading performance over time, as the data set has grown, we get operations like “get 1000 items into a <select> list” taking either 5ms or 10s under load. So basically, we measure the page with a stopwatch 😄 it’s not very sophisticated, we need to get observability in place. So I’m guessing some kind of CPU or memory contention, so the first step is to get some instrumentation in there and measure what is going on. The peer has some instrumentation via statsd so I can see that in Cloudwatch. However, the transactor is not currently outputting anything to Cloudwatch, so today I am trying to add that.

Gavin Davies15:11:40

do I need to have the S3 log copying bucket as an intermediary for Cloudwatch logs? i only added the aws-cloudwatch* lines, not an aws-s3* line… I don’t know if I need the S3 or if I can go straight to cloudwatch?

Joe Lane15:11:06

Are any of the issues related to transactions? If not, then your problem squarely sits inside the peers (not trying to dissuade you from adding metrics to the transactor).

Joe Lane15:11:43

If you want transactor logs to go into a cloudwatch logstream you will need to install and manage the cloudwatch agent yourself.

Joe Lane15:11:24

The built-in logging facilities solely upload to S3 (I think it's daily by default)

Gavin Davies15:11:25

I have no idea what the issues relate to yet, I’m sorry to say. I don’t really want the logs at this stage, all I want is things like heap usage etc to be pumped to Cloudwatch

Gavin Davies15:11:35

the problem may well be the peers, unfortunately we have no visibility at all yet. I was hoping I could just enter a few lines of config and get the JVM/datomic metrics pushed to Cloudwatch?

Gavin Davies15:11:08

OK, thanks. I have been through that and unfortunately I have failed to see any metrics in Cloudwatch. My background is in AWS rather than in Clojure/Datomic. I believe I have set the IAM role correctly and I have redeployed my transactor image with the correct config to send metrics to Cloudwatch. I have not set up anything for S3. Does the Cloudwatch bit rely on the S3 bit in some way? I’d have assumed not but maybe there’s some dependency? I see no logs even acknowledging Cloudwatch - when the transactor starts, I don’t see any mention of Cloudwatch, would I expect to?

jaret16:11:17

Hey @U02LH3SBBEJ I noticed that you have a metrics callback configured are your metric lines reporting there? If the s3 dimension is not setup it will create a bucket for log copying. Did an s3 bucket get made on your system? In non-DDB systems customers typically setup an s3 bucket and point #aws-s3-log-bucket-id= to it. I'd recommend setting that up with an exisiting bucket just to see if you get logs copied to the bucket. The piece that always trips up non DDB users is the permissions on the transactor role. https://docs.datomic.com/on-prem/overview/aws.html#other-storages. Can you confirm you have those perms set?

Joe Lane16:11:02

Also @U02LH3SBBEJ, do you see metrics if you comment out the metrics-callback=<REDACTED>.datomic-logging.core/report-metrics?

jaret16:11:34

I know you walked up to this system, but do you know if this worked previously? Does this work for another system? Where did this system live previously and are you copying it to test performance or tweaking it?

Gavin Davies10:11:14

YESSSSSS! IT WORKS! Thank you all! ❤️ Removing the metrics-callback means I am now seeing datomic stats in Cloudwatch. What a relief! Thank you all so much

👍 1
Gavin Davies10:11:03

> jaret  [4:05 PM] > I know you walked up to this system, but do you know if this worked previously?    Does this work for another system?  Where did this system live previously and are you copying it to test performance or tweaking it? Great questions! I have been at $ORG for a year, this app is about 4 years old. It runs fine for other clients with smaller data sizes, which are in separate AWS accounts which are identically configured via Gruntworks. Our largest client recently onboarded a bunch of new customers and that seems to have degraded performance for “poor” to “intermittently unacceptable”. I am not moving the system, it remains hosted in ECS, I’ve just been parachuted in like “hey Gav you’ve got (expired!) AWS certification can you make this perform more gooder and stuff until we can EOL this application in 6 months” So I suspect I may have more questions, but now I can see what the transactor is up to, I feel like I’ve got a fighting chance! (the peer was already emitting metrics to Cloudwatch)

😂 1
jaret23:11:14

@U02LH3SBBEJ When you have questions feel free to reach out to https://www.datomic.com/support.html. Cases can be created by e-mailing <mailto:[email protected]|[email protected]> or <mailto:[email protected]|[email protected]>. We'd be happy to help with any performance issue or tuning and perhaps we can have a call to give you some basic tips for reviewing/understand what your bottlenecks are likely to be.

1
Ivar Refsdal12:11:40

Do you have a REPL into prod or a connection to the prod database? I've used https://github.com/ptaoussanis/tufte/ for profiling Clojure code with decent success. My guess would be that your peer query is slow, but that is just a guess of course.

1
Gavin Davies14:11:41

thanks, we will reach out to Datomic support and our Clojure guy is looking into Tufte :-)

michele mendel16:11:37

datomic.client.api vs datomic.api Is datomic.api only for on-prem, since it's documentation is only found there - ? I tried it on my cloud setup, but it didn't work (maybe I need something in my deps).

favila17:11:19

> Is datomic.api only for on-prem

michele mendel06:11:05

Btw, why is this api not part of the cloud api? It looks that it has some convenient functions.

favila12:11:09

The client api is designed for low bandwidth (ie possible out-of-process implementation) few client dependencies, and little client state. Many portions of the peer api simply can’t be implemented in a way that meets those goals

michele mendel13:11:45

I see. Thanks again

mynomoto20:11:23

Are eid resolved inside a tuple when using d/pull? Example:

[{:db/ident       :example/id
  :db/valueType   :db.type/long
  :db/cardinality :db.cardinality/one}
 {:db/ident       :example/other
  :db/valueType   :db.type/ref
  :db/cardinality :db.cardinality/one}
 {:db/ident       :other/id
  :db/valueType   :db.type/long
  :db/cardinality :db.cardinality/one
  :db/unique      :db.unique/identity}
 {:db/ident       :example/id+other
  :db/valueType   :db.type/tuple
  :db/tupleAttrs  [:example/id :example/other]
  :db/cardinality :db.cardinality/one
  :db/unique      :db.unique/identity}]

(d/pull db [:*]
  [:example/id+other [1522 [:other/id 520832909]]])

favila20:11:30

tuple values are not inspected for entity refs; this won’t work

mynomoto20:11:06

Ok, so I need to query to be able to resolve this right?

favila20:11:54

You can use [:example/id+other [1552 (d/entid db [:other/id 520832909])]]

favila20:11:07

d/entid resolves any entity reference to an entity id if it can

favila20:11:14

nil if it can’t

mynomoto20:11:31

Oh, this is better, it should suffice. Thanks!

favila20:11:37

on-prem only. I don’t know how the cloud folks manage this without a query

mynomoto20:11:33

Well, this is a query right? It will be done before calling d/pull, or am I misunderstanding?

favila20:11:52

it’s not a d/q query, i.e. it doesn’t invoke a datalog query engine

favila20:11:21

but it will do IO if it needs to, if that’s what you mean by query

mynomoto20:11:44

Yeah, I see what you mean. Thanks, this was really helpful. I could not find that information on docs/searching the web.

mynomoto20:11:08

Is there something like this that works? I'm using on-prem if this is relevant.