Ejemplo n.º 1
0
def get_event(request):
    timer = statsd.Timer("%s_posthog_cloud" % (settings.STATSD_PREFIX, ))
    timer.start()
    now = timezone.now()
    try:
        data_from_request = load_data_from_request(request)
        data = data_from_request["data"]
    except TypeError:
        return cors_response(
            request,
            JsonResponse(
                {
                    "code":
                    "validation",
                    "message":
                    "Malformed request data. Make sure you're sending valid JSON.",
                },
                status=400,
            ),
        )
    if not data:
        return cors_response(
            request,
            JsonResponse(
                {
                    "code":
                    "validation",
                    "message":
                    "No data found. Make sure to use a POST request when sending the payload in the body of the request.",
                },
                status=400,
            ),
        )
    sent_at = _get_sent_at(data, request)

    token = _get_token(data, request)

    if not token:
        return cors_response(
            request,
            JsonResponse(
                {
                    "code":
                    "validation",
                    "message":
                    "API key not provided. You can find your project API key in PostHog project settings.",
                },
                status=401,
            ),
        )
    team = Team.objects.get_team_from_token(token)

    if team is None:
        try:
            project_id = _get_project_id(data, request)
        except:
            return cors_response(
                request,
                JsonResponse(
                    {
                        "code": "validation",
                        "message": "Invalid project ID.",
                    },
                    status=400,
                ),
            )
        if not project_id:
            return cors_response(
                request,
                JsonResponse(
                    {
                        "code":
                        "validation",
                        "message":
                        "Project API key invalid. You can find your project API key in PostHog project settings.",
                    },
                    status=401,
                ),
            )
        user = User.objects.get_from_personal_api_key(token)
        if user is None:
            return cors_response(
                request,
                JsonResponse(
                    {
                        "code": "validation",
                        "message": "Personal API key invalid.",
                    },
                    status=401,
                ),
            )
        team = user.teams.get(id=project_id)

    if isinstance(data, dict):
        if data.get("batch"):  # posthog-python and posthog-ruby
            data = data["batch"]
            assert data is not None
        elif "engage" in request.path_info:  # JS identify call
            data["event"] = "$identify"  # make sure it has an event name

    if isinstance(data, list):
        events = data
    else:
        events = [data]

    for event in events:
        try:
            distinct_id = _get_distinct_id(event)
        except KeyError:
            return cors_response(
                request,
                JsonResponse(
                    {
                        "code": "validation",
                        "message":
                        "You need to set user distinct ID field `distinct_id`.",
                        "item": event,
                    },
                    status=400,
                ),
            )
        if not event.get("event"):
            return cors_response(
                request,
                JsonResponse(
                    {
                        "code": "validation",
                        "message": "You need to set event name field `event`.",
                        "item": event,
                    },
                    status=400,
                ),
            )

        if not event.get("properties"):
            event["properties"] = {}

        _ensure_web_feature_flags_in_properties(event, team, distinct_id)

        event_uuid = UUIDT()

        if is_ee_enabled():
            log_topics = [KAFKA_EVENTS_WAL]

            if settings.PLUGIN_SERVER_INGESTION:
                log_topics.append(KAFKA_EVENTS_PLUGIN_INGESTION)
                statsd.Counter("%s_posthog_cloud_plugin_server_ingestion" %
                               (settings.STATSD_PREFIX, )).increment()

            log_event(
                distinct_id=distinct_id,
                ip=get_ip_address(request),
                site_url=request.build_absolute_uri("/")[:-1],
                data=event,
                team_id=team.id,
                now=now,
                sent_at=sent_at,
                event_uuid=event_uuid,
                topics=log_topics,
            )

            # must done after logging because process_event_ee modifies the event, e.g. by removing $elements
            if not settings.PLUGIN_SERVER_INGESTION:
                process_event_ee(
                    distinct_id=distinct_id,
                    ip=get_ip_address(request),
                    site_url=request.build_absolute_uri("/")[:-1],
                    data=event,
                    team_id=team.id,
                    now=now,
                    sent_at=sent_at,
                    event_uuid=event_uuid,
                )
        else:
            task_name = "posthog.tasks.process_event.process_event"
            if settings.PLUGIN_SERVER_INGESTION or team.plugins_opt_in:
                task_name += "_with_plugins"
                celery_queue = settings.PLUGINS_CELERY_QUEUE
            else:
                celery_queue = settings.CELERY_DEFAULT_QUEUE

            celery_app.send_task(
                name=task_name,
                queue=celery_queue,
                args=[
                    distinct_id,
                    get_ip_address(request),
                    request.build_absolute_uri("/")[:-1],
                    event,
                    team.id,
                    now.isoformat(),
                    sent_at,
                ],
            )
    timer.stop("event_endpoint")
    return cors_response(request, JsonResponse({"status": 1}))
