9
9
#include < kj/compat/url.h>
10
10
#include < kj/encoding.h>
11
11
#include < kj/map.h>
12
+ #include < capnp/message.h>
13
+ #include < capnp/compat/json.h>
14
+ #include < workerd/api/analytics-engine.capnp.h>
12
15
#include < workerd/io/worker-interface.h>
13
16
#include < workerd/io/worker-entrypoint.h>
14
17
#include < workerd/io/compatibility-date.h>
19
22
#include < openssl/pem.h>
20
23
#include < workerd/io/actor-cache.h>
21
24
#include < workerd/io/actor-sqlite.h>
25
+ #include < workerd/util/http-util.h>
22
26
#include < workerd/api/actor-state.h>
23
27
#include < workerd/util/mimetype.h>
24
28
#include " workerd-api.h"
@@ -1566,7 +1570,38 @@ private:
1566
1570
1567
1571
kj::Promise<void > writeLogfwdr (uint channel,
1568
1572
kj::FunctionParam<void (capnp::AnyPointer::Builder)> buildMessage) override {
1569
- KJ_FAIL_REQUIRE (" no logging channels" );
1573
+ auto & context = IoContext::current ();
1574
+
1575
+ auto headers = kj::HttpHeaders (context.getHeaderTable ());
1576
+ auto client = context.getHttpClient (channel, true , nullptr , " writeLogfwdr" _kjc);
1577
+
1578
+ auto urlStr = kj::str (" https://fake-host" );
1579
+
1580
+ capnp::MallocMessageBuilder requestMessage;
1581
+ auto requestBuilder = requestMessage.initRoot <capnp::AnyPointer>();
1582
+
1583
+ buildMessage (requestBuilder);
1584
+ capnp::JsonCodec json;
1585
+ auto requestJson = json.encode (requestBuilder.getAs <api::AnalyticsEngineEvent>());
1586
+
1587
+ co_await context.waitForOutputLocks ();
1588
+
1589
+ auto innerReq = client->request (kj::HttpMethod::POST, urlStr, headers, requestJson.size ());
1590
+
1591
+ struct RefcountedWrapper : public kj ::Refcounted {
1592
+ explicit RefcountedWrapper (kj::Own<kj::HttpClient> client): client(kj::mv(client)) {}
1593
+ kj::Own<kj::HttpClient> client;
1594
+ };
1595
+ auto rcClient = kj::refcounted<RefcountedWrapper>(kj::mv (client));
1596
+ auto request = attachToRequest (kj::mv (innerReq), kj::mv (rcClient));
1597
+
1598
+ co_await request.body ->write (requestJson.begin (), requestJson.size ())
1599
+ .attach (kj::mv (requestJson), kj::mv (request.body ));
1600
+ auto response = co_await request.response ;
1601
+
1602
+ KJ_REQUIRE (response.statusCode >= 200 && response.statusCode < 300 , " writeLogfwdr request returned an error" );
1603
+ co_await response.body ->readAllBytes ().attach (kj::mv (response.body )).ignoreResult ();
1604
+ co_return ;
1570
1605
}
1571
1606
1572
1607
kj::Own<ActorChannel> getGlobalActor (uint channel, const ActorIdFactory::ActorId& id,
@@ -1649,7 +1684,8 @@ static kj::Maybe<WorkerdApiIsolate::Global> createBinding(
1649
1684
Worker::ValidationErrorReporter& errorReporter,
1650
1685
kj::Vector<FutureSubrequestChannel>& subrequestChannels,
1651
1686
kj::Vector<FutureActorChannel>& actorChannels,
1652
- kj::HashMap<kj::String, kj::HashMap<kj::String, Server::ActorConfig>>& actorConfigs) {
1687
+ kj::HashMap<kj::String, kj::HashMap<kj::String, Server::ActorConfig>>& actorConfigs,
1688
+ bool experimental) {
1653
1689
// creates binding object or returns null and reports an error
1654
1690
using Global = WorkerdApiIsolate::Global;
1655
1691
kj::StringPtr bindingName = binding.getName ();
@@ -1883,7 +1919,7 @@ static kj::Maybe<WorkerdApiIsolate::Global> createBinding(
1883
1919
kj::Vector<Global> innerGlobals;
1884
1920
for (const auto & innerBinding: wrapped.getInnerBindings ()) {
1885
1921
KJ_IF_MAYBE (global, createBinding (workerName, conf, innerBinding,
1886
- errorReporter, subrequestChannels, actorChannels, actorConfigs)) {
1922
+ errorReporter, subrequestChannels, actorChannels, actorConfigs, experimental )) {
1887
1923
innerGlobals.add (kj::mv (*global));
1888
1924
} else {
1889
1925
// we've already communicated the error
@@ -1908,6 +1944,25 @@ static kj::Maybe<WorkerdApiIsolate::Global> createBinding(
1908
1944
}
1909
1945
}
1910
1946
1947
+ case config::Worker::Binding::ANALYTICS_ENGINE: {
1948
+ if (!experimental) {
1949
+ errorReporter.addError (kj::str (
1950
+ " AnalyticsEngine bindings are an experimental feature which may change or go away in the future."
1951
+ " You must run workerd with `--experimental` to use this feature." ));
1952
+ }
1953
+
1954
+ uint channel = (uint )subrequestChannels.size () + IoContext::SPECIAL_SUBREQUEST_CHANNEL_COUNT;
1955
+ subrequestChannels.add (FutureSubrequestChannel {
1956
+ binding.getAnalyticsEngine (),
1957
+ kj::mv (errorContext)
1958
+ });
1959
+
1960
+ return makeGlobal (Global::AnalyticsEngine{
1961
+ .subrequestChannel = channel,
1962
+ .dataset = kj::str (binding.getAnalyticsEngine ().getName ()),
1963
+ .version = 0 ,
1964
+ });
1965
+ }
1911
1966
}
1912
1967
errorReporter.addError (kj::str (
1913
1968
errorContext, " has unrecognized type. Was the config compiled with a newer version of "
@@ -2031,7 +2086,8 @@ kj::Own<Server::Service> Server::makeWorker(kj::StringPtr name, config::Worker::
2031
2086
kj::Vector<Global> globals (confBindings.size ());
2032
2087
for (auto binding: confBindings) {
2033
2088
KJ_IF_MAYBE (global, createBinding (name, conf, binding, errorReporter,
2034
- subrequestChannels, actorChannels, actorConfigs)) {
2089
+ subrequestChannels, actorChannels, actorConfigs,
2090
+ experimental)) {
2035
2091
globals.add (kj::mv (*global));
2036
2092
}
2037
2093
}
0 commit comments