Ejemplo n.º 2
0
def get_event(request):
    now = timezone.now()
    try:
        data_from_request = load_data_from_request(request)
        data = data_from_request["data"]
    except TypeError:
        return cors_response(
            request,
            JsonResponse(
                {
                    "code":
                    "validation",
                    "message":
                    "Malformed request data. Make sure you're sending valid JSON.",
                },
                status=400,
            ),
        )
    if not data:
        return cors_response(
            request,
            JsonResponse(
                {
                    "code":
                    "validation",
                    "message":
                    "No data found. Make sure to use a POST request when sending the payload in the body of the request.",
                },
                status=400,
            ),
        )
    sent_at = _get_sent_at(data, request)

    token = _get_token(data, request)
    is_personal_api_key = False
    if not token:
        token = PersonalAPIKeyAuthentication.find_key(
            request, data_from_request["body"],
            data if isinstance(data, dict) else None)
        is_personal_api_key = True
    if not token:
        return cors_response(
            request,
            JsonResponse(
                {
                    "code":
                    "validation",
                    "message":
                    "Neither api_key nor personal_api_key set. You can find your project API key in PostHog project settings.",
                },
                status=400,
            ),
        )

    team = Team.objects.get_team_from_token(token, is_personal_api_key)
    if team is None:
        return cors_response(
            request,
            JsonResponse(
                {
                    "code":
                    "validation",
                    "message":
                    "Project or personal API key invalid. You can find your project API key in PostHog project settings.",
                },
                status=400,
            ),
        )

    if isinstance(data, dict):
        if data.get("batch"):  # posthog-python and posthog-ruby
            data = data["batch"]
            assert data is not None
        elif "engage" in request.path_info:  # JS identify call
            data["event"] = "$identify"  # make sure it has an event name

    if isinstance(data, list):
        events = data
    else:
        events = [data]

    for event in events:
        try:
            distinct_id = _get_distinct_id(event)
        except KeyError:
            return cors_response(
                request,
                JsonResponse(
                    {
                        "code": "validation",
                        "message":
                        "You need to set user distinct ID field `distinct_id`.",
                        "item": event,
                    },
                    status=400,
                ),
            )
        if "event" not in event:
            return cors_response(
                request,
                JsonResponse(
                    {
                        "code": "validation",
                        "message": "You need to set event name field `event`.",
                        "item": event,
                    },
                    status=400,
                ),
            )

        if check_ee_enabled():
            process_event_ee.delay(
                distinct_id=distinct_id,
                ip=get_ip_address(request),
                site_url=request.build_absolute_uri("/")[:-1],
                data=event,
                team_id=team.id,
                now=now,
                sent_at=sent_at,
            )
            # log the event to kafka write ahead log for processing
            log_event(
                distinct_id=distinct_id,
                ip=get_ip_address(request),
                site_url=request.build_absolute_uri("/")[:-1],
                data=event,
                team_id=team.id,
                now=now,
                sent_at=sent_at,
            )
        else:
            process_event.delay(
                distinct_id=distinct_id,
                ip=get_ip_address(request),
                site_url=request.build_absolute_uri("/")[:-1],
                data=event,
                team_id=team.id,
                now=now,
                sent_at=sent_at,
            )

    return cors_response(request, JsonResponse({"status": 1}))
Ejemplo n.º 3
0
def get_event(request):
    timer = statsd.Timer("%s_posthog_cloud" % (settings.STATSD_PREFIX,))
    timer.start()
    now = timezone.now()
    try:
        data = load_data_from_request(request)
    except RequestParsingError as error:
        capture_exception(error)  # We still capture this on Sentry to identify actual potential bugs
        return cors_response(
            request, generate_exception_response(f"Malformed request data: {error}", code="invalid_payload"),
        )
    if not data:
        return cors_response(
            request,
            generate_exception_response(
                "No data found. Make sure to use a POST request when sending the payload in the body of the request.",
                code="no_data",
            ),
        )

    sent_at = _get_sent_at(data, request)

    token = _get_token(data, request)

    if not token:
        return cors_response(
            request,
            generate_exception_response(
                "API key not provided. You can find your project API key in PostHog project settings.",
                type="authentication_error",
                code="missing_api_key",
                status_code=status.HTTP_401_UNAUTHORIZED,
            ),
        )

    team = Team.objects.get_team_from_token(token)

    if team is None:
        try:
            project_id = _get_project_id(data, request)
        except ValueError:
            return cors_response(
                request, generate_exception_response("Invalid Project ID.", code="invalid_project", attr="project_id"),
            )
        if not project_id:
            return cors_response(
                request,
                generate_exception_response(
                    "Project API key invalid. You can find your project API key in PostHog project settings.",
                    type="authentication_error",
                    code="invalid_api_key",
                    status_code=status.HTTP_401_UNAUTHORIZED,
                ),
            )
        user = User.objects.get_from_personal_api_key(token)
        if user is None:
            return cors_response(
                request,
                generate_exception_response(
                    "Invalid Personal API key.",
                    type="authentication_error",
                    code="invalid_personal_api_key",
                    status_code=status.HTTP_401_UNAUTHORIZED,
                ),
            )
        team = user.teams.get(id=project_id)

    if isinstance(data, dict):
        if data.get("batch"):  # posthog-python and posthog-ruby
            data = data["batch"]
            assert data is not None
        elif "engage" in request.path_info:  # JS identify call
            data["event"] = "$identify"  # make sure it has an event name

    if isinstance(data, list):
        events = data
    else:
        events = [data]

    try:
        events = preprocess_session_recording_events(events)
    except ValueError as e:
        return cors_response(request, generate_exception_response(f"Invalid payload: {e}", code="invalid_payload"))

    for event in events:
        try:
            distinct_id = _get_distinct_id(event)
        except KeyError:
            return cors_response(
                request,
                generate_exception_response(
                    "You need to set user distinct ID field `distinct_id`.", code="required", attr="distinct_id"
                ),
            )
        if not event.get("event"):
            return cors_response(
                request,
                generate_exception_response(
                    "You need to set user event name, field `event`.", code="required", attr="event"
                ),
            )

        if not event.get("properties"):
            event["properties"] = {}

        _ensure_web_feature_flags_in_properties(event, team, distinct_id)

        event_uuid = UUIDT()
        ip = None if team.anonymize_ips else get_ip_address(request)

        if is_ee_enabled():
            log_topics = [KAFKA_EVENTS_WAL]

            if settings.PLUGIN_SERVER_INGESTION:
                log_topics.append(KAFKA_EVENTS_PLUGIN_INGESTION)
                statsd.Counter("%s_posthog_cloud_plugin_server_ingestion" % (settings.STATSD_PREFIX,)).increment()

            log_event(
                distinct_id=distinct_id,
                ip=ip,
                site_url=request.build_absolute_uri("/")[:-1],
                data=event,
                team_id=team.id,
                now=now,
                sent_at=sent_at,
                event_uuid=event_uuid,
                topics=log_topics,
            )

            # must done after logging because process_event_ee modifies the event, e.g. by removing $elements
            if not settings.PLUGIN_SERVER_INGESTION:
                process_event_ee(
                    distinct_id=distinct_id,
                    ip=ip,
                    site_url=request.build_absolute_uri("/")[:-1],
                    data=event,
                    team_id=team.id,
                    now=now,
                    sent_at=sent_at,
                    event_uuid=event_uuid,
                )
        else:
            task_name = "posthog.tasks.process_event.process_event_with_plugins"
            celery_queue = settings.PLUGINS_CELERY_QUEUE
            celery_app.send_task(
                name=task_name,
                queue=celery_queue,
                args=[distinct_id, ip, request.build_absolute_uri("/")[:-1], event, team.id, now.isoformat(), sent_at,],
            )
    timer.stop("event_endpoint")
    return cors_response(request, JsonResponse({"status": 1}))
Ejemplo n.º 4
0
def get_event(request):
    timer = statsd.Timer("%s_posthog_cloud" % (settings.STATSD_PREFIX,))
    timer.start()
    now = timezone.now()
    try:
        data_from_request = load_data_from_request(request)
        data = data_from_request["data"]
    except TypeError:
        return cors_response(
            request,
            JsonResponse(
                {"code": "validation", "message": "Malformed request data. Make sure you're sending valid JSON.",},
                status=400,
            ),
        )
    if not data:
        return cors_response(
            request,
            JsonResponse(
                {
                    "code": "validation",
                    "message": "No data found. Make sure to use a POST request when sending the payload in the body of the request.",
                },
                status=400,
            ),
        )
    sent_at = _get_sent_at(data, request)

    token = _get_token(data, request)

    if not token:
        return cors_response(
            request,
            JsonResponse(
                {
                    "code": "validation",
                    "message": "API key not provided. You can find your project API key in PostHog project settings.",
                },
                status=400,
            ),
        )
    team = Team.objects.get_team_from_token(token)

    if team is None:
        try:
            project_id = _get_project_id(data, request)
        except:
            return cors_response(
                request, JsonResponse({"code": "validation", "message": "Invalid project ID.",}, status=400,),
            )
        if not project_id:
            return cors_response(
                request,
                JsonResponse(
                    {
                        "code": "validation",
                        "message": "Project API key invalid. You can find your project API key in PostHog project settings.",
                    },
                    status=400,
                ),
            )
        user = User.objects.get_from_personal_api_key(token)
        if user is None:
            return cors_response(
                request, JsonResponse({"code": "validation", "message": "Personal API key invalid.",}, status=400,),
            )
        team = user.teams.get(id=project_id)

    if isinstance(data, dict):
        if data.get("batch"):  # posthog-python and posthog-ruby
            data = data["batch"]
            assert data is not None
        elif "engage" in request.path_info:  # JS identify call
            data["event"] = "$identify"  # make sure it has an event name

    if isinstance(data, list):
        events = data
    else:
        events = [data]

    for event in events:
        try:
            distinct_id = _get_distinct_id(event)
        except KeyError:
            return cors_response(
                request,
                JsonResponse(
                    {
                        "code": "validation",
                        "message": "You need to set user distinct ID field `distinct_id`.",
                        "item": event,
                    },
                    status=400,
                ),
            )
        if "event" not in event:
            return cors_response(
                request,
                JsonResponse(
                    {"code": "validation", "message": "You need to set event name field `event`.", "item": event,},
                    status=400,
                ),
            )

        if is_ee_enabled():
            process_event_ee(
                distinct_id=distinct_id,
                ip=get_ip_address(request),
                site_url=request.build_absolute_uri("/")[:-1],
                data=event,
                team_id=team.id,
                now=now,
                sent_at=sent_at,
            )
        else:
            task_name = "posthog.tasks.process_event.process_event"
            celery_queue = settings.CELERY_DEFAULT_QUEUE
            if team.plugins_opt_in:
                task_name += "_with_plugins"
                celery_queue = settings.PLUGINS_CELERY_QUEUE

            celery_app.send_task(
                name=task_name,
                queue=celery_queue,
                args=[
                    distinct_id,
                    get_ip_address(request),
                    request.build_absolute_uri("/")[:-1],
                    event,
                    team.id,
                    now.isoformat(),
                    sent_at,
                ],
            )

        if is_ee_enabled() and settings.LOG_TO_WAL:
            # log the event to kafka write ahead log for processing
            log_event(
                distinct_id=distinct_id,
                ip=get_ip_address(request),
                site_url=request.build_absolute_uri("/")[:-1],
                data=event,
                team_id=team.id,
                now=now,
                sent_at=sent_at,
            )
    timer.stop("event_endpoint")
    return cors_response(request, JsonResponse({"status": 1}))